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
20 texture_type img_bsod_squished_left;
21 texture_type img_bsod_squished_right;
22 texture_type img_bsod_falling_left;
23 texture_type img_bsod_falling_right;
24 texture_type img_laptop_flat_left;
25 texture_type img_laptop_flat_right;
26 texture_type img_laptop_falling_left;
27 texture_type img_laptop_falling_right;
28 texture_type img_bsod_left[4];
29 texture_type img_bsod_right[4];
30 texture_type img_laptop_left[3];
31 texture_type img_laptop_right[3];
32 texture_type img_money_left[2];
33 texture_type img_money_right[2];
34 texture_type img_mrbomb_left[4];
35 texture_type img_mrbomb_right[4];
36 texture_type img_stalactite;
37 texture_type img_stalactite_broken;
38 texture_type img_flame[2];
40 BadGuyKind badguykind_from_string(const std::string& str)
44 else if (str == "laptop")
46 else if (str == "bsod")
48 else if (str == "mrbomb")
50 else if (str == "stalactite")
51 return BAD_STALACTITE;
52 else if (str == "flame")
56 printf("Couldn't convert badguy: %s\n", str.c_str());
61 std::string badguykind_to_string(BadGuyKind kind)
89 BadGuy::init(float x, float y, BadGuyKind kind_)
103 timer_init(&timer, true);
104 physic_init(&physic);
106 if(kind == BAD_BOMB) {
107 timer_start(&timer, 1000);
109 // hack so that the bomb doesn't hurt until it expldes...
110 dying = DYING_SQUISHED;
111 } else if(kind == BAD_FLAME) {
112 base.ym = 0; // we misuse base.ym as angle for the flame
116 void BadGuy::action_bsod()
118 /* --- BLUE SCREEN OF DEATH MONSTER: --- */
120 /* Move left/right: */
121 if (dying == DYING_NOT ||
122 dying == DYING_FALLING)
124 base.x += base.xm * frame_ratio;
127 /* Move vertically: */
128 base.y = base.y + base.ym * frame_ratio;
130 if (dying != DYING_FALLING)
131 collision_swept_object_map(&old_base,&base);
134 check_horizontal_bump();
138 // Handle dying timer:
139 if (dying == DYING_SQUISHED)
141 /* Remove it if time's up: */
142 if(!timer_check(&timer)) {
149 void BadGuy::action_laptop()
151 /* Move left/right: */
152 if (mode == NORMAL || mode == KICK)
154 if (dying == DYING_NOT ||
155 dying == DYING_FALLING)
157 base.x += base.xm * frame_ratio;
160 else if (mode == HELD)
161 { /* FIXME: The pbad object shouldn't know about pplayer objects. */
162 /* If we're holding the laptop */
166 base.x = tux.base.x + 16;
167 base.y = tux.base.y + tux.base.height/1.5 - base.height;
169 else /* facing left */
171 base.x = tux.base.x - 16;
172 base.y = tux.base.y + tux.base.height/1.5 - base.height;
174 if(collision_object_map(&base))
177 base.y = tux.base.y + tux.base.height/1.5 - base.height;
180 if(tux.input.fire != DOWN) /* SHOOT! */
190 play_sound(sounds[SND_KICK],SOUND_CENTER_SPEAKER);
195 /* Move vertically: */
197 base.y = base.y + base.ym * frame_ratio;
199 if (dying != DYING_FALLING)
200 collision_swept_object_map(&old_base,&base);
201 /* Bump into things horizontally: */
206 check_horizontal_bump();
207 if(mode == KICK && changed != dir)
209 /* handle stereo sound (number 10 should be tweaked...)*/
210 if (base.x < scroll_x - 10)
211 play_sound(sounds[SND_RICOCHET], SOUND_LEFT_SPEAKER);
212 else if (base.x > scroll_x + 10)
213 play_sound(sounds[SND_RICOCHET], SOUND_RIGHT_SPEAKER);
215 play_sound(sounds[SND_RICOCHET], SOUND_CENTER_SPEAKER);
221 /* Handle mode timer: */
222 if (mode == FLAT && mode != HELD)
224 if(!timer_check(&timer))
230 else if (mode == KICK)
236 void BadGuy::check_horizontal_bump(bool checkcliff)
238 if (dir == LEFT && issolid( base.x, (int) base.y + 16))
244 if (dir == RIGHT && issolid( base.x + base.width, (int) base.y + 16))
251 // don't check for cliffs when we're falling
255 if(dir == LEFT && !issolid(base.x, (int) base.y + base.height + 16))
257 printf("Cliffcol left\n");
262 if(dir == RIGHT && !issolid(base.x + base.width,
263 (int) base.y + base.height + 16))
265 printf("Cliffcol right\n");
272 void BadGuy::fall(bool dojump)
274 /* Fall if we get off the ground: */
275 if (dying != DYING_FALLING)
277 if (!issolid(base.x+16, base.y + 32))
279 if(!physic_is_set(&physic))
281 physic_set_state(&physic,PH_VT);
282 physic_set_start_vy(&physic, dojump ? 2. : 0.);
287 base.ym = physic_get_velocity(&physic);
296 base.y = (int)(base.y / 32) * 32;
299 physic_init(&physic);
304 if(!physic_is_set(&physic))
306 physic_set_state(&physic,PH_VT);
307 physic_set_start_vy(&physic,0.);
309 base.ym = physic_get_velocity(&physic);
312 // BadGuy fall below the ground
313 if (base.y > screen->h) {
319 void BadGuy::remove_me()
321 std::vector<BadGuy>::iterator i;
322 for(i = bad_guys.begin(); i != bad_guys.end(); ++i) {
323 if( & (*i) == this) {
330 void BadGuy::action_money()
332 /* Move vertically: */
333 base.y = base.y + base.ym * frame_ratio;
335 if (dying != DYING_FALLING)
336 collision_swept_object_map(&old_base,&base);
338 if (base.y > screen->h) {
343 if(physic_get_state(&physic) == -1)
345 physic_set_state(&physic,PH_VT);
346 physic_set_start_vy(&physic,0.);
349 if (dying != DYING_FALLING)
352 if(issolid(base.x, base.y + 32))
354 physic_set_state(&physic,PH_VT);
355 physic_set_start_vy(&physic,6.);
356 base.ym = physic_get_velocity(&physic);
358 /* // matze: is this code needed?
359 else if(issolid(base.x, base.y))
360 { // This works, but isn't the best solution imagineable
361 physic_set_state(&physic,PH_VT);
362 physic_set_start_vy(&physic,0.);
363 base.ym = physic_get_velocity(&physic);
368 base.ym = physic_get_velocity(&physic);
373 if(!physic_is_set(&physic))
375 physic_set_state(&physic,PH_VT);
376 physic_set_start_vy(&physic,0.);
378 base.ym = physic_get_velocity(&physic);
382 void BadGuy::action_mrbomb()
385 base.x += base.xm * frame_ratio;
388 /* Move vertically: */
389 base.y += base.ym * frame_ratio;
391 if (dying != DYING_FALLING)
392 collision_swept_object_map(&old_base,&base);
394 check_horizontal_bump(true);
398 void BadGuy::action_bomb()
400 // eventually fall down
401 base.y += base.ym * frame_ratio;
402 collision_swept_object_map(&old_base,&base);
405 if(!timer_check(&timer)) {
406 if(mode == BOMB_TICKING) {
408 dying = DYING_NOT; // now the bomb hurts
409 timer_start(&timer, 1000);
410 } else if(mode == BOMB_EXPLODE) {
417 void BadGuy::action_stalactite()
420 if(tux.base.x + 32 > base.x - 40 && tux.base.x < base.x + 32 + 40) {
421 timer_start(&timer, 800);
422 mode = STALACTITE_SHAKING;
424 } if(mode == STALACTITE_SHAKING) {
425 base.x = old_base.x + (rand() % 6) - 3; // TODO this could be done nicer...
426 if(!timer_check(&timer)) {
427 mode = STALACTITE_FALL;
429 } else if(mode == STALACTITE_FALL) {
430 base.y += base.ym * frame_ratio;
431 /* Destroy if collides land */
432 if(issolid(base.x+16, base.y+32))
434 timer_start(&timer, 3000);
435 dying = DYING_SQUISHED;
442 BadGuy::action_flame()
444 static const float radius = 100;
445 static const float speed = 0.02;
446 base.x = old_base.x + cos(base.ym) * radius;
447 base.y = old_base.y + sin(base.ym) * radius;
449 base.ym = fmodf(base.ym + frame_ratio * speed, 2*M_PI);
489 // Remove if it's far off the screen:
490 if (base.x < scroll_x - OFFSCREEN_DISTANCE)
497 // Once it's on screen, it's activated!
498 if (base.x <= scroll_x + screen->w + OFFSCREEN_DISTANCE)
506 texture_type* texture = 0;
508 if(dying == DYING_NOT) {
509 size_t frame = (global_frame_counter / 5) % 4;
510 texture = (dir == LEFT) ? &img_bsod_left[frame] : &img_bsod_right[frame];
511 } else if(dying == DYING_FALLING) {
512 texture = (dir == LEFT) ? &img_bsod_falling_left : &img_bsod_falling_right;
513 } else if(dying == DYING_SQUISHED) {
514 texture = (dir == LEFT)
515 ? &img_bsod_squished_left : &img_bsod_squished_right;
519 texture_draw(texture, base.x - scroll_x, y);
523 BadGuy::draw_laptop()
525 texture_type* texture;
526 size_t frame = (global_frame_counter / 5) % 3;
528 if(dying == DYING_NOT) {
531 texture = &img_laptop_left[frame];
533 texture = &img_laptop_right[frame];
535 texture = (dir == LEFT) ? &img_laptop_flat_left : &img_laptop_flat_right;
538 texture = (dir == LEFT)
539 ? &img_laptop_falling_left : &img_laptop_falling_right;
542 texture_draw(texture, base.x - scroll_x, base.y);
548 texture_type* texture;
549 size_t frame = (base.ym != 300) ? 0 : 1;
551 if(tux.base.x + tux.base.width < base.x) {
552 texture = &img_money_left[frame];
554 texture = &img_money_right[frame];
557 texture_draw(texture, base.x - scroll_x, base.y);
561 BadGuy::draw_mrbomb()
563 texture_type* texture;
564 size_t frame = (global_frame_counter/5) % 4;
567 texture = &img_mrbomb_left[frame];
569 texture = &img_mrbomb_right[frame];
571 texture_draw(texture, base.x - scroll_x, base.y);
577 texture_type* texture;
579 // TODO add real bomb graphics
580 if(mode == BOMB_TICKING) {
581 texture = &img_bsod_squished_right;
583 texture = &img_bsod_squished_left;
586 texture_draw(texture, base.x - scroll_x, base.y);
590 BadGuy::draw_stalactite()
592 texture_type* texture;
594 texture = &img_stalactite;
596 texture = &img_stalactite_broken;
598 texture_draw(texture, base.x - scroll_x, base.y);
604 size_t frame = (global_frame_counter / 10) % 2;
605 texture_type* texture = &img_flame[frame];
607 texture_draw(texture, base.x - scroll_x, base.y);
613 // Don't try to draw stuff that is outside of the screen
614 if (base.x > scroll_x - 32 &&
615 base.x < scroll_x + screen->w)
654 if(kind == BAD_BSOD || kind == BAD_LAPTOP || kind == BAD_BOMB) {
655 dying = DYING_FALLING;
657 play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
662 BadGuy::make_player_jump(Player* player)
664 physic_set_state(&player->vphysic,PH_VT);
665 physic_set_start_vy(&player->vphysic,2.);
666 player->base.y = base.y - player->base.height - 1;
670 BadGuy::squich(Player* player)
672 if(kind == BAD_MRBOMB) {
673 // mrbomb transforms into a bomb now
674 add_bad_guy(base.x, base.y, BAD_BOMB);
676 make_player_jump(player);
677 add_score(base.x - scroll_x, base.y, 50 * score_multiplier);
678 play_sound(sounds[SND_SQUISH], SOUND_CENTER_SPEAKER);
684 } else if(kind == BAD_BSOD) {
685 dying = DYING_SQUISHED;
686 timer_start(&timer,4000);
688 make_player_jump(player);
690 add_score(base.x - scroll_x, base.y, 50 * score_multiplier);
691 play_sound(sounds[SND_SQUISH], SOUND_CENTER_SPEAKER);
695 } else if (kind == BAD_LAPTOP) {
696 if (mode == NORMAL || mode == KICK)
699 play_sound(sounds[SND_STOMP], SOUND_CENTER_SPEAKER);
703 timer_start(&timer, 4000);
704 } else if (mode == FLAT) {
706 play_sound(sounds[SND_KICK], SOUND_CENTER_SPEAKER);
708 if (player->base.x < base.x + (base.width/2))
716 timer_start(&timer,5000);
719 make_player_jump(player);
721 add_score(base.x - scroll_x,
723 25 * score_multiplier);
730 BadGuy::collision(void *p_c_object, int c_object, CollisionType type)
732 BadGuy* pbad_c = NULL;
734 if(type == COLLISION_BUMP) {
738 if(type == COLLISION_SQUICH) {
739 Player* player = static_cast<Player*>(p_c_object);
747 if(kind == BAD_BOMB || kind == BAD_STALACTITE || kind == BAD_FLAME)
750 dying = DYING_FALLING;
753 /* Gain some points: */
754 if (kind == BAD_BSOD)
755 add_score(base.x - scroll_x, base.y,
756 50 * score_multiplier);
757 else if (kind == BAD_LAPTOP)
758 add_score(base.x - scroll_x, base.y,
759 25 * score_multiplier);
760 else if (kind == BAD_MONEY)
761 add_score(base.x - scroll_x, base.y,
762 50 * score_multiplier);
764 /* Play death sound: */
765 play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
769 pbad_c = (BadGuy*) p_c_object;
774 else if(mode == KICK)
776 /* We're in kick mode, kill the other guy
777 and yourself(wuahaha) : */
779 pbad_c->dying = DYING_FALLING;
780 pbad_c->base.ym = -8;
781 play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
783 add_score(base.x - scroll_x,
785 pbad_c->dying = DYING_FALLING;
787 dying = DYING_FALLING;
790 add_score(pbad_c->base.x - scroll_x,
791 pbad_c->base.y, 100);
797 //---------------------------------------------------------------------------
799 void load_badguy_gfx()
802 texture_load(&img_bsod_left[0], datadir +
803 "/images/shared/bsod-left-0.png",
806 texture_load(&img_bsod_left[1], datadir +
807 "/images/shared/bsod-left-1.png",
810 texture_load(&img_bsod_left[2], datadir +
811 "/images/shared/bsod-left-2.png",
814 texture_load(&img_bsod_left[3], datadir +
815 "/images/shared/bsod-left-3.png",
818 texture_load(&img_bsod_right[0], datadir +
819 "/images/shared/bsod-right-0.png",
822 texture_load(&img_bsod_right[1], datadir +
823 "/images/shared/bsod-right-1.png",
826 texture_load(&img_bsod_right[2], datadir +
827 "/images/shared/bsod-right-2.png",
830 texture_load(&img_bsod_right[3], datadir +
831 "/images/shared/bsod-right-3.png",
834 texture_load(&img_bsod_squished_left, datadir +
835 "/images/shared/bsod-squished-left.png",
838 texture_load(&img_bsod_squished_right, datadir +
839 "/images/shared/bsod-squished-right.png",
842 texture_load(&img_bsod_falling_left, datadir +
843 "/images/shared/bsod-falling-left.png",
846 texture_load(&img_bsod_falling_right, datadir +
847 "/images/shared/bsod-falling-right.png",
853 texture_load(&img_laptop_left[0], datadir +
854 "/images/shared/laptop-left-0.png",
857 texture_load(&img_laptop_left[1], datadir +
858 "/images/shared/laptop-left-1.png",
861 texture_load(&img_laptop_left[2], datadir +
862 "/images/shared/laptop-left-2.png",
865 texture_load(&img_laptop_right[0], datadir +
866 "/images/shared/laptop-right-0.png",
869 texture_load(&img_laptop_right[1], datadir +
870 "/images/shared/laptop-right-1.png",
873 texture_load(&img_laptop_right[2], datadir +
874 "/images/shared/laptop-right-2.png",
877 texture_load(&img_laptop_flat_left, datadir +
878 "/images/shared/laptop-flat-left.png",
881 texture_load(&img_laptop_flat_right, datadir +
882 "/images/shared/laptop-flat-right.png",
885 texture_load(&img_laptop_falling_left, datadir +
886 "/images/shared/laptop-falling-left.png",
889 texture_load(&img_laptop_falling_right, datadir +
890 "/images/shared/laptop-falling-right.png",
896 texture_load(&img_money_left[0], datadir +
897 "/images/shared/bag-left-0.png",
900 texture_load(&img_money_left[1], datadir +
901 "/images/shared/bag-left-1.png",
904 texture_load(&img_money_right[0], datadir +
905 "/images/shared/bag-right-0.png",
908 texture_load(&img_money_right[1], datadir +
909 "/images/shared/bag-right-1.png",
913 for(int i=0; i<4; ++i) {
915 snprintf(num, 4, "%d", i);
916 texture_load(&img_mrbomb_left[i],
917 datadir + "/images/shared/mrbomb-left-" + num + ".png", USE_ALPHA);
918 texture_load(&img_mrbomb_right[i],
919 datadir + "/images/shared/mrbomb-right-" + num + ".png", USE_ALPHA);
923 texture_load(&img_stalactite,
924 datadir + "/images/shared/stalactite.png", USE_ALPHA);
925 texture_load(&img_stalactite_broken,
926 datadir + "/images/shared/stalactite-broken.png", USE_ALPHA);
929 texture_load(&img_flame[0],
930 datadir + "/images/shared/flame-0.png", USE_ALPHA);
931 texture_load(&img_flame[1],
932 datadir + "/images/shared/flame-1.png", USE_ALPHA);
935 void free_badguy_gfx()
937 for (int i = 0; i < 4; i++)
939 texture_free(&img_bsod_left[i]);
940 texture_free(&img_bsod_right[i]);
943 texture_free(&img_bsod_squished_left);
944 texture_free(&img_bsod_squished_right);
946 texture_free(&img_bsod_falling_left);
947 texture_free(&img_bsod_falling_right);
949 for (int i = 0; i < 3; i++)
951 texture_free(&img_laptop_left[i]);
952 texture_free(&img_laptop_right[i]);
955 texture_free(&img_laptop_flat_left);
956 texture_free(&img_laptop_flat_right);
958 texture_free(&img_laptop_falling_left);
959 texture_free(&img_laptop_falling_right);
961 for (int i = 0; i < 2; i++)
963 texture_free(&img_money_left[i]);
964 texture_free(&img_money_right[i]);
967 for(int i = 0; i < 4; i++) {
968 texture_free(&img_mrbomb_left[i]);
969 texture_free(&img_mrbomb_right[i]);
972 texture_free(&img_stalactite);
973 texture_free(&img_stalactite_broken);
975 texture_free(&img_flame[0]);
976 texture_free(&img_flame[1]);