36eb7a3fadabd79a832085589ffa20358676162f
[supertux.git] / src / badguy.cpp
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 #include <math.h>
13
14 #include "globals.h"
15 #include "defines.h"
16 #include "badguy.h"
17 #include "scene.h"
18 #include "screen.h"
19 #include "world.h"
20 #include "tile.h"
21
22 texture_type img_bsod_squished_left[1];
23 texture_type img_bsod_squished_right[1];
24 texture_type img_bsod_falling_left[1];
25 texture_type img_bsod_falling_right[1];
26 texture_type img_laptop_flat_left[1];
27 texture_type img_laptop_flat_right[1];
28 texture_type img_laptop_falling_left[1];
29 texture_type img_laptop_falling_right[1];
30 texture_type img_bsod_left[4];
31 texture_type img_bsod_right[4];
32 texture_type img_laptop_left[4];
33 texture_type img_laptop_right[4];
34 texture_type img_money_left[2];
35 texture_type img_money_right[2];
36 texture_type img_mrbomb_left[4];
37 texture_type img_mrbomb_right[4];
38 texture_type img_mrbomb_ticking_left[1];
39 texture_type img_mrbomb_ticking_right[1];
40 texture_type img_mrbomb_explosion[1];
41 texture_type img_stalactite[1];
42 texture_type img_stalactite_broken[1];
43 texture_type img_flame[2];
44 texture_type img_fish[2];
45 texture_type img_bouncingsnowball_left[6];
46 texture_type img_bouncingsnowball_right[6];
47 texture_type img_bouncingsnowball_squished[1];
48 texture_type img_flyingsnowball[2];
49 texture_type img_flyingsnowball_squished[1];
50 texture_type img_spiky_left[3];
51 texture_type img_spiky_right[3];
52 texture_type img_snowball_left[4];
53 texture_type img_snowball_right[4];
54 texture_type img_snowball_squished_left[1];
55 texture_type img_snowball_squished_right[1];
56
57 BadGuyKind  badguykind_from_string(const std::string& str)
58 {
59   if (str == "money")
60     return BAD_MONEY;
61   else if (str == "laptop" || str == "mriceblock")
62     return BAD_LAPTOP;
63   else if (str == "bsod")
64     return BAD_BSOD;
65   else if (str == "mrbomb")
66     return BAD_MRBOMB;
67   else if (str == "stalactite")
68     return BAD_STALACTITE;
69   else if (str == "flame")
70     return BAD_FLAME;
71   else if (str == "fish")
72     return BAD_FISH;
73   else if (str == "bouncingsnowball")
74     return BAD_BOUNCINGSNOWBALL;
75   else if (str == "flyingsnowball")
76     return BAD_FLYINGSNOWBALL;
77   else if (str == "spiky")
78     return BAD_SPIKY;
79   else if (str == "snowball")
80     return BAD_SNOWBALL;
81   else
82     {
83       printf("Couldn't convert badguy: '%s'\n", str.c_str());
84       return BAD_BSOD;
85     }
86 }
87
88 std::string badguykind_to_string(BadGuyKind kind)
89 {
90   switch(kind)
91     {
92     case BAD_MONEY:
93       return "money";
94       break;
95     case BAD_LAPTOP:
96       return "laptop";
97       break;
98     case BAD_BSOD:
99       return "bsod";
100       break;
101     case BAD_MRBOMB:
102       return "mrbomb";
103       break;
104     case BAD_STALACTITE:
105       return "stalactite";
106       break;
107     case BAD_FLAME:
108       return "flame";
109       break;
110     case BAD_FISH:
111       return "fish";
112       break;
113     case BAD_BOUNCINGSNOWBALL:
114       return "bouncingsnowball";
115       break;
116     case BAD_FLYINGSNOWBALL:
117       return "flyingsnowball";
118       break;
119     case BAD_SPIKY:
120       return "spiky";
121       break;
122     case BAD_SNOWBALL:
123       return "snowball";
124       break;
125     default:
126       return "bsod";
127     }
128 }
129
130 void
131 BadGuy::init(float x, float y, BadGuyKind kind_)
132 {
133   base.x   = x;
134   base.y   = y;    
135   base.width  = 0;
136   base.height = 0;
137   base.xm  = 0;
138   base.ym  = 0;
139
140   mode     = NORMAL;
141   dying    = DYING_NOT;
142   kind     = kind_;
143   old_base = base;
144   dir      = LEFT;
145   seen     = false;
146   animation_speed = 1;
147   animation_length = 1;
148   animation_offset = 0;
149   texture_left = texture_right = 0;
150   physic.reset();
151   timer_init(&timer, true);
152
153   if(kind == BAD_BSOD) {
154     physic.set_velocity(-1.3, 0);
155     set_texture(img_bsod_left, img_bsod_right, 4);
156   } else if(kind == BAD_MRBOMB) {
157     physic.set_velocity(-1.3, 0);
158     set_texture(img_mrbomb_left, img_mrbomb_right, 4);
159   } else if (kind == BAD_LAPTOP) {
160     physic.set_velocity(-1.3, 0);
161     set_texture(img_laptop_left, img_laptop_right, 4, 5);
162   } else if(kind == BAD_MONEY) {
163     set_texture(img_money_left, img_money_right, 1);
164   } else if(kind == BAD_BOMB) {
165     set_texture(img_mrbomb_ticking_left, img_mrbomb_ticking_right, 1);
166     // hack so that the bomb doesn't hurt until it expldes...
167     dying = DYING_SQUISHED;
168   } else if(kind == BAD_FLAME) {
169     base.ym = 0; // we misuse base.ym as angle for the flame
170     physic.enable_gravity(false);
171     set_texture(img_flame, img_flame, 2, 0.5);
172   } else if(kind == BAD_BOUNCINGSNOWBALL) {
173     physic.set_velocity(-1.3, 0);
174     set_texture(img_bouncingsnowball_left, img_bouncingsnowball_right, 6);
175   } else if(kind == BAD_STALACTITE) {
176     physic.enable_gravity(false);
177     set_texture(img_stalactite, img_stalactite, 1);
178   } else if(kind == BAD_FISH) {
179     set_texture(img_fish, img_fish, 2, 1);
180     physic.enable_gravity(true);
181   } else if(kind == BAD_FLYINGSNOWBALL) {
182     set_texture(img_flyingsnowball, img_flyingsnowball, 2, 5);
183     physic.enable_gravity(false);
184   } else if(kind == BAD_SPIKY) {
185     physic.set_velocity(-1.3, 0);
186     set_texture(img_spiky_left, img_spiky_right, 3);
187   } else if(kind == BAD_SNOWBALL) {
188     physic.set_velocity(-1.3, 0);
189     set_texture(img_snowball_left, img_snowball_right, 4, 5);
190   }
191
192   // if we're in a solid tile at start correct that now
193   if(kind != BAD_FLAME && kind != BAD_FISH && collision_object_map(&base)) {
194     printf("Warning: badguy started in wall!.\n");
195     while(collision_object_map(&base))
196       --base.y;
197   }
198 }
199
200 void
201 BadGuy::action_bsod()
202 {
203   static const float BSODJUMP = 2;
204     
205   if (dying == DYING_NOT)
206     check_horizontal_bump();
207
208   fall();
209
210   // jump when we're about to fall
211   if (physic.get_velocity_y() == 0 && 
212           !issolid(base.x+base.width/2, base.y + base.height)) {
213     physic.enable_gravity(true);
214     physic.set_velocity(physic.get_velocity_x(), BSODJUMP);
215   }
216
217   // Handle dying timer:
218   if (dying == DYING_SQUISHED && !timer_check(&timer))       
219     {
220       /* Remove it if time's up: */
221       remove_me();
222       return;
223     }
224
225   // move
226   physic.apply(base.x, base.y);
227   if(dying != DYING_FALLING)
228     collision_swept_object_map(&old_base, &base);
229 }
230
231 void
232 BadGuy::action_laptop()
233 {
234   Player& tux = *World::current()->get_tux();
235
236   fall();
237   
238   /* Move left/right: */
239   if (mode == NORMAL || mode == KICK)
240     {
241       // move
242       physic.apply(base.x, base.y);
243       if (dying != DYING_FALLING)
244         collision_swept_object_map(&old_base,&base);
245     }
246   else if (mode == HELD)
247     { /* FIXME: The pbad object shouldn't know about pplayer objects. */
248       /* If we're holding the laptop */
249       dir = tux.dir;
250       if(dir==RIGHT)
251         {
252           base.x = tux.base.x + 16;
253           base.y = tux.base.y + tux.base.height/1.5 - base.height;
254         }
255       else /* facing left */
256         {
257           base.x = tux.base.x - 16;
258           base.y = tux.base.y + tux.base.height/1.5 - base.height;
259         }
260       if(collision_object_map(&base))
261         {
262           base.x = tux.base.x;
263           base.y = tux.base.y + tux.base.height/1.5 - base.height;
264         }
265
266       if(tux.input.fire != DOWN) /* SHOOT! */
267         {
268           if(dir == LEFT)
269             base.x -= 24;
270           else
271             base.x += 24;
272
273           mode=KICK;
274           set_texture(img_laptop_flat_left, img_laptop_flat_right, 1);
275           physic.set_velocity((dir == LEFT) ? -8 : 8, -8);
276           play_sound(sounds[SND_KICK],SOUND_CENTER_SPEAKER);
277         }
278     }
279
280   if (!dying)
281     {
282       int changed = dir;
283       check_horizontal_bump();
284       if(mode == KICK && changed != dir)
285         {
286           /* handle stereo sound (number 10 should be tweaked...)*/
287           if (base.x < scroll_x + screen->w/2 - 10)
288             play_sound(sounds[SND_RICOCHET], SOUND_LEFT_SPEAKER);
289           else if (base.x > scroll_x + screen->w/2 + 10)
290             play_sound(sounds[SND_RICOCHET], SOUND_RIGHT_SPEAKER);
291           else
292             play_sound(sounds[SND_RICOCHET], SOUND_CENTER_SPEAKER);
293         }
294     }
295
296   /* Handle mode timer: */
297   if (mode == FLAT)
298     {
299       if(!timer_check(&timer))
300         {
301           mode = NORMAL;
302           set_texture(img_laptop_left, img_laptop_right, 4, 5);
303           physic.set_velocity( (dir == LEFT) ? -1.3 : 1.3, 0);
304         }
305     }
306 }
307
308 void
309 BadGuy::check_horizontal_bump(bool checkcliff)
310 {
311     float halfheight = base.height / 2;
312     if (dir == LEFT && issolid( base.x, (int) base.y + halfheight))
313     {
314         dir = RIGHT;
315         physic.set_velocity(-physic.get_velocity_x(), physic.get_velocity_y());
316         return;
317     }
318     if (dir == RIGHT && issolid( base.x + base.width, (int)base.y + halfheight))
319     {
320         dir = LEFT;
321         physic.set_velocity(-physic.get_velocity_x(), physic.get_velocity_y());
322         return;
323     }
324
325     // don't check for cliffs when we're falling
326     if(!checkcliff)
327         return;
328     if(!issolid(base.x + base.width/2, base.y + base.height))
329         return;
330     
331     if(dir == LEFT && !issolid(base.x, (int) base.y + base.height + halfheight))
332     {
333         dir = RIGHT;
334         physic.set_velocity(-physic.get_velocity_x(), physic.get_velocity_y());
335         return;
336     }
337     if(dir == RIGHT && !issolid(base.x + base.width,
338                 (int) base.y + base.height + halfheight))
339     {
340         dir = LEFT;
341         physic.set_velocity(-physic.get_velocity_x(), physic.get_velocity_y());
342         return;
343     }
344 }
345
346 void
347 BadGuy::fall()
348 {
349   /* Fall if we get off the ground: */
350   if (dying != DYING_FALLING)
351     {
352       if (!issolid(base.x+base.width/2, base.y + base.height))
353         {
354           // not solid below us? enable gravity
355           physic.enable_gravity(true);
356         }
357       else
358         {
359           /* Land: */
360           if (physic.get_velocity_y() < 0)
361             {
362               base.y = int((base.y + base.height)/32) * 32 - base.height;
363               physic.set_velocity(physic.get_velocity_x(), 0);
364             }
365           // no gravity anymore please
366           physic.enable_gravity(false);
367         }
368     }
369   else
370     {
371       physic.enable_gravity(true);
372     }
373 }
374
375 void
376 BadGuy::remove_me()
377 {
378   for(std::vector<BadGuy>::iterator i = World::current()->bad_guys.begin(); 
379       i != World::current()->bad_guys.end(); ++i) 
380     {
381       if( & (*i) == this) {
382         World::current()->bad_guys.erase(i);
383         return;
384       }
385     }
386 }
387
388 void
389 BadGuy::action_money()
390 {
391   Player& tux = *World::current()->get_tux();
392
393   static const float JUMPV = 6;
394     
395   fall();
396   // jump when on ground
397   if(dying == DYING_NOT && issolid(base.x, base.y+32))
398     {
399       physic.set_velocity(physic.get_velocity_x(), JUMPV);
400       physic.enable_gravity(true);
401       set_texture(&img_money_left[1], &img_money_right[1], 1);
402       mode = MONEY_JUMP;
403     }
404   else if(mode == MONEY_JUMP)
405     {
406       set_texture(&img_money_left[0], &img_money_right[0], 1);
407       mode = NORMAL;
408     }
409
410   // set direction based on tux
411   if(tux.base.x > base.x)
412     dir = RIGHT;
413   else
414     dir = LEFT;
415
416   // move
417   physic.apply(base.x, base.y);
418   if(dying == DYING_NOT)
419     collision_swept_object_map(&old_base, &base);
420 }
421
422 void
423 BadGuy::action_mrbomb()
424 {
425   if (dying == DYING_NOT)
426     check_horizontal_bump(true);
427
428   fall();
429
430   physic.apply(base.x, base.y);
431   if (dying != DYING_FALLING)
432     collision_swept_object_map(&old_base,&base); 
433 }
434
435 void
436 BadGuy::action_bomb()
437 {
438   static const int TICKINGTIME = 1000;
439   static const int EXPLODETIME = 1000;
440     
441   fall();
442
443   if(mode == NORMAL) {
444     mode = BOMB_TICKING;
445     timer_start(&timer, TICKINGTIME);
446   } else if(!timer_check(&timer)) {
447     if(mode == BOMB_TICKING) {
448       mode = BOMB_EXPLODE;
449       set_texture(img_mrbomb_explosion, img_mrbomb_explosion, 1);
450       dying = DYING_NOT; // now the bomb hurts
451       timer_start(&timer, EXPLODETIME);
452     } else if(mode == BOMB_EXPLODE) {
453       remove_me();
454       return;
455     }
456   }
457
458   // move
459   physic.apply(base.x, base.y);                 
460   collision_swept_object_map(&old_base,&base);
461 }
462
463 void
464 BadGuy::action_stalactite()
465 {
466   Player& tux = *World::current()->get_tux();
467
468   static const int SHAKETIME = 800;
469   static const int RANGE = 40;
470     
471   if(mode == NORMAL) {
472     // start shaking when tux is below the stalactite and at least 40 pixels
473     // near
474     if(tux.base.x + 32 > base.x - RANGE && tux.base.x < base.x + 32 + RANGE
475             && tux.base.y + tux.base.height > base.y) {
476       timer_start(&timer, SHAKETIME);
477       mode = STALACTITE_SHAKING;
478     }
479   } if(mode == STALACTITE_SHAKING) {
480     base.x = old_base.x + (rand() % 6) - 3; // TODO this could be done nicer...
481     if(!timer_check(&timer)) {
482       mode = STALACTITE_FALL;
483     }
484   } else if(mode == STALACTITE_FALL) {
485     fall();
486     /* Destroy if we collides with land */
487     if(issolid(base.x+base.width/2, base.y+base.height))
488     {
489       timer_start(&timer, 2000);
490       dying = DYING_SQUISHED;
491       mode = FLAT;
492       set_texture(img_stalactite_broken, img_stalactite_broken, 1);
493     }
494   } else if(mode == FLAT) {
495     fall();
496   }
497
498   // move
499   physic.apply(base.x, base.y);
500
501   if(dying == DYING_SQUISHED && !timer_check(&timer))
502     remove_me();
503 }
504
505 void
506 BadGuy::action_flame()
507 {
508     static const float radius = 100;
509     static const float speed = 0.02;
510     base.x = old_base.x + cos(base.ym) * radius;
511     base.y = old_base.y + sin(base.ym) * radius;
512
513     base.ym = fmodf(base.ym + frame_ratio * speed, 2*M_PI);
514 }
515
516 void
517 BadGuy::action_fish()
518 {
519   static const float JUMPV = 6;
520   static const int WAITTIME = 1000;
521     
522   // go in wait mode when back in water
523   if(dying == DYING_NOT && gettile(base.x, base.y+ base.height)->water
524         && physic.get_velocity_y() <= 0 && mode == NORMAL)
525     {
526       mode = FISH_WAIT;
527       set_texture(0, 0);
528       physic.set_velocity(0, 0);
529       physic.enable_gravity(false);
530       timer_start(&timer, WAITTIME);
531     }
532   else if(mode == FISH_WAIT && !timer_check(&timer))
533     {
534       // jump again
535       set_texture(img_fish, img_fish, 2, 1.5);
536       animation_offset = global_frame_counter; // restart animation
537       mode = NORMAL;
538       physic.set_velocity(0, JUMPV);
539       physic.enable_gravity(true);
540     }
541
542   physic.apply(base.x, base.y);
543   if(dying == DYING_NOT)
544     collision_swept_object_map(&old_base, &base);
545 }
546
547 void
548 BadGuy::action_bouncingsnowball()
549 {
550   static const float JUMPV = 4.5;
551     
552   fall();
553
554   // jump when on ground
555   if(dying == DYING_NOT && issolid(base.x, base.y+32))
556     {
557       physic.set_velocity(physic.get_velocity_x(), JUMPV);
558       physic.enable_gravity(true);
559     }                                                     
560   else
561     {
562       mode = NORMAL;
563     }
564
565   // check for right/left collisions
566   check_horizontal_bump();
567
568   physic.apply(base.x, base.y);
569   if(dying == DYING_NOT)
570     collision_swept_object_map(&old_base, &base);
571
572   // Handle dying timer:
573   if (dying == DYING_SQUISHED && !timer_check(&timer))       
574     {
575       /* Remove it if time's up: */
576       remove_me();
577       return;
578     }
579 }
580
581 void
582 BadGuy::action_flyingsnowball()
583 {
584   static const float FLYINGSPEED = 1;
585   static const int DIRCHANGETIME = 1000;
586     
587   // go into flyup mode if none specified yet
588   if(dying == DYING_NOT && mode == NORMAL) {
589     mode = FLY_UP;
590     physic.set_velocity(physic.get_velocity_x(), FLYINGSPEED);
591     timer_start(&timer, DIRCHANGETIME/2);
592   }
593
594   if(dying == DYING_NOT && !timer_check(&timer)) {
595     if(mode == FLY_UP) {
596       mode = FLY_DOWN;
597       physic.set_velocity(physic.get_velocity_x(), -FLYINGSPEED);
598     } else if(mode == FLY_DOWN) {
599       mode = FLY_UP;
600       physic.set_velocity(physic.get_velocity_x(), FLYINGSPEED);
601     }
602     timer_start(&timer, DIRCHANGETIME);
603   }
604
605   if(dying != DYING_NOT)
606     physic.enable_gravity(true);
607
608   physic.apply(base.x, base.y);
609   if(dying == DYING_NOT || dying == DYING_SQUISHED)
610     collision_swept_object_map(&old_base, &base);
611
612   // Handle dying timer:
613   if (dying == DYING_SQUISHED && !timer_check(&timer))       
614     {
615       /* Remove it if time's up: */
616       remove_me();
617       return;
618     }                                                          
619 }
620
621 void
622 BadGuy::action_spiky()
623 {
624   if (dying == DYING_NOT)
625     check_horizontal_bump();
626
627   fall();
628 #if 0
629   // jump when we're about to fall
630   if (physic.get_velocity_y() == 0 && 
631           !issolid(base.x+base.width/2, base.y + base.height)) {
632     physic.enable_gravity(true);
633     physic.set_velocity(physic.get_velocity_x(), 2);
634   }
635 #endif
636
637   physic.apply(base.x, base.y);
638   if (dying != DYING_FALLING)
639     collision_swept_object_map(&old_base,&base);   
640 }
641
642 void
643 BadGuy::action_snowball()
644 {
645   if (dying == DYING_NOT)
646     check_horizontal_bump();
647
648   fall();
649
650   physic.apply(base.x, base.y);
651   if (dying != DYING_FALLING)
652     collision_swept_object_map(&old_base,&base);
653 }
654
655 void
656 BadGuy::action()
657 {
658   // Remove if it's far off the screen:
659   if (base.x < scroll_x - OFFSCREEN_DISTANCE)
660     {
661       remove_me();                                                
662       return;
663     }
664
665   // BadGuy fall below the ground
666   if (base.y > screen->h) {
667     remove_me();
668     return;
669   }
670
671   // Once it's on screen, it's activated!
672   if (base.x <= scroll_x + screen->w + OFFSCREEN_DISTANCE)
673     seen = true;
674
675   if(!seen)
676     return;
677
678   switch (kind)
679     {
680     case BAD_BSOD:
681       action_bsod();
682       break;
683
684     case BAD_LAPTOP:
685       action_laptop();
686       break;
687   
688     case BAD_MONEY:
689       action_money();
690       break;
691
692     case BAD_MRBOMB:
693       action_mrbomb();
694       break;
695     
696     case BAD_BOMB:
697       action_bomb();
698       break;
699
700     case BAD_STALACTITE:
701       action_stalactite();
702       break;
703
704     case BAD_FLAME:
705       action_flame();
706       break;
707
708     case BAD_FISH:
709       action_fish();
710       break;
711
712     case BAD_BOUNCINGSNOWBALL:
713       action_bouncingsnowball();
714       break;
715
716     case BAD_FLYINGSNOWBALL:
717       action_flyingsnowball();
718       break;
719
720     case BAD_SPIKY:
721       action_spiky();
722       break;
723
724     case BAD_SNOWBALL:
725       action_snowball();
726       break;
727     }
728 }
729
730 void
731 BadGuy::draw()
732 {
733   // Don't try to draw stuff that is outside of the screen
734   if(base.x <= scroll_x - base.width || base.x >= scroll_x + screen->w)
735     return;
736   if(texture_left == 0 || texture_right == 0)
737     return;
738
739   float global_frame = (float(global_frame_counter - animation_offset) / 10);
740   global_frame *= animation_speed;
741   size_t frame = size_t(global_frame) % animation_length;
742   texture_type* texture = 
743       (dir == LEFT) ? &texture_left[frame] : &texture_right[frame];
744   texture_draw(texture, base.x - scroll_x, base.y);
745 }
746
747 void
748 BadGuy::set_texture(texture_type* left, texture_type* right,
749     int nanimlength, float nanimspeed)
750 {
751   if(left != 0) {
752     if(base.width == 0 && base.height == 0) {
753       base.width = left->w;
754       base.height = left->h;
755     } else if(base.width != left->w || base.height != left->h) {
756       base.x -= (left->w - base.width) / 2;
757       base.y -= left->h - base.height;
758       base.width = left->w;
759       base.height = left->h;
760       old_base = base;
761     }
762   } else {
763     base.width = base.height = 0;
764   }
765
766   animation_length = nanimlength;
767   animation_speed = nanimspeed;
768   animation_offset = 0;
769   texture_left = left;
770   texture_right = right;
771 }
772
773 void
774 BadGuy::bump()
775 {
776   if(kind == BAD_BSOD || kind == BAD_LAPTOP || kind == BAD_MRBOMB
777       || kind == BAD_BOUNCINGSNOWBALL) {
778     kill_me();
779   }
780 }
781
782 void
783 BadGuy::make_player_jump(Player* player)
784 {
785   player->physic.set_velocity(player->physic.get_velocity_x(), 2);
786   player->base.y = base.y - player->base.height - 2;
787 }
788
789 void
790 BadGuy::squish_me(Player* player)
791 {
792   make_player_jump(player);
793     
794   World::current()->add_score(base.x - scroll_x, base.y, 50 * score_multiplier);
795   play_sound(sounds[SND_SQUISH], SOUND_CENTER_SPEAKER);
796   score_multiplier++;
797
798   dying = DYING_SQUISHED;
799   timer_start(&timer, 2000);
800   physic.set_velocity(0, 0);
801 }
802
803 void
804 BadGuy::squish(Player* player)
805 {
806   if(kind == BAD_MRBOMB) {
807     // mrbomb transforms into a bomb now
808     World::current()->add_bad_guy(base.x, base.y, BAD_BOMB);
809     
810     make_player_jump(player);
811     World::current()->add_score(base.x - scroll_x, base.y, 50 * score_multiplier);
812     play_sound(sounds[SND_SQUISH], SOUND_CENTER_SPEAKER);
813     score_multiplier++;
814       
815     remove_me();
816     return;
817
818   } else if(kind == BAD_BSOD) {
819     squish_me(player);
820     set_texture(img_bsod_squished_left, img_bsod_squished_right, 1);
821     physic.set_velocity(0, physic.get_velocity_y());
822     return;
823       
824   } else if (kind == BAD_LAPTOP) {
825     if (mode == NORMAL || mode == KICK)
826       {
827         /* Flatten! */
828         play_sound(sounds[SND_STOMP], SOUND_CENTER_SPEAKER);
829         mode = FLAT;
830         set_texture(img_laptop_flat_left, img_laptop_flat_right, 1);
831         physic.set_velocity(0, physic.get_velocity_y());
832
833         timer_start(&timer, 4000);
834       } else if (mode == FLAT) {
835         /* Kick! */
836         play_sound(sounds[SND_KICK], SOUND_CENTER_SPEAKER);
837
838         if (player->base.x < base.x + (base.width/2)) {
839           physic.set_velocity(5, physic.get_velocity_y());
840           dir = RIGHT;
841         } else {
842           physic.set_velocity(-5, physic.get_velocity_y());
843           dir = LEFT;
844         }
845
846         mode = KICK;
847         set_texture(img_laptop_flat_left, img_laptop_flat_right, 1);
848       }
849
850     make_player_jump(player);
851               
852     World::current()->add_score(base.x - scroll_x, base.y, 25 * score_multiplier);
853     score_multiplier++;
854     return;
855   } else if(kind == BAD_FISH) {
856     make_player_jump(player);
857               
858     World::current()->add_score(base.x - scroll_x, base.y, 25 * score_multiplier);
859     score_multiplier++;
860      
861     // simply remove the fish...
862     remove_me();
863     return;
864   } else if(kind == BAD_BOUNCINGSNOWBALL) {
865     squish_me(player);
866     set_texture(img_bouncingsnowball_squished,img_bouncingsnowball_squished,1);
867     return;
868   } else if(kind == BAD_FLYINGSNOWBALL) {
869     squish_me(player);
870     set_texture(img_flyingsnowball_squished,img_flyingsnowball_squished,1);
871     return;
872   } else if(kind == BAD_SNOWBALL) {
873     squish_me(player);
874     set_texture(img_snowball_squished_left, img_snowball_squished_right, 1);
875     return;
876   }
877 }
878
879 void
880 BadGuy::kill_me()
881 {
882   if(kind == BAD_BOMB || kind == BAD_STALACTITE || kind == BAD_FLAME)
883     return;
884
885   dying = DYING_FALLING;
886   if(kind == BAD_LAPTOP)
887     set_texture(img_laptop_falling_left, img_laptop_falling_right, 1);
888   else if(kind == BAD_BSOD)
889     set_texture(img_bsod_falling_left, img_bsod_falling_right, 1);
890   
891   physic.enable_gravity(true);
892   physic.set_velocity(physic.get_velocity_x(), 0);
893
894   /* Gain some points: */
895   if (kind == BAD_BSOD)
896     World::current()->add_score(base.x - scroll_x, base.y,
897                     50 * score_multiplier);
898   else 
899     World::current()->add_score(base.x - scroll_x, base.y,                                 
900                     25 * score_multiplier);
901
902   /* Play death sound: */
903   play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
904 }
905
906 void
907 BadGuy::collision(void *p_c_object, int c_object, CollisionType type)
908 {
909   BadGuy* pbad_c    = NULL;
910
911   if(type == COLLISION_BUMP) {
912     bump();
913     return;
914   }
915   if(type == COLLISION_SQUISH) {
916     Player* player = static_cast<Player*>(p_c_object);
917     squish(player);
918     return;
919   }
920
921   switch (c_object)
922     {
923     case CO_BULLET:
924       kill_me();
925       break;
926
927     case CO_BADGUY:
928       pbad_c = (BadGuy*) p_c_object;
929       if(kind == BAD_LAPTOP && mode == KICK &&
930             pbad_c->kind != BAD_FLAME && pbad_c->kind != BAD_BOMB)
931         {
932           /* We're in kick mode, kill the other guy
933              and yourself(wuahaha) : */
934           pbad_c->kill_me();
935           kill_me();
936         }
937       break;
938     }
939 }
940
941 //---------------------------------------------------------------------------
942
943 void load_badguy_gfx()
944 {
945   /* (BSOD) */
946   texture_load(&img_bsod_left[0], datadir +
947                "/images/shared/bsod-left-0.png",
948                USE_ALPHA);
949
950   texture_load(&img_bsod_left[1], datadir +
951                "/images/shared/bsod-left-1.png",
952                USE_ALPHA);
953
954   texture_load(&img_bsod_left[2], datadir +
955                "/images/shared/bsod-left-2.png",
956                USE_ALPHA);
957
958   texture_load(&img_bsod_left[3], datadir +
959                "/images/shared/bsod-left-3.png",
960                USE_ALPHA);
961
962   texture_load(&img_bsod_right[0], datadir +
963                "/images/shared/bsod-right-0.png",
964                USE_ALPHA);
965
966   texture_load(&img_bsod_right[1], datadir +
967                "/images/shared/bsod-right-1.png",
968                USE_ALPHA);
969
970   texture_load(&img_bsod_right[2], datadir +
971                "/images/shared/bsod-right-2.png",
972                USE_ALPHA);
973
974   texture_load(&img_bsod_right[3], datadir +
975                "/images/shared/bsod-right-3.png",
976                USE_ALPHA);
977
978   texture_load(&img_bsod_squished_left[0], datadir +
979                "/images/shared/bsod-squished-left.png",
980                USE_ALPHA);
981
982   texture_load(&img_bsod_squished_right[0], datadir +
983                "/images/shared/bsod-squished-right.png",
984                USE_ALPHA);
985
986   texture_load(&img_bsod_falling_left[0], datadir +
987                "/images/shared/bsod-falling-left.png",
988                USE_ALPHA);
989
990   texture_load(&img_bsod_falling_right[0], datadir +
991                "/images/shared/bsod-falling-right.png",
992                USE_ALPHA);
993
994
995   /* (Laptop) */
996
997   texture_load(&img_laptop_left[0], datadir + "/images/shared/mriceblock-left-0.png", USE_ALPHA);
998   texture_load(&img_laptop_left[1], datadir + "/images/shared/mriceblock-left-1.png", USE_ALPHA);
999   texture_load(&img_laptop_left[2], datadir + "/images/shared/mriceblock-left-2.png", USE_ALPHA);
1000   texture_load(&img_laptop_left[3], datadir + "/images/shared/mriceblock-left-1.png", USE_ALPHA);
1001
1002   texture_load(&img_laptop_right[0], datadir + "/images/shared/mriceblock-right-0.png", USE_ALPHA);
1003   texture_load(&img_laptop_right[1], datadir + "/images/shared/mriceblock-right-1.png", USE_ALPHA);
1004   texture_load(&img_laptop_right[2], datadir + "/images/shared/mriceblock-right-2.png", USE_ALPHA);
1005   texture_load(&img_laptop_right[3], datadir + "/images/shared/mriceblock-right-1.png", USE_ALPHA);
1006   
1007   texture_load(&img_laptop_flat_left[0], 
1008                datadir + "/images/shared/laptop-flat-left.png",
1009                USE_ALPHA);
1010
1011   texture_load(&img_laptop_flat_right[0], datadir +
1012                "/images/shared/laptop-flat-right.png",
1013                USE_ALPHA);
1014
1015   texture_load(&img_laptop_falling_left[0], datadir +
1016                "/images/shared/laptop-falling-left.png",
1017                USE_ALPHA);
1018
1019   texture_load(&img_laptop_falling_right[0], datadir +
1020                "/images/shared/laptop-falling-right.png",
1021                USE_ALPHA);
1022
1023
1024   /* (Money) */
1025
1026   texture_load(&img_money_left[0], datadir +
1027                "/images/shared/bag-left-0.png",
1028                USE_ALPHA);
1029
1030   texture_load(&img_money_left[1], datadir +
1031                "/images/shared/bag-left-1.png",
1032                USE_ALPHA);
1033
1034   texture_load(&img_money_right[0], datadir +
1035                "/images/shared/bag-right-0.png",
1036                USE_ALPHA);
1037
1038   texture_load(&img_money_right[1], datadir +
1039                "/images/shared/bag-right-1.png",
1040                USE_ALPHA);
1041
1042   /* Mr. Bomb */
1043   for(int i=0; i<4; ++i) {
1044       char num[4];
1045       snprintf(num, 4, "%d", i);
1046       texture_load(&img_mrbomb_left[i],
1047               datadir + "/images/shared/mrbomb-left-" + num + ".png", USE_ALPHA);
1048       texture_load(&img_mrbomb_right[i],
1049               datadir + "/images/shared/mrbomb-right-" + num + ".png", USE_ALPHA);
1050   }
1051   texture_load(&img_mrbomb_ticking_left[0],
1052           datadir + "/images/shared/mrbombx-left-0.png", USE_ALPHA);
1053   texture_load(&img_mrbomb_ticking_right[0],
1054           datadir + "/images/shared/mrbombx-right-0.png", USE_ALPHA);
1055   texture_load(&img_mrbomb_explosion[0],
1056           datadir + "/images/shared/mrbomb-explosion.png", USE_ALPHA);
1057
1058   /* stalactite */
1059   texture_load(&img_stalactite[0], 
1060           datadir + "/images/shared/stalactite.png", USE_ALPHA);
1061   texture_load(&img_stalactite_broken[0],
1062           datadir + "/images/shared/stalactite-broken.png", USE_ALPHA);
1063
1064   /* flame */
1065   texture_load(&img_flame[0],
1066           datadir + "/images/shared/flame-0.png", USE_ALPHA);
1067   texture_load(&img_flame[1],
1068           datadir + "/images/shared/flame-1.png", USE_ALPHA);  
1069
1070   /* fish */
1071   texture_load(&img_fish[0],
1072           datadir + "/images/shared/fish-left-0.png", USE_ALPHA);
1073   texture_load(&img_fish[1],
1074           datadir + "/images/shared/fish-left-1.png", USE_ALPHA);
1075
1076   /* bouncing snowball */
1077   for(int i=0; i<6; ++i) {
1078       char num[4];
1079       snprintf(num, 4, "%d", i);
1080       texture_load(&img_bouncingsnowball_left[i],
1081               datadir + "/images/shared/bouncingsnowball-left-" + num + ".png",
1082               USE_ALPHA);
1083       texture_load(&img_bouncingsnowball_right[i],
1084               datadir + "/images/shared/bouncingsnowball-right-" + num + ".png",
1085               USE_ALPHA);
1086   } 
1087   texture_load(&img_bouncingsnowball_squished[0],
1088           datadir + "/images/shared/bsod-squished-left.png", USE_ALPHA);
1089
1090   /* flying snowball */
1091   texture_load(&img_flyingsnowball[0],
1092           datadir + "/images/shared/flyingsnowball-left-0.png", USE_ALPHA);
1093   texture_load(&img_flyingsnowball[1],
1094           datadir + "/images/shared/flyingsnowball-left-1.png", USE_ALPHA);  
1095   texture_load(&img_flyingsnowball_squished[0],
1096           datadir + "/images/shared/bsod-squished-left.png", USE_ALPHA);
1097
1098   /* spiky */
1099   for(int i = 0; i < 3; ++i) {
1100         char num[4];
1101         snprintf(num, 4, "%d", i);
1102         texture_load(&img_spiky_left[i],                                 
1103                 datadir + "/images/shared/spiky-left-" + num + ".png",   
1104                 USE_ALPHA);
1105         texture_load(&img_spiky_right[i],
1106                 datadir + "/images/shared/spiky-right-" + num + ".png",
1107                 USE_ALPHA);
1108   }
1109
1110   /** snowball */
1111   texture_load(&img_snowball_left[0], datadir + "/images/shared/snowball-left-0.png", USE_ALPHA);
1112   texture_load(&img_snowball_left[1], datadir + "/images/shared/snowball-left-1.png", USE_ALPHA);
1113   texture_load(&img_snowball_left[2], datadir + "/images/shared/snowball-left-2.png", USE_ALPHA);
1114   texture_load(&img_snowball_left[3], datadir + "/images/shared/snowball-left-1.png", USE_ALPHA);
1115
1116   texture_load(&img_snowball_right[0], datadir + "/images/shared/snowball-right-0.png", USE_ALPHA);
1117   texture_load(&img_snowball_right[1], datadir + "/images/shared/snowball-right-1.png", USE_ALPHA);
1118   texture_load(&img_snowball_right[2], datadir + "/images/shared/snowball-right-2.png", USE_ALPHA);
1119   texture_load(&img_snowball_right[3], datadir + "/images/shared/snowball-right-1.png", USE_ALPHA);
1120
1121   texture_load(&img_snowball_squished_left[0],
1122           datadir + "/images/shared/bsod-squished-left.png", USE_ALPHA);
1123   texture_load(&img_snowball_squished_right[0],
1124           datadir + "/images/shared/bsod-squished-right.png", USE_ALPHA);  
1125 }
1126
1127 void free_badguy_gfx()
1128 {
1129   for (int i = 0; i < 4; i++)
1130     {
1131       texture_free(&img_bsod_left[i]);
1132       texture_free(&img_bsod_right[i]);
1133     }
1134
1135   texture_free(&img_bsod_squished_left[0]);
1136   texture_free(&img_bsod_squished_right[0]);
1137
1138   texture_free(&img_bsod_falling_left[0]);
1139   texture_free(&img_bsod_falling_right[0]);
1140
1141   for (int i = 0; i < 4; i++)
1142     {
1143       texture_free(&img_laptop_left[i]);
1144       texture_free(&img_laptop_right[i]);
1145     }
1146
1147   texture_free(&img_laptop_flat_left[0]);
1148   texture_free(&img_laptop_flat_right[0]);
1149
1150   texture_free(&img_laptop_falling_left[0]);
1151   texture_free(&img_laptop_falling_right[0]);
1152
1153   for (int i = 0; i < 2; i++)
1154     {
1155       texture_free(&img_money_left[i]);
1156       texture_free(&img_money_right[i]);
1157     }
1158
1159   for(int i = 0; i < 4; i++) {
1160       texture_free(&img_mrbomb_left[i]);
1161       texture_free(&img_mrbomb_right[i]);
1162   }
1163
1164   texture_free(&img_mrbomb_ticking_left[0]);
1165   texture_free(&img_mrbomb_ticking_right[0]);
1166   texture_free(&img_mrbomb_explosion[0]);
1167
1168   texture_free(&img_stalactite[0]);
1169   texture_free(&img_stalactite_broken[0]);
1170
1171   texture_free(&img_flame[0]);
1172   texture_free(&img_flame[1]);
1173
1174   texture_free(&img_fish[0]);
1175   texture_free(&img_fish[1]);
1176
1177   for(int i=0; i<6; ++i) {
1178     texture_free(&img_bouncingsnowball_left[i]);
1179     texture_free(&img_bouncingsnowball_right[i]);
1180   }
1181   texture_free(&img_bouncingsnowball_squished[0]);
1182
1183   texture_free(&img_flyingsnowball[0]);
1184   texture_free(&img_flyingsnowball[1]);
1185   texture_free(&img_flyingsnowball_squished[0]);
1186
1187   for(int i = 0; i<3; ++i) {
1188     texture_free(&img_spiky_left[i]);
1189     texture_free(&img_spiky_right[i]);
1190   }
1191   for(int i = 0; i<4; ++i) {
1192     texture_free(&img_snowball_left[i]);
1193     texture_free(&img_snowball_right[i]);
1194   }
1195   texture_free(&img_snowball_squished_left[0]);
1196   texture_free(&img_snowball_squished_right[0]); 
1197 }
1198
1199 // EOF //