// 02111-1307, USA.
#include <iostream>
-#include <math.h>
+#include <cmath>
-#include "globals.h"
+#include "app/globals.h"
#include "defines.h"
+#include "special/sprite_manager.h"
+#include "utils/lispwriter.h"
#include "badguy.h"
#include "tile.h"
#include "resources.h"
-#include "sprite_manager.h"
#include "camera.h"
-#include "lispwriter.h"
#include "level.h"
#include "sector.h"
#include "tilemap.h"
+#include "statistics.h"
Sprite* img_mriceblock_flat_left;
Sprite* img_mriceblock_flat_right;
Sprite* img_fish_down;
Sprite* img_fish_iced;
Sprite* img_fish_iced_down;
+Sprite* img_flamefish;
+Sprite* img_flamefish_down;
Sprite* img_bouncingsnowball_left;
Sprite* img_bouncingsnowball_right;
Sprite* img_bouncingsnowball_squished;
return BAD_FLAME;
else if (str == "fish")
return BAD_FISH;
+ else if (str == "flamefish")
+ return BAD_FLAMEFISH;
else if (str == "bouncingsnowball")
return BAD_BOUNCINGSNOWBALL;
else if (str == "flyingsnowball")
case BAD_FISH:
return "fish";
break;
+ case BAD_FLAMEFISH:
+ return "flamefish";
+ break;
case BAD_BOUNCINGSNOWBALL:
return "bouncingsnowball";
break;
timer.init(true);
// if we're in a solid tile at start correct that now
- if(kind != BAD_FLAME && kind != BAD_FISH && collision_object_map(base))
+ if(Sector::current()) {
+ if(kind != BAD_FLAME && kind != BAD_FISH && kind != BAD_FLAMEFISH && collision_object_map(base))
{
std::cout << "Warning: badguy started in wall: kind: " << badguykind_to_string(kind)
<< " pos: (" << base.x << ", " << base.y << ")" << std::endl;
--base.y;
}
- if(Sector::current() && Sector::current()->camera) {
+ if(Sector::current()->camera) {
Vector scroll = Sector::current()->camera->get_translation();
if(start_position.x > scroll.x - X_OFFSCREEN_DISTANCE &&
start_position.y < scroll.y + screen->h + Y_OFFSCREEN_DISTANCE) {
activate(LEFT);
}
- } else {
+ } } else {
if(start_position.x > 0 && start_position.x <= screen->w
&& start_position.y > 0 && start_position.y <= screen->h)
activate(LEFT);
} else if(kind == BAD_FISH) {
set_sprite(img_fish, img_fish);
physic.enable_gravity(true);
+ } else if(kind == BAD_FLAMEFISH) {
+ set_sprite(img_flamefish, img_flamefish);
+ physic.enable_gravity(true);
} else if(kind == BAD_FLYINGSNOWBALL) {
set_sprite(img_flyingsnowball, img_flyingsnowball);
physic.enable_gravity(false);
if (mode != HELD)
{
// move
- physic.apply(elapsed_time, base.x, base.y);
+ physic.apply(elapsed_time, base.x, base.y, Sector::current()->gravity);
if (dying != DYING_FALLING)
collision_swept_object_map(&old_base,&base);
}
{ /* FIXME: The pbad object shouldn't know about pplayer objects. */
/* If we're holding the iceblock */
dir = tux.dir;
- if(dir==RIGHT)
+ if(tux.size == SMALL)
{
- base.x = tux.base.x + 16;
- base.y = tux.base.y + tux.base.height/1.5 - base.height;
+ if(dir == RIGHT)
+ base.x = tux.base.x + 24;
+ else // dir == LEFT
+ base.x = tux.base.x - 12;
+ base.y = tux.base.y + tux.base.height/1.5 - base.height;
}
- else /* facing left */
+ else // TUX == BIG
{
- base.x = tux.base.x - 16;
- base.y = tux.base.y + tux.base.height/1.5 - base.height;
+ if(dir == RIGHT)
+ base.x = tux.base.x + 24;
+ else // dir == LEFT
+ base.x = tux.base.x - 4;
+ base.y = tux.base.y + tux.base.height/1.5 - base.height;
}
+
if(collision_object_map(base))
{
base.x = tux.base.x;
if(tux.input.fire != DOWN) /* SHOOT! */
{
if(dir == LEFT)
- base.x -= 24;
+ base.x = tux.base.x - base.width;
else
- base.x += 24;
+ base.x = tux.base.x + tux.base.width;
old_base = base;
mode=KICK;
tux.kick_timer.start(KICKING_TIME);
set_sprite(img_mriceblock_flat_left, img_mriceblock_flat_right);
physic.set_velocity_x((dir == LEFT) ? -3.5 : 3.5);
- play_sound(sounds[SND_KICK],SOUND_CENTER_SPEAKER);
+ SoundManager::get()->play_sound(IDToSound(SND_KICK), this, Sector::current()->player->get_pos());
}
}
check_horizontal_bump();
if(mode == KICK && changed != dir)
{
- float scroll_x = Sector::current()->camera->get_translation().x;
-
- /* handle stereo sound (number 10 should be tweaked...)*/
- if (base.x < scroll_x + screen->w/2 - 10)
- play_sound(sounds[SND_RICOCHET], SOUND_LEFT_SPEAKER);
- else if (base.x > scroll_x + screen->w/2 + 10)
- play_sound(sounds[SND_RICOCHET], SOUND_RIGHT_SPEAKER);
- else
- play_sound(sounds[SND_RICOCHET], SOUND_CENTER_SPEAKER);
+ SoundManager::get()->play_sound(IDToSound(SND_RICOCHET), get_pos(), Sector::current()->player->get_pos());
}
}
BadGuy::check_horizontal_bump(bool checkcliff)
{
float halfheight = base.height / 2;
- if (dir == LEFT && issolid( base.x, (int) base.y + halfheight))
+ if (dir == LEFT && issolid( base.x, base.y + halfheight))
{
if (kind == BAD_MRICEBLOCK && mode == KICK)
+ {
Sector::current()->trybreakbrick(Vector(base.x, base.y + halfheight), false);
+ Sector::current()->tryemptybox(Vector(base.x, base.y + halfheight), dir);
+ }
dir = RIGHT;
physic.set_velocity(-physic.get_velocity_x(), physic.get_velocity_y());
return;
}
- if (dir == RIGHT && issolid( base.x + base.width, (int)base.y + halfheight))
+ if (dir == RIGHT && issolid( base.x + base.width, base.y + halfheight))
{
if (kind == BAD_MRICEBLOCK && mode == KICK)
+ {
Sector::current()->trybreakbrick(
- Vector(base.x + base.width, (int) base.y + halfheight), false);
+ Vector(base.x + base.width, base.y + halfheight), false);
+ Sector::current()->tryemptybox(
+ Vector(base.x + base.width, base.y + halfheight), dir);
+ }
dir = LEFT;
physic.set_velocity(-physic.get_velocity_x(), physic.get_velocity_y());
dir = LEFT;
// move
- physic.apply(elapsed_time, base.x, base.y);
+ physic.apply(elapsed_time, base.x, base.y, Sector::current()->gravity);
if(dying == DYING_NOT)
collision_swept_object_map(&old_base, &base);
}
fall();
- physic.apply(elapsed_time, base.x, base.y);
+ physic.apply(elapsed_time, base.x, base.y, Sector::current()->gravity);
if (dying != DYING_FALLING)
collision_swept_object_map(&old_base,&base);
}
dying = DYING_NOT; // now the bomb hurts
timer.start(EXPLODETIME);
- float scroll_x = Sector::current()->camera->get_translation().x;
-
- /* play explosion sound */ // FIXME: is the stereo all right? maybe we should use player cordinates...
- if (base.x < scroll_x + screen->w/2 - 10)
- play_sound(sounds[SND_EXPLODE], SOUND_LEFT_SPEAKER);
- else if (base.x > scroll_x + screen->w/2 + 10)
- play_sound(sounds[SND_EXPLODE], SOUND_RIGHT_SPEAKER);
- else
- play_sound(sounds[SND_EXPLODE], SOUND_CENTER_SPEAKER);
-
+ SoundManager::get()->play_sound(IDToSound(SND_EXPLODE), this, Sector::current()->player->get_pos());
} else if(mode == BOMB_EXPLODE) {
remove_me();
return;
}
// move
- physic.apply(elapsed_time, base.x, base.y);
+ physic.apply(elapsed_time, base.x, base.y, Sector::current()->gravity);
collision_swept_object_map(&old_base,&base);
}
// start shaking when tux is below the stalactite and at least 40 pixels
// near
if(tux.base.x + 32 > base.x - RANGE && tux.base.x < base.x + 32 + RANGE
- && tux.base.y + tux.base.height > base.y) {
+ && tux.base.y + tux.base.height > base.y
+ && tux.dying == DYING_NOT) {
timer.start(SHAKETIME);
mode = STALACTITE_SHAKING;
}
}
// move
- physic.apply(elapsed_time, base.x, base.y);
+ physic.apply(elapsed_time, base.x, base.y, Sector::current()->gravity);
if(dying == DYING_SQUISHED && !timer.check())
remove_me();
// go in wait mode when back in water
if(dying == DYING_NOT
- && gettile(base.x, base.y+ base.height)->attributes & Tile::WATER
+ && gettile(base.x, base.y + base.height)
+ && gettile(base.x, base.y + base.height)->attributes & Tile::WATER
&& physic.get_velocity_y() <= 0 && mode == NORMAL)
{
mode = FISH_WAIT;
else if(mode == FISH_WAIT && !timer.check())
{
// jump again
- set_sprite(img_fish, img_fish);
+ if(kind == BAD_FISH)
+ set_sprite(img_fish, img_fish);
+ else // BAD_FLAMEFISH
+ set_sprite(img_flamefish, img_flamefish);
mode = NORMAL;
physic.set_velocity(0, JUMPV);
physic.enable_gravity(true);
}
- physic.apply(elapsed_time, base.x, base.y);
+ physic.apply(elapsed_time, base.x, base.y, Sector::current()->gravity);
if(dying == DYING_NOT)
collision_swept_object_map(&old_base, &base);
if(physic.get_velocity_y() < 0)
- set_sprite(img_fish_down, img_fish_down);
+ {
+ if(kind == BAD_FISH)
+ set_sprite(img_fish_down, img_fish_down);
+ else // BAD_FLAMEFISH
+ set_sprite(img_flamefish_down, img_flamefish_down);
+ }
}
void
// check for right/left collisions
check_horizontal_bump();
- physic.apply(elapsed_time, base.x, base.y);
+ physic.apply(elapsed_time, base.x, base.y, Sector::current()->gravity);
if(dying == DYING_NOT)
collision_swept_object_map(&old_base, &base);
if(dying != DYING_NOT)
physic.enable_gravity(true);
- physic.apply(elapsed_time, base.x, base.y);
+ physic.apply(elapsed_time, base.x, base.y, Sector::current()->gravity);
if(dying == DYING_NOT || dying == DYING_SQUISHED)
collision_swept_object_map(&old_base, &base);
}
#endif
- physic.apply(elapsed_time, base.x, base.y);
+ physic.apply(elapsed_time, base.x, base.y, Sector::current()->gravity);
if (dying != DYING_FALLING)
collision_swept_object_map(&old_base,&base);
}
fall();
- physic.apply(elapsed_time, base.x, base.y);
+ physic.apply(elapsed_time, base.x, base.y, Sector::current()->gravity);
if (dying != DYING_FALLING)
collision_swept_object_map(&old_base,&base);
physic.set_velocity(dirsign * WINGLING_FLY_SPEED, 0);
}
- physic.apply(elapsed_time, base.x, base.y);
+ physic.apply(elapsed_time, base.x, base.y, Sector::current()->gravity);
// Handle dying timer:
void
BadGuy::action_walkingtree(double elapsed_time)
{
- Player& tux = *Sector::current()->player;
- Direction v_dir = physic.get_velocity_x() < 0 ? LEFT : RIGHT;
-
if (dying == DYING_NOT)
check_horizontal_bump();
fall();
- if (mode == BGM_BIG)
- {
- if ((tux.base.x + tux.base.width/2 > base.x + base.width/2) && v_dir == LEFT)
- {
- dir = RIGHT;
- physic.set_velocity_x(-physic.get_velocity_x());
- }
- else if ((tux.base.x + tux.base.width/2 < base.x + base.width/2) && v_dir == RIGHT)
- {
- dir = LEFT;
- physic.set_velocity_x(-physic.get_velocity_x());
- }
- }
-
-
- physic.apply(elapsed_time, base.x, base.y);
+ physic.apply(elapsed_time, base.x, base.y, Sector::current()->gravity);
if (dying != DYING_FALLING)
collision_swept_object_map(&old_base,&base);
break;
case BAD_FISH:
+ case BAD_FLAMEFISH:
action_fish(elapsed_time);
break;
return;
if(dying == DYING_FALLING && physic.get_velocity_y() < 0)
- sprite->draw(context, Vector(base.x, base.y), LAYER_OBJECTS, VERTICAL_FLIP);
+ sprite->draw(context, Vector(base.x, base.y), LAYER_FOREGROUNDTILES+1, VERTICAL_FLIP);
else
sprite->draw(context, Vector(base.x, base.y), LAYER_OBJECTS);
{
// these can't be bumped
if(kind == BAD_FLAME || kind == BAD_BOMB || kind == BAD_FISH
- || kind == BAD_FLYINGSNOWBALL)
+ || kind == BAD_FLAMEFISH || kind == BAD_FLYINGSNOWBALL)
return;
physic.set_velocity_y(3);
}
void
-BadGuy::make_player_jump(Player* player)
-{
- player->physic.set_velocity_y(2);
- player->base.y = base.y - player->base.height - 2;
-}
-
-void
BadGuy::squish_me(Player* player)
{
- make_player_jump(player);
+ player->bounce(this);
Sector::current()->add_score(Vector(base.x, base.y),
- 50 * player_status.score_multiplier);
- play_sound(sounds[SND_SQUISH], SOUND_CENTER_SPEAKER);
+ 25 * player_status.score_multiplier);
+
+ SoundManager::get()->play_sound(IDToSound(SND_SQUISH), get_pos(), Sector::current()->player->get_pos());
player_status.score_multiplier++;
dying = DYING_SQUISHED;
// mrbomb transforms into a bomb now
explode(false);
- make_player_jump(player);
+ player->bounce(this);
Sector::current()->add_score(Vector(base.x, base.y),
- 50 * player_status.score_multiplier);
- play_sound(sounds[SND_SQUISH], SOUND_CENTER_SPEAKER);
+ 25 * player_status.score_multiplier);
+ SoundManager::get()->play_sound(IDToSound(SND_SQUISH), get_pos(), Sector::current()->player->get_pos());
+
player_status.score_multiplier++;
return;
if (mode == NORMAL || mode == KICK)
{
/* Flatten! */
- play_sound(sounds[SND_STOMP], SOUND_CENTER_SPEAKER);
+ SoundManager::get()->play_sound(IDToSound(SND_STOMP), get_pos(), Sector::current()->player->get_pos());
mode = FLAT;
set_sprite(img_mriceblock_flat_left, img_mriceblock_flat_right);
physic.set_velocity_x(0);
timer.start(4000);
} else if (mode == FLAT) {
/* Kick! */
- play_sound(sounds[SND_KICK], SOUND_CENTER_SPEAKER);
+ SoundManager::get()->play_sound(IDToSound(SND_KICK), this, Sector::current()->player->get_pos());
if (player->base.x < base.x + (base.width/2)) {
physic.set_velocity_x(5);
set_sprite(img_mriceblock_flat_left, img_mriceblock_flat_right);
}
- make_player_jump(player);
+ player->bounce(this);
player_status.score_multiplier++;
}
return;
- } else if(kind == BAD_FISH) {
+ } else if(kind == BAD_FISH || kind == BAD_FLAMEFISH) {
// fish can only be killed when falling down
if(physic.get_velocity_y() >= 0)
return;
- make_player_jump(player);
+ player->bounce(this);
Sector::current()->add_score(Vector(base.x, base.y),
25 * player_status.score_multiplier);
+
player_status.score_multiplier++;
// simply remove the fish...
{
set_sprite(img_walkingtree_left_small, img_walkingtree_left_small);
physic.set_velocity_x(physic.get_velocity_x() * 2.0f);
+
+ /* Move to the player's direction */
+ if(dir != Sector::current()->player->dir)
+ physic.set_velocity_x(-physic.get_velocity_x());
+ dir = Sector::current()->player->dir;
+
// XXX magic number: 66 is BGM_BIG height
- make_player_jump(player);
+ player->bounce(this);
base.y += 66 - base.height;
-
+
Sector::current()->add_score(Vector(base.x, base.y),
25 * player_status.score_multiplier);
player_status.score_multiplier++;
if(kind == BAD_BOMB)
return;
+ if(mode != HELD)
+ global_stats.add_points(BADGUYS_KILLED_STAT, 1);
+
dying = DYING_FALLING;
if(kind == BAD_MRICEBLOCK) {
set_sprite(img_mriceblock_falling_left, img_mriceblock_falling_right);
score * player_status.score_multiplier);
/* Play death sound: */
- play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
+ SoundManager::get()->play_sound(IDToSound(SND_FALL), this, Sector::current()->player->get_pos());
}
void
if(pbullet_c->kind == FIRE_BULLET)
{
- if (kind != BAD_BOMB && kind != BAD_STALACTITE && kind != BAD_FLAME)
+ if (kind != BAD_BOMB && kind != BAD_STALACTITE && kind != BAD_FLAME
+ && kind != BAD_FLAMEFISH)
kill_me(10);
}
else if(pbullet_c->kind == ICE_BULLET)
{
- //if(kind == BAD_FLAME)
- // kill_me(10);
- //else
+ if(kind == BAD_FLAME || kind == BAD_FLAMEFISH)
+ kill_me(10);
+ else
frozen_timer.start(FROZEN_TIME);
}
break;
pbad_c->explode(true);
return;
}
- else if (pbad_c->kind != BAD_MRBOMB)
+ else
{
pbad_c->kill_me(50);
}
// Jumpy, fish, flame, stalactites, wingling are exceptions
if (pbad_c->kind == BAD_JUMPY || pbad_c->kind == BAD_FLAME
- || pbad_c->kind == BAD_STALACTITE || pbad_c->kind == BAD_FISH)
+ || pbad_c->kind == BAD_STALACTITE || pbad_c->kind == BAD_FISH
+ || pbad_c->kind == BAD_FLAMEFISH)
break;
// Bounce off of other badguy if we land on top of him
dir = RIGHT;
physic.set_velocity_x(fabsf(physic.get_velocity_x()));
- // in case badguys get "jammed"
+ // Put bad guys a part (or they get jammed)
+ // only needed to do to one of them
if (physic.get_velocity_x() != 0)
- base.x = pbad_c->base.x + pbad_c->base.width;
+ base.x = pbad_c->base.x + pbad_c->base.width + 1;
}
else if (dir == RIGHT)
{
/* Get kicked if were flat */
if (mode == FLAT && !dying)
{
- play_sound(sounds[SND_KICK], SOUND_CENTER_SPEAKER);
+ SoundManager::get()->play_sound(IDToSound(SND_KICK), this, Sector::current()->player->get_pos());
// Hit from left side
if (player->base.x < base.x) {
img_fish_down = sprite_manager->load("fish-down");
img_fish_iced = sprite_manager->load("fish-iced");
img_fish_iced_down = sprite_manager->load("fish-iced-down");
+ img_flamefish = sprite_manager->load("flamefish");
+ img_flamefish_down = sprite_manager->load("flamefish-down");
img_bouncingsnowball_left = sprite_manager->load("bouncingsnowball-left");
img_bouncingsnowball_right = sprite_manager->load("bouncingsnowball-right");
img_bouncingsnowball_squished = sprite_manager->load("bouncingsnowball-squished");