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, img_bsod_squished_right,
20 img_bsod_falling_left, img_bsod_falling_right,
21 img_laptop_flat_left, img_laptop_flat_right,
22 img_laptop_falling_left, img_laptop_falling_right;
23 texture_type img_bsod_left[4], img_bsod_right[4],
24 img_laptop_left[3], img_laptop_right[3],
25 img_money_left[2], img_money_right[2];
28 void badguy_create_bitmasks()
30 /*bm_bsod = img_bsod_left[0];*/
33 void badguy_init(bad_guy_type* pbad, float x, float y, int kind)
35 pbad->base.width = 32;
36 pbad->base.height = 32;
44 pbad->old_base = pbad->base;
47 timer_init(&pbad->timer,YES);
48 physic_init(&pbad->physic);
51 void badguy_action(bad_guy_type* pbad)
56 if (pbad->kind == BAD_BSOD)
58 /* --- BLUE SCREEN OF DEATH MONSTER: --- */
60 /* Move left/right: */
62 if (pbad->dying == NO ||
63 pbad->dying == FALLING)
65 if (pbad->dir == RIGHT)
66 pbad->base.x = pbad->base.x + pbad->base.xm * frame_ratio;
67 else if (pbad->dir == LEFT)
68 pbad->base.x = pbad->base.x - pbad->base.xm * frame_ratio;
72 /* Move vertically: */
74 pbad->base.y = pbad->base.y + pbad->base.ym * frame_ratio;
76 if (pbad->dying != FALLING)
77 collision_swept_object_map(&pbad->old_base,&pbad->base);
78 if (pbad->base.y > screen->h)
79 bad_guys.erase(static_cast<std::vector<bad_guy_type>::iterator>(pbad));
81 /* Bump into things horizontally: */
85 if (issolid( pbad->base.x, (int) pbad->base.y + 16))
89 else if (issolid( pbad->base.x + pbad->base.width, (int) pbad->base.y + 16))
95 /* Fall if we get off the ground: */
97 if (pbad->dying != FALLING)
99 if (!issolid(pbad->base.x+16, pbad->base.y + 32))
101 if(!physic_is_set(&pbad->physic))
103 physic_set_state(&pbad->physic,PH_VT);
104 physic_set_start_vy(&pbad->physic,2.);
107 pbad->base.ym = physic_get_velocity(&pbad->physic);
113 if (pbad->base.ym > 0)
115 pbad->base.y = (int)(pbad->base.y / 32) * 32;
118 physic_init(&pbad->physic);
123 if(!physic_is_set(&pbad->physic))
125 physic_set_state(&pbad->physic,PH_VT);
126 physic_set_start_vy(&pbad->physic,2.);
128 pbad->base.ym = physic_get_velocity(&pbad->physic);
131 if (pbad->base.y > screen->h)
132 bad_guys.erase(static_cast<std::vector<bad_guy_type>::iterator>(pbad));
134 else if (pbad->kind == BAD_LAPTOP)
136 /* --- LAPTOP MONSTER: --- */
138 /* Move left/right: */
140 if (pbad->mode == NORMAL || pbad->mode == KICK)
142 if (pbad->dying == NO ||
143 pbad->dying == FALLING)
145 if (pbad->dir == RIGHT)
146 pbad->base.x = pbad->base.x + pbad->base.xm * frame_ratio;
147 else if (pbad->dir == LEFT)
148 pbad->base.x = pbad->base.x - pbad->base.xm * frame_ratio;
151 else if (pbad->mode == HELD)
152 { /* FIXME: The pbad object shouldn't know about pplayer objects. */
153 /* If we're holding the laptop */
157 pbad->base.x = tux.base.x + 16;
158 pbad->base.y = tux.base.y + tux.base.height/1.5 - pbad->base.height;
160 else /* facing left */
162 pbad->base.x = tux.base.x - 16;
163 pbad->base.y = tux.base.y + tux.base.height/1.5 - pbad->base.height;
165 if(collision_object_map(&pbad->base))
167 pbad->base.x = tux.base.x;
168 pbad->base.y = tux.base.y + tux.base.height/1.5 - pbad->base.height;
171 if(tux.input.fire != DOWN) /* SHOOT! */
173 if(pbad->dir == LEFT)
181 play_sound(sounds[SND_KICK],SOUND_CENTER_SPEAKER);
186 /* Move vertically: */
188 if(pbad->mode != HELD)
189 pbad->base.y = pbad->base.y + pbad->base.ym * frame_ratio;
191 if (pbad->dying != FALLING)
192 collision_swept_object_map(&pbad->old_base,&pbad->base);
193 if (pbad->base.y > screen->h)
194 bad_guys.erase(static_cast<std::vector<bad_guy_type>::iterator>(pbad));
195 /* Bump into things horizontally: */
197 /* Bump into things horizontally: */
201 int changed = pbad->dir;
202 if (issolid( pbad->base.x, (int) pbad->base.y + 16))
206 else if (issolid( pbad->base.x + pbad->base.width, (int) pbad->base.y + 16))
210 if(pbad->mode == KICK && changed != pbad->dir)
212 /* handle stereo sound */
213 /* FIXME: In theory a badguy object doesn't know anything about player objects */
214 if (tux.base.x > pbad->base.x)
215 play_sound(sounds[SND_RICOCHET], SOUND_LEFT_SPEAKER);
216 else if (tux.base.x < pbad->base.x)
217 play_sound(sounds[SND_RICOCHET], SOUND_RIGHT_SPEAKER);
219 play_sound(sounds[SND_RICOCHET], SOUND_CENTER_SPEAKER);
225 /* Fall if we get off the ground: */
227 if (pbad->dying != FALLING)
229 if (!issolid(pbad->base.x+16, pbad->base.y + 32))
231 if(!physic_is_set(&pbad->physic))
233 physic_set_state(&pbad->physic,PH_VT);
234 physic_set_start_vy(&pbad->physic,0.);
237 if(pbad->mode != HELD)
239 pbad->base.ym = physic_get_velocity(&pbad->physic);
246 if (pbad->base.ym > 0)
248 pbad->base.y = (int)(pbad->base.y / 32) * 32;
251 physic_init(&pbad->physic);
256 if(!physic_is_set(&pbad->physic))
258 physic_set_state(&pbad->physic,PH_VT);
259 physic_set_start_vy(&pbad->physic,0.);
261 pbad->base.ym = physic_get_velocity(&pbad->physic);
266 else if (pbad->kind == BAD_MONEY)
268 /* --- MONEY BAGS: --- */
271 /* Move vertically: */
273 pbad->base.y = pbad->base.y + pbad->base.ym * frame_ratio;
275 if (pbad->dying != FALLING)
276 collision_swept_object_map(&pbad->old_base,&pbad->base);
278 if (pbad->base.y > screen->h)
279 bad_guys.erase(static_cast<std::vector<bad_guy_type>::iterator>(pbad));
281 if(physic_get_state(&pbad->physic) == -1)
283 physic_set_state(&pbad->physic,PH_VT);
284 physic_set_start_vy(&pbad->physic,0.);
287 if (pbad->dying != FALLING)
289 if(issolid(pbad->base.x, pbad->base.y + 32))
291 physic_set_state(&pbad->physic,PH_VT);
292 physic_set_start_vy(&pbad->physic,6.);
293 pbad->base.ym = physic_get_velocity(&pbad->physic);
295 else if(issolid(pbad->base.x, pbad->base.y))
296 { /* This works, but isn't the best solution imagineable */
297 physic_set_state(&pbad->physic,PH_VT);
298 physic_set_start_vy(&pbad->physic,0.);
299 pbad->base.ym = physic_get_velocity(&pbad->physic);
304 pbad->base.ym = physic_get_velocity(&pbad->physic);
309 if(!physic_is_set(&pbad->physic))
311 physic_set_state(&pbad->physic,PH_VT);
312 physic_set_start_vy(&pbad->physic,0.);
314 pbad->base.ym = physic_get_velocity(&pbad->physic);
317 else if (pbad->kind == -1)
321 else if (pbad->kind == -1)
324 /* Handle mode timer: */
326 if (pbad->mode == FLAT && pbad->mode != HELD)
328 if(!timer_check(&pbad->timer))
334 else if (pbad->mode == KICK)
336 timer_check(&pbad->timer);
340 /* Handle dying timer: */
342 if (pbad->dying == SQUISHED)
344 /* Remove it if time's up: */
345 if(!timer_check(&pbad->timer))
346 bad_guys.erase(static_cast<std::vector<bad_guy_type>::iterator>(pbad));
350 /* Remove if it's far off the screen: */
352 if (pbad->base.x < scroll_x - OFFSCREEN_DISTANCE)
353 bad_guys.erase(static_cast<std::vector<bad_guy_type>::iterator>(pbad));
356 /* Once it's on screen, it's activated! */
358 if (pbad->base.x <= scroll_x + screen->w + OFFSCREEN_DISTANCE)
364 void badguy_draw(bad_guy_type* pbad)
366 if (pbad->base.x > scroll_x - 32 &&
367 pbad->base.x < scroll_x + screen->w)
369 if (pbad->kind == BAD_BSOD)
371 /* --- BLUE SCREEN OF DEATH MONSTER: --- */
373 if (pbad->dying == NO)
377 if (pbad->dir == LEFT)
379 texture_draw(&img_bsod_left[(frame / 5) % 4],
380 pbad->base.x - scroll_x,
386 texture_draw(&img_bsod_right[(frame / 5) % 4],
387 pbad->base.x - scroll_x,
392 else if (pbad->dying == FALLING)
396 if (pbad->dir == LEFT)
398 texture_draw(&img_bsod_falling_left,
399 pbad->base.x - scroll_x,
405 texture_draw(&img_bsod_falling_right,
406 pbad->base.x - scroll_x,
411 else if (pbad->dying == SQUISHED)
413 /* Dying - Squished: */
415 if (pbad->dir == LEFT)
417 texture_draw(&img_bsod_squished_left,
418 pbad->base.x - scroll_x,
424 texture_draw(&img_bsod_squished_right,
425 pbad->base.x - scroll_x,
431 else if (pbad->kind == BAD_LAPTOP)
433 /* --- LAPTOP MONSTER: --- */
435 if (pbad->dying == NO)
439 if (pbad->mode == NORMAL)
443 if (pbad->dir == LEFT)
445 texture_draw(&img_laptop_left[(frame / 5) % 3],
446 pbad->base.x - scroll_x,
452 texture_draw(&img_laptop_right[(frame / 5) % 3],
453 pbad->base.x - scroll_x,
462 if (pbad->dir == LEFT)
464 texture_draw(&img_laptop_flat_left,
465 pbad->base.x - scroll_x,
471 texture_draw(&img_laptop_flat_right,
472 pbad->base.x - scroll_x,
478 else if (pbad->dying == FALLING)
482 if (pbad->dir == LEFT)
484 texture_draw(&img_laptop_falling_left,
485 pbad->base.x - scroll_x,
491 texture_draw(&img_laptop_falling_right,
492 pbad->base.x - scroll_x,
498 else if (pbad->kind == BAD_MONEY)
500 if (pbad->base.ym != 300 /* > -16*/)
502 if (pbad->dir == LEFT)
504 texture_draw(&img_money_left[0],
505 pbad->base.x - scroll_x,
511 texture_draw(&img_money_right[0],
512 pbad->base.x - scroll_x,
519 if (pbad->dir == LEFT)
521 texture_draw(&img_money_left[1],
522 pbad->base.x - scroll_x,
528 texture_draw(&img_money_right[1],
529 pbad->base.x - scroll_x,
535 else if (pbad->kind == -1)
540 void badguy_collision(bad_guy_type* pbad, void *p_c_object, int c_object)
542 bad_guy_type* pbad_c = NULL;
543 player_type* pplayer_c = NULL;
548 pbad->dying = FALLING;
551 /* Gain some points: */
553 if (pbad->kind == BAD_BSOD)
554 add_score(pbad->base.x - scroll_x, pbad->base.y,
555 50 * score_multiplier);
556 else if (pbad->kind == BAD_LAPTOP)
557 add_score(pbad->base.x - scroll_x, pbad->base.y,
558 25 * score_multiplier);
559 else if (pbad->kind == BAD_MONEY)
560 add_score(pbad->base.x - scroll_x, pbad->base.y,
561 50 * score_multiplier);
563 /* Play death sound: */
564 play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
567 pbad_c = (bad_guy_type*) p_c_object;
568 if (pbad->mode == NORMAL)
572 else if(pbad->mode == KICK)
574 /* We're in kick mode, kill the other guy
575 and yourself(wuahaha) : */
577 pbad_c->dying = FALLING;
578 pbad_c->base.ym = -8;
579 play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
581 add_score(pbad->base.x - scroll_x,
583 pbad_c->dying = FALLING;
585 pbad->dying = FALLING;
588 add_score(pbad_c->base.x - scroll_x,
589 pbad_c->base.y, 100);
593 pplayer_c = (player_type*) p_c_object;
594 if(pbad->kind != BAD_MONEY)
596 if (pbad->kind == BAD_BSOD)
598 pbad->dying = SQUISHED;
599 timer_start(&pbad->timer,4000);
600 physic_set_state(&pplayer_c->vphysic,PH_VT);
601 physic_set_start_vy(&pplayer_c->vphysic,2.);
602 pplayer_c->base.y = pbad->base.y - pplayer_c->base.height - 1;
604 add_score(pbad->base.x - scroll_x, pbad->base.y,
605 50 * score_multiplier);
607 play_sound(sounds[SND_SQUISH], SOUND_CENTER_SPEAKER);
609 else if (pbad->kind == BAD_LAPTOP)
612 if (pbad->mode == NORMAL || pbad->mode == KICK)
616 play_sound(sounds[SND_STOMP], SOUND_CENTER_SPEAKER);
620 timer_start(&pbad->timer,10000);
622 physic_set_state(&pplayer_c->vphysic,PH_VT);
623 physic_set_start_vy(&pplayer_c->vphysic,2.);
624 pplayer_c->base.y = pbad->base.y - pplayer_c->base.height - 1;
626 else if (pbad->mode == FLAT)
629 play_sound(sounds[SND_KICK], SOUND_CENTER_SPEAKER);
631 if (pplayer_c->base.x < pbad->base.x + (pbad->base.width/2))
639 timer_start(&pbad->timer,5000);
642 physic_set_state(&pplayer_c->vphysic,PH_VT);
643 physic_set_start_vy(&pplayer_c->vphysic,2.);
644 pplayer_c->base.y = pbad->base.y - pplayer_c->base.height - 1;
646 add_score(pbad->base.x - scroll_x,
648 25 * score_multiplier);
650 /* play_sound(sounds[SND_SQUISH]); */