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