1 /* ************************************************************************* *
2 OldSkoolGravityGame (OSGG) Lunar Lander-like game for linux.
3 Copyright (C) 2008 Jimmy Christensen ( dusted at dusted dot dk )
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 * ************************************************************************* */
18
19 #include <iostream>
20 #include <SDL/SDL.h>
21 #include <vector>
22 #include <list>
23 #include <math.h>
24 #include <fstream>
25 #include <iostream>
26 #include <sstream>
27
28 #include <sys/time.h>
29
30 #define VERSION "1.0SVN"
31
32
33
34 #ifndef DATADIR
35 #define DATADIR "./"
36 #endif
37
38 using namespace std;
39
40 #define THRUSTINCRATE 0.01
41 #define GRAVITY 0.002
42 #define TURNINCRATE 0.15
43
44 enum entTypes { entLine, entShip, entBase, entWp, entEnemy };
45 enum gameStateEnum { GameStateEditor, GameStatePlaying, GameStatePause, GameStateQuit, GameStateNewGame, GameStateGameOver, GameStateNextLevel, GameStateStartEditor };
46 uint gameState = GameStateEditor;
47
48
49 struct pStruct {
50 int x,y;
51 };
52
53 string levelFile;
54
55 struct glPstruct {
56 float x, y;
57 };
58
59 struct structVert {
60 float color[3];
61 struct glPstruct p;
62 int collision; // 0 = none, 1 = normal(damage), 2 = platform/Landing gear
63 };
64
65 typedef struct structVert vert;
66 typedef struct glPstruct gPs;
67 typedef struct pStruct pS;
68
69 struct structEnt {
70 struct glPstruct p; //position
71 float rotation; //In DEG
72 gPs vel; //Velocity, only used for enemies right now
73 gPs baseP; //Base (start) position, used for nme
74 int type; //type
75 int id;
76 bool base; // If it's a base, don't translate it every time..
77 };
78 typedef struct structEnt entity;
79
80
81 struct structGameRules {
82 int startLevel; //what level to start in
83 float maxLandingRotForce;
84 float maxLandingYel;
85 float maxLandingXvel;
86 int fuelConsumptionThrust;
87 int fuelConsumptionTurn;
88 int fuelMaxFuel;
89 int ammoMaxAmmo;
90 };
91
92 struct structGameRules gameRules;
93
94 struct gameInfoStruct {
95 float thrust;
96 gPs velocity;
97 float speed; //Relative speed
98
99 float rotationForce;
100 float distance;
101
102 int fuel;
103 int reloadTime; //After this amount of fames (60th's of 1 sec) player can shoot again
104 int ammo;
105
106 gPs radarDest; //Destination for package, points to the base where package should be delivered
107 int destBase; // 0 = no package, id of base.
108 int numBases; // Number of bases on map, set by loadMap
109 int score;
110 int numMissions; //number of finished missions
111 int level;
112 int lives;
113
114 vector<vert> shipVerts;
115 vector<vert> baseVerts;
116 vector<vert> enemyVerts;
117
118 vector<vert> shipStaticVerts;
119 vector<vert> baseStaticVerts;
120 vector<vert> enemyStaticVerts;
121
122 vector<int> nextObjective; //Where to deliver to next.
123 int currentObjective; //What right now?
124
125 };
126 struct gameInfoStruct gameInfo;
127
abs2(float x)128 float abs2(float x)
129 {
130 if (x<0) {return -x;}
131 return x;
132 }
133
LinesCross(gPs aLineA,gPs aLineB,gPs bLineA,gPs bLineB)134 bool LinesCross(gPs aLineA, gPs aLineB, gPs bLineA, gPs bLineB)
135 {
136 //First line, first point
137 float x0 = aLineA.x;
138 float y0 = aLineA.y;
139 //First Line, second point
140 float x1 = aLineB.x;
141 float y1 = aLineB.y;
142 //Second Line, First point
143 float x2 = bLineA.x;
144 float y2 = bLineA.y;
145 //Second Line, Second point
146 float x3 = bLineB.x;
147 float y3 = bLineB.y;
148
149
150 float d=(x1-x0)*(y3-y2)-(y1-y0)*(x3-x2);
151 if (abs2(d)<0.001f) {return 0;}
152 float AB=((y0-y2)*(x3-x2)-(x0-x2)*(y3-y2))/d;
153 if (AB>0.0 && AB<1.0)
154 {
155 float CD=((y0-y2)*(x1-x0)-(x0-x2)*(y1-y0))/d;
156 if (CD>0.0 && CD<1.0)
157 {
158 return 1;
159 }
160 }
161
162 return 0;
163 }
164
165
166
167 struct structShot {
168 gPs pa,pb;
169 gPs v;
170 int age, life;
171 bool fromShip; //if 1, wont collide with ship
172 };
173
174 class classBullets {
175 private:
176 vector<struct structShot> shots;
177 public:
178 void shoot(entity owner, gPs velocity);
179 void render();
180 bool col(vector<vert> target, bool isShip);
181 void envCol(vector< vector<vert> > polys);
182 };
183
envCol(vector<vector<vert>> polys)184 void classBullets::envCol(vector< vector<vert> > polys)
185 {
186 for(vector< vector<vert> >::iterator PolyIt = polys.begin(); PolyIt != polys.end(); ++PolyIt)
187 {
188 classBullets::col(*PolyIt, 0);
189 }
190 }
191
col(vector<vert> target,bool isShip)192 bool classBullets::col(vector<vert> target, bool isShip)
193 {
194 gPs tLineA, tLineB;
195 for(vector<struct structShot>::iterator it = shots.begin(); it != shots.end(); ++it)
196 {
197 if(it->fromShip != isShip)
198 {
199 for(int ii=0; ii < target.size(); ii++)
200 {
201 if(ii==0)
202 {
203 tLineB = target[ii].p;
204 } else {
205 tLineA = tLineB;
206 tLineB = target[ii].p;
207
208 if(LinesCross(tLineA, tLineB, it->pa, it->pb))
209 {
210 //Remove bullet.
211 it = shots.erase(it);
212 return(1);
213 }
214 }
215 }
216 }
217 }
218 }
219
shoot(entity owner,gPs velocity)220 void classBullets::shoot(entity owner, gPs velocity)
221 {
222 struct structShot ts;
223
224 ts.pb = owner.p;
225 ts.pa.x = owner.p.x + 6.0* cos( owner.rotation * 0.0174532925 );
226 ts.pa.y = owner.p.y + 6.0* sin( owner.rotation * 0.0174532925 );
227
228 ts.v.x = velocity.x + 1.0 * cos( owner.rotation * 0.0174532925 );
229 ts.v.y = velocity.y + 1.0 * sin( owner.rotation * 0.0174532925 );
230
231 ts.age = 0;
232 ts.life = 40;
233
234 if(owner.type == entShip)
235 {
236 ts.fromShip=1;
237 } else {
238 ts.fromShip=0;
239 }
240
241 shots.push_back(ts);
242 }
243
render()244 void classBullets::render()
245 {
246
247 for(vector<struct structShot>::iterator it = shots.begin(); it != shots.end(); ++it)
248 {
249 it->pa.x += it->v.x;
250 it->pa.y += it->v.y;
251 it->pb.x += it->v.x;
252 it->pb.y += it->v.y;
253
254 it->age++;
255 if(it->age > it->life)
256 {
257 it = shots.erase(it);
258 if(shots.size() < 1)
259 break;
260 }
261 }
262 }
263 class classBullets bullets;
264
265 //Move and rotate an entity according to ent.p and ent.rotation
updateEntVerts(entity ent,vector<vert> & entverts,vector<vert> statV)266 void updateEntVerts(entity ent, vector<vert>& entverts, vector<vert> statV )
267 {
268 entverts = statV;
269
270 float tx, ty;
271
272 for(vector<vert>::iterator i = entverts.begin(); i != entverts.end(); ++i)
273 {
274 tx = i->p.x * cos( (ent.rotation-90.0) * 0.0174532925 ) - ( i->p.y *sin( (ent.rotation-90.0) * 0.0174532925 )) ;
275 ty = i->p.x * sin( (ent.rotation-90.0) * 0.0174532925 ) + ( i->p.y *cos( (ent.rotation-90.0) * 0.0174532925 ));
276 i->p.x=tx;
277 i->p.y=ty;
278 i->p.x += ent.p.x;
279 i->p.y += ent.p.y;
280 }
281
282 }
283
284
285 #define PI 3.14159265
286
loadMap(vector<vector<vert>> & polys,vector<entity> & ents)287 void loadMap(vector< vector<vert> >& polys, vector<entity>& ents)
288 {
289 polys.clear();
290 ents.clear();
291 string line;
292 ifstream load;
293 vector<vert> tvs; //temp to store the poly as we read it
294 vert tv; //temp to store the vert as we read it
295 entity te; //temp to store the entity while we read it
296 gameInfo.numBases=0;
297 gameInfo.nextObjective.clear();
298 load.open(levelFile.data());
299
300 if(!load.is_open())
301 {
302 cout << "could not load '" << levelFile << "'" << endl;
303 return;
304 }
305
306 int parseState=0, dataNum=0;
307
308 while(!load.eof())
309 {
310 getline(load, line);
311 if(line == "StartPoly")
312 {
313 parseState=1;
314 } else if(line=="EndPoly")
315 {
316 parseState=0;
317 polys.push_back(tvs);
318 tvs.clear();
319 } else if(parseState==1)
320 {
321 if(line == "StartVert")
322 {
323 parseState=2;
324 dataNum=0;
325 }
326 } else if(parseState==2)
327 {
328 if(line == "EndVert")
329 {
330 tvs.push_back(tv);
331 parseState=1;
332 } else {
333 dataNum++;
334 switch(dataNum)
335 {
336 case 1:
337 tv.p.x = atof(line.data());
338 break;
339 case 2:
340 tv.p.y = atof(line.data());
341 break;
342 case 3:
343 tv.color[0] = atof(line.data());
344 break;
345 case 4:
346 tv.color[1] = atof(line.data());
347 break;
348 case 5:
349 tv.color[2] = atof(line.data());
350 break;
351 case 6:
352 tv.collision = atoi(line.data());
353 break;
354 default:
355 cout << "??" << line << endl;
356 break;
357 }
358 }
359 } else if(line =="StartEntity")
360 {
361 parseState=3;
362 dataNum=0;
363 } else if(parseState==3)
364 {
365 if(line=="EndEntity")
366 {
367 dataNum=0;
368 te.baseP = te.p;
369 ents.push_back(te);
370 parseState=0;
371 } else {
372 dataNum++;
373 switch(dataNum)
374 {
375 case 1:
376 te.p.x = atof(line.data());
377 break;
378 case 2:
379 te.p.y = atof(line.data());
380 break;
381 case 3:
382 te.type = atoi(line.data());
383 if(te.type==entBase)
384 {
385 gameInfo.numBases++;
386 }
387 break;
388 case 4:
389 te.rotation = atof(line.data());
390 break;
391 case 5:
392 te.id = atoi(line.data());
393 if(te.type==entBase && te.id != gameInfo.numBases)
394 {
395 cout << "error: base entity have id:" << te.id << " but numBases is:" << gameInfo.numBases << endl;
396 }
397 break;
398 default:
399 cout << ">?" << line << endl;
400 break;
401 }
402 }
403 } else if(line=="StartMission")
404 {
405 parseState=4;
406 } else if(parseState==4)
407 {
408 if(line=="EndMission")
409 {
410 parseState=0;
411 } else {
412 gameInfo.nextObjective.push_back( atoi(line.data()) );
413 }
414 }
415 }
416
417
418 }
419
readEnt(string File,vector<vert> & verts)420 void readEnt(string File, vector<vert>& verts)
421 {
422 string line;
423 ifstream f;
424 vert tv; //temp to store the vert as we read it
425
426 f.open(File.data());
427 if(!f.is_open())
428 {
429 cout << "Failed to open file" << endl;
430 return;
431 }
432
433 int parseState=0, dataNum=0;
434
435 while(!f.eof())
436 {
437 getline(f, line);
438 if(line == "StartVert")
439 {
440 parseState=1;
441 dataNum=0;
442 } else if(parseState==1)
443 {
444 if(line == "EndVert")
445 {
446 parseState=0;
447 verts.push_back(tv);
448 } else {
449 dataNum++;
450 switch(dataNum)
451 {
452 case 1:
453 tv.p.x = atof(line.data());
454 break;
455 case 2:
456 tv.p.y = atof(line.data());
457 case 3:
458 tv.color[0] = atof(line.data());
459 break;
460 case 4:
461 tv.color[1] = atof(line.data());
462 break;
463 case 5:
464 tv.color[2] = atof(line.data());
465 break;
466 case 6:
467 tv.collision = atoi(line.data());
468 break;
469 default:
470 cout << "??" << line << endl;
471 break;
472 }
473
474 }
475 }
476 }
477
478 }
479
boxCol(gPs posa,gPs posb,float dist)480 bool boxCol(gPs posa, gPs posb, float dist)
481 {
482 if(posa.x < posb.x+dist && posa.x > posb.x-dist)
483 {
484 if(posa.y < posb.y+dist && posa.y > posb.y-dist)
485 {
486 return(1);
487 }
488 }
489 return(0);
490 }
491
PolyCol(vector<vert> PolyA,vector<vert> PolyB)492 bool PolyCol( vector<vert> PolyA, vector<vert> PolyB )
493 {
494 gPs paLineA, paLineB, pbLineA, pbLineB;
495 bool paFirst=1, pbFirst=1;
496 int prevColType=0;
497 int checks=0;
498
499 for( vector<vert>::iterator paVertIt = PolyA.begin(); paVertIt != PolyA.end(); ++paVertIt)
500 {
501 if(paVertIt->collision)
502 {
503 if(paFirst || prevColType == 2) //if the last one was a 2, this one is the start of the next line to collision detect
504 {
505 paFirst=0;
506 paLineB=paVertIt->p;
507 } else {
508 paLineA=paLineB;
509 paLineB=paVertIt->p;
510
511
512 pbFirst=1;
513 //Great now we have a line, lets check it against every line in the other poly.
514 for(vector<vert>::iterator pbVertIt = PolyB.begin(); pbVertIt != PolyB.end(); ++pbVertIt)
515 {
516 if(pbVertIt->collision)
517 {
518 if(pbFirst)
519 {
520 pbFirst=0;
521 pbLineB=pbVertIt->p;
522 } else {
523 pbLineA=pbLineB;
524 pbLineB=pbVertIt->p;
525
526 //Here we have two lines. paLineA, paLineB, and pbLineA, pbLineB.
527 checks++;
528 if(LinesCross(paLineA, paLineB, pbLineA, pbLineB))
529 {
530 return(1);
531 }
532
533 }
534 }
535 }
536
537 }
538 }
539 prevColType = paVertIt->collision;
540 }
541 return(0);
542 }
543
544
landCol(vector<vert> baseVerts,vector<vert> shipVerts)545 bool landCol(vector<vert> baseVerts, vector<vert> shipVerts)
546 {
547
548 gPs baseA, baseB;
549 gPs shipA, shipB;
550 int prevColType=0;
551
552 //Find points on ship
553 for(vector<vert>::iterator shipIt = shipVerts.begin(); shipIt != shipVerts.end(); ++shipIt)
554 {
555 if(shipIt->collision == 2)
556 {
557 if(prevColType == 0)
558 {
559 shipA = shipIt->p;
560 prevColType++;
561 } else {
562 shipB = shipIt->p;
563 prevColType++;
564 }
565 }
566 }
567
568 prevColType=0;
569 for(vector<vert>::iterator baseIt = baseVerts.begin(); baseIt != baseVerts.end(); ++baseIt)
570 {
571 //Find the line to check with
572 if(prevColType==2)
573 {
574 baseB = baseIt->p;
575 if(shipA.x > baseA.x && shipA.x < baseB.x) //Is left side inside
576 {
577 if(shipB.x > baseA.x && shipB.x < baseB.x) // Is right side inside
578 {
579 if(shipA.y < baseA.y && shipB.y < baseB.y) //Is left side under the line
580 {
581 if(shipB.y < baseA.y && shipB.y < baseB.y) //Is right side under the line
582 {
583 if(shipA.y > baseA.y-1.0 && shipB.y > baseA.y-1.0) //Check that left side is above the height
584 {
585 //check velocity:
586 //cout << "Impact:"<<endl<<"Xvel:" << gameInfo.velocity.x<<" Yvel: " << gameInfo.velocity.y << endl << "Rot:" << gameInfo.rotationForce << "." << endl;
587
588 if(gameInfo.velocity.y >= gameRules.maxLandingYel) //If it's not smaller, it's not faster
589 {
590 float temp = gameInfo.velocity.x;
591 if(temp < 0)
592 temp *= -1.0;
593
594 if(temp <= gameRules.maxLandingXvel) //it have to be slower
595 {
596
597 temp = gameInfo.rotationForce;
598 if(temp < 0)
599 temp *= -1.0;
600 if(temp <= gameRules.maxLandingRotForce)
601 {
602 return(1);
603 }
604 }
605 }
606 }
607 }
608 }
609 }
610 }
611 }
612 prevColType = baseIt->collision;
613 if(prevColType==2)
614 baseA = baseIt->p;
615 }
616 return(0);
617 }
618
setMission(int missionId,vector<entity> ents)619 void setMission(int missionId, vector<entity> ents)
620 {
621 gameInfo.destBase = gameInfo.nextObjective[missionId];
622
623 //Set destination on radar.
624 for(vector<entity>::iterator searchIt = ents.begin(); searchIt != ents.end(); ++searchIt)
625 {
626 if(searchIt->id == gameInfo.destBase)
627 {
628 gameInfo.radarDest = searchIt->p;
629 }
630 }
631 }
632
initGame(vector<vector<vert>> & polys,vector<entity> & ents)633 void initGame(vector< vector<vert> >& polys, vector<entity>& ents)
634 {
635 loadMap(polys, ents);
636
637 gameInfo.currentObjective=0;
638 gameInfo.score=0;
639 gameInfo.destBase=0;
640 gameInfo.fuel = gameRules.fuelMaxFuel;
641 gameInfo.ammo = gameRules.ammoMaxAmmo;
642
643 if(gameInfo.nextObjective.size() > 1)
644 setMission(0,ents);
645
646
647
648 }
649
650
651
initNewGame(vector<vector<vert>> & polys,vector<entity> & ents)652 void initNewGame(vector< vector<vert> >& polys, vector<entity>& ents)
653 {
654 gameRules.maxLandingRotForce = 1.0; //degrees, both ways
655 gameRules.maxLandingYel = -0.20; //downward
656 gameRules.maxLandingXvel= 0.15; //both sides
657 gameRules.fuelConsumptionThrust = 15;
658 gameRules.fuelConsumptionTurn = 4;
659 gameRules.fuelMaxFuel = 5500;
660 gameRules.ammoMaxAmmo = 1000;
661
662
663 gameState = GameStatePlaying;
664
665 gameInfo.numMissions=0; //Amount of missions taken
666 gameInfo.level=gameRules.startLevel;
667 initGame(polys, ents);
668
669 }
670
shipCrash(entity ship)671 void shipCrash(entity ship)
672 {
673
674 gameInfo.velocity.x=0;
675 gameInfo.velocity.y=0;
676 gameInfo.thrust=0;
677 gameInfo.rotationForce=0;
678 gameState = GameStateGameOver;
679
680 cout << endl;
681 cout << "Dead" << endl;
682 cout << "Level "<<gameInfo.level << endl;
683 }
684
685 struct gameInfoStruct snap;
686
687
parseCmdLine(int argc,char ** argv)688 bool parseCmdLine(int argc, char **argv)
689 {
690 bool chosenLevel=0, chosenDemo=0;
691 for(int i=1; i < argc; i++)
692 {
693 if( i == 1)
694 {
695 if(argv[1][0] != '-')
696 {
697 gameRules.startLevel = atoi(argv[1]);
698 levelFile = DATADIR"levels/";
699 levelFile.append(argv[1]);
700 levelFile.append(".level");
701 chosenLevel=1;
702 }
703 }
704
705 if( strcmp(argv[i], "--levelfile") == 0 )
706 {
707 i++;
708 if(i > argc)
709 {
710 cout << "Error: Specify level file." << endl;
711 return(0);
712 }
713 chosenLevel=1;
714 levelFile = argv[i];
715 } else if(i!=1) {
716 cout << "Error: unknown argument '" << argv[i] << "'" << endl;
717 return(0);
718 }
719
720
721 }
722
723 return(1);
724 }
725
main(int argc,char ** argv)726 int main(int argc, char **argv)
727 {
728
729 srand ( time(NULL) );
730
731 /* These can be overwritten by the call to parseCmdLine */
732 levelFile = DATADIR"levels/0.level";
733
734 gameState = GameStateNewGame;
735
736 if(!parseCmdLine(argc, argv))
737 {
738 return(1);
739 }
740
741 SDL_Event event;
742 //Init sdl and screen
743 if(SDL_Init(SDL_INIT_TIMER) <0 )
744 {
745 cout << SDL_GetError() << endl;
746 }
747
748
749 cout << "Osgg Server"<<endl;
750 cout << "Using level file '" << levelFile << "'" << endl;
751
752
753
754 int ticks=0, lastTicks=0;
755
756
757 /** GameVars **/
758 vector<vert> testVerts;
759 vert tempVert;
760 gPs collisionPoint;
761 bool crashed=0;
762 char score[256];
763 vector<entity> ents; //entities
764 vector<vert> activeVerts;
765 vector< vector<vert> > polys;
766
767 readEnt("ship.txt", gameInfo.shipStaticVerts);
768 readEnt("base.txt", gameInfo.baseStaticVerts);
769 readEnt("enemy.txt", gameInfo.enemyStaticVerts);
770
771 //Enter Main loop
772 while(gameState != GameStateQuit)
773 {
774
775 while(SDL_PollEvent(&event))
776 {
777
778 switch(gameState)
779 {
780 case GameStateNewGame:
781 initNewGame(polys,ents);
782 gameState=GameStatePlaying;
783 break;
784
785 case GameStatePlaying:
786
787 //Check if any bullets hit the enviroment:
788 bullets.envCol(polys);
789 bullets.render();
790
791 //Ents:
792 for(vector<entity>::iterator it = ents.begin(); it != ents.end(); ++it)
793 {
794 if(it->type == entShip)
795 {
796 Uint8* keyStates = SDL_GetKeyState( NULL );
797
798 if(keyStates[SDLK_LEFT])
799 {
800 if(gameInfo.fuel > 0)
801 {
802 gameInfo.rotationForce += TURNINCRATE;
803 gameInfo.fuel -= gameRules.fuelConsumptionTurn;
804 }
805 } else if(keyStates[SDLK_RIGHT])
806 {
807 if(gameInfo.fuel > 0)
808 {
809 gameInfo.rotationForce -= TURNINCRATE;
810 gameInfo.fuel -= gameRules.fuelConsumptionTurn;
811 }
812 }
813
814 if(keyStates[SDLK_UP])
815 {
816 if(gameInfo.fuel > 0)
817 {
818 gameInfo.thrust = THRUSTINCRATE;
819 gameInfo.fuel -= gameRules.fuelConsumptionThrust;
820 } else {
821 gameInfo.thrust = 0;
822 }
823 } else
824 {
825 gameInfo.thrust = 0;
826 }
827
828 if(gameInfo.reloadTime != 0)
829 {
830 gameInfo.reloadTime--;
831 }
832 if(keyStates[SDLK_SPACE])
833 {
834 if(gameInfo.reloadTime == 0 && gameInfo.ammo >= 100)
835 {
836 gameInfo.ammo -= 100;
837 gameInfo.reloadTime = 25;
838 bullets.shoot(*it, gameInfo.velocity);
839 }
840 }
841
842 //Update the speed
843 gameInfo.speed = abs2(gameInfo.velocity.x*100)+abs2(gameInfo.velocity.y*100);
844
845 //Update velocities
846 gameInfo.velocity.x += gameInfo.thrust * cos( (it->rotation*0.0174532925) );
847 gameInfo.velocity.y += gameInfo.thrust * sin( (it->rotation*0.0174532925) );
848
849 gameInfo.velocity.y -= GRAVITY;
850
851
852 if(gameInfo.rotationForce > 0)
853 {
854
855 gameInfo.rotationForce /= 1.01;
856 if(gameInfo.rotationForce < 0)
857 {
858 gameInfo.rotationForce = 0;
859 }
860 } else if(gameInfo.rotationForce < 0)
861 {
862 gameInfo.rotationForce /= 1.01;
863 if(gameInfo.rotationForce > 0)
864 {
865 gameInfo.rotationForce = 0;
866 }
867 }
868
869 //Collision with terrain
870 for(vector< vector<vert> >::iterator PolyIt = polys.begin(); PolyIt != polys.end(); ++PolyIt)
871 {
872 if(PolyCol(*PolyIt, gameInfo.shipVerts))
873 {
874 shipCrash(*it);
875 }
876 }
877
878 crashed=0;
879 //Collision with ents
880 for(vector<entity>::iterator entIt = ents.begin(); entIt != ents.end(); ++entIt)
881 {
882 //Collition with entities
883 if(entIt->type==entBase)
884 {
885 updateEntVerts(*entIt, gameInfo.baseVerts, gameInfo.baseStaticVerts);
886 crashed=PolyCol(gameInfo.baseVerts, gameInfo.shipVerts);
887 } else if(entIt->type==entEnemy)
888 {
889 updateEntVerts(*entIt, gameInfo.enemyVerts, gameInfo.enemyStaticVerts);
890 crashed=PolyCol(gameInfo.enemyVerts, gameInfo.shipVerts);
891
892 //check if this enemy is being hit
893 if(bullets.col(gameInfo.enemyVerts, 0))
894 {
895 entIt = ents.erase(entIt);
896 // gameInfo.score -= 3000;
897 break;
898 }
899 }
900
901 if(crashed)
902 {
903 shipCrash(*it);
904 } else {
905 //Is he landing on a base?
906 if(entIt->type==entBase)
907 {
908 if(landCol(gameInfo.baseVerts, gameInfo.shipVerts))
909 {
910
911 //Subtract 1 from score again
912 // gameInfo.score -= 1;
913
914 if(gameInfo.fuel < gameRules.fuelMaxFuel)
915 gameInfo.fuel += 15;
916 if(gameInfo.fuel > gameRules.fuelMaxFuel)
917 gameInfo.fuel = gameRules.fuelMaxFuel;
918
919 if(gameInfo.ammo < gameRules.ammoMaxAmmo)
920 gameInfo.ammo += 3;
921 if(gameInfo.ammo > gameRules.ammoMaxAmmo)
922 gameInfo.ammo = gameRules.ammoMaxAmmo;
923
924
925 it->rotation=90.0;
926
927 if(gameInfo.velocity.y < 0.0)
928 gameInfo.velocity.y=0;
929
930 gameInfo.velocity.x=0;
931 gameInfo.rotationForce=0;
932
933 if(gameInfo.numBases > 1)
934 {
935 //Is this the destination base?
936 if(gameInfo.destBase == entIt->id)
937 {
938
939 gameInfo.numMissions++;
940
941 //Do he have more missions left?
942 gameInfo.currentObjective++;
943 if(gameInfo.currentObjective < gameInfo.nextObjective.size())
944 {
945 //Give it to him
946 setMission(gameInfo.currentObjective, ents);
947 } else {
948 gameState = GameStateNextLevel;
949 }
950 }
951 }
952 }
953 }
954 } //not crashing
955 }
956
957 it->rotation += gameInfo.rotationForce;
958 it->p.x += gameInfo.velocity.x;
959 it->p.y += gameInfo.velocity.y;
960
961 } else
962 /** Update enemies **/
963 if(it->type == entEnemy)
964 {
965 it->vel.y -= GRAVITY;
966
967 if(it->p.y <= it->baseP.y-0.3)
968 {
969 it->vel.y += 0.01;
970 }
971 it->p.y += it->vel.y;
972 }
973 }
974
975
976
977 break;
978
979 /** END OF GAME **/
980
981 }
982
983
984
985
986 }
987
988 ticks += SDL_GetTicks() - lastTicks;
989 lastTicks = SDL_GetTicks();
990 SDL_Delay(10);
991 }
992
993
994 return(0);
995 }
996