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