summaryrefslogtreecommitdiff
path: root/engine.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engine.cpp')
-rw-r--r--engine.cpp929
1 files changed, 929 insertions, 0 deletions
diff --git a/engine.cpp b/engine.cpp
new file mode 100644
index 0000000..50b39ee
--- /dev/null
+++ b/engine.cpp
@@ -0,0 +1,929 @@
1#include "engine.h"
2
3UserShip* getShipWithName(string shipname)
4{
5 string path = "data/ships/user/";
6 ifstream ships;
7 ships.open((path + "userships.txt").c_str());
8 char workaround;
9 ships >> workaround;
10 while(ships.good())
11 {
12 string shipPath;
13 getline(ships, shipPath);
14 ifstream ins;
15 ins.open((path + workaround + shipPath).c_str());
16// cout << path + workaround + shipPath << endl;
17 char workaround2;
18 ins >> workaround2;
19 string thisShipname;
20 getline(ins, thisShipname);
21 thisShipname = workaround2 + thisShipname;
22 ins.close();
23 if(thisShipname == shipname)
24 {
25 ships.close();
26 return new UserShip(path + workaround + shipPath);
27 }
28 ships >> workaround;
29 }
30 ships.close();
31 cout << "Save File corrupted: unable to find Ship with name " << shipname << endl;
32 return NULL;
33}
34
35Weapon* getWeaponWithName(string weaponname)
36{
37 string path = "data/weapons/";
38 ifstream weapons;
39 weapons.open((path + "weapons.txt").c_str());
40 char workaround;
41 weapons >> workaround;
42 while(weapons.good())
43 {
44 string weaponPath;
45 getline(weapons, weaponPath);
46 ifstream ins;
47 ins.open((path + workaround + weaponPath).c_str());
48 char workaround2;
49 ins >> workaround2;
50 string thisWeaponname;
51 getline(ins, thisWeaponname);
52 thisWeaponname = workaround2 + thisWeaponname;
53 ins.close();
54 if(thisWeaponname == weaponname)
55 {
56 weapons.close();
57 return new Weapon(path + workaround + weaponPath);
58 }
59 weapons >> workaround;
60 }
61 weapons.close();
62 cout << "Save File corrupted: unable to find Weapon with name " << weaponname << endl;
63 return NULL;
64}
65
66Account::Account()
67{
68 gold = 0;
69 highscore = 0;
70 ifstream ins;
71 string path = "data/ships/user/";
72 ins.open((path + "userships.txt").c_str());
73 current = 0;
74 string shippath;
75 getline(ins, shippath);
76 UserShip *startShip = new UserShip(path + shippath);
77 ships.push_back(startShip);
78}
79
80Account::~Account()
81{
82 for(int i = 0; i < (int) ships.size(); i++)
83 delete ships[i];
84 for(int i = 0; i < (int) weapons.size(); i++)
85 delete weapons[i];
86}
87
88void Account::resetShips()
89{
90 for(int i = 0; i < (int) ships.size(); ++i)
91 {
92 ships[i]->reset();
93// ships[i]->hp = ships[i]->maxhp;
94// ships[i]->energy = ships[i]->maxEnergy;
95// ships[i]->xSpeed = 0;
96// ships[i]->ySpeed = 0;
97 }
98}
99
100
101
102Account::Account(string filename)
103{
104 ifstream ins;
105 ins.open((filename).c_str());
106 getline(ins, name);
107 ins >> gold;
108 ins >> highscore;
109 int Nships;
110 ins >> Nships;
111 for(int i = 0; i < (int) Nships; ++i)
112 {
113 string shipname;
114 char workaround;
115 ins >> workaround;
116 getline(ins, shipname);
117 shipname = workaround + shipname;
118 UserShip* s = getShipWithName(shipname);
119 vector<Upgradeable*> tu = s->getUpgradeables();
120 for(int j = 0; j < (int) tu.size(); ++j)
121 tu[j]->load(ins);
122 int Nweapons;
123 ins >> Nweapons;
124 for(int j = 0; j < Nweapons; ++j)
125 {
126 ins >> workaround;
127 string weaponname;
128 getline(ins, weaponname);
129 weaponname = workaround + weaponname;
130 delete s->weapons[j];
131 s->weapons[j] = getWeaponWithName(weaponname);
132 }
133 ships.push_back(s);
134 }
135 ins >> current;
136 int Nlevels;
137 ins >> Nlevels;
138 for(int i = 0; i < Nlevels; ++i)
139 {
140 int level;
141 ins >> level;
142 levels.push_back(level);
143 }
144 double nexp;
145 ins >> nexp;
146 addExp(nexp);
147 ins.close();
148}
149
150void Account::save()
151{
152 spaceto_(name);
153 bool was_saved = false;
154 ifstream ins;
155 ins.open("save/saves.txt");
156 string line;
157 getline(ins, line);
158 if(line == name)
159 was_saved = true;
160 string allSaves = line;
161 while(ins.good())
162 {
163 string line;
164 getline(ins, line);
165 if(line == name)
166 was_saved = true;
167 allSaves += "\n" + line;
168 }
169 ins.close();
170 if(!was_saved)
171 {
172 ofstream makeEntry;
173 makeEntry.open("save/saves.txt");
174 makeEntry << allSaves << '\n' << name;
175 }
176 ofstream ofs;
177 ofs.open(("save/" + name + ".txt").c_str());
178 _tospace(name);
179 ofs << name << endl;
180 ofs << gold << endl;
181 ofs << highscore << endl;
182 ofs << ships.size() << endl;
183 for(int i = 0; i < (int) ships.size(); ++i)
184 {
185 ofs << ships[i]->name << endl;
186 vector<Upgradeable*> tu = ships[i]->getUpgradeables();
187 for(int j = 0; j < (int) tu.size(); ++j)
188 tu[j]->save(ofs);
189 ofs << ships[i]->weapons.size() << endl;
190 for(int j = 0; j < (int) ships[i]->weapons.size(); ++j)
191 ofs << ships[i]->weapons[j]->name << endl;
192 }
193 ofs << current << endl;
194 ofs << levels.size() << endl;
195 for(int i = 0; i < (int) levels.size(); ++i)
196 ofs << levels[i] << endl;
197
198 ofs << exp;
199 ofs.close();
200}
201
202ObjectHandler::ObjectHandler(Account* newuser, SDL_Surface* newscreen, SDL_Surface* background)
203{
204 user = newuser;
205 screen = newscreen;
206 BG = new SlidingBackground(background,0,50);
207 highscore = 0;
208 gold = 0;
209}
210
211void ObjectHandler::spawnEnemy(EnemyShip* enemy,double nx, double ny)
212{
213 enemy->x = nx;
214 enemy->y = ny;
215 enemies.push_back(enemy);
216}
217
218ObjectHandler::~ObjectHandler()
219{
220 for(list<Projectile*>::iterator i = friendlyProjectiles.begin(); i!= friendlyProjectiles.end();++i)
221 delete *i;
222 for(list<Projectile*>::iterator i = enemyProjectiles.begin(); i!= enemyProjectiles.end();++i)
223 delete *i;
224 for(list<EnemyShip*>::iterator i = enemies.begin(); i!= enemies.end();++i)
225 delete *i;
226 delete BG;
227}
228
229void ObjectHandler::frameEnemy(EnemyShip* s, double time)
230{
231 vector<Projectile*> moreProjectiles = s->frame(time);
232 for(int i = 0; i < (int) moreProjectiles.size(); ++i)
233 enemyProjectiles.push_back(moreProjectiles[i]);
234}
235
236int ObjectHandler::frame(double time)
237{
238 UserShip *s = user->ships[user->current];
239 //applies controles
240 Uint8 *keyState = SDL_GetKeyState(NULL);
241 s->down = -keyState[SDLK_UP]+keyState[SDLK_DOWN];
242 s->right = -keyState[SDLK_LEFT]+keyState[SDLK_RIGHT];
243 s->shooting = keyState[SDLK_SPACE];
244 //frames the content
245 list<Projectile*>::iterator l1;
246 list<EnemyShip*>::iterator l2;
247 l1 = friendlyProjectiles.begin();
248 while(l1 != friendlyProjectiles.end())
249 {
250 //looking for collisions with enemies
251 double startx,starty;
252 startx = (*l1)->x;
253 starty = (*l1)->y;
254 (*l1)->frame(time);
255 bool hit = false;
256 for(l2 = enemies.begin(); l2!= enemies.end(); ++l2)
257 {
258 if((*l2)->hp > 0 && intersects((*l1)->collisionSize + (*l2)->collisionSize, startx-(*l2)->x, starty-(*l2)->y, (*l1)->x-(*l2)->x, (*l1)->y-(*l2)->y))
259 {
260 (*l2)->hit(**l1);
261// cout << (*l2)-> hp << endl;
262 hit = true;
263 break;
264 }
265 }
266 if(ooB(*l1,screen) || hit)
267 {
268 delete *l1;
269 l1 = friendlyProjectiles.erase(l1);
270 }
271 else
272 l1++;
273 }
274 l1 = enemyProjectiles.begin();
275 while(l1 != enemyProjectiles.end())
276 {
277 double startx = (*l1)->x;
278 double starty = (*l1)->y;
279 (*l1)->frame(time);
280 bool hit = false;
281 if(intersects((*l1)->collisionSize + s->collisionSize, startx-s->x, starty-s->y, (*l1)->x-s->x, (*l1)->y-s->y))
282 {
283 s->hit(**l1);
284 hit = true;
285 }
286 if(ooB(*l1,screen) || hit)
287 {
288 delete *l1;
289 l1 = enemyProjectiles.erase(l1);
290 //return 1;
291 }
292 else
293 l1++;
294 }
295 //cout << enemyProjectiles.size() << endl;
296 l2 = enemies.begin();
297 while(l2 != enemies.end())
298 {
299 frameEnemy(*l2,time);
300 if((*l2)->hp <= 0)
301 {
302 highscore += (*l2)->score;
303 gold += (*l2)->gold;
304 if(user->addExp((*l2)->exp))
305 {
306 cout << "Level Up!" << endl;
307 user->gold += user->getLevel() * 15;
308 cout << "Got " << user->getLevel() * 15 << "gold to compromise for the missing Skillsystem!" << endl;
309 }
310 delete *l2;
311 l2 = enemies.erase(l2);
312 }
313 else if(ooB(*l2,screen) && (*l2)->current == (*l2)->path.size()-1 && (*l2)->path[(*l2)->current] == make_pair((*l2)->x,(*l2)->y))
314 {
315 delete *l2;
316 l2 = enemies.erase(l2);
317 }
318 else
319 l2++;
320 }
321// cout << s->energy << endl;
322 if(s->hp <= 0)
323 return LEVEL_FAILED;
324 vector<Projectile*> moreProjectiles = s->frame(time,screen);
325 for(int i = 0; i < (int) moreProjectiles.size(); ++i)
326 friendlyProjectiles.push_back(moreProjectiles[i]);
327
328 //apply background
329 BG->frame(1/60.0);
330 BG->draw(screen);
331
332 //draws all Objects
333 for(list<EnemyShip*>::iterator i = enemies.begin(); i!= enemies.end();++i)
334 {
335 (*i)->draw(screen);
336 }
337 for(list<Projectile*>::iterator i = friendlyProjectiles.begin(); i!= friendlyProjectiles.end();++i)
338 {
339 (*i)->draw(screen);
340 }
341 for(list<Projectile*>::iterator i = enemyProjectiles.begin(); i!= enemyProjectiles.end();++i)
342 {
343 (*i)->draw(screen);
344 }
345 s->draw(screen);
346 return 0;
347}
348
349
350
351HUD::HUD(long long *nhighscore, double *nhp, double nhpmax, double *nenergy, double nmaxEnergy, double* ngold, double* nexp)
352{
353 font = NULL;
354 textColor.r = 255;
355 textColor.g = 255;
356 textColor.b = 255;
357 highscore = nhighscore;
358 hp = nhp;
359 hpmax = nhpmax;
360 energy = nenergy;
361 maxEnergy = nmaxEnergy;
362 gold = ngold;
363 exp = nexp;
364 energyRaw = loadBMP("data/images/energy_raw2.bmp");
365 SDL_Surface *bubbles = loadBMP("data/images/energy_bubbles3.bmp");
366 energyBubbles = new SlidingBackground(bubbles,0,-200);
367 energyMasc = loadBMP("data/images/energy_masc2.bmp");
368 hpRaw = loadBMP("data/images/hp_raw.bmp");
369 hpMasc = loadBMP("data/images/hp_masc2.bmp");
370 background = loadBMP("data/images/hud_background.bmp");
371 font = TTF_OpenFont("data/fonts/OpenSans-Semibold.ttf",12);
372 if(font == NULL)
373 {
374 cout << "Error loading font in HUD" << endl;
375 }
376 Uint32 colorkey = SDL_MapRGB(energyMasc->format,255 , 255, 255);
377 SDL_SetColorKey(energyMasc, 0, colorkey);
378 SDL_SetColorKey(energyMasc, SDL_SRCCOLORKEY, colorkey);
379 SDL_SetColorKey(hpMasc, 0, colorkey);
380 SDL_SetColorKey(hpMasc, SDL_SRCCOLORKEY, colorkey);
381}
382
383HUD::~HUD()
384{
385 SDL_FreeSurface(energyRaw);
386 delete energyBubbles;
387 SDL_FreeSurface(energyMasc);
388 SDL_FreeSurface(hpRaw);
389 SDL_FreeSurface(hpMasc);
390 TTF_CloseFont(font);
391}
392
393void HUD::draw(SDL_Surface* screen)
394{
395
396 //applying HUD-background
397 SDL_Rect dest,src;
398 dest.x = 300;
399 dest.y = 0;
400 SDL_BlitSurface(background,NULL,screen,&dest);
401 //making a SDL_Surface to hold the bar as it is being painted
402 SDL_Surface *energyBar = copyImage(energyRaw);
403 dest.x = 0;
404 dest.y = 0;
405 dest.w = energyBar->w;
406 dest.h = energyBar->h;
407 SDL_FillRect(energyBar,&dest,0);
408 //drawing Raw energy
409 int energyPixel = (energyRaw->h * *energy / maxEnergy);
410 dest.x = 0;
411 dest.y = energyBar->h - energyPixel;
412 src.w = energyRaw->w;
413 src.h = energyPixel;
414 src.x = 0;
415 src.y = energyRaw->h - src.h;
416 SDL_BlitSurface(energyRaw,&src,energyBar,&dest);
417
418 //apply bubbles
419 energyBubbles->ySpeed = -60* (3.0-1.5 * *energy/ maxEnergy);
420 energyBubbles->frame(1/60.0);
421 SDL_Surface *bubbles = copyImage(energyRaw);
422 dest.x = 0;
423 dest.y = 0;
424 dest.w = energyBar->w;
425 dest.h = energyBar->h;
426 SDL_FillRect(bubbles,&dest,0x00000102);
427 energyBubbles->draw(bubbles);
428 //amount by wich the bubbles extend further than the raw energy
429 int surplus = 6 - 5* *energy/ maxEnergy;
430 src.w = energyBar->w;
431 src.h = min(energyPixel+surplus,energyBar->h);
432 src.x = 0;
433 src.y = energyRaw->h - src.h;
434 dest.x = 0;
435 dest.y = energyBar->h - min(energyPixel+surplus,energyBar->h);
436 SDL_BlitSurface(bubbles,&src,energyBar,&dest);
437 SDL_FreeSurface(bubbles);
438 //lay masc over everything
439 dest.y = energyBar->h - energyMasc->h;
440 src.w = energyMasc->w;
441 src.h = energyMasc->h;
442 src.x = 0;
443 src.y = 0;
444 SDL_BlitSurface(energyMasc,&src,energyBar,&dest);
445 dest.x = 320;
446 dest.y = 480 - energyBar->h;
447 SDL_BlitSurface(energyBar,NULL,screen,&dest);
448 SDL_FreeSurface(energyBar);
449
450 //drawing Raw hp
451 SDL_Surface *hpBar = copyImage(hpRaw);
452 dest.x = 0;
453 dest.y = 0;
454 dest.w = hpRaw->w;
455 dest.h = hpRaw->h;
456 SDL_FillRect(hpBar,&dest,0);
457 int hpPixel = (hpRaw->h * *hp / hpmax);
458 dest.x = 0;
459 dest.y = hpBar->h - hpPixel;
460 src.w = hpBar->w;
461 src.h = hpPixel;
462 src.x = 0;
463 src.y = hpRaw->h - src.h;
464 SDL_BlitSurface(hpRaw,&src,hpBar,&dest);
465
466 //lay masc over everything
467 dest.x = 0;
468 dest.y = hpBar->h - hpMasc->h;
469 src.w = hpMasc->w;
470 src.h = hpMasc->h;
471 src.x = 0;
472 src.y = 0;
473 SDL_BlitSurface(hpMasc,&src,hpBar,&dest);
474 dest.x = 360;
475 dest.y = 480-hpBar->h;
476 SDL_BlitSurface(hpBar,NULL,screen,&dest);
477 SDL_FreeSurface(hpBar);
478
479 string mtemp;
480 SDL_Surface *message = NULL;
481 //display highscore
482 mtemp = "highscore: " + lltostr(*highscore);
483 message = TTF_RenderText_Solid(font, mtemp.c_str(),textColor);
484 if(message == NULL)
485 {
486 cout << "error rendering text in HUD" << endl;
487 }
488 dest.x = 316;
489 dest.y = 14;
490 SDL_BlitSurface(message,NULL,screen,&dest);
491 SDL_FreeSurface(message);
492 //display gold
493 mtemp = "gold: " + lltostr(*gold);
494 message = TTF_RenderText_Solid(font, mtemp.c_str(),textColor);
495 if(message == NULL)
496 {
497 cout << "error rendering text in HUD" << endl;
498 }
499 dest.x = 316;
500 dest.y = 30;
501 SDL_BlitSurface(message,NULL,screen,&dest);
502 SDL_FreeSurface(message);
503 //display exp
504 mtemp = "exp: " + lltostr(*exp);
505 message = TTF_RenderText_Solid(font, mtemp.c_str(),textColor);
506 if(message == NULL)
507 {
508 cout << "error rendering text in HUD" << endl;
509 }
510 dest.x = 316;
511 dest.y = 46;
512 SDL_BlitSurface(message,NULL,screen,&dest);
513 SDL_FreeSurface(message);
514}
515
516
517LevelEvent* createEvent(ifstream& ins)
518{
519 cout << "this Event is not yet implemented!" << endl;
520 return NULL;
521}
522
523
524
525//generates a Wave of enemies
526//[t-t0,path]
527vector<pair<double,vector<pair<double,double> > > > generateWave(int number, int Nweapons,SDL_Surface* screen)
528{
529 double margin = 20;
530 double spawnLength = screen->w - 80;
531 vector<pair<double,vector<pair<double,double> > > > result;
532 bool symmetric = true;
533 if(number % 2 || rand()%2)
534 symmetric = false;
535 if(symmetric)
536 number /= 2;
537 bool done = false;
538 int mirror = rand()%2;
539 int attemps = 0;
540 while(!done && attemps < 1000)
541 {
542 attemps++;
543 int type = rand()%5;
544 switch(type)
545 {
546 case 0:{
547 //diagonal line
548 if(number > 2)
549 {
550 done = true;
551 double dur = (rand()%500)/50.0;
552 for(int i = 0; i < number; ++i)
553 {
554 vector<pair<double, double> > path;
555 double spawnx;
556 spawnx = margin + spawnLength*i/((double) number);
557 if(mirror)
558 spawnx = screen->w - spawnx;
559 path.push_back(make_pair(spawnx,screen->h+margin));
560 path.push_back(make_pair(spawnx,-margin));
561 result.push_back(make_pair(dur - dur/number*i,path));
562 }
563 }
564 break;
565 }
566 case 1:{
567 //chaotic
568 if(!symmetric && number > 7)
569 {
570 done = true;
571 double dur = sqrt(number) * (rand()%1000)/500.0;
572 for(int i = 0; i < number; ++i)
573 {
574 vector<pair<double, double> > path;
575 double spawnx = margin + rand()%10000/10000.0*spawnLength;
576 path.push_back(make_pair(spawnx,screen->h+margin));
577 path.push_back(make_pair(spawnx,-margin));
578 result.push_back(make_pair(dur*((rand()%1000)/1000.0),path));
579 }
580 }
581 break;
582 }
583 case 2:{
584 if(number > 2)
585 {
586 //down diagonalup down
587 done = true;
588 double dur = (rand()%500)/50.0;
589 for(int i = 0; i < number; ++i)
590 {
591 vector<pair<double, double> > path;
592 double spawnx;
593 spawnx = margin + spawnLength*i/((double) number);
594 if(mirror)
595 spawnx = screen->w - spawnx;
596 path.push_back(make_pair(spawnx,screen->h-3*margin));
597 path.push_back(make_pair(screen->w-spawnx,2*margin));
598 path.push_back(make_pair(screen->w-spawnx,screen->h+margin));
599 path.push_back(make_pair(spawnx,-margin));
600 result.push_back(make_pair(dur/((double) number)*i,path));
601
602 }
603 }
604 break;
605 }
606 case 3:{
607 //back and forth at top
608 if(number < 5 && Nweapons > 0)
609 {
610 done = true;
611 int baf = min(rand()%6+1,rand()%6+1);
612 int right = rand()%2;
613 double spawnx;
614 if(right)
615 spawnx = screen->w - margin;
616 else
617 spawnx = margin;
618 for(int j = 0; j < number; ++j)
619 {
620 vector<pair<double, double> > path;
621 for(int i = 0; i < baf; ++i)
622 {
623 if(right)
624 path.push_back(make_pair(screen->w-spawnx,2*margin));
625 else
626 path.push_back(make_pair(margin,2*margin));
627 right = !right;
628 }
629 if(right)
630 path.push_back(make_pair(margin,screen->h+margin));
631 else
632 path.push_back(make_pair(screen->w-spawnx,screen->h + margin));
633 path.push_back(make_pair(spawnx,-margin));
634 result.push_back(make_pair(j/(rand()%3+2),path));
635 }
636 }
637 break;
638 }
639 case 4:{
640 //circles
641 done = true;
642 int rounds = min(rand()%2+1,rand()%2+1);
643 double spawnx = margin;
644 if(mirror)
645 spawnx = screen->w - margin;
646 for(int j = 0; j < number; ++j)
647 {
648 vector<pair<double, double> > path;
649 for(int i = 0; i < rounds*20; ++i)
650 {
651 if(mirror)
652 path.push_back(make_pair(screen->w*0.2*cos(2*M_PI*i/20.0)+screen->w/2.0,screen->w*0.2*sin(2*M_PI*i/20.0)+screen->h/2.0));
653 else
654 path.push_back(make_pair(screen->w*0.2*cos(2*M_PI*i/20.0)+screen->w/2.0,-screen->w*0.2*sin(2*M_PI*i/20.0)+screen->h/2.0));
655 }
656 if(right)
657 path.push_back(make_pair(margin,screen->h+margin));
658 else
659 path.push_back(make_pair(screen->w-spawnx,screen->h + margin));
660 path.push_back(make_pair(spawnx,-margin));
661 result.push_back(make_pair(j/sqrt(number)*1.5,path));
662 }
663 break;
664 }
665 default:{}
666 }
667 }
668 int oldsize = result.size();
669 if(symmetric)
670 for(int i = 0; i < oldsize; ++i)
671 {
672 vector<pair<double, double> > path;
673 for(int j = 0; j < (int) result[i].second.size(); ++j)
674 {
675 path.push_back(make_pair(screen->w-result[i].second[j].first,result[i].second[j].second));
676 }
677 result.push_back(make_pair(result[i].first,path));
678 }
679 if(attemps == 1000)
680 cout << "failed to generate wave with " << number << " units!" << endl;
681 return result;
682}
683
684/*structure of a LevelFile
685IntroLevel #name
686data/images/bg_stars.bmp #path of background
68730 #speed of background
6881 #wether to randomize background position
68960 #duration [s]
69012346543 #seed
6912 #number of Shiptypes
692data/tork_capsule.txt #path of Ship
69350 #how many of them should spawn
694data/tork_spacerocket.txt #path of Ship
69512 #how many
6961 #how many events shall happen
6970.5 #percentage of completion the event happens
698****event***** #an event as specified in createEvent
699*/
700LevelGenerator::LevelGenerator(string filename, Account* user, SDL_Surface* nscreen)
701{
702 vector<int> shouldSpawn;
703 screen = nscreen;
704 SDL_Surface* fakeScreen = loadBMP("data/images/game_screen.bmp");
705 current = 0;
706 completed = 0;
707 event = false;
708
709 ifstream ins;
710 ins.open(filename.c_str());
711 if(!ins.is_open())
712 {
713 cout << "Error: Could not open Level file " << filename << endl;
714 return;
715 }
716 getline(ins, name);
717 string backgroundPath;
718 getline(ins, backgroundPath);
719 SDL_Surface* background = loadBMP(backgroundPath);
720 OH = new ObjectHandler(user, fakeScreen,background);
721 UserShip *s = user->ships[user->current];
722 hud = new HUD(&OH->highscore, &s->hp, s->maxhp, &s->energy, s->maxEnergy, &OH->gold, user->getExpPointer());
723 ins >> OH->BG->ySpeed;
724 bool rdbg;
725 ins >> rdbg;
726 OH->BG->setRandom(rdbg);
727 ins >> duration;
728 ins >> seed;
729 int NShipTypes;
730 ins >> NShipTypes;
731 for(;NShipTypes;NShipTypes--)
732 {
733 char workaround;
734 //discards \n
735 ins >> workaround;
736 string shipFilename;
737 getline(ins, shipFilename);
738 EnemyShip* enemy = new EnemyShip(workaround + shipFilename);
739 prototypes.push_back(enemy);
740 for(int l = 0; l < (int) enemy->weapons.size(); ++l)
741 for(int i = 0; i < (int) enemy->weapons[l]->sounds.size(); ++i)
742 for(int j = 0; j < (int) enemy->weapons[l]->sounds[i].size(); ++j)
743 toDelete.push_back(enemy->weapons[l]->sounds[i][j]);
744 int number;
745 ins >> number;
746 shouldSpawn.push_back(number);
747 }
748 int NEvents;
749 ins >> NEvents;
750 for(;NEvents;NEvents--)
751 {
752 double eventtime = 0;
753 ins >> eventtime;
754 events.push_back(make_pair(eventtime,createEvent(ins)));
755 }
756 s->x = OH->screen->w/2;
757 s->y = OH->screen->h - 30;
758 srand(seed);
759 //Fill up the Queue
760 double spawnTotal = 0;
761 int spawnMax = 0;
762 for(int i = 0; i < (int) shouldSpawn.size(); ++i)
763 {
764 spawnTotal += shouldSpawn[i];
765 spawnMax = max(spawnMax,shouldSpawn[i]);
766 }
767 for(int i = 0; i < (int) prototypes.size(); ++i)
768 {
769 int rest = shouldSpawn[i];
770 int Nwaves = shouldSpawn[i]*duration/spawnTotal/(rand()%8+2.5);
771 if(Nwaves == 0)
772 Nwaves = 1;
773 vector<int> willSpawn;
774 for(int j = 0; j < Nwaves; ++j)
775 {
776 willSpawn.push_back(rest/(Nwaves-j));
777 rest -= willSpawn[j];
778 }
779 //random the evenly distributed wavesizes a bit
780 if(Nwaves > 1)
781 for(int j = 0; j < Nwaves; ++j)
782 {
783 int temp = 1;
784 if(shouldSpawn[i]/Nwaves >= 2)
785 {
786 temp = rand()%((int) shouldSpawn[i]/Nwaves);
787 temp = min(temp,rand()%((int) shouldSpawn[i]/Nwaves));
788 temp = min(temp,rand()%((int) shouldSpawn[i]/Nwaves));
789 temp = min(temp,rand()%((int) shouldSpawn[i]/Nwaves));
790 }
791 if(temp == 0)
792 temp = 1;
793 int index = rand()%Nwaves;
794 if(willSpawn[j] < temp)
795 temp = willSpawn[j];
796 if(willSpawn[j] - temp < sqrt(shouldSpawn[i])/3)
797 temp = willSpawn[j];
798
799 willSpawn[j] -= temp;
800 willSpawn[index] += temp;
801 }
802// cout << "Waves randomed a bit!" << endl;
803// cout << "Generated for " << i << endl;
804// cout << Nwaves << " waves" << endl;
805// for(int l = 0; l < Nwaves; ++l)
806// {
807// cout << willSpawn[l] << " ";
808// }
809// cout << endl;
810 double currentTime = 1;
811 //generate the waves
812 for(int j = 0; j < (int) willSpawn.size(); ++j)
813 {
814 if(willSpawn[j] > 0)
815 {
816 //determine the time of the wave
817 if((j != 0 || shouldSpawn[i] != spawnMax) && ((int) (duration - currentTime)/(Nwaves-j)*2) > 1)
818 {
819 currentTime += min(duration- currentTime - 15, (double) (rand()%((int) (duration - currentTime)/(Nwaves-j)*2)));
820 }
821 vector<pair<double, vector<pair<double,double> > > > temp = generateWave(willSpawn[j],prototypes[i]->weapons.size(),OH->screen);
822 int realSpawn = 0;
823 for(int k = 0; k < (int) temp.size(); ++k)
824 {
825 spawnQueue.push_back(make_pair((temp[k].first+currentTime)/duration,make_pair(i,temp[k].second)));
826 realSpawn++;
827 }
828 }
829 }
830
831// int attemps = 0;
832// while(rest && attemps < 1000)
833// {
834// double waveTime = rand()%10000/10000.0*(duration-15)/duration;
835// if(!(rand()%3))
836// waveTime = max(waveTime,rand()%1000/1000.0-15/duration);
837// int NperWave = 0;
838// if(rest < 3)
839// NperWave = rand()%2 + 1;
840// else
841// {
842// NperWave = rand()%((int) (shouldSpawn[i]/1.8 - shouldSpawn[i]/10.0))+1;
843// NperWave = min(NperWave, (int) rand()%((int) (shouldSpawn[i]/1.8 - shouldSpawn[i]/10.0)))+1;
844// NperWave = min(NperWave, (int) rand()%((int) (shouldSpawn[i]/1.8 - shouldSpawn[i]/10.0)))+1;
845// }
846//// cout << waveTime << " " << rest << " " << NperWave << endl;
847// if(NperWave > rest)
848// NperWave = rest;
849// vector<pair<double, vector<pair<double,double> > > > temp = generateWave(NperWave,OH->screen);
850// for(int j = 0; j < (int) temp.size(); ++j)
851// {
852// spawnQueue.push_back(make_pair(temp[j].first/duration+waveTime,make_pair(i,temp[j].second)));
853// }
854// rest-= NperWave;
855// attemps++;
856// }
857// if(attemps == 1000)
858// cout << "failed to generate level at unit " << i << endl;
859 }
860 sort(spawnQueue.begin(),spawnQueue.end());
861// for(int i = 0; i < spawnQueue.size(); ++i)
862// {
863// cout << spawnQueue[i].first
864// }
865 srand(time(0));
866
867}
868
869LevelGenerator::~LevelGenerator()
870{
871 SDL_FreeSurface(OH->screen);
872 delete OH;
873 for(int i = 0; i < (int) prototypes.size(); ++i)
874 delete prototypes[i];
875 for(int i = 0; i < (int) events.size(); ++i)
876 delete events[i].second;
877 delete hud;
878 for(int i = 0; i < (int) toDelete.size(); ++i)
879 delete toDelete[i];
880}
881
882int LevelGenerator::frame(double time)
883{
884// double oldcompleted = completed;
885 completed += time / duration;
886 if(!event)
887 {
888 //cout << current << " " << completed << endl;
889 //spawn enemies
890 while(current != (int) spawnQueue.size() && spawnQueue[current].first < completed)
891 {
892 EnemyShip* enemy = new EnemyShip(*prototypes[spawnQueue[current].second.first]);
893 enemy->x = spawnQueue[current].second.second[spawnQueue[current].second.second.size()-1].first;
894 enemy->y = spawnQueue[current].second.second[spawnQueue[current].second.second.size()-1].second;
895 spawnQueue[current].second.second.pop_back();
896 enemy->path = spawnQueue[current].second.second;
897 OH->spawnEnemy(enemy, enemy->x,enemy->y);
898 OH->frameEnemy(enemy, (completed - spawnQueue[current].first) * duration);
899 current++;
900 }
901 if(completed > 1)
902 {
903 return LEVEL_COMPLETED;
904 }
905 }
906
907
908 int result = OH->frame(time);
909 SDL_Rect r;
910 r.w = screen->w;
911 r.h = screen->h;
912 r.x = 0;
913 r.y = 0;
914 SDL_FillRect(screen,&r,0);
915 r.w = OH->screen->w;
916 r.h = OH->screen->h;
917 r.x = 0;
918 r.y = 0;
919 r.w+=2;
920 r.h+=2;
921 SDL_FillRect(screen,&r,0xFFFFFFFF);
922 r.x = 1;
923 r.y = 1;
924 r.w--;
925 r.h--;
926 SDL_BlitSurface(OH->screen,NULL,screen,&r);
927 hud->draw(screen);
928 return result;
929}