2 // C Implementation: badguy
7 // Author: Tobias Glaesser <tobi.web@gmx.de> & Bill Kendrick, (C) 2004
9 // Copyright: See COPYING file that comes with this distribution
19 texture_type img_bsod_squished_left;
20 texture_type img_bsod_squished_right;
21 texture_type img_bsod_falling_left;
22 texture_type img_bsod_falling_right;
23 texture_type img_laptop_flat_left;
24 texture_type img_laptop_flat_right;
25 texture_type img_laptop_falling_left;
26 texture_type img_laptop_falling_right;
27 texture_type img_bsod_left[4];
28 texture_type img_bsod_right[4];
29 texture_type img_laptop_left[3];
30 texture_type img_laptop_right[3];
31 texture_type img_money_left[2];
32 texture_type img_money_right[2];
33 texture_type img_mrbomb_left[4];
34 texture_type img_mrbomb_right[4];
35 texture_type img_stalactite;
36 texture_type img_stalactite_broken;
38 BadGuyKind badguykind_from_string(const std::string& str)
42 else if (str == "laptop")
44 else if (str == "bsod")
46 else if (str == "mrbomb")
48 else if (str == "stalactite")
49 return BAD_STALACTITE;
52 printf("Couldn't convert badguy: %s\n", str.c_str());
57 std::string badguykind_to_string(BadGuyKind kind)
82 BadGuy::init(float x, float y, BadGuyKind kind_)
96 timer_init(&timer, true);
99 if(kind == BAD_BOMB) {
100 timer_start(&timer, 1000);
102 // hack so that the bomb doesn't hurt until it expldes...
103 dying = DYING_SQUISHED;
107 void BadGuy::action_bsod()
109 /* --- BLUE SCREEN OF DEATH MONSTER: --- */
111 /* Move left/right: */
112 if (dying == DYING_NOT ||
113 dying == DYING_FALLING)
115 base.x += base.xm * frame_ratio;
118 /* Move vertically: */
119 base.y = base.y + base.ym * frame_ratio;
121 if (dying != DYING_FALLING)
122 collision_swept_object_map(&old_base,&base);
125 check_horizontal_bump();
129 // Handle dying timer:
130 if (dying == DYING_SQUISHED)
132 /* Remove it if time's up: */
133 if(!timer_check(&timer)) {
140 void BadGuy::action_laptop()
142 /* Move left/right: */
143 if (mode == NORMAL || mode == KICK)
145 if (dying == DYING_NOT ||
146 dying == DYING_FALLING)
148 base.x += base.xm * frame_ratio;
151 else if (mode == HELD)
152 { /* FIXME: The pbad object shouldn't know about pplayer objects. */
153 /* If we're holding the laptop */
157 base.x = tux.base.x + 16;
158 base.y = tux.base.y + tux.base.height/1.5 - base.height;
160 else /* facing left */
162 base.x = tux.base.x - 16;
163 base.y = tux.base.y + tux.base.height/1.5 - base.height;
165 if(collision_object_map(&base))
168 base.y = tux.base.y + tux.base.height/1.5 - base.height;
171 if(tux.input.fire != DOWN) /* SHOOT! */
181 play_sound(sounds[SND_KICK],SOUND_CENTER_SPEAKER);
186 /* Move vertically: */
188 base.y = base.y + base.ym * frame_ratio;
190 if (dying != DYING_FALLING)
191 collision_swept_object_map(&old_base,&base);
192 /* Bump into things horizontally: */
197 check_horizontal_bump();
198 if(mode == KICK && changed != dir)
200 /* handle stereo sound (number 10 should be tweaked...)*/
201 if (base.x < scroll_x - 10)
202 play_sound(sounds[SND_RICOCHET], SOUND_LEFT_SPEAKER);
203 else if (base.x > scroll_x + 10)
204 play_sound(sounds[SND_RICOCHET], SOUND_RIGHT_SPEAKER);
206 play_sound(sounds[SND_RICOCHET], SOUND_CENTER_SPEAKER);
212 /* Handle mode timer: */
213 if (mode == FLAT && mode != HELD)
215 if(!timer_check(&timer))
221 else if (mode == KICK)
227 void BadGuy::check_horizontal_bump(bool checkcliff)
229 if (dir == LEFT && issolid( base.x, (int) base.y + 16))
235 if (dir == RIGHT && issolid( base.x + base.width, (int) base.y + 16))
242 // don't check for cliffs when we're falling
246 if(dir == LEFT && !issolid(base.x, (int) base.y + base.height + 16))
248 printf("Cliffcol left\n");
253 if(dir == RIGHT && !issolid(base.x + base.width,
254 (int) base.y + base.height + 16))
256 printf("Cliffcol right\n");
263 void BadGuy::fall(bool dojump)
265 /* Fall if we get off the ground: */
266 if (dying != DYING_FALLING)
268 if (!issolid(base.x+16, base.y + 32))
270 if(!physic_is_set(&physic))
272 physic_set_state(&physic,PH_VT);
273 physic_set_start_vy(&physic, dojump ? 2. : 0.);
278 base.ym = physic_get_velocity(&physic);
287 base.y = (int)(base.y / 32) * 32;
290 physic_init(&physic);
295 if(!physic_is_set(&physic))
297 physic_set_state(&physic,PH_VT);
298 physic_set_start_vy(&physic,0.);
300 base.ym = physic_get_velocity(&physic);
303 // BadGuy fall below the ground
304 if (base.y > screen->h) {
310 void BadGuy::remove_me()
312 std::vector<BadGuy>::iterator i;
313 for(i = bad_guys.begin(); i != bad_guys.end(); ++i) {
314 if( & (*i) == this) {
321 void BadGuy::action_money()
323 /* Move vertically: */
324 base.y = base.y + base.ym * frame_ratio;
326 if (dying != DYING_FALLING)
327 collision_swept_object_map(&old_base,&base);
329 if (base.y > screen->h) {
334 if(physic_get_state(&physic) == -1)
336 physic_set_state(&physic,PH_VT);
337 physic_set_start_vy(&physic,0.);
340 if (dying != DYING_FALLING)
343 if(issolid(base.x, base.y + 32))
345 physic_set_state(&physic,PH_VT);
346 physic_set_start_vy(&physic,6.);
347 base.ym = physic_get_velocity(&physic);
349 /* // matze: is this code needed?
350 else if(issolid(base.x, base.y))
351 { // This works, but isn't the best solution imagineable
352 physic_set_state(&physic,PH_VT);
353 physic_set_start_vy(&physic,0.);
354 base.ym = physic_get_velocity(&physic);
359 base.ym = physic_get_velocity(&physic);
364 if(!physic_is_set(&physic))
366 physic_set_state(&physic,PH_VT);
367 physic_set_start_vy(&physic,0.);
369 base.ym = physic_get_velocity(&physic);
373 void BadGuy::action_mrbomb()
376 base.x += base.xm * frame_ratio;
379 /* Move vertically: */
380 base.y += base.ym * frame_ratio;
382 if (dying != DYING_FALLING)
383 collision_swept_object_map(&old_base,&base);
385 check_horizontal_bump(true);
389 void BadGuy::action_bomb()
391 // eventually fall down
392 base.y += base.ym * frame_ratio;
393 collision_swept_object_map(&old_base,&base);
396 if(!timer_check(&timer)) {
397 if(mode == BOMB_TICKING) {
399 dying = DYING_NOT; // now the bomb hurts
400 timer_start(&timer, 1000);
401 } else if(mode == BOMB_EXPLODE) {
408 void BadGuy::action_stalactite()
411 if(tux.base.x + 32 > base.x - 40 && tux.base.x < base.x + 32 + 40) {
412 timer_start(&timer, 800);
413 mode = STALACTITE_SHAKING;
415 } if(mode == STALACTITE_SHAKING) {
416 base.x = old_base.x + (rand() % 6) - 3; // TODO this could be done nicer...
417 if(!timer_check(&timer)) {
418 mode = STALACTITE_FALL;
420 } else if(mode == STALACTITE_FALL) {
421 base.y += base.ym * frame_ratio;
422 /* Destroy if collides land */
423 if(issolid(base.x+16, base.y+32))
425 timer_start(&timer, 3000);
426 dying = DYING_SQUISHED;
466 // Remove if it's far off the screen:
467 if (base.x < scroll_x - OFFSCREEN_DISTANCE)
474 // Once it's on screen, it's activated!
475 if (base.x <= scroll_x + screen->w + OFFSCREEN_DISTANCE)
483 texture_type* texture = 0;
485 if(dying == DYING_NOT) {
486 size_t frame = (global_frame_counter / 5) % 4;
487 texture = (dir == LEFT) ? &img_bsod_left[frame] : &img_bsod_right[frame];
488 } else if(dying == DYING_FALLING) {
489 texture = (dir == LEFT) ? &img_bsod_falling_left : &img_bsod_falling_right;
490 } else if(dying == DYING_SQUISHED) {
491 texture = (dir == LEFT)
492 ? &img_bsod_squished_left : &img_bsod_squished_right;
496 texture_draw(texture, base.x - scroll_x, y);
500 BadGuy::draw_laptop()
502 texture_type* texture;
503 size_t frame = (global_frame_counter / 5) % 3;
505 if(dying == DYING_NOT) {
508 texture = &img_laptop_left[frame];
510 texture = &img_laptop_right[frame];
512 texture = (dir == LEFT) ? &img_laptop_flat_left : &img_laptop_flat_right;
515 texture = (dir == LEFT)
516 ? &img_laptop_falling_left : &img_laptop_falling_right;
519 texture_draw(texture, base.x - scroll_x, base.y);
525 texture_type* texture;
526 size_t frame = (base.ym != 300) ? 0 : 1;
528 if(tux.base.x + tux.base.width < base.x) {
529 texture = &img_money_left[frame];
531 texture = &img_money_right[frame];
534 texture_draw(texture, base.x - scroll_x, base.y);
538 BadGuy::draw_mrbomb()
540 texture_type* texture;
541 size_t frame = (global_frame_counter/5) % 4;
544 texture = &img_mrbomb_left[frame];
546 texture = &img_mrbomb_right[frame];
548 texture_draw(texture, base.x - scroll_x, base.y);
554 texture_type* texture;
556 // TODO add real bomb graphics
557 if(mode == BOMB_TICKING) {
558 texture = &img_bsod_squished_right;
560 texture = &img_bsod_squished_left;
563 texture_draw(texture, base.x - scroll_x, base.y);
567 BadGuy::draw_stalactite()
569 texture_type* texture;
571 texture = &img_stalactite;
573 texture = &img_stalactite_broken;
575 texture_draw(texture, base.x - scroll_x, base.y);
581 // Don't try to draw stuff that is outside of the screen
582 if (base.x > scroll_x - 32 &&
583 base.x < scroll_x + screen->w)
617 if(kind == BAD_BSOD || kind == BAD_LAPTOP || kind == BAD_BOMB) {
618 dying = DYING_FALLING;
620 play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
625 BadGuy::make_player_jump(Player* player)
627 physic_set_state(&player->vphysic,PH_VT);
628 physic_set_start_vy(&player->vphysic,2.);
629 player->base.y = base.y - player->base.height - 1;
633 BadGuy::squich(Player* player)
635 if(kind == BAD_MRBOMB) {
636 // mrbomb transforms into a bomb now
637 add_bad_guy(base.x, base.y, BAD_BOMB);
639 make_player_jump(player);
640 add_score(base.x - scroll_x, base.y, 50 * score_multiplier);
641 play_sound(sounds[SND_SQUISH], SOUND_CENTER_SPEAKER);
647 } else if(kind == BAD_BSOD) {
648 dying = DYING_SQUISHED;
649 timer_start(&timer,4000);
651 make_player_jump(player);
653 add_score(base.x - scroll_x, base.y, 50 * score_multiplier);
654 play_sound(sounds[SND_SQUISH], SOUND_CENTER_SPEAKER);
658 } else if (kind == BAD_LAPTOP) {
659 if (mode == NORMAL || mode == KICK)
662 play_sound(sounds[SND_STOMP], SOUND_CENTER_SPEAKER);
666 timer_start(&timer, 4000);
667 } else if (mode == FLAT) {
669 play_sound(sounds[SND_KICK], SOUND_CENTER_SPEAKER);
671 if (player->base.x < base.x + (base.width/2))
679 timer_start(&timer,5000);
682 make_player_jump(player);
684 add_score(base.x - scroll_x,
686 25 * score_multiplier);
693 BadGuy::collision(void *p_c_object, int c_object, CollisionType type)
695 BadGuy* pbad_c = NULL;
697 if(type == COLLISION_BUMP) {
701 if(type == COLLISION_SQUICH) {
702 Player* player = static_cast<Player*>(p_c_object);
710 if(kind == BAD_BOMB || kind == BAD_STALACTITE)
713 dying = DYING_FALLING;
716 /* Gain some points: */
717 if (kind == BAD_BSOD)
718 add_score(base.x - scroll_x, base.y,
719 50 * score_multiplier);
720 else if (kind == BAD_LAPTOP)
721 add_score(base.x - scroll_x, base.y,
722 25 * score_multiplier);
723 else if (kind == BAD_MONEY)
724 add_score(base.x - scroll_x, base.y,
725 50 * score_multiplier);
727 /* Play death sound: */
728 play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
732 pbad_c = (BadGuy*) p_c_object;
737 else if(mode == KICK)
739 /* We're in kick mode, kill the other guy
740 and yourself(wuahaha) : */
742 pbad_c->dying = DYING_FALLING;
743 pbad_c->base.ym = -8;
744 play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
746 add_score(base.x - scroll_x,
748 pbad_c->dying = DYING_FALLING;
750 dying = DYING_FALLING;
753 add_score(pbad_c->base.x - scroll_x,
754 pbad_c->base.y, 100);