QueueDrawSpriteColorize now with alpha
[Lilanci.git] / ebulanci.c
blob02e0d44dd478893efb4b1980de607fb2aafa32d3
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"
9 #include "particle.h"
12 int gamestate=0;
14 typedef struct{
15 int Up;
16 int Down;
17 int Left;
18 int Right;
19 int Shoot;
20 int Suicide;
21 int Switch;
22 }TKeyBinding;//TODO: s/int/real data type for a key
24 typedef struct{
25 Vect Pos; //where he is
26 Vect Move; //how he want to move
27 Vect BSize; //Size of bounding rect
28 Area *Shape; //how fat he is
29 //Area *TrShape; //translated Shape -- don't optimize yet
30 int Frags; //no comment
31 int Deaths; //R.I.P.
32 double Speed; //meters per second
33 int Orientation; //1-up 2-left 3-down 4-right 0-down
34 int WannaShoot; //1-want 0-don't want
35 double ReloadTime; //time from last shot
36 int WannaDie; //1-want suicide 2-died and still holding suicide 0-don't want
37 double AnimationTime; //in seconds
38 TKeyBinding Keys;
39 int *Ammo;
40 int ActiveWeapon;
41 int SwitchLock;
42 int Alive;
43 char Name[16];
44 SDL_Color Color;
45 }TLilanek;
48 typedef struct{
49 Vect Pos;
50 Area *Shape;
51 int WID; //Weapon ID
52 int Exists; // 0- doesn't exist 1-exists
53 int Ammo;
54 int MaxAmmo;
55 int Burst;
56 double ReloadTime;
57 }TWeapon;
59 typedef struct{
60 Vect Pos;
61 Area *Shape;
62 Vect Vel; //velocity i m/s
63 double Speed; //for Templates
64 double Range; //How far it can travel
65 int WID; //Weapon ID
66 int lid; //who shoot this bullet?
67 int Exists; // 0- doesn't exist 1-exists
68 double SFuzzy; // Fuzzy factor for spawning 0-1 :)
69 double VFuzzy; // Fuzzy factor for traveling 0-1 :)
70 }TBullet;
73 typedef struct{
74 TMap *Map; //where we are playing
75 TLilanek *Lilanek; //our heroes-ehm bad guys
76 int noLilaneks;
78 TWeapon *Weapon; //Weapons lying on floor
79 int noWeapons;
80 TWeapon *WeaponTemplate;
81 TBullet *BulletTemplate;
82 int noWID; //biggest WID, also number of WeaponTemplates
83 TBullet *Bullet;
84 int noBullets;
85 double PWeapondrop; // Probability of weapon drop per second
86 }Game;
88 Vect Orientations[5];
90 Sprite *lil[5];
91 Sprite *bg;
92 Sprite *kul;
93 Sprite *explo;
94 Sprite *brok;
95 Sprite *kulka;
96 Sprite *mine;
97 Sprite *mines;
98 Sprite *hud;
99 Sprite *hud_mine;
100 Sprite *hud_kul;
101 Sprite *hud_brok;
102 Sprite *hud_ammo;
103 Sprite *hud_reload;
104 int s_die;
105 int s_bonus;
106 int s_expl;
107 int s_shoot;
108 int s_mine;
110 int frames=0;
111 void SwitchNextWeapon(Game *g, int lid);
113 int InitBase(){
114 Orientations[0].x=0;
115 Orientations[0].y=0;
116 Orientations[1].x=0;
117 Orientations[1].y=-1;
118 Orientations[2].x=-1;
119 Orientations[2].y=0;
120 Orientations[3].x=0;
121 Orientations[3].y=1;
122 Orientations[4].x=1;
123 Orientations[4].y=0;
124 //TODO: write code
126 return 0;
129 void SpawnLilanek(Game *g, int lid){
130 Vect Pos;
131 int tries;
132 Area *tp, *oltp;
133 int good;
134 int olid;
136 oltp = 0;
137 tp = 0;
138 for(tries=0; tries <1000; tries++){ //TODO: remove exact number
139 Pos.x = RandD(0,g->Map->XX);
140 Pos.y = RandD(0,g->Map->YY);
141 good=1;
142 tp = TranslateArea(g->Lilanek[lid].Shape, &Pos);
143 printf("%s\n", Area2String(tp));
144 if(!AreaInMap(g->Map, tp,0,1)){
145 good=0;
148 for(olid=0; olid < g->noLilaneks; olid++){
149 if(olid == lid)
150 continue;
151 if(!g->Lilanek[olid].Alive){
152 continue;
154 oltp = TranslateArea(g->Lilanek[olid].Shape, &g->Lilanek[olid].Pos);
155 if(AreaInArea(tp, oltp)){
156 good=0;
158 FreeArea(oltp);
159 oltp = 0;
162 if(good){
163 FreeArea(tp);
164 tp=0;
165 g->Lilanek[lid].Pos.x = Pos.x;
166 g->Lilanek[lid].Pos.y = Pos.y;
167 g->Lilanek[lid].Alive = 1;
168 break;
170 FreeArea(tp);
171 tp=0;
175 void DropWeapon(Game *g, int weapon){
176 Vect Pos;
177 int tries;
178 int WID;
179 Area *tp;
181 for(tries=0; tries <100; tries++){ //TODO: remove exact number
182 Pos.x = RandD(0,g->Map->XX);
183 Pos.y = RandD(0,g->Map->YY);
184 WID = RandI(0, g->noWID);
185 tp = TranslateArea(g->WeaponTemplate[WID].Shape, &Pos);
186 if(AreaInMap(g->Map, tp, 0, g->Map->noLayer)){
187 FreeArea(tp);
188 tp=0;
189 memcpy(&g->Weapon[weapon], &g->WeaponTemplate[WID], sizeof(TWeapon));
190 g->Weapon[weapon].Shape = g->WeaponTemplate[WID].Shape;
191 g->Weapon[weapon].Pos.x = Pos.x;
192 g->Weapon[weapon].Pos.y = Pos.y;
193 g->Weapon[weapon].WID = WID;
194 g->Weapon[weapon].Exists = 1;
195 break;
197 FreeArea(tp);
198 tp=0;
202 void DropWeapons(Game *g, double dtime){
203 int i;
205 if( RandD(0.0, 1.0) >= (g->PWeapondrop*dtime))
206 return;
207 for(i=0; i < g->noWeapons; i++){
208 if(g->Weapon[i].Exists)continue; //we don't like teleporting weapons :)
210 printf("A Weapon drop!\n");
211 DropWeapon(g, i);
212 break; //spawn max one weapon per update
216 void WeaponPickedUp(Game *g, double dtime, int lid, int wid){
217 TLilanek *l;
218 TWeapon *w;
220 l = &g->Lilanek[lid];
221 w = &g->Weapon[wid];
223 l->Ammo[w->WID] += w->Ammo;
224 if(l->Ammo[w->WID] > w->MaxAmmo)
225 l->Ammo[w->WID] = w->MaxAmmo;
226 printf("Ammo: %d\n",l->Ammo[w->WID]);
227 l->ActiveWeapon = w->WID;
228 printf("AW: %d\n",l->ActiveWeapon);
230 w->Exists = 0;
232 PlaySound(s_bonus);
235 void PickUpWeapons(Game *g, double dtime){
236 int lid,wid;
237 Area *WArea, *LArea;
239 for(lid=0; lid<g->noLilaneks; lid++){
240 LArea = TranslateArea(g->Lilanek[lid].Shape, &g->Lilanek[lid].Pos);
241 for(wid=0; wid < g->noWeapons; wid++){
242 if(!g->Weapon[wid].Exists)
243 continue;
244 WArea = TranslateArea(g->Weapon[wid].Shape, &g->Weapon[wid].Pos);
245 if(!AreaInArea( WArea, LArea)){
246 FreeArea(WArea);
247 continue;
249 WeaponPickedUp(g, dtime, lid, wid);
250 FreeArea(WArea);
252 FreeArea(LArea);
256 void BulletExplodes(Game *g, int i){
257 g->Bullet[i].Exists=0;
258 //TODO: some effects
261 void MoveBullet(Game *g, double dtime, int i){
262 double ff;
263 Vect dp;
264 dp.x = g->Bullet[i].Pos.x;
265 dp.y = g->Bullet[i].Pos.y;
266 ff= g->Bullet[i].Speed*g->Bullet[i].VFuzzy;
267 g->Bullet[i].Pos.x += (g->Bullet[i].Vel.x += RandD(-ff,ff))* dtime;
268 g->Bullet[i].Pos.y += (g->Bullet[i].Vel.y += RandD(-ff,ff))* dtime;
269 dp.x -= g->Bullet[i].Pos.x;
270 dp.y -= g->Bullet[i].Pos.y;
271 g->Bullet[i].Range -= sqrt(DotProduct(&dp, &dp));
274 void CollideBulletMap(Game *g, double dtime, int i){
275 Area *p;
277 p=TranslateArea(g->Bullet[i].Shape, &g->Bullet[i].Pos);
278 if(AreaInMap(g->Map, p, 1,1)==0)
279 BulletExplodes(g, i);
280 FreeArea(p);
282 void LilanekKilled(Game *g, double dtime, int BulletID, int LilanekID){
283 int i;
284 g->Bullet[BulletID].Exists = 0;
285 g->Lilanek[LilanekID].Deaths ++;
286 g->Lilanek[g->Bullet[BulletID].lid].Frags ++;
287 SpawnLilanek(g, LilanekID);
288 for(i=0; i<g->noWID; i++){
289 g->Lilanek[LilanekID].Ammo[i] = 0;
291 PlaySound(s_die);
294 #define NO_EXPLOSIONS 10 //MAGIC_NUMBER
295 #define EXPLOSION_SPEED 5 //MAGIC_NUMBER
296 #define EXPLOSION_RANGE 1.0 //MAGIC_NUMBER
298 void SpawnExplosions(Game *g, double dtime, int BulletID){
299 int bid = 0;
300 int i = 0;
301 TBullet *b;
302 Vect Pos;
303 double speed;
305 Pos.x = g->Bullet[BulletID].Pos.x;
306 Pos.y = g->Bullet[BulletID].Pos.y;
307 for(i=0; i<NO_EXPLOSIONS; i++){
308 for(bid=0; bid<g->noBullets; bid++){
309 if(g->Bullet[bid].Exists)
310 continue;
311 b = &g->Bullet[bid];
312 b->Pos.x = Pos.x;
313 b->Pos.y = Pos.y;
314 b->Vel.x = RandD(0.0, 1.0)*(RandI(0,100)>50?-1:1);
315 b->Vel.y = RandD(0.0, 1.0)*(RandI(0,100)>50?-1:1);
316 NormV(&b->Vel);
317 speed = RandD(0.3, 1.0)*EXPLOSION_SPEED;
318 b->Speed = speed;
319 b->Vel.x *= speed;
320 b->Vel.y *= speed;
321 b->WID = -1;
322 b->lid = g->Bullet[BulletID].lid;
323 b->Exists = 1;
324 b->SFuzzy = 0;
325 b->VFuzzy = 0;
326 b->Range = EXPLOSION_RANGE;
327 b->Shape = g->Bullet[BulletID].Shape;
328 printf("%lf ", speed);
329 break;
332 g->Bullet[BulletID].Exists = 0;
333 PlaySound(s_expl);
336 void CollideBulletLilanek(Game *g, double dtime, int BulletID){
337 Area *BArea, *LArea;
338 int LilanekID;
340 BArea=TranslateArea(g->Bullet[BulletID].Shape, &g->Bullet[BulletID].Pos);
341 for(LilanekID=0; LilanekID<g->noLilaneks; LilanekID++){
342 LArea=TranslateArea(g->Lilanek[LilanekID].Shape, &g->Lilanek[LilanekID].Pos);
343 if(AreaInArea(LArea,BArea)){
344 //if it is a mine, spawn explosion instead of killing instantly
345 if(g->Bullet[BulletID].WID == 1){
346 SpawnExplosions(g, dtime, BulletID);
347 }else{
348 LilanekKilled(g, dtime, BulletID, LilanekID);
351 FreeArea(LArea);
352 LArea=0;
354 FreeArea(BArea);
355 BArea=0;
358 void UpdateBullets(Game *g, double dtime){
359 int BulletID;
360 for(BulletID=0; BulletID<g->noBullets; BulletID++){
361 if(g->Bullet[BulletID].Exists==0)
362 continue; //We won't update non-existending bullets
363 MoveBullet(g, dtime, BulletID);
364 if(g->Bullet[BulletID].Range < 0){
365 g->Bullet[BulletID].Exists = 0;
366 continue;
368 CollideBulletMap(g, dtime, BulletID);
369 CollideBulletLilanek(g, dtime, BulletID);
373 int CheckLilanekvsLilaneks(Game *g, Area *a, int LilanekID){ //returns 0 if he collides with others, 1 if it's OK to move there
374 int i;
375 Area *nb;
376 int rval=1;
378 nb=0;
379 for(i=0; i<g->noLilaneks && rval==1; i++){
380 if(i==LilanekID)
381 continue;
382 nb = TranslateArea(g->Lilanek[i].Shape, &g->Lilanek[i].Pos);
383 if(AreaInArea(nb, a))
384 rval=0;
385 FreeArea(nb);
386 nb=0;
388 return rval;
391 void MoveLilaneks(Game *g, double dtime){
392 int i, steps;
393 Area *pa;
394 Vect va;
395 double dt;
397 pa=0;
398 for(i=0; i<g->noLilaneks; i++){
399 //skip this Lilanek if he doesn't wanna move
400 if(g->Lilanek[i].Move.x == 0.0 && g->Lilanek[i].Move.y == 0.0)
401 continue;
402 for(dt=dtime, steps=0; steps<4; dt/=2.0, steps++){ //TODO: get rid of exact number
403 //make future Area
404 va.x = g->Lilanek[i].Pos.x + dt*g->Lilanek[i].Move.x;
405 va.y = g->Lilanek[i].Pos.y + dt*g->Lilanek[i].Move.y;
406 FreeArea(pa); //we don't want memory leaks
407 pa = TranslateArea(g->Lilanek[i].Shape, &va);
408 //check for collision with map
409 if(AreaInMap(g->Map, pa, 0, 1)==0)
410 continue; //try smaller dt if he collided with map
411 //check for collision with other Lilaneks
412 if(CheckLilanekvsLilaneks(g, pa, i)==0)
413 continue;
414 //move him if we got here
415 g->Lilanek[i].Pos.x += dt*g->Lilanek[i].Move.x;
416 g->Lilanek[i].Pos.y += dt*g->Lilanek[i].Move.y;
417 FreeArea(pa);
418 pa=0;
420 FreeArea(pa); //For sure
421 pa=0;
425 void ParseInput(Game *g, double dtime){
426 int i;
427 Uint8 *keystate;
428 TLilanek *curlil;
429 int wannamove;
431 keystate = SDL_GetKeyState(NULL);
432 //pause
433 if(gamestate == 1){
434 if(keystate['o']){
435 printf("unpause\n");
436 gamestate = 0;
437 }else return;
439 if(keystate['p']){
440 printf("pause\n");
441 gamestate = 1;
444 for(i=0; i< g->noLilaneks; i++){
445 curlil = &g->Lilanek[i];
446 wannamove=0;
447 // Up;
448 if(keystate[curlil->Keys.Up]){
449 curlil->Orientation = 1;
450 curlil->Move.x = curlil->Speed * Orientations[1].x;
451 curlil->Move.y = curlil->Speed * Orientations[1].y;
452 wannamove=1;
454 // Down;
455 if(keystate[curlil->Keys.Down]){
456 curlil->Orientation = 3;
457 curlil->Move.x = curlil->Speed * Orientations[3].x;
458 curlil->Move.y = curlil->Speed * Orientations[3].y;
459 wannamove=1;
461 // Left;
462 if(keystate[curlil->Keys.Left]){
463 curlil->Orientation = 2;
464 curlil->Move.x = curlil->Speed * Orientations[2].x;
465 curlil->Move.y = curlil->Speed * Orientations[2].y;
466 wannamove=1;
468 // Right;
469 if(keystate[curlil->Keys.Right]){
470 curlil->Orientation = 4;
471 curlil->Move.x = curlil->Speed * Orientations[4].x;
472 curlil->Move.y = curlil->Speed * Orientations[4].y;
473 wannamove=1;
476 if(!wannamove){
477 curlil->Move.x = 0;
478 curlil->Move.y = 0;
480 // Shoot;
481 if(keystate[curlil->Keys.Shoot]){
482 curlil->WannaShoot = 1;
483 }else{
484 curlil->WannaShoot = 0;
486 // Suicide;
487 if(keystate[curlil->Keys.Suicide]){
488 if(curlil->WannaDie != 2){
489 curlil->WannaDie = 1;
491 }else{
492 curlil->WannaDie = 0;
494 // Switch;
495 if(keystate[curlil->Keys.Switch]){
496 if(!curlil->SwitchLock){
497 SwitchNextWeapon(g, i);
498 curlil->SwitchLock = 1;
500 }else{
501 curlil->SwitchLock = 0;
506 void SpawnBullet(Game *g, double dtime, int lid, int bid){
507 Area *LArea, *BArea;
508 TBullet *b, *bt;
509 double vx, vy; //because we need to spawn also mines with no velocity
512 LArea = TranslateArea(g->Lilanek[lid].Shape, &g->Lilanek[lid]. Pos);
513 b = &g->Bullet[bid];
514 bt = &g->BulletTemplate[g->Lilanek[lid].ActiveWeapon];
515 memcpy (b, bt, sizeof(TBullet));
516 b->Exists = 1;
517 b->Pos.x = g->Lilanek[lid].Pos.x+g->Lilanek[lid].BSize.x*0.5;
518 b->Pos.y = g->Lilanek[lid].Pos.y+g->Lilanek[lid].BSize.y*0.5;
519 b->WID = bt->WID;
520 b->Range = bt->Range;
521 b->Vel.x = Orientations[g->Lilanek[lid].Orientation].x * b->Speed +RandD(-b->Speed*b->SFuzzy, b->Speed*b->SFuzzy);
522 b->Vel.y = Orientations[g->Lilanek[lid].Orientation].y * b->Speed +RandD(-b->Speed*b->SFuzzy, b->Speed*b->SFuzzy);
523 if(DotProduct(&b->Vel, &b->Vel) <=0.01){
524 vx = -1*Orientations[g->Lilanek[lid].Orientation].x;
525 vy = -1*Orientations[g->Lilanek[lid].Orientation].y;
526 }else{
527 vx = b->Vel.x;
528 vy = b->Vel.y;
530 b->lid =lid;
531 while(1){
532 BArea = TranslateArea(b->Shape, &b->Pos);
533 if(!AreaInArea(BArea, LArea))
534 break;
535 b->Pos.x += vx* dtime*0.5;
536 b->Pos.y += vy* dtime*0.5;
538 FreeArea(LArea);
541 void ShootParticles(Game *g, double dtime, int lid)
543 int i;
544 double a;
545 double v;
546 Particle *p;
548 for(i = 1; i < 20; i ++){
549 p = malloc(sizeof(Particle));
550 memset(p, 0, sizeof(Particle));
551 a = RandD(0.0, 2*M_PI);
552 v = RandD(0.0, 2.0);
553 p->x = g->Lilanek[lid].Pos.x;
554 p->y = g->Lilanek[lid].Pos.y;
555 p->t = 1.0;
556 p->vx = v*sin(a);
557 p->vy = v*cos(a);
558 p->vt = 0.0-1.0;
559 p->s = explo;
560 AddParticle(p);
564 void Shoot(Game *g, double dtime, int lid){
565 int bid;
566 int i;
568 for(i=0; i<g->WeaponTemplate[g->Lilanek[lid].ActiveWeapon].Burst; i++){
569 if(g->Lilanek[lid].Ammo[g->Lilanek[lid].ActiveWeapon] == 0)
570 return;
571 for(bid=0; bid<g->noBullets; bid++){
572 if(g->Bullet[bid].Exists)
573 continue;
574 SpawnBullet(g, dtime, lid, bid);
575 g->Lilanek[lid].Ammo[g->Lilanek[lid].ActiveWeapon]--;
576 g->Lilanek[lid].ReloadTime = 0;
577 break;
580 ShootParticles(g, dtime, lid);
581 switch(g->Lilanek[lid].ActiveWeapon){
582 case 0: PlaySound(s_shoot); break;
583 case 1: PlaySound(s_mine); break;
584 case 2: PlaySound(s_shoot); break;
585 default: break;
589 void SwitchNextWeapon(Game *g, int lid){
590 int i;
591 TLilanek *l;
592 l = &g->Lilanek[lid];
593 for(i = 1; i < g->noWID; i++){
594 if(l->Ammo[(l->ActiveWeapon+i)%(g->noWID)]){
595 l->ActiveWeapon = (l->ActiveWeapon+i)%(g->noWID);
596 return;
601 void ShootIfTheyWantTo(Game *g, double dtime){
602 int lid;
604 for(lid=0; lid<g->noLilaneks; lid++){
605 //if(!g->Lilanek[lid].Exists)
606 //continue;
607 if(g->Lilanek[lid].Ammo[g->Lilanek[lid].ActiveWeapon] == 0)
608 SwitchNextWeapon(g,lid);
610 if(g->Lilanek[lid].ReloadTime < g->WeaponTemplate[g->Lilanek[lid].ActiveWeapon].ReloadTime){
611 g->Lilanek[lid].ReloadTime += dtime;
612 }else{
613 if(!g->Lilanek[lid].WannaShoot)
614 continue;
615 Shoot(g, dtime, lid);
620 int UpdateLogic(Game *g,double dtime){
621 if(gamestate == 0){
622 DropWeapons(g, dtime);
623 UpdateBullets(g, dtime);
625 ParseInput(g, dtime);
626 if(gamestate == 0){
627 MoveLilaneks(g, dtime);
628 PickUpWeapons(g, dtime);
629 ShootIfTheyWantTo(g, dtime);
631 return 0; //TODO: return something useful
634 Game *testgame(){ //return testing game, function for use before we have some menu/loading mechanism
635 Game *g;
636 Poly *p, *pp;
637 Area *a;
638 int i;
639 Config conf = GetConfig();
641 g = malloc(sizeof(Game));
642 memset(g, 0, sizeof(Game));
643 g->noWID=3;
644 g->Map = malloc(sizeof(TMap));
645 g->Map->noLayer=2;
646 g->Map->Layer = malloc(sizeof(TMapLayer *)*g->Map->noLayer);
647 g->Map->Layer[0] = malloc(sizeof(TMapLayer));
648 g->Map->Layer[0]->noFArea = 1;
649 g->Map->Layer[0]->FArea = malloc(sizeof(Area *) * g->Map->Layer[0]->noFArea);
650 p = NewRect(4,2.5,3,2);
651 a = NewArea();
652 AddToArea(a, p);
653 FreePoly(p);
654 g->Map->Layer[0]->FArea[0] = a;
656 g->Map->Layer[1] = malloc(sizeof(TMapLayer));
657 g->Map->Layer[1]->noFArea = 1;
658 g->Map->Layer[1]->FArea = malloc(sizeof(Area *) * g->Map->Layer[1]->noFArea);
659 p = NewPoly();
660 AddToPolyXY(p, 0.30, 0.41);
661 AddToPolyXY(p, 0.73, 0.41);
662 AddToPolyXY(p, 0.77, 0.79);
663 AddToPolyXY(p, 0.65, 0.955);
664 AddToPolyXY(p, 0.365, 0.965);
665 AddToPolyXY(p, 0.235, 0.785);
666 MultiplyPoly(p, 4, 4);
667 pp = TranslatePolyXY(p, 7, 7);
668 a = NewArea();
669 AddToArea(a, pp);
670 FreePoly(pp);
671 FreePoly(p);
672 g->Map->Layer[1]->FArea[0] = a;
673 p = NewRect(1,1,16,15);
674 a = NewArea();
675 AddToArea(a, p);
676 FreePoly(p);
677 g->Map->BoundingArea = a;
678 g->Map->XX = 17;
679 g->Map->YY = 16;
680 g->Map->X = 1;
681 g->Map->Y = 1;
683 g->Map->noSprites = 2;
684 g->Map->Sprites = (Sprite **) malloc(sizeof(Sprite*)*g->Map->noSprites);
685 g->Map->SpritePos = (Vect *) malloc(sizeof(Vect)*g->Map->noSprites);
686 g->Map->SpritePos[0].x = 3.0;
687 g->Map->SpritePos[0].y = 1.0;
688 g->Map->SpritePos[1].x = 6.0;
689 g->Map->SpritePos[1].y = 6.0;
691 g->noWeapons = 8;
692 g->Weapon = malloc(sizeof(TWeapon) * g->noWeapons);
693 if(!g->Weapon){
694 fprintf(stderr, "Cannot allocate memory for Weapons\n");
696 for(i=0; i<g->noWeapons; i++){
697 g->Weapon[i].Exists = 0;
698 g->Weapon[i].Shape = 0;
701 g->noLilaneks = 2;
702 g->Lilanek = malloc(sizeof(TLilanek) * g->noLilaneks);
703 memset(g->Lilanek, 0, sizeof(TLilanek) * g->noLilaneks);
704 g->Lilanek[0].BSize.x = 1;
705 g->Lilanek[0].BSize.y = 1;
706 //g->Lilanek[0].Shape = NewRect(0.6,0.2,0.8,1.6);
707 p = NewPoly();
708 AddToPolyXY(p, 1, 0);
709 AddToPolyXY(p, 1.4, 0.2);
710 AddToPolyXY(p, 1.66, 1.38);
711 AddToPolyXY(p, 1.42, 2);
712 AddToPolyXY(p, 0.6, 2);
713 AddToPolyXY(p, 0.4, 1.46);
714 AddToPolyXY(p, 0.66, 0.2);
715 MultiplyPoly(p, 0.5*g->Lilanek[0].BSize.x, 0.5*g->Lilanek[0].BSize.y);
716 a = NewArea();
717 AddToArea(a, p);
718 FreePoly(p);
719 g->Lilanek[0].Shape = a;
720 g->Lilanek[0].Pos.x = 12;
721 g->Lilanek[0].Pos.y = 4;
722 g->Lilanek[0].Speed = 4;
723 g->Lilanek[0].Alive = 0;
724 g->Lilanek[0].Keys.Up = conf.pl1_key_up;
725 g->Lilanek[0].Keys.Down = conf.pl1_key_down;
726 g->Lilanek[0].Keys.Left = conf.pl1_key_left;
727 g->Lilanek[0].Keys.Right = conf.pl1_key_right;
728 g->Lilanek[0].Keys.Shoot = conf.pl1_key_fire;
729 g->Lilanek[0].Keys.Suicide = conf.pl1_key_suicide;
730 g->Lilanek[0].Keys.Switch = conf.pl1_key_switch;
731 g->Lilanek[0].Ammo = malloc(sizeof(int)*g->noWID);
732 for(i=0; i<g->noWID; i++){
733 g->Lilanek[0].Ammo[i] = 0;
735 g->Lilanek[0].ActiveWeapon = 0;
737 SDL_Color red = {255,211,211,255};
738 char redn[8]="Red";
739 g->Lilanek[0].Color = red;
740 strcpy(g->Lilanek[0].Name, redn);
742 g->Lilanek[1].Alive = 0; // little hack for SpawnLilanek to work
743 SpawnLilanek(g, 0);
745 p = g->Lilanek[0].Shape->p[0];
746 a = NewArea();
747 AddToArea(a, p);
748 g->Lilanek[1].Shape = a;
749 g->Lilanek[1].BSize.x = g->Lilanek[0].BSize.x;
750 g->Lilanek[1].BSize.y = g->Lilanek[0].BSize.y;
751 g->Lilanek[1].Pos.x = 14;
752 g->Lilanek[1].Pos.y = 4;
753 g->Lilanek[1].Speed = 4;
754 g->Lilanek[1].Alive = 0;
755 g->Lilanek[1].Keys.Up = conf.pl2_key_up;
756 g->Lilanek[1].Keys.Down = conf.pl2_key_down;
757 g->Lilanek[1].Keys.Left = conf.pl2_key_left;
758 g->Lilanek[1].Keys.Right = conf.pl2_key_right;
759 g->Lilanek[1].Keys.Shoot = conf.pl2_key_fire;
760 g->Lilanek[1].Keys.Suicide = conf.pl2_key_suicide;
761 g->Lilanek[1].Keys.Switch = conf.pl2_key_switch;
762 g->Lilanek[1].Ammo = malloc(sizeof(int)*g->noWID);
763 for(i=0; i<g->noWID; i++){
764 g->Lilanek[1].Ammo[i] = 0;
766 g->Lilanek[1].ActiveWeapon = 0;
768 SDL_Color blue = {180,180,255, 255};
769 char bluen[8]="Blue";
770 g->Lilanek[1].Color = blue;
771 strcpy(g->Lilanek[1].Name, bluen);
773 SpawnLilanek(g, 1);
775 g->WeaponTemplate = malloc(sizeof(TWeapon)*g->noWID);
776 p = NewRect(0,0,0.5,0.5);
777 a = NewArea();
778 AddToArea(a, p);
779 FreePoly(p);
780 g->WeaponTemplate[0].Shape = a;
781 g->WeaponTemplate[0].WID = 0;
782 g->WeaponTemplate[0].Exists = 1;
783 g->WeaponTemplate[0].Ammo = 30;
784 g->WeaponTemplate[0].MaxAmmo = 120;
785 g->WeaponTemplate[0].ReloadTime = 0.7;
786 g->WeaponTemplate[0].Burst = 10;
788 g->BulletTemplate = malloc(sizeof(TBullet) * g->noWID);
789 p = NewRect(0,0,0.1,0.1);
790 a = NewArea();
791 AddToArea(a, p);
792 FreePoly(p);
793 g->BulletTemplate[0].Shape = a;
794 g->BulletTemplate[0].WID = 0;
795 g->BulletTemplate[0].Speed = 20;
796 g->BulletTemplate[0].Range = 20;
797 g->BulletTemplate[0].SFuzzy = 0.160;
798 g->BulletTemplate[0].VFuzzy = 0.000;
800 p = NewRect(0,0,0.5,0.5);
801 a = NewArea();
802 AddToArea(a, p);
803 FreePoly(p);
804 g->WeaponTemplate[1].Shape = a;
805 g->WeaponTemplate[1].WID = 1;
806 g->WeaponTemplate[1].Exists = 1;
807 g->WeaponTemplate[1].Ammo = 3;
808 g->WeaponTemplate[1].MaxAmmo = 6;
809 g->WeaponTemplate[1].ReloadTime = 0.5;
810 g->WeaponTemplate[1].Burst = 1;
812 p = NewRect(0,0,0.5,0.5);
813 a = NewArea();
814 AddToArea(a, p);
815 FreePoly(p);
816 g->BulletTemplate[1].Shape = a;
817 g->BulletTemplate[1].WID = 1;
818 g->BulletTemplate[1].Speed = 0;
819 g->BulletTemplate[1].Range = 20;
820 g->BulletTemplate[1].SFuzzy = 0.0;
821 g->BulletTemplate[1].VFuzzy = 0.0;
823 p = NewRect(0,0,0.5,0.5);
824 a = NewArea();
825 AddToArea(a, p);
826 FreePoly(p);
827 g->WeaponTemplate[2].Shape = a;
828 g->WeaponTemplate[2].WID = 0;
829 g->WeaponTemplate[2].Exists = 1;
830 g->WeaponTemplate[2].Ammo = 10;
831 g->WeaponTemplate[2].MaxAmmo = 50;
832 g->WeaponTemplate[2].ReloadTime = 0.1;
833 g->WeaponTemplate[2].Burst = 1;
835 p = NewRect(0,0,0.1,0.1);
836 a = NewArea();
837 AddToArea(a, p);
838 FreePoly(p);
839 g->BulletTemplate[2].Shape = a;
840 g->BulletTemplate[2].WID = 0;
841 g->BulletTemplate[2].Speed = 20;
842 g->BulletTemplate[2].Range = 20;
843 g->BulletTemplate[2].SFuzzy = 0.040;
844 g->BulletTemplate[2].VFuzzy = 0.010;
845 g->noBullets = 64;
846 g->Bullet = malloc(sizeof(TBullet) * g->noBullets);
847 for(i=0; i<g->noBullets; i++){
848 g->Bullet[i].Exists = 0;
849 g->Bullet[i].Shape = 0;
852 g->PWeapondrop = 0.4;
854 return g;
858 void onExit()
860 GrKill();
861 SDL_Quit();
864 Uint32 callback_fps(Uint32 interval, void *param)
866 SDL_Event event;
867 event.type = SDL_USEREVENT;
868 SDL_PushEvent(&event);
870 return 1000;
873 void Draw(Game *g){
874 int i;
876 QueueDrawSprite(bg, 0.0, 0.0,-1.0);
877 for(i=0; i < g->Map->noSprites; i++)
878 QueueDrawSprite(g->Map->Sprites[i], g->Map->SpritePos[i].x, g->Map->SpritePos[i].y, g->Map->Sprites[i]->z);
879 //Lilaneks
880 for(i=0; i < g->noLilaneks; i++){
881 SDL_Color c;
882 double pd;
883 c =g->Lilanek[i].Color;
884 if(g->Lilanek[i].ReloadTime < g->WeaponTemplate[g->Lilanek[i].ActiveWeapon].ReloadTime){
885 c.r *= 0.5;
886 c.g *= 0.5;
887 c.b *= 0.5;
888 c.unused *= 0.8;
890 QueueDrawSpriteColorize(lil[g->Lilanek[i].Orientation], g->Lilanek[i].Pos.x-1.0, g->Lilanek[i].Pos.y-1.0, 1, c );
891 QueueDrawSpriteColorize(hud,16.0,4.0*i, 1.0, c );
892 switch(g->Lilanek[i].ActiveWeapon){
893 case 0: QueueDrawSprite(hud_brok, 16.0, 0.0+4.0*i,0.0);
894 break;
895 case 1: QueueDrawSprite(hud_mine, 16.0, 0.0+4.0*i,0.0);
896 break;
897 case 2: QueueDrawSprite(hud_kul, 16.0, 0.0+4.0*i,0.0);
898 break;
900 pd = (double)g->Lilanek[i].Ammo[g->Lilanek[i].ActiveWeapon]/(double)g->WeaponTemplate[g->Lilanek[i].ActiveWeapon].MaxAmmo;
901 QueueDrawSpriteColorizeStretch(hud_ammo, 18.0-2.0*pd, 0.0+4.0*i,4.0*pd, 4.0, 2.0,c);
902 pd = (double)g->Lilanek[i].ReloadTime/(double)g->WeaponTemplate[g->Lilanek[i].ActiveWeapon].ReloadTime;
903 if(pd>1.0)pd=1.0;
904 QueueDrawSpriteColorizeStretch(hud_reload, 18.0-2.0*pd, 0.0+4.0*i,4.0*pd, 4.0, 2.0,c);
906 //Weapons
907 for(i=0; i < g->noWeapons; i++)
908 if(g->Weapon[i].Exists)
909 switch(g->Weapon[i].WID){
910 case 0: QueueDrawSprite(brok, g->Weapon[i].Pos.x - 1.0, g->Weapon[i].Pos.y - 1.0,1.0);
911 break;
912 case 1: QueueDrawSprite(mines, g->Weapon[i].Pos.x - 1.0, g->Weapon[i].Pos.y - 1.0,1.0);
913 break;
914 case 2: QueueDrawSprite(kul, g->Weapon[i].Pos.x - 1.0, g->Weapon[i].Pos.y - 1.0,1.0);
915 break;
918 for(i=0; i < g->noBullets; i++)
919 if(g->Bullet[i].Exists)
920 switch(g->Bullet[i].WID){
921 case 0: QueueDrawSprite(kulka, g->Bullet[i].Pos.x - 1.0, g->Bullet[i].Pos.y - 1.0,1.0);break;
922 case 1: QueueDrawSprite(mine, g->Bullet[i].Pos.x - 1.0, g->Bullet[i].Pos.y - 1.0,1.0);break;
923 case 2: QueueDrawSprite(kulka, g->Bullet[i].Pos.x - 1.0, g->Bullet[i].Pos.y - 1.0,1.0);break;
924 case -1: QueueDrawSprite(explo, g->Bullet[i].Pos.x - 1.0, g->Bullet[i].Pos.y - 1.0,1.0);break;
929 int InitAll(Game **g){
930 Config conf;
931 conf = GetConfig();
932 SaveConfig();
933 //TODO: odstranit SaveConfig... je to tu jenom kvuli debugovani
936 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER |SDL_INIT_AUDIO ) < 0) {
937 fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());
938 return 1;
940 atexit(onExit);
942 InitBase();
943 GrInit();
944 SoundInit();
945 *g = testgame();
946 lil[0] = LoadSpriteSVG("graphics/lil.svg", 1.0, 1.0);
947 lil[1] = LoadSpriteSVG("graphics/lilb.svg", 1.0, 1.0);
948 lil[2] = LoadSpriteSVG("graphics/lill.svg", 1.0, 1.0);
949 lil[3] = LoadSpriteSVG("graphics/lil.svg", 1.0, 1.0);
950 lil[4] = LoadSpriteSVG("graphics/lilr.svg", 1.0, 1.0);
951 (*g)->Map->Sprites[0] = LoadSpriteSVG("graphics/prek1.svg", 3.0, 3.0);
952 (*g)->Map->Sprites[1] = LoadSpriteSVG("graphics/prek2.svg", 4.0, 4.0);
953 (*g)->Map->Sprites[0]->z = 1;
954 (*g)->Map->Sprites[1]->z = 1;
955 bg=0;
956 bg = LoadSpriteSVG("graphics/bg.svg", 16.0, 15.0);
957 kul = LoadSpriteSVG("graphics/kul.svg", 0.5, 0.5);
958 explo = LoadSpriteSVG("graphics/exp.svg", 0.5, 0.5);
959 brok = LoadSpriteSVG("graphics/brok.svg", 0.5, 0.5);
960 kulka = LoadSpriteSVG("graphics/kulka.svg", 0.1, 0.1);
961 mine = LoadSpriteSVG("graphics/mine.svg", 0.5, 0.5);
962 mines = LoadSpriteSVG("graphics/mines.svg", 0.5, 0.5);
963 hud = LoadSpriteSVG("graphics/hud.svg", 4.0, 4.0);
964 hud_mine = LoadSpriteSVG("graphics/mines.svg", 2.2, 2.2);
965 hud_kul = LoadSpriteSVG("graphics/kul.svg", 2.2, 2.2);
966 hud_brok = LoadSpriteSVG("graphics/brok.svg", 2.2, 2.2);
967 hud_ammo = LoadSpriteSVG("graphics/hud_ammo.svg", 4.0, 4.0);
968 hud_reload = LoadSpriteSVG("graphics/hud_reload.svg", 4.0, 4.0);
970 s_die = LoadSound("sounds/die.wav");
971 s_bonus = LoadSound("sounds/bonus.wav");
972 s_expl = LoadSound("sounds/expl.wav");
973 s_shoot = LoadSound("sounds/shoot.wav");
974 s_mine = LoadSound("sounds/mine.wav");
976 SDL_AddTimer(1000, callback_fps, NULL);
978 return 0;
981 int GameLoop(Game *g){
982 SDL_Event event;
983 Config conf;
984 double lasttime, dtime;
986 lasttime = SDL_GetTicks()*0.001;
987 while (1) {
988 while (SDL_PollEvent(&event)) {
989 switch (event.type) {
990 case SDL_KEYDOWN:
991 if (event.key.keysym.sym == SDLK_q) {
992 return 0;
994 break;
996 case SDL_QUIT:
997 return 0;
998 break;
1000 case SDL_VIDEORESIZE:
1001 /* Resize the screen and redraw */
1002 conf=GetConfig();
1003 conf.screen_width=event.resize.w;
1004 conf.screen_height=event.resize.h;
1005 SetConfig(conf);
1007 InvalidateSprites();
1008 break;
1010 case SDL_USEREVENT:
1011 printf("%d frames\n",frames);
1012 frames=0;
1013 break;
1015 default:
1016 break;
1019 dtime = SDL_GetTicks()*0.001-lasttime;
1020 lasttime += dtime;
1021 if(dtime < 0)
1022 dtime=0.0;
1023 if(dtime > 0.1)
1024 dtime=0.1;
1025 UpdateLogic(g, dtime*0.5);
1026 UpdateLogic(g, dtime*0.5);
1027 ClrScr();
1028 Draw(g);
1029 UpdateAndQueueDrawParticles(dtime);
1030 DrawSprites();
1031 frames++;
1032 //we don't want to waste cpu...
1033 if(frames >=50){
1034 SDL_Delay(10);
1037 return 0;
1040 int main(int argc, char **argv){
1041 Game *g;
1042 srand(time(0));
1043 InitAll(&g);
1044 GameLoop(g);
1045 return 0;