diff options
Diffstat (limited to 'enginecore.cpp')
-rw-r--r-- | enginecore.cpp | 835 |
1 files changed, 835 insertions, 0 deletions
diff --git a/enginecore.cpp b/enginecore.cpp new file mode 100644 index 0000000..047511e --- /dev/null +++ b/enginecore.cpp | |||
@@ -0,0 +1,835 @@ | |||
1 | #include "enginecore.h" | ||
2 | |||
3 | DObject::DObject(){}; | ||
4 | |||
5 | DObject::DObject(string filename, double newx, double newy) | ||
6 | { | ||
7 | image = NULL; | ||
8 | image = loadBMP(filename); | ||
9 | if(!image) | ||
10 | cout << "Problem loading file!" << endl; | ||
11 | x = newx; | ||
12 | y = newy; | ||
13 | } | ||
14 | |||
15 | DObject::DObject(SDL_Surface* newImage, double newx, double newy) | ||
16 | { | ||
17 | image = NULL; | ||
18 | image = copyImage(newImage); | ||
19 | if(!image) | ||
20 | cout << "Problem loading file!" << endl; | ||
21 | x = newx; | ||
22 | y = newy; | ||
23 | } | ||
24 | |||
25 | DObject::DObject(const DObject &o) | ||
26 | { | ||
27 | image = NULL; | ||
28 | image = copyImage(o.image); | ||
29 | if(!image) | ||
30 | cout << "Problem copying file!" << endl; | ||
31 | x = o.x; | ||
32 | y = o.y; | ||
33 | } | ||
34 | |||
35 | DObject::~DObject() | ||
36 | { | ||
37 | SDL_FreeSurface(image); | ||
38 | } | ||
39 | |||
40 | void DObject::draw(SDL_Surface* screen) | ||
41 | { | ||
42 | SDL_Rect position; | ||
43 | position.x = x - image->w / 2.0; | ||
44 | position.y = y - image->h / 2.0; | ||
45 | SDL_BlitSurface(image,NULL,screen,&position); | ||
46 | } | ||
47 | |||
48 | //checks if DObject is out of Bounds | ||
49 | bool ooB(const DObject* o, SDL_Surface* screen) | ||
50 | { | ||
51 | if(o->x < 0) | ||
52 | return true; | ||
53 | if(o->y < 0) | ||
54 | return true; | ||
55 | if(o->x > screen->w) | ||
56 | return true; | ||
57 | if(o->y > screen->h) | ||
58 | return true; | ||
59 | return false; | ||
60 | } | ||
61 | |||
62 | double armorF(double damage, double armor) | ||
63 | { | ||
64 | if(armor > 0) | ||
65 | armor *= armor/(armor+damage); | ||
66 | damage *= pow(0.5,armor/50); | ||
67 | return damage; | ||
68 | } | ||
69 | |||
70 | |||
71 | Levelable::Levelable() | ||
72 | { | ||
73 | exp = 0; | ||
74 | level = 1; | ||
75 | lin = 30; | ||
76 | quad = 10; | ||
77 | cube = 2; | ||
78 | next = lin; | ||
79 | } | ||
80 | |||
81 | int Levelable::addExp(double moreExp) | ||
82 | { | ||
83 | int levelups = 0; | ||
84 | exp += moreExp; | ||
85 | while(exp > next) | ||
86 | { | ||
87 | levelups++; | ||
88 | level++; | ||
89 | next += lin; | ||
90 | lin += quad; | ||
91 | quad += cube; | ||
92 | } | ||
93 | return levelups; | ||
94 | } | ||
95 | |||
96 | int Levelable::getLevel() | ||
97 | { | ||
98 | return level; | ||
99 | } | ||
100 | |||
101 | double Levelable::getExp() | ||
102 | { | ||
103 | return exp; | ||
104 | } | ||
105 | |||
106 | double* Levelable::getExpPointer() | ||
107 | { | ||
108 | return &exp; | ||
109 | } | ||
110 | |||
111 | |||
112 | Projectile::Projectile(SDL_Surface* newimage, double newx, double newy, double newdamage, double newcollisionSize, double newxSpeed, double newySpeed) : DObject(newimage, newx, newy) | ||
113 | { | ||
114 | damage = newdamage; | ||
115 | collisionSize = newcollisionSize; | ||
116 | xSpeed = newxSpeed; | ||
117 | ySpeed = newySpeed; | ||
118 | armorPiercing = 0; | ||
119 | } | ||
120 | |||
121 | Projectile::Projectile(const Projectile& P) : DObject((DObject) P) | ||
122 | { | ||
123 | damage = P.damage; | ||
124 | armorPiercing = P.armorPiercing; | ||
125 | collisionSize = P.collisionSize; | ||
126 | xSpeed = P.xSpeed; | ||
127 | ySpeed = P.ySpeed; | ||
128 | } | ||
129 | |||
130 | /*structure of a ProjectileFile | ||
131 | data/projectile2.bmp #path of the imagefile | ||
132 | data/sounds/spit #path of the soundfile without n.wav for int n | ||
133 | 10 #damage | ||
134 | 2 #armorPiercing | ||
135 | 1.4142 #collisionSize | ||
136 | */ | ||
137 | Projectile::Projectile(string filename, vector<Mix_Chunk*>& sounds) | ||
138 | { | ||
139 | ifstream ins; | ||
140 | ins.open(filename.c_str()); | ||
141 | if(!ins.is_open()) | ||
142 | { | ||
143 | cout << "Error: Could not load from file " << filename << endl; | ||
144 | } | ||
145 | string imageFilename; | ||
146 | getline(ins, imageFilename); | ||
147 | image = loadBMP(imageFilename); | ||
148 | string soundPath; | ||
149 | getline(ins, soundPath); | ||
150 | bool good = true; | ||
151 | long long files = 1; | ||
152 | while(good) | ||
153 | { | ||
154 | string actualPath = soundPath + lltostr(files) + ".wav"; | ||
155 | Mix_Chunk* temp = NULL; | ||
156 | temp = Mix_LoadWAV(actualPath.c_str()); | ||
157 | if(temp == NULL) | ||
158 | good = false; | ||
159 | else | ||
160 | sounds.push_back(temp); | ||
161 | ++files; | ||
162 | } | ||
163 | ins >> damage; | ||
164 | ins >> armorPiercing; | ||
165 | ins >> collisionSize; | ||
166 | } | ||
167 | |||
168 | void Projectile::frame(double time) | ||
169 | { | ||
170 | x += xSpeed*time; | ||
171 | y += ySpeed*time; | ||
172 | } | ||
173 | |||
174 | void Projectile::rotateAccordingly() | ||
175 | { | ||
176 | double norm = sqrt(xSpeed*xSpeed + ySpeed*ySpeed); | ||
177 | if(norm != 0) | ||
178 | { | ||
179 | double angle = asin(xSpeed / norm); | ||
180 | if(ySpeed < 0) | ||
181 | { | ||
182 | angle = M_PI-angle; | ||
183 | } | ||
184 | SDL_Surface* temp = image; | ||
185 | image = rotozoomSurface(image,angle/M_PI*180,1,0); | ||
186 | SDL_FreeSurface(temp); | ||
187 | } | ||
188 | } | ||
189 | |||
190 | |||
191 | |||
192 | Item::Item(const Item& item):DObject((DObject) item) | ||
193 | { | ||
194 | cost = item.cost; | ||
195 | sellable = item.sellable; | ||
196 | } | ||
197 | |||
198 | Item::Item(const DObject& dObject):DObject(dObject) | ||
199 | { | ||
200 | } | ||
201 | |||
202 | SDL_Surface* Item::getImage() | ||
203 | { | ||
204 | return image; | ||
205 | } | ||
206 | |||
207 | Weapon::Weapon(const Weapon& w):Item((Item) w) | ||
208 | { | ||
209 | playSound = true; | ||
210 | for(int i = 0; i < (int) w.prototypes.size(); ++i) | ||
211 | { | ||
212 | prototypes.push_back(new Projectile(*w.prototypes[i])); | ||
213 | } | ||
214 | for(int i = 0; i < (int) w.sounds.size(); ++i) | ||
215 | { | ||
216 | vector<Mix_Chunk*> temp; | ||
217 | for(int j = 0; j < (int) w.sounds[i].size(); ++j) | ||
218 | { | ||
219 | temp.push_back(w.sounds[i][j]); | ||
220 | } | ||
221 | sounds.push_back(temp); | ||
222 | } | ||
223 | sellable = w.sellable; | ||
224 | cost = w.cost; | ||
225 | active = true; | ||
226 | energyUsage = w.energyUsage; | ||
227 | name = w.name; | ||
228 | cooldown = w.cooldown; | ||
229 | startTimer = w.startTimer; | ||
230 | currentTimer = startTimer; | ||
231 | } | ||
232 | |||
233 | /* structure of a Weaponfile: | ||
234 | epic imbaweapon of massdestruction #name | ||
235 | data/weapon89.bmp #filename of image of weapon | ||
236 | 0.5 #energyusage | ||
237 | 0 #sellable | ||
238 | 10000000 #cost | ||
239 | 2 #number of distinguished Projectiles | ||
240 | 1 #cooldown | ||
241 | 0.5 #startTimer | ||
242 | data/projectile11.txt #path | ||
243 | 0 #xSpeed | ||
244 | 700 #-ySpeed | ||
245 | 5 #cooldown | ||
246 | 0 #startTimer | ||
247 | data/projectile14.txt #path | ||
248 | 0 #xSpeed | ||
249 | 500 #-ySpeed | ||
250 | */ | ||
251 | Weapon::Weapon(string filename) | ||
252 | { | ||
253 | playSound = true; | ||
254 | ifstream ins; | ||
255 | ins.open(filename.c_str()); | ||
256 | if(!ins.is_open()) | ||
257 | { | ||
258 | cout << "Error: Could not open file " << filename << endl; | ||
259 | } | ||
260 | getline(ins,name); | ||
261 | string imageFilename; | ||
262 | getline(ins, imageFilename); | ||
263 | // cout << imageFilename << endl; | ||
264 | image = loadBMP(imageFilename); | ||
265 | active = true; | ||
266 | ins >> energyUsage; | ||
267 | ins >> sellable; | ||
268 | ins >> cost; | ||
269 | int Nprojectiles; | ||
270 | ins >> Nprojectiles; | ||
271 | for(;Nprojectiles;Nprojectiles--) | ||
272 | { | ||
273 | double temp; | ||
274 | ins >> temp; | ||
275 | cooldown.push_back(temp); | ||
276 | ins >> temp; | ||
277 | startTimer.push_back(temp); | ||
278 | string projectileFilename; | ||
279 | //this workaround discards all \n | ||
280 | char workaround; | ||
281 | ins >> workaround; | ||
282 | getline(ins,projectileFilename); | ||
283 | vector<Mix_Chunk*> projectileSounds; | ||
284 | prototypes.push_back(new Projectile(workaround + projectileFilename, projectileSounds)); | ||
285 | ins >> prototypes[prototypes.size()-1]->xSpeed; | ||
286 | ins >> prototypes[prototypes.size()-1]->ySpeed; | ||
287 | prototypes[prototypes.size()-1]->ySpeed *= -1; | ||
288 | sounds.push_back(projectileSounds); | ||
289 | } | ||
290 | currentTimer = startTimer; | ||
291 | ins.close(); | ||
292 | if(cost == 0) | ||
293 | cost = round_beautiful(estimateValue(*this)); | ||
294 | } | ||
295 | |||
296 | Weapon::~Weapon() | ||
297 | { | ||
298 | for(int i = 0; i < (int) prototypes.size(); ++i) | ||
299 | delete prototypes[i]; | ||
300 | } | ||
301 | |||
302 | vector<Projectile*> Weapon::frame(double time) | ||
303 | { | ||
304 | vector<Projectile*> result; | ||
305 | for(int i = 0; i < (int) prototypes.size(); ++i) | ||
306 | { | ||
307 | currentTimer[i] += time; | ||
308 | while(currentTimer[i] > cooldown[i]) | ||
309 | { | ||
310 | Projectile* tempP = new Projectile(*prototypes[i]); | ||
311 | if(sounds[i].size() && playSound) | ||
312 | { | ||
313 | int temp = Mix_PlayChannel(-1,sounds[i][rand()%sounds[i].size()],0); | ||
314 | if(temp == -1) | ||
315 | { | ||
316 | cout << "there was an error playing sound of projectile" << " from weapon " << name << endl; | ||
317 | } | ||
318 | } | ||
319 | tempP->x = x; | ||
320 | tempP->y = y; | ||
321 | tempP->rotateAccordingly(); | ||
322 | currentTimer[i] -= cooldown[i]; | ||
323 | tempP->frame(currentTimer[i]); | ||
324 | result.push_back(tempP); | ||
325 | } | ||
326 | } | ||
327 | return result; | ||
328 | } | ||
329 | |||
330 | void Weapon::mirror() | ||
331 | { | ||
332 | for(int i = 0; i < (int) prototypes.size(); ++i) | ||
333 | prototypes[i]->ySpeed *= -1; | ||
334 | } | ||
335 | |||
336 | double Weapon::getDPS() const | ||
337 | { | ||
338 | double result = 0; | ||
339 | for(int i = 0; i < (int) prototypes.size(); ++i) | ||
340 | result += prototypes[i]->damage/cooldown[i]; | ||
341 | return result; | ||
342 | } | ||
343 | |||
344 | double Weapon::getDPE() const | ||
345 | { | ||
346 | if(energyUsage == 0) | ||
347 | return 0; | ||
348 | return getDPS()/energyUsage; | ||
349 | } | ||
350 | |||
351 | double estimateValue(const Weapon& w) | ||
352 | { | ||
353 | double result = w.getDPS()*w.getDPS()*5; | ||
354 | if(w.getDPE() != 0) | ||
355 | result /= 0.3 + 1 / w.getDPE(); | ||
356 | else | ||
357 | result /= 0.3; | ||
358 | return result; | ||
359 | } | ||
360 | |||
361 | void Upgradeable::setValue(double nvalue) | ||
362 | { | ||
363 | value = nvalue; | ||
364 | } | ||
365 | |||
366 | double Upgradeable::getValue() const | ||
367 | { | ||
368 | return value; | ||
369 | } | ||
370 | |||
371 | Upgradeable::Upgradeable() | ||
372 | { | ||
373 | level = 1; | ||
374 | cost = 0; | ||
375 | maxLevel = 0; | ||
376 | } | ||
377 | |||
378 | Upgradeable::operator double() const | ||
379 | { | ||
380 | return value; | ||
381 | } | ||
382 | |||
383 | Upgradeable& Upgradeable::operator=(const double& d) | ||
384 | { | ||
385 | value = d; | ||
386 | return *this; | ||
387 | } | ||
388 | |||
389 | Upgradeable::Upgradeable(double nvalue) | ||
390 | { | ||
391 | level = 1; | ||
392 | cost = 0; | ||
393 | maxLevel = 0; | ||
394 | value = nvalue; | ||
395 | } | ||
396 | |||
397 | void Upgradeable::upgrade() | ||
398 | { | ||
399 | if(level == maxLevel) | ||
400 | { | ||
401 | cout << "Can't Upgrade! Already at max Level." << endl; | ||
402 | } | ||
403 | level++; | ||
404 | cost += cost * (3+level)/10.0; | ||
405 | value += 0.3*value; | ||
406 | } | ||
407 | |||
408 | |||
409 | void Upgradeable::save(ofstream& o) | ||
410 | { | ||
411 | o << name << endl; | ||
412 | o << value << endl; | ||
413 | o << cost << endl; | ||
414 | o << level << endl; | ||
415 | o << maxLevel << endl; | ||
416 | } | ||
417 | |||
418 | void Upgradeable::load(ifstream& i) | ||
419 | { | ||
420 | char workaround; | ||
421 | i >> workaround; | ||
422 | getline(i,name); | ||
423 | name = workaround + name; | ||
424 | i >> value; | ||
425 | i >> cost; | ||
426 | i >> level; | ||
427 | i >> maxLevel; | ||
428 | } | ||
429 | |||
430 | ifstream& operator>>(ifstream& ins, Upgradeable& u) | ||
431 | { | ||
432 | double d; | ||
433 | ins >> d; | ||
434 | u = d; | ||
435 | return ins; | ||
436 | } | ||
437 | |||
438 | Ship::Ship(string filename,int x, int y):DObject(filename,x,y) | ||
439 | { | ||
440 | collisionSize = image->w; | ||
441 | } | ||
442 | |||
443 | Ship::~Ship() | ||
444 | { | ||
445 | for(int i = 0; i < (int) weapons.size();++i) | ||
446 | delete weapons[i]; | ||
447 | } | ||
448 | |||
449 | vector<Projectile*> Ship::frame(double time) | ||
450 | { | ||
451 | vector<Projectile*> result; | ||
452 | return result; | ||
453 | } | ||
454 | |||
455 | int Ship::hit(const Projectile& P) | ||
456 | { | ||
457 | double tempArmor = 0; | ||
458 | if(armor > 0) | ||
459 | tempArmor = max(tempArmor,armor-P.armorPiercing); | ||
460 | hp -= armorF(P.damage,tempArmor); | ||
461 | if(hp < 0) | ||
462 | return 1; | ||
463 | return 0; | ||
464 | } | ||
465 | |||
466 | Ship::Ship(const Ship& s):DObject((DObject) s) | ||
467 | { | ||
468 | name = s.name; | ||
469 | maxhp = s.maxhp; | ||
470 | hp = maxhp; | ||
471 | moveSpeed = s.moveSpeed; | ||
472 | collisionSize = s.collisionSize; | ||
473 | armor = s.armor; | ||
474 | for(int i = 0; i < (int) s.weapons.size(); ++i) | ||
475 | { | ||
476 | weapons.push_back(new Weapon(*s.weapons[i])); | ||
477 | slotPositions.push_back(s.slotPositions[i]); | ||
478 | } | ||
479 | } | ||
480 | |||
481 | |||
482 | EnemyShip::EnemyShip(const EnemyShip& s): Ship((Ship) s) | ||
483 | { | ||
484 | path = s.path; | ||
485 | gold = s.gold; | ||
486 | exp = s.exp; | ||
487 | score = s.score; | ||
488 | current = 0; | ||
489 | if(!path.size()) | ||
490 | { | ||
491 | path.push_back(make_pair(s.x,s.y)); | ||
492 | } | ||
493 | x = path[0].first; | ||
494 | y = path[0].second; | ||
495 | |||
496 | } | ||
497 | |||
498 | /*structure of an EnemShipfile | ||
499 | Tork Spacerocket #name | ||
500 | data/images/tork_spacerocket.bmp #path of imagefile | ||
501 | 7 #maxhp | ||
502 | 5 #armor | ||
503 | 50 #moveSpeed | ||
504 | 4 #collisionSize | ||
505 | 3 #Gold | ||
506 | 3 #exp | ||
507 | 3 #score | ||
508 | 1 #number of weapons | ||
509 | 0 -1 #relative Position of weapon | ||
510 | data/fireball.txt #path of weapon | ||
511 | */ | ||
512 | EnemyShip::EnemyShip(string filename) | ||
513 | { | ||
514 | current = 0; | ||
515 | path.push_back(make_pair(0,0)); | ||
516 | ifstream ins; | ||
517 | ins.open(filename.c_str()); | ||
518 | if(!ins.is_open()) | ||
519 | cout << "Error: Could not open enemyfile " << filename << endl; | ||
520 | getline(ins, name); | ||
521 | string imagePath; | ||
522 | getline(ins, imagePath); | ||
523 | image = loadBMP(imagePath); | ||
524 | ins >> maxhp; | ||
525 | hp = maxhp; | ||
526 | ins >> armor; | ||
527 | ins >> moveSpeed; | ||
528 | ins >> collisionSize; | ||
529 | ins >> gold; | ||
530 | ins >> exp; | ||
531 | ins >> score; | ||
532 | int Nweapons = 0; | ||
533 | ins >> Nweapons; | ||
534 | for(;Nweapons;Nweapons--) | ||
535 | { | ||
536 | double temp1, temp2; | ||
537 | ins >> temp1; | ||
538 | ins >> temp2; | ||
539 | slotPositions.push_back(make_pair(temp1,temp2)); | ||
540 | //A workaround that helps discarting \n | ||
541 | char workaround; | ||
542 | ins >> workaround; | ||
543 | string weaponpath; | ||
544 | getline(ins, weaponpath); | ||
545 | weapons.push_back(new Weapon(workaround + weaponpath)); | ||
546 | weapons[weapons.size()-1]->mirror(); | ||
547 | } | ||
548 | if(!(exp || gold || score)) | ||
549 | assignValue(); | ||
550 | } | ||
551 | |||
552 | vector<Projectile*> EnemyShip::frame(double time) | ||
553 | { | ||
554 | //adjusting position | ||
555 | while(current != path.size()-1 && path[current] == make_pair(x,y)) | ||
556 | current++; | ||
557 | if(path[current] != make_pair(x,y)) | ||
558 | { | ||
559 | double dirx = path[current].first - x; | ||
560 | double diry = path[current].second - y; | ||
561 | double norm = sqrt(dirx*dirx + diry*diry); | ||
562 | dirx /= norm; | ||
563 | diry /= norm; | ||
564 | if(norm < moveSpeed*time) | ||
565 | { | ||
566 | x = path[current].first; | ||
567 | y = path[current].second; | ||
568 | } | ||
569 | else | ||
570 | { | ||
571 | x += dirx * moveSpeed * time; | ||
572 | y += diry * moveSpeed * time; | ||
573 | } | ||
574 | } | ||
575 | for(int i = 0; i < (int) weapons.size(); ++i) | ||
576 | { | ||
577 | weapons[i]->x = x + slotPositions[i].first; | ||
578 | weapons[i]->y = y + slotPositions[i].second; | ||
579 | // cout << weapons[i]->x << " " << weapons[i]->y << " weapon " << i << endl; | ||
580 | } | ||
581 | |||
582 | |||
583 | vector<Projectile*> result; | ||
584 | for(int i = 0; i < (int) weapons.size(); ++i) | ||
585 | { | ||
586 | vector<Projectile*> temp; | ||
587 | temp = weapons[i]->frame(time); | ||
588 | for(int j = 0; j < (int) temp.size(); ++j) | ||
589 | result.push_back(temp[j]); | ||
590 | } | ||
591 | return result; | ||
592 | } | ||
593 | |||
594 | void EnemyShip::assignValue() | ||
595 | { | ||
596 | exp = 0; | ||
597 | for(int i = 0; i < (int) weapons.size(); ++i) | ||
598 | exp += weapons[i]->getDPS(); | ||
599 | // exp *= 4; | ||
600 | gold = maxhp * pow(2,armor/(50.0+maxhp/10))*2.5; | ||
601 | score = gold * moveSpeed / 140; | ||
602 | double sum = (gold + score + exp)/9; | ||
603 | exp = (int)(sqrt(exp+sum)+0.5); | ||
604 | gold = (int)(sqrt(gold+sum) +0.5); | ||
605 | score = (int)(sqrt(score+sum)+0.5); | ||
606 | // cout << s.name << '\n'; | ||
607 | // cout << "gold: " << s.gold << " -> " << gold << '\n'; | ||
608 | // cout << "high: " << s.score << " -> " << high << '\n'; | ||
609 | // cout << "exp: " << s.exp << " -> " << exp << '\n'; | ||
610 | // cout << "sum: " << sum << '\n'; | ||
611 | } | ||
612 | |||
613 | |||
614 | vector<Upgradeable*> UserShip::getUpgradeables() | ||
615 | { | ||
616 | vector<Upgradeable*> result; | ||
617 | result.push_back(&maxhp); | ||
618 | result.push_back(&armor); | ||
619 | result.push_back(&maxEnergy); | ||
620 | result.push_back(&energyProduction); | ||
621 | result.push_back(&handling); | ||
622 | result.push_back(&moveSpeed); | ||
623 | return result; | ||
624 | } | ||
625 | |||
626 | vector<Projectile*> UserShip::frame(double time, SDL_Surface* screen) | ||
627 | { | ||
628 | vector<Projectile*> result; | ||
629 | //adjust energy | ||
630 | energy += energyProduction*time; | ||
631 | if(energy > maxEnergy) | ||
632 | energy = maxEnergy; | ||
633 | if(shooting) | ||
634 | { | ||
635 | double energyNeed = 0; | ||
636 | for(int i = 0; i < (int) weapons.size(); ++i) | ||
637 | energyNeed += weapons[i]->energyUsage*time; | ||
638 | if(energyNeed < energy) | ||
639 | { | ||
640 | energy -= energyNeed; | ||
641 | for(int i = 0; i < (int) weapons.size(); ++i) | ||
642 | { | ||
643 | vector<Projectile*> temp; | ||
644 | temp = weapons[i]->frame(time); | ||
645 | for(int j = 0; j < (int) temp.size(); ++j) | ||
646 | result.push_back(temp[j]); | ||
647 | } | ||
648 | } | ||
649 | } | ||
650 | |||
651 | //adjust speed and position of the ship | ||
652 | double norm1 = sqrt(right*right + down*down); | ||
653 | double norm2 = sqrt(xSpeed*xSpeed + ySpeed*ySpeed); | ||
654 | double handconst = time*handling; | ||
655 | double speedconst = norm2/moveSpeed; | ||
656 | if(handconst * speedconst > norm2 || norm2 == 0) | ||
657 | { | ||
658 | xSpeed = 0; | ||
659 | ySpeed = 0; | ||
660 | } | ||
661 | else | ||
662 | { | ||
663 | xSpeed *= 1 - speedconst * handconst / norm2; | ||
664 | ySpeed *= 1 - speedconst * handconst / norm2 ; | ||
665 | } | ||
666 | norm2 = sqrt(xSpeed*xSpeed + ySpeed*ySpeed); | ||
667 | if(norm1 != 0) | ||
668 | { | ||
669 | xSpeed += handconst*right / norm1; | ||
670 | ySpeed += handconst*down / norm1; | ||
671 | } | ||
672 | else | ||
673 | { | ||
674 | if(handconst > norm2) | ||
675 | { | ||
676 | xSpeed = 0; | ||
677 | ySpeed = 0; | ||
678 | } | ||
679 | else | ||
680 | { | ||
681 | xSpeed -= handconst * xSpeed / norm2; | ||
682 | ySpeed -= handconst * ySpeed / norm2; | ||
683 | } | ||
684 | } | ||
685 | // cout << xSpeed << " " << ySpeed << endl; | ||
686 | x += xSpeed*time; | ||
687 | y += ySpeed*time; | ||
688 | if(x - image->w/2.0 < 0) | ||
689 | { | ||
690 | x = image->w/2.0; | ||
691 | xSpeed = 0; | ||
692 | } | ||
693 | if(y - image->h/2.0 < 0) | ||
694 | { | ||
695 | y = image->h/2.0; | ||
696 | ySpeed = 0; | ||
697 | } | ||
698 | if(x + image->w/2.0 > screen->w) | ||
699 | { | ||
700 | x = screen->w - image->w/2.0; | ||
701 | xSpeed = 0; | ||
702 | } | ||
703 | if(y + image->h/2.0 > screen->h) | ||
704 | { | ||
705 | y = screen->h - image->h/2.0; | ||
706 | ySpeed = 0; | ||
707 | } | ||
708 | for(int i = 0; i < (int) weapons.size(); ++i) | ||
709 | { | ||
710 | weapons[i]->x = slotPositions[i].first + x; | ||
711 | weapons[i]->y = slotPositions[i].second + y; | ||
712 | } | ||
713 | return result; | ||
714 | } | ||
715 | |||
716 | /*structure of an UserShipfile | ||
717 | small Fighter #name | ||
718 | data/images/small_fighter.bmp #path of imagefile | ||
719 | 200 #cost | ||
720 | 7 #maxhp | ||
721 | 50 #armor | ||
722 | 200 #moveSpeed | ||
723 | 100 #handling | ||
724 | 10 #maxEnergy | ||
725 | 2 #energyProduction | ||
726 | 7 #collisionSize | ||
727 | 2 #number of weapons | ||
728 | 4 4 #relative Position of weapon | ||
729 | 3 #maxSize of attached weapon | ||
730 | data/fireball.txt #path of weapon | ||
731 | 4 4 #relative Position of weapon | ||
732 | 3 #maxSize of attached weapon | ||
733 | data/fireball.txt #path of weapon | ||
734 | */ | ||
735 | UserShip::UserShip(string filename) | ||
736 | { | ||
737 | xSpeed = 0; | ||
738 | ySpeed = 0; | ||
739 | down = 0; | ||
740 | right = 0; | ||
741 | shooting = 0; | ||
742 | ifstream ins; | ||
743 | ins.open(filename.c_str()); | ||
744 | if(!ins.is_open()) | ||
745 | cout << "Error: Could not open userShip " << filename << endl; | ||
746 | getline(ins, name); | ||
747 | string imagePath; | ||
748 | getline(ins, imagePath); | ||
749 | image = loadBMP(imagePath); | ||
750 | ins >> cost; | ||
751 | ins >> maxhp; | ||
752 | maxhp.name = "Hitpoints"; | ||
753 | maxhp.cost = cost/10; | ||
754 | hp = maxhp; | ||
755 | ins >> armor; | ||
756 | armor.name = "Armor"; | ||
757 | armor.cost = cost/10; | ||
758 | ins >> moveSpeed; | ||
759 | moveSpeed.name = "Max Speed"; | ||
760 | moveSpeed.cost = cost/10; | ||
761 | ins >> handling; | ||
762 | handling.name = "Acceleration"; | ||
763 | handling.cost = cost/10; | ||
764 | ins >> maxEnergy; | ||
765 | maxEnergy.name = "Battery"; | ||
766 | maxEnergy.cost = cost/10; | ||
767 | energy = maxEnergy; | ||
768 | ins >> energyProduction; | ||
769 | energyProduction.name = "Generator"; | ||
770 | energyProduction.cost = cost/10; | ||
771 | ins >> collisionSize; | ||
772 | ins >> weaponSlots; | ||
773 | for(int i = 0; i < weaponSlots;i++) | ||
774 | { | ||
775 | double temp1, temp2; | ||
776 | ins >> temp1; | ||
777 | ins >> temp2; | ||
778 | slotPositions.push_back(make_pair(temp1,temp2)); | ||
779 | ins >> temp1; | ||
780 | maxSize.push_back(temp1); | ||
781 | //A workaround that helps discarting \n | ||
782 | char workaround; | ||
783 | ins >> workaround; | ||
784 | string weaponpath; | ||
785 | getline(ins, weaponpath); | ||
786 | weapons.push_back(new Weapon(workaround + weaponpath)); | ||
787 | } | ||
788 | if(cost == 0) | ||
789 | cost = round_beautiful(estimateValue(*this)); | ||
790 | ins.close(); | ||
791 | } | ||
792 | |||
793 | void UserShip::reset() | ||
794 | { | ||
795 | hp = maxhp; | ||
796 | energy = maxEnergy; | ||
797 | xSpeed = 0; | ||
798 | ySpeed = 0; | ||
799 | for(int i = 0; i < (int) weapons.size(); ++i) | ||
800 | { | ||
801 | weapons[i]->playSound = false; | ||
802 | vector<Projectile*> dump = weapons[i]->frame((rand()%2000)/1000.0); | ||
803 | weapons[i]->playSound = true; | ||
804 | for(int j = 0; j < (int) dump.size(); ++j) | ||
805 | delete dump[j]; | ||
806 | } | ||
807 | } | ||
808 | |||
809 | void UserShip::draw(SDL_Surface* screen) | ||
810 | { | ||
811 | DObject::draw(screen); | ||
812 | for(int i = 0; i < (int) weapons.size(); ++i) | ||
813 | weapons[i]->draw(screen); | ||
814 | } | ||
815 | |||
816 | SDL_Surface* UserShip::getImage() | ||
817 | { | ||
818 | return image; | ||
819 | } | ||
820 | |||
821 | double estimateValue(const UserShip& s) | ||
822 | { | ||
823 | double result; | ||
824 | result = s.maxhp * pow(2,s.armor/(50.0+s.maxhp/10)); | ||
825 | result *= result; | ||
826 | result += s.maxEnergy*s.maxEnergy + s.energyProduction * s.energyProduction * 50; | ||
827 | result *= s.weapons.size(); | ||
828 | result *= s.moveSpeed / 300 * s.handling / 300; | ||
829 | |||
830 | return result/11; | ||
831 | } | ||
832 | |||
833 | |||
834 | |||
835 | |||