arrays are dynamic now, fixed bugs, more code cleanups
[supertux.git] / src / badguy.c
1 //
2 // C Implementation: badguy
3 //
4 // Description:
5 //
6 //
7 // Author: Tobias Glaesser <tobi.web@gmx.de>, (C) 2004
8 //
9 // Copyright: See COPYING file that comes with this distribution
10 //
11 //
12
13 #include "globals.h"
14 #include "defines.h"
15 #include "badguy.h"
16 #include "scene.h"
17 #include "screen.h"
18
19 void badguy_create_bitmasks()
20 {
21   /*bm_bsod = img_bsod_left[0];*/
22 }
23
24 void badguy_init(bad_guy_type* pbad)
25 {
26   pbad->base.updated = SDL_GetTicks();
27   pbad->base.alive = NO;
28   pbad->base.width = 32;
29   pbad->base.height = 32;
30
31 }
32
33 void badguy_action(bad_guy_type* pbad)
34 {
35
36   double frame_ratio = get_frame_ratio(&pbad->base);
37
38   if (pbad->base.alive)
39     {
40       if (pbad->seen)
41         {
42           if (pbad->kind == BAD_BSOD)
43             {
44               /* --- BLUE SCREEN OF DEATH MONSTER: --- */
45
46               /* Move left/right: */
47
48               if (pbad->dying == NO ||
49                   pbad->dying == FALLING)
50                 {
51                   if (pbad->dir == RIGHT)
52                     pbad->base.x = pbad->base.x + pbad->base.xm * frame_ratio;
53                   else if (pbad->dir == LEFT)
54                     pbad->base.x = pbad->base.x - pbad->base.xm * frame_ratio;
55                 }
56
57
58               /* Move vertically: */
59
60               pbad->base.y = pbad->base.y + pbad->base.ym * frame_ratio;
61
62
63               /* Bump into things horizontally: */
64
65               if (!pbad->dying)
66                 {
67                   if (issolid(pbad->base.x, pbad->base.y))
68                     pbad->dir = !pbad->dir;
69                 }
70
71               /* Fall if we get off the ground: */
72
73               if (pbad->dying != FALLING)
74                 {
75                   if (!issolid(pbad->base.x, pbad->base.y + 32) &&
76                       pbad->base.ym < MAX_YM)
77                     {
78                       pbad->base.ym = pbad->base.ym + GRAVITY;
79                     }
80                   else
81                     {
82                       /* Land: */
83
84                       if (pbad->base.ym > 0)
85                         {
86                           pbad->base.y = (int)(pbad->base.y / 32) * 32;
87                           pbad->base.ym = 0;
88                         }
89                     }
90                 }
91               else
92                 pbad->base.ym = pbad->base.ym + GRAVITY;
93
94               if (pbad->base.y > screen->h)
95                 pbad->base.alive = NO;
96             }
97           else if (pbad->kind == BAD_LAPTOP)
98             {
99               /* --- LAPTOP MONSTER: --- */
100
101               /* Move left/right: */
102
103               if (pbad->mode != KICK && pbad->mode != HELD)
104                 {
105                   if (pbad->dying == NO ||
106                       pbad->dying == FALLING)
107                     {
108                       if (pbad->dir == RIGHT)
109                         pbad->base.x = pbad->base.x + pbad->base.xm * frame_ratio;
110                       else if (pbad->dir == LEFT)
111                         pbad->base.x = pbad->base.x - pbad->base.xm * frame_ratio;
112                     }
113                 }
114               else if (pbad->mode == KICK)
115                 {
116                 /* Obsolete
117                   if (pbad->dir == RIGHT)
118                     pbad->base.x = pbad->base.x + 16;
119                   else if (pbad->dir == LEFT)
120                     pbad->base.x = pbad->base.x - 16;*/
121                 }
122               else if (pbad->mode == HELD)
123                 { /* FIXME: The pbad object shouldn't know about pplayer objects. */
124                   /* If we're holding the laptop */
125                   if(tux.dir==RIGHT)
126                     {
127                       pbad->base.x = tux.base.x - 16;
128                       pbad->base.y = tux.base.y - 8 - (tux.size*16);
129                     }
130                   else /* facing left */
131                     {
132                       pbad->base.x = tux.base.x - 16;
133                       pbad->base.y = tux.base.y - 8 - (tux.size*16);
134                     }
135
136                   if(tux.input.fire != DOWN) /* SHOOT! */
137                     {
138                       pbad->dir=tux.dir;
139                       pbad->mode=KICK;
140                       pbad->base.ym-=8;
141                       play_sound(sounds[SND_KICK],SOUND_CENTER_SPEAKER);
142                     }
143                 }
144
145
146               /* Move vertically: */
147
148               if(pbad->mode != HELD)
149                 pbad->base.y = pbad->base.y + pbad->base.ym * frame_ratio;
150
151               /* Bump into things horizontally: */
152
153               if (!pbad->dying)
154                 {
155                   if (issolid(pbad->base.x, pbad->base.y))
156                     {
157                       pbad->dir = !pbad->dir;
158
159                       if (pbad->mode == KICK)
160                         {
161                           /* handle stereo sound */
162                           /* FIXME: In theory a badguy object doesn't know anything about player objects */
163                           if (tux.base.x  > pbad->base.x)
164                             play_sound(sounds[SND_RICOCHET], SOUND_LEFT_SPEAKER);
165                           else if (tux.base.x  < pbad->base.x)
166                             play_sound(sounds[SND_RICOCHET], SOUND_RIGHT_SPEAKER);
167                           else
168                             play_sound(sounds[SND_RICOCHET], SOUND_CENTER_SPEAKER);
169                         }
170                     }
171                 }
172
173
174               /* Fall if we get off the ground: */
175
176               if (pbad->dying != FALLING)
177                 {
178                   if (!issolid(pbad->base.x, pbad->base.y + 32) &&
179                       pbad->base.ym < MAX_YM)
180                     {
181                       if(pbad->mode != HELD)
182                         pbad->base.ym = pbad->base.ym + GRAVITY;
183                     }
184                   else
185                     {
186                       /* Land: */
187
188                       if (pbad->base.ym > 0)
189                         {
190                           pbad->base.y = (int)(pbad->base.y / 32) * 32;
191                           pbad->base.ym = 0;
192                         }
193                     }
194                 }
195               else
196                 pbad->base.ym = pbad->base.ym + GRAVITY;
197
198               if (pbad->base.y > screen->h)
199                 pbad->base.alive = NO;
200             }
201           else if (pbad->kind == BAD_MONEY)
202             {
203               /* --- MONEY BAGS: --- */
204
205
206               /* Move vertically: */
207
208               pbad->base.y = pbad->base.y + pbad->base.ym *frame_ratio;
209
210
211               /* Fall if we get off the ground: */
212
213               if (pbad->dying != FALLING)
214                 {
215                   if (!issolid(pbad->base.x, pbad->base.y + 32))
216                     {
217                       if (pbad->base.ym < MAX_YM)
218                         {
219                           pbad->base.ym = pbad->base.ym + GRAVITY;
220                         }
221                     }
222                   else
223                     {
224                       /* Land: */
225
226                       if (pbad->base.ym > 0)
227                         {
228                           pbad->base.y = (int)(pbad->base.y / 32) * 32;
229                           pbad->base.ym = -MAX_YM;
230                         }
231                     }
232                 }
233               else
234                 pbad->base.ym = pbad->base.ym + GRAVITY;
235
236               if (pbad->base.y > screen->h)
237                 pbad->base.alive = NO;
238             }
239           else if (pbad->kind == -1)
240           {}
241
242         }
243       else if (pbad->kind == -1)
244       {}
245
246
247     }
248
249   /* Handle mode timer: */
250
251   if (pbad->mode == FLAT /* && bad_guys[1].mode != HELD*/)
252     {
253       if(!timer_check(&pbad->timer))
254         pbad->mode = NORMAL;
255     }
256   /* else if (pbad->mode == KICK)
257      {
258        if (pbad->timer > 0)
259          pbad->timer--;
260      }*/
261
262
263   /* Handle dying timer: */
264
265   if (pbad->dying == SQUISHED)
266     {
267       /* Remove it if time's up: */
268       if(!timer_check(&pbad->timer))
269         pbad->base.alive = NO;
270     }
271
272
273   /* Remove if it's far off the screen: */
274
275   if (pbad->base.x < scroll_x - OFFSCREEN_DISTANCE)
276     pbad->base.alive = NO;
277   else /* !seen */
278     {
279       /* Once it's on screen, it's activated! */
280
281       if (pbad->base.x <= scroll_x + screen->w + OFFSCREEN_DISTANCE)
282         pbad->seen = YES;
283     }
284   /*}*/
285 }
286
287 void badguy_draw(bad_guy_type* pbad)
288 {
289   if (pbad->base.alive &&
290       pbad->base.x > scroll_x - 32 &&
291       pbad->base.x < scroll_x + screen->w)
292     {
293       if (pbad->kind == BAD_BSOD)
294         {
295           /* --- BLUE SCREEN OF DEATH MONSTER: --- */
296
297           if (pbad->dying == NO)
298             {
299               /* Alive: */
300
301               if (pbad->dir == LEFT)
302                 {
303                   texture_draw(&img_bsod_left[(frame / 5) % 4],
304                                pbad->base.x - scroll_x,
305                                pbad->base.y,
306                                NO_UPDATE);
307                 }
308               else
309                 {
310                   texture_draw(&img_bsod_right[(frame / 5) % 4],
311                                pbad->base.x - scroll_x,
312                                pbad->base.y,
313                                NO_UPDATE);
314                 }
315             }
316           else if (pbad->dying == FALLING)
317             {
318               /* Falling: */
319
320               if (pbad->dir == LEFT)
321                 {
322                   texture_draw(&img_bsod_falling_left,
323                                pbad->base.x - scroll_x,
324                                pbad->base.y,
325                                NO_UPDATE);
326                 }
327               else
328                 {
329                   texture_draw(&img_bsod_falling_right,
330                                pbad->base.x - scroll_x,
331                                pbad->base.y,
332                                NO_UPDATE);
333                 }
334             }
335           else if (pbad->dying == SQUISHED)
336             {
337               /* Dying - Squished: */
338
339               if (pbad->dir == LEFT)
340                 {
341                   texture_draw(&img_bsod_squished_left,
342                                pbad->base.x - scroll_x,
343                                pbad->base.y + 24,
344                                NO_UPDATE);
345                 }
346               else
347                 {
348                   texture_draw(&img_bsod_squished_right,
349                                pbad->base.x - scroll_x,
350                                pbad->base.y + 24,
351                                NO_UPDATE);
352                 }
353             }
354         }
355       else if (pbad->kind == BAD_LAPTOP)
356         {
357           /* --- LAPTOP MONSTER: --- */
358
359           if (pbad->dying == NO)
360             {
361               /* Alive: */
362
363               if (pbad->mode == NORMAL)
364                 {
365                   /* Not flat: */
366
367                   if (pbad->dir == LEFT)
368                     {
369                       texture_draw(&img_laptop_left[(frame / 5) % 3],
370                                    pbad->base.x - scroll_x,
371                                    pbad->base.y,
372                                    NO_UPDATE);
373                     }
374                   else
375                     {
376                       texture_draw(&img_laptop_right[(frame / 5) % 3],
377                                    pbad->base.x - scroll_x,
378                                    pbad->base.y,
379                                    NO_UPDATE);
380                     }
381                 }
382               else
383                 {
384                   /* Flat: */
385
386                   if (pbad->dir == LEFT)
387                     {
388                       texture_draw(&img_laptop_flat_left,
389                                    pbad->base.x - scroll_x,
390                                    pbad->base.y,
391                                    NO_UPDATE);
392                     }
393                   else
394                     {
395                       texture_draw(&img_laptop_flat_right,
396                                    pbad->base.x - scroll_x,
397                                    pbad->base.y,
398                                    NO_UPDATE);
399                     }
400                 }
401             }
402           else if (pbad->dying == FALLING)
403             {
404               /* Falling: */
405
406               if (pbad->dir == LEFT)
407                 {
408                   texture_draw(&img_laptop_falling_left,
409                                pbad->base.x - scroll_x,
410                                pbad->base.y,
411                                NO_UPDATE);
412                 }
413               else
414                 {
415                   texture_draw(&img_laptop_falling_right,
416                                pbad->base.x - scroll_x,
417                                pbad->base.y,
418                                NO_UPDATE);
419                 }
420             }
421         }
422       else if (pbad->kind == BAD_MONEY)
423         {
424           if (pbad->base.ym > -16)
425             {
426               if (pbad->dir == LEFT)
427                 {
428                   texture_draw(&img_money_left[0],
429                                pbad->base.x - scroll_x,
430                                pbad->base.y,
431                                NO_UPDATE);
432                 }
433               else
434                 {
435                   texture_draw(&img_money_right[0],
436                                pbad->base.x - scroll_x,
437                                pbad->base.y,
438                                NO_UPDATE);
439                 }
440             }
441           else
442             {
443               if (pbad->dir == LEFT)
444                 {
445                   texture_draw(&img_money_left[1],
446                                pbad->base.x - scroll_x,
447                                pbad->base.y,
448                                NO_UPDATE);
449                 }
450               else
451                 {
452                   texture_draw(&img_money_right[1],
453                                pbad->base.x - scroll_x,
454                                pbad->base.y,
455                                NO_UPDATE);
456                 }
457             }
458         }
459       else if (pbad->kind == -1)
460       {}
461     }
462 }
463
464 void badguy_collision(bad_guy_type* pbad, void *p_c_object, int c_object)
465 {
466   bad_guy_type* pbad_c = NULL;
467   player_type* pplayer_c = NULL;
468
469   switch (c_object)
470     {
471     case CO_BULLET:
472       pbad->dying = FALLING;
473       pbad->base.ym = -8;
474
475       /* Gain some points: */
476
477       if (pbad->kind == BAD_BSOD)
478         add_score(pbad->base.x - scroll_x, pbad->base.y,
479                   50 * score_multiplier);
480       else if (pbad->kind == BAD_LAPTOP)
481         add_score(pbad->base.x - scroll_x, pbad->base.y,
482                   25 * score_multiplier);
483
484       /* Play death sound: */
485       play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
486       break;
487     case CO_BADGUY:
488       pbad_c = p_c_object;
489       if (pbad->mode != KICK)
490         pbad->dir = !pbad->dir;
491       else
492         {
493           /* We're in kick mode, kill the other guy: */
494
495           pbad_c->dying = FALLING;
496           pbad_c->base.ym = -8;
497           play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
498
499           add_score(pbad->base.x - scroll_x,
500                     pbad->base.y, 100);
501         }
502       pbad->dir = !pbad->dir;
503       break;
504     case CO_PLAYER:
505       pplayer_c = p_c_object;
506       if (pbad->kind == BAD_BSOD)
507         {
508           pbad->dying = SQUISHED;
509           timer_start(&pbad->timer,4000);
510           pplayer_c->base.ym = -KILL_BOUNCE_YM;
511
512           add_score(pbad->base.x - scroll_x, pbad->base.y,
513                     50 * score_multiplier);
514
515           play_sound(sounds[SND_SQUISH], SOUND_CENTER_SPEAKER);
516         }
517       else if (pbad->kind == BAD_LAPTOP)
518         {
519           if (pbad->mode != FLAT)
520             {
521               /* Flatten! */
522
523               play_sound(sounds[SND_STOMP], SOUND_CENTER_SPEAKER);
524               pbad->mode = FLAT;
525               pbad->base.xm = 4;
526
527               timer_start(&pbad->timer,10000);
528
529               pplayer_c->base.y = pplayer_c->base.y - 32;
530             }
531           else
532             {
533               /* Kick! */
534
535               pbad->mode = KICK;
536               play_sound(sounds[SND_KICK], SOUND_CENTER_SPEAKER);
537
538               if (pplayer_c->base.x <= pbad->base.x)
539                 pbad->dir = RIGHT;
540               else
541                 pbad->dir = LEFT;
542
543               timer_start(&pbad->timer,5000);
544             }
545
546           pplayer_c->base.ym = -KILL_BOUNCE_YM;
547
548           add_score(pbad->base.x - scroll_x,
549                     pbad->base.y,
550                     25 * score_multiplier);
551
552           /* play_sound(sounds[SND_SQUISH]); */
553         }
554       break;
555     }
556
557 }