no ammo when killed
[Lilanci.git] / ebulanci.c
blob603e21df80cefeb38137b6e720b81ac665685360
1 #include <math.h>
2 #include <time.h>
3 #include "geometry.h"
4 #include "util.h"
5 #include "config.h"
6 #include "gr.h"
7 #include "map.h"
8 #include "snd.h"
11 int gamestate=0;
13 typedef struct{
14 int Up;
15 int Down;
16 int Left;
17 int Right;
18 int Shoot;
19 int Suicide;
20 int Switch;
21 }TKeyBinding;//TODO: s/int/real data type for a key
23 typedef struct{
24 Vect Pos; //where he is
25 Vect Move; //how he want to move
26 Vect BSize; //Size of bounding rect
27 Area *Shape; //how fat he is
28 //Area *TrShape; //translated Shape -- don't optimize yet
29 int Frags; //no comment
30 int Deaths; //R.I.P.
31 double Speed; //meters per second
32 int Orientation; //1-up 2-left 3-down 4-right 0-down
33 int WannaShoot; //1-want 0-don't want
34 double ReloadTime; //time from last shot
35 int WannaDie; //1-want suicide 2-died and still holding suicide 0-don't want
36 double AnimationTime; //in seconds
37 TKeyBinding Keys;
38 int *Ammo;
39 int ActiveWeapon;
40 int SwitchLock;
41 int Alive;
42 char Name[16];
43 SDL_Color Color;
44 }TLilanek;
47 typedef struct{
48 Vect Pos;
49 Area *Shape;
50 int WID; //Weapon ID
51 int Exists; // 0- doesn't exist 1-exists
52 int Ammo;
53 int MaxAmmo;
54 int Burst;
55 double ReloadTime;
56 }TWeapon;
58 typedef struct{
59 Vect Pos;
60 Area *Shape;
61 Vect Vel; //velocity i m/s
62 double Speed; //for Templates
63 double Range; //How far it can travel
64 int WID; //Weapon ID
65 int lid; //who shoot this bullet?
66 int Exists; // 0- doesn't exist 1-exists
67 double SFuzzy; // Fuzzy factor for spawning 0-1 :)
68 double VFuzzy; // Fuzzy factor for traveling 0-1 :)
69 }TBullet;
72 typedef struct{
73 TMap *Map; //where we are playing
74 TLilanek *Lilanek; //our heroes-ehm bad guys
75 int noLilaneks;
77 TWeapon *Weapon; //Weapons lying on floor
78 int noWeapons;
79 TWeapon *WeaponTemplate;
80 TBullet *BulletTemplate;
81 int noWID; //biggest WID, also number of WeaponTemplates
82 TBullet *Bullet;
83 int noBullets;
84 double PWeapondrop; // Probability of weapon drop per second
85 }Game;
87 Vect Orientations[5];
89 Sprite *lil[5];
90 Sprite *bg;
91 Sprite *kul;
92 Sprite *explo;
93 Sprite *brok;
94 Sprite *kulka;
95 Sprite *mine;
96 Sprite *mines;
97 Sprite *hud;
98 Sprite *hud_mine;
99 Sprite *hud_kul;
100 Sprite *hud_brok;
101 Sprite *hud_ammo;
102 Sprite *hud_reload;
103 int s_die;
104 int s_bonus;
105 int s_expl;
106 int s_shoot;
107 int s_mine;
109 int frames=0;
110 void SwitchNextWeapon(Game *g, int lid);
112 int InitBase(){
113 Orientations[0].x=0;
114 Orientations[0].y=0;
115 Orientations[1].x=0;
116 Orientations[1].y=-1;
117 Orientations[2].x=-1;
118 Orientations[2].y=0;
119 Orientations[3].x=0;
120 Orientations[3].y=1;
121 Orientations[4].x=1;
122 Orientations[4].y=0;
123 //TODO: write code
125 return 0;
128 void SpawnLilanek(Game *g, int lid){
129 Vect Pos;
130 int tries;
131 Area *tp, *oltp;
132 int good;
133 int olid;
135 oltp = 0;
136 tp = 0;
137 for(tries=0; tries <1000; tries++){ //TODO: remove exact number
138 Pos.x = RandD(0,g->Map->XX);
139 Pos.y = RandD(0,g->Map->YY);
140 good=1;
141 tp = TranslateArea(g->Lilanek[lid].Shape, &Pos);
142 printf("%s\n", Area2String(tp));
143 if(!AreaInMap(g->Map, tp,0,1)){
144 good=0;
147 for(olid=0; olid < g->noLilaneks; olid++){
148 if(olid == lid)
149 continue;
150 if(!g->Lilanek[olid].Alive){
151 continue;
153 oltp = TranslateArea(g->Lilanek[olid].Shape, &g->Lilanek[olid].Pos);
154 if(AreaInArea(tp, oltp)){
155 good=0;
157 FreeArea(oltp);
158 oltp = 0;
161 if(good){
162 FreeArea(tp);
163 tp=0;
164 g->Lilanek[lid].Pos.x = Pos.x;
165 g->Lilanek[lid].Pos.y = Pos.y;
166 g->Lilanek[lid].Alive = 1;
167 break;
169 FreeArea(tp);
170 tp=0;
174 void DropWeapon(Game *g, int weapon){
175 Vect Pos;
176 int tries;
177 int WID;
178 Area *tp;
180 for(tries=0; tries <100; tries++){ //TODO: remove exact number
181 Pos.x = RandD(0,g->Map->XX);
182 Pos.y = RandD(0,g->Map->YY);
183 WID = RandI(0, g->noWID);
184 tp = TranslateArea(g->WeaponTemplate[WID].Shape, &Pos);
185 if(AreaInMap(g->Map, tp, 0, g->Map->noLayer)){
186 FreeArea(tp);
187 tp=0;
188 memcpy(&g->Weapon[weapon], &g->WeaponTemplate[WID], sizeof(TWeapon));
189 g->Weapon[weapon].Shape = g->WeaponTemplate[WID].Shape;
190 g->Weapon[weapon].Pos.x = Pos.x;
191 g->Weapon[weapon].Pos.y = Pos.y;
192 g->Weapon[weapon].WID = WID;
193 g->Weapon[weapon].Exists = 1;
194 break;
196 FreeArea(tp);
197 tp=0;
201 void DropWeapons(Game *g, double dtime){
202 int i;
204 if( RandD(0.0, 1.0) >= (g->PWeapondrop*dtime))
205 return;
206 for(i=0; i < g->noWeapons; i++){
207 if(g->Weapon[i].Exists)continue; //we don't like teleporting weapons :)
209 printf("A Weapon drop!\n");
210 DropWeapon(g, i);
211 break; //spawn max one weapon per update
215 void WeaponPickedUp(Game *g, double dtime, int lid, int wid){
216 TLilanek *l;
217 TWeapon *w;
219 l = &g->Lilanek[lid];
220 w = &g->Weapon[wid];
222 l->Ammo[w->WID] += w->Ammo;
223 if(l->Ammo[w->WID] > w->MaxAmmo)
224 l->Ammo[w->WID] = w->MaxAmmo;
225 printf("Ammo: %d\n",l->Ammo[w->WID]);
226 l->ActiveWeapon = w->WID;
227 printf("AW: %d\n",l->ActiveWeapon);
229 w->Exists = 0;
231 PlaySound(s_bonus);
234 void PickUpWeapons(Game *g, double dtime){
235 int lid,wid;
236 Area *WArea, *LArea;
238 for(lid=0; lid<g->noLilaneks; lid++){
239 LArea = TranslateArea(g->Lilanek[lid].Shape, &g->Lilanek[lid].Pos);
240 for(wid=0; wid < g->noWeapons; wid++){
241 if(!g->Weapon[wid].Exists)
242 continue;
243 WArea = TranslateArea(g->Weapon[wid].Shape, &g->Weapon[wid].Pos);
244 if(!AreaInArea( WArea, LArea)){
245 FreeArea(WArea);
246 continue;
248 WeaponPickedUp(g, dtime, lid, wid);
249 FreeArea(WArea);
251 FreeArea(LArea);
255 void BulletExplodes(Game *g, int i){
256 g->Bullet[i].Exists=0;
257 //TODO: some effects
260 void MoveBullet(Game *g, double dtime, int i){
261 double ff;
262 Vect dp;
263 dp.x = g->Bullet[i].Pos.x;
264 dp.y = g->Bullet[i].Pos.y;
265 ff= g->Bullet[i].Speed*g->Bullet[i].VFuzzy;
266 g->Bullet[i].Pos.x += (g->Bullet[i].Vel.x += RandD(-ff,ff))* dtime;
267 g->Bullet[i].Pos.y += (g->Bullet[i].Vel.y += RandD(-ff,ff))* dtime;
268 dp.x -= g->Bullet[i].Pos.x;
269 dp.y -= g->Bullet[i].Pos.y;
270 g->Bullet[i].Range -= sqrt(DotProduct(&dp, &dp));
273 void CollideBulletMap(Game *g, double dtime, int i){
274 Area *p;
276 p=TranslateArea(g->Bullet[i].Shape, &g->Bullet[i].Pos);
277 if(AreaInMap(g->Map, p, 1,1)==0)
278 BulletExplodes(g, i);
279 FreeArea(p);
281 void LilanekKilled(Game *g, double dtime, int BulletID, int LilanekID){
282 int i;
283 g->Bullet[BulletID].Exists = 0;
284 g->Lilanek[LilanekID].Deaths ++;
285 g->Lilanek[g->Bullet[BulletID].lid].Frags ++;
286 SpawnLilanek(g, LilanekID);
287 for(i=0; i<g->noWID; i++){
288 g->Lilanek[LilanekID].Ammo[i] = 0;
290 PlaySound(s_die);
293 #define NO_EXPLOSIONS 10 //MAGIC_NUMBER
294 #define EXPLOSION_SPEED 5 //MAGIC_NUMBER
295 #define EXPLOSION_RANGE 1.0 //MAGIC_NUMBER
297 void SpawnExplosions(Game *g, double dtime, int BulletID){
298 int bid = 0;
299 int i = 0;
300 TBullet *b;
301 Vect Pos;
302 double speed;
304 Pos.x = g->Bullet[BulletID].Pos.x;
305 Pos.y = g->Bullet[BulletID].Pos.y;
306 for(i=0; i<NO_EXPLOSIONS; i++){
307 for(bid=0; bid<g->noBullets; bid++){
308 if(g->Bullet[bid].Exists)
309 continue;
310 b = &g->Bullet[bid];
311 b->Pos.x = Pos.x;
312 b->Pos.y = Pos.y;
313 b->Vel.x = RandD(0.0, 1.0)*(RandI(0,100)>50?-1:1);
314 b->Vel.y = RandD(0.0, 1.0)*(RandI(0,100)>50?-1:1);
315 NormV(&b->Vel);
316 speed = RandD(0.3, 1.0)*EXPLOSION_SPEED;
317 b->Speed = speed;
318 b->Vel.x *= speed;
319 b->Vel.y *= speed;
320 b->WID = -1;
321 b->lid = g->Bullet[BulletID].lid;
322 b->Exists = 1;
323 b->SFuzzy = 0;
324 b->VFuzzy = 0;
325 b->Range = EXPLOSION_RANGE;
326 b->Shape = g->Bullet[BulletID].Shape;
327 printf("%lf ", speed);
328 break;
331 g->Bullet[BulletID].Exists = 0;
332 PlaySound(s_expl);
335 void CollideBulletLilanek(Game *g, double dtime, int BulletID){
336 Area *BArea, *LArea;
337 int LilanekID;
339 BArea=TranslateArea(g->Bullet[BulletID].Shape, &g->Bullet[BulletID].Pos);
340 for(LilanekID=0; LilanekID<g->noLilaneks; LilanekID++){
341 LArea=TranslateArea(g->Lilanek[LilanekID].Shape, &g->Lilanek[LilanekID].Pos);
342 if(AreaInArea(LArea,BArea)){
343 //if it is a mine, spawn explosion instead of killing instantly
344 if(g->Bullet[BulletID].WID == 1){
345 SpawnExplosions(g, dtime, BulletID);
346 }else{
347 LilanekKilled(g, dtime, BulletID, LilanekID);
350 FreeArea(LArea);
351 LArea=0;
353 FreeArea(BArea);
354 BArea=0;
357 void UpdateBullets(Game *g, double dtime){
358 int BulletID;
359 for(BulletID=0; BulletID<g->noBullets; BulletID++){
360 if(g->Bullet[BulletID].Exists==0)
361 continue; //We won't update non-existending bullets
362 MoveBullet(g, dtime, BulletID);
363 if(g->Bullet[BulletID].Range < 0){
364 g->Bullet[BulletID].Exists = 0;
365 continue;
367 CollideBulletMap(g, dtime, BulletID);
368 CollideBulletLilanek(g, dtime, BulletID);
372 int CheckLilanekvsLilaneks(Game *g, Area *a, int LilanekID){ //returns 0 if he collides with others, 1 if it's OK to move there
373 int i;
374 Area *nb;
375 int rval=1;
377 nb=0;
378 for(i=0; i<g->noLilaneks && rval==1; i++){
379 if(i==LilanekID)
380 continue;
381 nb = TranslateArea(g->Lilanek[i].Shape, &g->Lilanek[i].Pos);
382 if(AreaInArea(nb, a))
383 rval=0;
384 FreeArea(nb);
385 nb=0;
387 return rval;
390 void MoveLilaneks(Game *g, double dtime){
391 int i, steps;
392 Area *pa;
393 Vect va;
394 double dt;
396 pa=0;
397 for(i=0; i<g->noLilaneks; i++){
398 //skip this Lilanek if he doesn't wanna move
399 if(g->Lilanek[i].Move.x == 0.0 && g->Lilanek[i].Move.y == 0.0)
400 continue;
401 for(dt=dtime, steps=0; steps<4; dt/=2.0, steps++){ //TODO: get rid of exact number
402 //make future Area
403 va.x = g->Lilanek[i].Pos.x + dt*g->Lilanek[i].Move.x;
404 va.y = g->Lilanek[i].Pos.y + dt*g->Lilanek[i].Move.y;
405 FreeArea(pa); //we don't want memory leaks
406 pa = TranslateArea(g->Lilanek[i].Shape, &va);
407 //check for collision with map
408 if(AreaInMap(g->Map, pa, 0, 1)==0)
409 continue; //try smaller dt if he collided with map
410 //check for collision with other Lilaneks
411 if(CheckLilanekvsLilaneks(g, pa, i)==0)
412 continue;
413 //move him if we got here
414 g->Lilanek[i].Pos.x += dt*g->Lilanek[i].Move.x;
415 g->Lilanek[i].Pos.y += dt*g->Lilanek[i].Move.y;
416 FreeArea(pa);
417 pa=0;
419 FreeArea(pa); //For sure
420 pa=0;
424 void ParseInput(Game *g, double dtime){
425 int i;
426 Uint8 *keystate;
427 TLilanek *curlil;
428 int wannamove;
430 keystate = SDL_GetKeyState(NULL);
431 //pause
432 if(gamestate == 1){
433 if(keystate['o']){
434 printf("unpause\n");
435 gamestate = 0;
436 }else return;
438 if(keystate['p']){
439 printf("pause\n");
440 gamestate = 1;
443 for(i=0; i< g->noLilaneks; i++){
444 curlil = &g->Lilanek[i];
445 wannamove=0;
446 // Up;
447 if(keystate[curlil->Keys.Up]){
448 curlil->Orientation = 1;
449 curlil->Move.x = curlil->Speed * Orientations[1].x;
450 curlil->Move.y = curlil->Speed * Orientations[1].y;
451 wannamove=1;
453 // Down;
454 if(keystate[curlil->Keys.Down]){
455 curlil->Orientation = 3;
456 curlil->Move.x = curlil->Speed * Orientations[3].x;
457 curlil->Move.y = curlil->Speed * Orientations[3].y;
458 wannamove=1;
460 // Left;
461 if(keystate[curlil->Keys.Left]){
462 curlil->Orientation = 2;
463 curlil->Move.x = curlil->Speed * Orientations[2].x;
464 curlil->Move.y = curlil->Speed * Orientations[2].y;
465 wannamove=1;
467 // Right;
468 if(keystate[curlil->Keys.Right]){
469 curlil->Orientation = 4;
470 curlil->Move.x = curlil->Speed * Orientations[4].x;
471 curlil->Move.y = curlil->Speed * Orientations[4].y;
472 wannamove=1;
475 if(!wannamove){
476 curlil->Move.x = 0;
477 curlil->Move.y = 0;
479 // Shoot;
480 if(keystate[curlil->Keys.Shoot]){
481 curlil->WannaShoot = 1;
482 }else{
483 curlil->WannaShoot = 0;
485 // Suicide;
486 if(keystate[curlil->Keys.Suicide]){
487 if(curlil->WannaDie != 2){
488 curlil->WannaDie = 1;
490 }else{
491 curlil->WannaDie = 0;
493 // Switch;
494 if(keystate[curlil->Keys.Switch]){
495 if(!curlil->SwitchLock){
496 SwitchNextWeapon(g, i);
497 curlil->SwitchLock = 1;
499 }else{
500 curlil->SwitchLock = 0;
505 void SpawnBullet(Game *g, double dtime, int lid, int bid){
506 Area *LArea, *BArea;
507 TBullet *b, *bt;
508 double vx, vy; //because we need to spawn also mines with no velocity
511 LArea = TranslateArea(g->Lilanek[lid].Shape, &g->Lilanek[lid]. Pos);
512 b = &g->Bullet[bid];
513 bt = &g->BulletTemplate[g->Lilanek[lid].ActiveWeapon];
514 memcpy (b, bt, sizeof(TBullet));
515 b->Exists = 1;
516 b->Pos.x = g->Lilanek[lid].Pos.x+g->Lilanek[lid].BSize.x*0.5;
517 b->Pos.y = g->Lilanek[lid].Pos.y+g->Lilanek[lid].BSize.y*0.5;
518 b->WID = bt->WID;
519 b->Range = bt->Range;
520 b->Vel.x = Orientations[g->Lilanek[lid].Orientation].x * b->Speed +RandD(-b->Speed*b->SFuzzy, b->Speed*b->SFuzzy);
521 b->Vel.y = Orientations[g->Lilanek[lid].Orientation].y * b->Speed +RandD(-b->Speed*b->SFuzzy, b->Speed*b->SFuzzy);
522 if(DotProduct(&b->Vel, &b->Vel) <=0.01){
523 vx = -1*Orientations[g->Lilanek[lid].Orientation].x;
524 vy = -1*Orientations[g->Lilanek[lid].Orientation].y;
525 }else{
526 vx = b->Vel.x;
527 vy = b->Vel.y;
529 b->lid =lid;
530 while(1){
531 BArea = TranslateArea(b->Shape, &b->Pos);
532 if(!AreaInArea(BArea, LArea))
533 break;
534 b->Pos.x += vx* dtime*0.5;
535 b->Pos.y += vy* dtime*0.5;
537 FreeArea(LArea);
540 void Shoot(Game *g, double dtime, int lid){
541 int bid;
542 int i;
544 for(i=0; i<g->WeaponTemplate[g->Lilanek[lid].ActiveWeapon].Burst; i++){
545 if(g->Lilanek[lid].Ammo[g->Lilanek[lid].ActiveWeapon] == 0)
546 return;
547 for(bid=0; bid<g->noBullets; bid++){
548 if(g->Bullet[bid].Exists)
549 continue;
550 SpawnBullet(g, dtime, lid, bid);
551 g->Lilanek[lid].Ammo[g->Lilanek[lid].ActiveWeapon]--;
552 g->Lilanek[lid].ReloadTime = 0;
553 break;
556 switch(g->Lilanek[lid].ActiveWeapon){
557 case 0: PlaySound(s_shoot); break;
558 case 1: PlaySound(s_mine); break;
559 case 2: PlaySound(s_shoot); break;
560 default: break;
564 void SwitchNextWeapon(Game *g, int lid){
565 int i;
566 TLilanek *l;
567 l = &g->Lilanek[lid];
568 for(i = 1; i < g->noWID; i++){
569 if(l->Ammo[(l->ActiveWeapon+i)%(g->noWID)]){
570 l->ActiveWeapon = (l->ActiveWeapon+i)%(g->noWID);
571 return;
576 void ShootIfTheyWantTo(Game *g, double dtime){
577 int lid;
579 for(lid=0; lid<g->noLilaneks; lid++){
580 //if(!g->Lilanek[lid].Exists)
581 //continue;
582 if(g->Lilanek[lid].Ammo[g->Lilanek[lid].ActiveWeapon] == 0)
583 SwitchNextWeapon(g,lid);
585 if(g->Lilanek[lid].ReloadTime < g->WeaponTemplate[g->Lilanek[lid].ActiveWeapon].ReloadTime){
586 g->Lilanek[lid].ReloadTime += dtime;
587 }else{
588 if(!g->Lilanek[lid].WannaShoot)
589 continue;
590 Shoot(g, dtime, lid);
595 int UpdateLogic(Game *g,double dtime){
596 if(gamestate == 0){
597 DropWeapons(g, dtime);
598 UpdateBullets(g, dtime);
600 ParseInput(g, dtime);
601 if(gamestate == 0){
602 MoveLilaneks(g, dtime);
603 PickUpWeapons(g, dtime);
604 ShootIfTheyWantTo(g, dtime);
606 return 0; //TODO: return something useful
609 Game *testgame(){ //return testing game, function for use before we have some menu/loading mechanism
610 Game *g;
611 Poly *p, *pp;
612 Area *a;
613 int i;
614 Config conf = GetConfig();
616 g = malloc(sizeof(Game));
617 memset(g, 0, sizeof(Game));
618 g->noWID=3;
619 g->Map = malloc(sizeof(TMap));
620 g->Map->noLayer=2;
621 g->Map->Layer = malloc(sizeof(TMapLayer *)*g->Map->noLayer);
622 g->Map->Layer[0] = malloc(sizeof(TMapLayer));
623 g->Map->Layer[0]->noFArea = 1;
624 g->Map->Layer[0]->FArea = malloc(sizeof(Area *) * g->Map->Layer[0]->noFArea);
625 p = NewRect(4,2.5,3,2);
626 a = NewArea();
627 AddToArea(a, p);
628 FreePoly(p);
629 g->Map->Layer[0]->FArea[0] = a;
631 g->Map->Layer[1] = malloc(sizeof(TMapLayer));
632 g->Map->Layer[1]->noFArea = 1;
633 g->Map->Layer[1]->FArea = malloc(sizeof(Area *) * g->Map->Layer[1]->noFArea);
634 p = NewPoly();
635 AddToPolyXY(p, 0.30, 0.41);
636 AddToPolyXY(p, 0.73, 0.41);
637 AddToPolyXY(p, 0.77, 0.79);
638 AddToPolyXY(p, 0.65, 0.955);
639 AddToPolyXY(p, 0.365, 0.965);
640 AddToPolyXY(p, 0.235, 0.785);
641 MultiplyPoly(p, 4, 4);
642 pp = TranslatePolyXY(p, 7, 7);
643 a = NewArea();
644 AddToArea(a, pp);
645 FreePoly(pp);
646 FreePoly(p);
647 g->Map->Layer[1]->FArea[0] = a;
648 p = NewRect(1,1,16,15);
649 a = NewArea();
650 AddToArea(a, p);
651 FreePoly(p);
652 g->Map->BoundingArea = a;
653 g->Map->XX = 17;
654 g->Map->YY = 16;
655 g->Map->X = 1;
656 g->Map->Y = 1;
658 g->Map->noSprites = 2;
659 g->Map->Sprites = (Sprite **) malloc(sizeof(Sprite*)*g->Map->noSprites);
660 g->Map->SpritePos = (Vect *) malloc(sizeof(Vect)*g->Map->noSprites);
661 g->Map->SpritePos[0].x = 3.0;
662 g->Map->SpritePos[0].y = 1.0;
663 g->Map->SpritePos[1].x = 6.0;
664 g->Map->SpritePos[1].y = 6.0;
666 g->noWeapons = 8;
667 g->Weapon = malloc(sizeof(TWeapon) * g->noWeapons);
668 if(!g->Weapon){
669 fprintf(stderr, "Cannot allocate memory for Weapons\n");
671 for(i=0; i<g->noWeapons; i++){
672 g->Weapon[i].Exists = 0;
673 g->Weapon[i].Shape = 0;
676 g->noLilaneks = 2;
677 g->Lilanek = malloc(sizeof(TLilanek) * g->noLilaneks);
678 memset(g->Lilanek, 0, sizeof(TLilanek) * g->noLilaneks);
679 g->Lilanek[0].BSize.x = 1;
680 g->Lilanek[0].BSize.y = 1;
681 //g->Lilanek[0].Shape = NewRect(0.6,0.2,0.8,1.6);
682 p = NewPoly();
683 AddToPolyXY(p, 1, 0);
684 AddToPolyXY(p, 1.4, 0.2);
685 AddToPolyXY(p, 1.66, 1.38);
686 AddToPolyXY(p, 1.42, 2);
687 AddToPolyXY(p, 0.6, 2);
688 AddToPolyXY(p, 0.4, 1.46);
689 AddToPolyXY(p, 0.66, 0.2);
690 MultiplyPoly(p, 0.5*g->Lilanek[0].BSize.x, 0.5*g->Lilanek[0].BSize.y);
691 a = NewArea();
692 AddToArea(a, p);
693 FreePoly(p);
694 g->Lilanek[0].Shape = a;
695 g->Lilanek[0].Pos.x = 12;
696 g->Lilanek[0].Pos.y = 4;
697 g->Lilanek[0].Speed = 4;
698 g->Lilanek[0].Alive = 0;
699 g->Lilanek[0].Keys.Up = conf.pl1_key_up;
700 g->Lilanek[0].Keys.Down = conf.pl1_key_down;
701 g->Lilanek[0].Keys.Left = conf.pl1_key_left;
702 g->Lilanek[0].Keys.Right = conf.pl1_key_right;
703 g->Lilanek[0].Keys.Shoot = conf.pl1_key_fire;
704 g->Lilanek[0].Keys.Suicide = conf.pl1_key_suicide;
705 g->Lilanek[0].Keys.Switch = conf.pl1_key_switch;
706 g->Lilanek[0].Ammo = malloc(sizeof(int)*g->noWID);
707 for(i=0; i<g->noWID; i++){
708 g->Lilanek[0].Ammo[i] = 0;
710 g->Lilanek[0].ActiveWeapon = 0;
712 SDL_Color red = {255,211,211};
713 char redn[8]="Red";
714 g->Lilanek[0].Color = red;
715 strcpy(g->Lilanek[0].Name, redn);
717 g->Lilanek[1].Alive = 0; // little hack for SpawnLilanek to work
718 SpawnLilanek(g, 0);
720 p = g->Lilanek[0].Shape->p[0];
721 a = NewArea();
722 AddToArea(a, p);
723 g->Lilanek[1].Shape = a;
724 g->Lilanek[1].BSize.x = g->Lilanek[0].BSize.x;
725 g->Lilanek[1].BSize.y = g->Lilanek[0].BSize.y;
726 g->Lilanek[1].Pos.x = 14;
727 g->Lilanek[1].Pos.y = 4;
728 g->Lilanek[1].Speed = 4;
729 g->Lilanek[1].Alive = 0;
730 g->Lilanek[1].Keys.Up = conf.pl2_key_up;
731 g->Lilanek[1].Keys.Down = conf.pl2_key_down;
732 g->Lilanek[1].Keys.Left = conf.pl2_key_left;
733 g->Lilanek[1].Keys.Right = conf.pl2_key_right;
734 g->Lilanek[1].Keys.Shoot = conf.pl2_key_fire;
735 g->Lilanek[1].Keys.Suicide = conf.pl2_key_suicide;
736 g->Lilanek[1].Keys.Switch = conf.pl2_key_switch;
737 g->Lilanek[1].Ammo = malloc(sizeof(int)*g->noWID);
738 for(i=0; i<g->noWID; i++){
739 g->Lilanek[1].Ammo[i] = 0;
741 g->Lilanek[1].ActiveWeapon = 0;
743 SDL_Color blue = {180,180,255};
744 char bluen[8]="Blue";
745 g->Lilanek[1].Color = blue;
746 strcpy(g->Lilanek[1].Name, bluen);
748 SpawnLilanek(g, 1);
750 g->WeaponTemplate = malloc(sizeof(TWeapon)*g->noWID);
751 p = NewRect(0,0,0.5,0.5);
752 a = NewArea();
753 AddToArea(a, p);
754 FreePoly(p);
755 g->WeaponTemplate[0].Shape = a;
756 g->WeaponTemplate[0].WID = 0;
757 g->WeaponTemplate[0].Exists = 1;
758 g->WeaponTemplate[0].Ammo = 30;
759 g->WeaponTemplate[0].MaxAmmo = 120;
760 g->WeaponTemplate[0].ReloadTime = 1.5;
761 g->WeaponTemplate[0].Burst = 10;
763 g->BulletTemplate = malloc(sizeof(TBullet) * g->noWID);
764 p = NewRect(0,0,0.1,0.1);
765 a = NewArea();
766 AddToArea(a, p);
767 FreePoly(p);
768 g->BulletTemplate[0].Shape = a;
769 g->BulletTemplate[0].WID = 0;
770 g->BulletTemplate[0].Speed = 20;
771 g->BulletTemplate[0].Range = 20;
772 g->BulletTemplate[0].SFuzzy = 0.060;
773 g->BulletTemplate[0].VFuzzy = 0.000;
775 p = NewRect(0,0,0.5,0.5);
776 a = NewArea();
777 AddToArea(a, p);
778 FreePoly(p);
779 g->WeaponTemplate[1].Shape = a;
780 g->WeaponTemplate[1].WID = 1;
781 g->WeaponTemplate[1].Exists = 1;
782 g->WeaponTemplate[1].Ammo = 3;
783 g->WeaponTemplate[1].MaxAmmo = 6;
784 g->WeaponTemplate[1].ReloadTime = 0.5;
785 g->WeaponTemplate[1].Burst = 1;
787 p = NewRect(0,0,0.5,0.5);
788 a = NewArea();
789 AddToArea(a, p);
790 FreePoly(p);
791 g->BulletTemplate[1].Shape = a;
792 g->BulletTemplate[1].WID = 1;
793 g->BulletTemplate[1].Speed = 0;
794 g->BulletTemplate[1].Range = 20;
795 g->BulletTemplate[1].SFuzzy = 0.0;
796 g->BulletTemplate[1].VFuzzy = 0.0;
798 p = NewRect(0,0,0.5,0.5);
799 a = NewArea();
800 AddToArea(a, p);
801 FreePoly(p);
802 g->WeaponTemplate[2].Shape = a;
803 g->WeaponTemplate[2].WID = 0;
804 g->WeaponTemplate[2].Exists = 1;
805 g->WeaponTemplate[2].Ammo = 10;
806 g->WeaponTemplate[2].MaxAmmo = 50;
807 g->WeaponTemplate[2].ReloadTime = 0.1;
808 g->WeaponTemplate[2].Burst = 1;
810 p = NewRect(0,0,0.1,0.1);
811 a = NewArea();
812 AddToArea(a, p);
813 FreePoly(p);
814 g->BulletTemplate[2].Shape = a;
815 g->BulletTemplate[2].WID = 0;
816 g->BulletTemplate[2].Speed = 20;
817 g->BulletTemplate[2].Range = 20;
818 g->BulletTemplate[2].SFuzzy = 0.040;
819 g->BulletTemplate[2].VFuzzy = 0.010;
820 g->noBullets = 64;
821 g->Bullet = malloc(sizeof(TBullet) * g->noBullets);
822 for(i=0; i<g->noBullets; i++){
823 g->Bullet[i].Exists = 0;
824 g->Bullet[i].Shape = 0;
827 g->PWeapondrop = 0.4;
829 return g;
833 void onExit()
835 GrKill();
836 SDL_Quit();
839 Uint32 callback_fps(Uint32 interval, void *param)
841 SDL_Event event;
842 event.type = SDL_USEREVENT;
843 SDL_PushEvent(&event);
845 return 1000;
848 void Draw(Game *g){
849 int i;
851 QueueDrawSprite(bg, 0.0, 0.0,-1.0);
852 for(i=0; i < g->Map->noSprites; i++)
853 QueueDrawSprite(g->Map->Sprites[i], g->Map->SpritePos[i].x, g->Map->SpritePos[i].y, g->Map->Sprites[i]->z);
854 //Lilaneks
855 for(i=0; i < g->noLilaneks; i++){
856 SDL_Color c;
857 double pd;
858 c =g->Lilanek[i].Color;
859 if(g->Lilanek[i].ReloadTime < g->WeaponTemplate[g->Lilanek[i].ActiveWeapon].ReloadTime){
860 c.r *= 0.5;
861 c.g *= 0.5;
862 c.b *= 0.5;
864 QueueDrawSpriteColorize(lil[g->Lilanek[i].Orientation], g->Lilanek[i].Pos.x-1.0, g->Lilanek[i].Pos.y-1.0, 1, c );
865 QueueDrawSpriteColorize(hud,16.0,4.0*i, 1.0, c );
866 switch(g->Lilanek[i].ActiveWeapon){
867 case 0: QueueDrawSprite(hud_brok, 16.0, 0.0+4.0*i,0.0);
868 break;
869 case 1: QueueDrawSprite(hud_mine, 16.0, 0.0+4.0*i,0.0);
870 break;
871 case 2: QueueDrawSprite(hud_kul, 16.0, 0.0+4.0*i,0.0);
872 break;
874 pd = (double)g->Lilanek[i].Ammo[g->Lilanek[i].ActiveWeapon]/(double)g->WeaponTemplate[g->Lilanek[i].ActiveWeapon].MaxAmmo;
875 QueueDrawSpriteColorizeStretch(hud_ammo, 18.0-2.0*pd, 0.0+4.0*i,4.0*pd, 4.0, 2.0,c);
876 pd = (double)g->Lilanek[i].ReloadTime/(double)g->WeaponTemplate[g->Lilanek[i].ActiveWeapon].ReloadTime;
877 if(pd>1.0)pd=1.0;
878 QueueDrawSpriteColorizeStretch(hud_reload, 18.0-2.0*pd, 0.0+4.0*i,4.0*pd, 4.0, 2.0,c);
880 //Weapons
881 for(i=0; i < g->noWeapons; i++)
882 if(g->Weapon[i].Exists)
883 switch(g->Weapon[i].WID){
884 case 0: QueueDrawSprite(brok, g->Weapon[i].Pos.x - 1.0, g->Weapon[i].Pos.y - 1.0,1.0);
885 break;
886 case 1: QueueDrawSprite(mines, g->Weapon[i].Pos.x - 1.0, g->Weapon[i].Pos.y - 1.0,1.0);
887 break;
888 case 2: QueueDrawSprite(kul, g->Weapon[i].Pos.x - 1.0, g->Weapon[i].Pos.y - 1.0,1.0);
889 break;
892 for(i=0; i < g->noBullets; i++)
893 if(g->Bullet[i].Exists)
894 switch(g->Bullet[i].WID){
895 case 0: QueueDrawSprite(kulka, g->Bullet[i].Pos.x - 1.0, g->Bullet[i].Pos.y - 1.0,1.0);break;
896 case 1: QueueDrawSprite(mine, g->Bullet[i].Pos.x - 1.0, g->Bullet[i].Pos.y - 1.0,1.0);break;
897 case 2: QueueDrawSprite(kulka, g->Bullet[i].Pos.x - 1.0, g->Bullet[i].Pos.y - 1.0,1.0);break;
898 case -1: QueueDrawSprite(explo, g->Bullet[i].Pos.x - 1.0, g->Bullet[i].Pos.y - 1.0,1.0);break;
903 int InitAll(Game **g){
904 Config conf;
905 conf = GetConfig();
906 SaveConfig();
907 //TODO: odstranit SaveConfig... je to tu jenom kvuli debugovani
910 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER |SDL_INIT_AUDIO ) < 0) {
911 fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());
912 return 1;
914 atexit(onExit);
916 InitBase();
917 GrInit();
918 SoundInit();
919 *g = testgame();
920 lil[0] = LoadSpriteSVG("graphics/lil.svg", 1.0, 1.0);
921 lil[1] = LoadSpriteSVG("graphics/lilb.svg", 1.0, 1.0);
922 lil[2] = LoadSpriteSVG("graphics/lill.svg", 1.0, 1.0);
923 lil[3] = LoadSpriteSVG("graphics/lil.svg", 1.0, 1.0);
924 lil[4] = LoadSpriteSVG("graphics/lilr.svg", 1.0, 1.0);
925 (*g)->Map->Sprites[0] = LoadSpriteSVG("graphics/prek1.svg", 3.0, 3.0);
926 (*g)->Map->Sprites[1] = LoadSpriteSVG("graphics/prek2.svg", 4.0, 4.0);
927 (*g)->Map->Sprites[0]->z = 1;
928 (*g)->Map->Sprites[1]->z = 1;
929 bg=0;
930 bg = LoadSpriteSVG("graphics/bg.svg", 16.0, 15.0);
931 kul = LoadSpriteSVG("graphics/kul.svg", 0.5, 0.5);
932 explo = LoadSpriteSVG("graphics/exp.svg", 0.5, 0.5);
933 brok = LoadSpriteSVG("graphics/brok.svg", 0.5, 0.5);
934 kulka = LoadSpriteSVG("graphics/kulka.svg", 0.1, 0.1);
935 mine = LoadSpriteSVG("graphics/mine.svg", 0.5, 0.5);
936 mines = LoadSpriteSVG("graphics/mines.svg", 0.5, 0.5);
937 hud = LoadSpriteSVG("graphics/hud.svg", 4.0, 4.0);
938 hud_mine = LoadSpriteSVG("graphics/mines.svg", 2.2, 2.2);
939 hud_kul = LoadSpriteSVG("graphics/kul.svg", 2.2, 2.2);
940 hud_brok = LoadSpriteSVG("graphics/brok.svg", 2.2, 2.2);
941 hud_ammo = LoadSpriteSVG("graphics/hud_ammo.svg", 4.0, 4.0);
942 hud_reload = LoadSpriteSVG("graphics/hud_reload.svg", 4.0, 4.0);
944 s_die = LoadSound("sounds/die.wav");
945 s_bonus = LoadSound("sounds/bonus.wav");
946 s_expl = LoadSound("sounds/expl.wav");
947 s_shoot = LoadSound("sounds/shoot.wav");
948 s_mine = LoadSound("sounds/mine.wav");
950 SDL_AddTimer(1000, callback_fps, NULL);
952 return 0;
955 int GameLoop(Game *g){
956 SDL_Event event;
957 Config conf;
958 double lasttime, dtime;
960 lasttime = SDL_GetTicks()*0.001;
961 while (1) {
962 while (SDL_PollEvent(&event)) {
963 switch (event.type) {
964 case SDL_KEYDOWN:
965 if (event.key.keysym.sym == SDLK_q) {
966 return 0;
968 break;
970 case SDL_QUIT:
971 return 0;
972 break;
974 case SDL_VIDEORESIZE:
975 /* Resize the screen and redraw */
976 conf=GetConfig();
977 conf.screen_width=event.resize.w;
978 conf.screen_height=event.resize.h;
979 SetConfig(conf);
981 InvalidateSprites();
982 break;
984 case SDL_USEREVENT:
985 printf("%d frames\n",frames);
986 frames=0;
987 break;
989 default:
990 break;
993 dtime = SDL_GetTicks()*0.001-lasttime;
994 lasttime += dtime;
995 if(dtime < 0)
996 dtime=0.0;
997 if(dtime > 0.1)
998 dtime=0.1;
999 UpdateLogic(g, dtime*0.5);
1000 UpdateLogic(g, dtime*0.5);
1001 ClrScr();
1002 Draw(g);
1003 DrawSprites();
1004 frames++;
1005 //we don't want to waste cpu...
1006 if(frames >=50){
1007 SDL_Delay(10);
1010 return 0;
1013 int main(int argc, char **argv){
1014 Game *g;
1015 srand(time(0));
1016 InitAll(&g);
1017 GameLoop(g);
1018 return 0;