diff options
Diffstat (limited to 'engine.cpp')
-rw-r--r-- | engine.cpp | 929 |
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 | |||
3 | UserShip* 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 | |||
35 | Weapon* 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 | |||
66 | Account::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 | |||
80 | Account::~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 | |||
88 | void 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 | |||
102 | Account::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 | |||
150 | void 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 | |||
202 | ObjectHandler::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 | |||
211 | void ObjectHandler::spawnEnemy(EnemyShip* enemy,double nx, double ny) | ||
212 | { | ||
213 | enemy->x = nx; | ||
214 | enemy->y = ny; | ||
215 | enemies.push_back(enemy); | ||
216 | } | ||
217 | |||
218 | ObjectHandler::~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 | |||
229 | void 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 | |||
236 | int 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 | |||
351 | HUD::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 | |||
383 | HUD::~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 | |||
393 | void 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 | |||
517 | LevelEvent* 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] | ||
527 | vector<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 | ||
685 | IntroLevel #name | ||
686 | data/images/bg_stars.bmp #path of background | ||
687 | 30 #speed of background | ||
688 | 1 #wether to randomize background position | ||
689 | 60 #duration [s] | ||
690 | 12346543 #seed | ||
691 | 2 #number of Shiptypes | ||
692 | data/tork_capsule.txt #path of Ship | ||
693 | 50 #how many of them should spawn | ||
694 | data/tork_spacerocket.txt #path of Ship | ||
695 | 12 #how many | ||
696 | 1 #how many events shall happen | ||
697 | 0.5 #percentage of completion the event happens | ||
698 | ****event***** #an event as specified in createEvent | ||
699 | */ | ||
700 | LevelGenerator::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 | |||
869 | LevelGenerator::~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 | |||
882 | int 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 | } | ||