Badguys keep track of floor normal they are standing on.
SVN-Revision: 4435
return ABORT_MOVE;
case STATE_ACTIVE: {
BadGuy* badguy = dynamic_cast<BadGuy*> (&other);
- if(badguy && badguy->state == STATE_ACTIVE && badguy->get_group() == COLGROUP_MOVING)
- return collision_badguy(*badguy, hit);
+ if(badguy && badguy->state == STATE_ACTIVE && badguy->get_group() == COLGROUP_MOVING) {
+
+ // hit from above?
+ if (badguy->get_bbox().p2.y < (bbox.p1.y + 16)) {
+ if(collision_squished(*badguy)) {
+ return ABORT_MOVE;
+ }
+ }
+
+ return collision_badguy(*badguy, hit);
+ }
Player* player = dynamic_cast<Player*> (&other);
- if(player)
+ if(player) {
+
+ // hit from above?
+ if (player->get_bbox().p2.y < (bbox.p1.y + 16)) {
+ if(collision_squished(*player)) {
+ return ABORT_MOVE;
+ }
+ }
+
return collision_player(*player, hit);
+ }
Bullet* bullet = dynamic_cast<Bullet*> (&other);
if(bullet)
HitResponse
BadGuy::collision_player(Player& player, const CollisionHit& )
{
- // hit from above?
- if(player.get_bbox().p2.y < (bbox.p1.y + 16)) {
- // if it's not possible to squish us, then this will hurt
- if(collision_squished(player)) {
- return ABORT_MOVE;
- }
- }
-
if(player.is_invincible()) {
kill_fall();
return ABORT_MOVE;
}
bool
-BadGuy::collision_squished(Player& )
+BadGuy::collision_squished(GameObject& )
{
return false;
}
}
void
-BadGuy::kill_squished(Player& player)
+BadGuy::kill_squished(GameObject& object)
{
sound_manager->play("sounds/squish.wav", get_pos());
physic.enable_gravity(true);
physic.set_velocity_y(0);
set_state(STATE_SQUISHED);
set_group(COLGROUP_MOVING_ONLY_STATIC);
- if (countMe) Sector::current()->get_level()->stats.badguys++;
- player.bounce(*this);
+ Player* player = dynamic_cast<Player*>(&object);
+ if (player) {
+ if (countMe) Sector::current()->get_level()->stats.badguys++;
+ player->bounce(*this);
+ }
}
void
void
BadGuy::update_on_ground_flag(const CollisionHit& hit)
{
- if (hit.bottom) on_ground_flag = true;
+ if (hit.bottom) {
+ on_ground_flag = true;
+ floor_normal = hit.slope_normal;
+ }
}
bool
return on_ground_flag;
}
+Vector
+BadGuy::get_floor_normal()
+{
+ return floor_normal;
+}
+
void
BadGuy::freeze()
{
/** Called when the player hit the badguy from above. You should return true
* if the badguy was squished, false if squishing wasn't possible
*/
- virtual bool collision_squished(Player& player);
+ virtual bool collision_squished(GameObject& object);
/** Called when the badguy collided with a bullet */
virtual HitResponse collision_bullet(Bullet& bullet, const CollisionHit& hit);
/** called when the badguy has been deactivated */
virtual void deactivate();
- void kill_squished(Player& player);
+ void kill_squished(GameObject& object);
void set_state(State state);
State get_state() const
*/
bool on_ground();
+ /**
+ * Returns floor normal stored the last time when update_on_ground_flag was called and we touched something solid from above.
+ */
+ Vector get_floor_normal();
+
bool frozen;
bool ignited; /**< true if this badguy is currently on fire */
State state;
Timer state_timer;
- bool on_ground_flag;
+ bool on_ground_flag; /**< true if we touched something solid from above and update_on_ground_flag was called last frame */
+ Vector floor_normal; /**< floor normal stored the last time when update_on_ground_flag was called and we touched something solid from above */
+
};
#endif
}
bool
-BouncingSnowball::collision_squished(Player& player)
+BouncingSnowball::collision_squished(GameObject& object)
{
sprite->set_action("squished");
- kill_squished(player);
+ kill_squished(object);
return true;
}
virtual BouncingSnowball* clone() const { return new BouncingSnowball(*this); }
protected:
- bool collision_squished(Player& player);
+ bool collision_squished(GameObject& object);
};
#endif
//TODO: Add launching velocity to certain badguys
bool
-Dispenser::collision_squished(Player& player)
+Dispenser::collision_squished(GameObject& object)
{
//TODO: Should it act like a normal tile when killed?
sprite->set_action(dir == LEFT ? "broken-left" : "broken-right");
dispense_timer.start(0);
- player.bounce(*this);
- kill_squished(player);
+ Player* player = dynamic_cast<Player*>(&object);
+ if (player) player->bounce(*this);
+ kill_squished(object);
return true;
}
virtual Dispenser* clone() const { return new Dispenser(*this); }
protected:
- bool collision_squished(Player& player);
+ bool collision_squished(GameObject& object);
void launch_badguy();
float cycle;
std::string badguy;
}
bool
-FlyingSnowBall::collision_squished(Player& player)
+FlyingSnowBall::collision_squished(GameObject& object)
{
sprite->set_action(dir == LEFT ? "squished-left" : "squished-right");
- kill_squished(player);
+ kill_squished(object);
return true;
}
FLY_DOWN
};
FlyingSnowballMode mode;
- bool collision_squished(Player& player);
+ bool collision_squished(GameObject& object);
private:
Timer timer;
Timer puff_timer; /**< time until the next smoke puff is spawned */
: WalkingBadguy(reader, "images/creatures/igel/igel.sprite", "walking-left", "walking-right")
{
walk_speed = WALKSPEED;
- max_drop_height = 0;
+ max_drop_height = 16;
}
Igel::Igel(const Vector& pos, Direction d)
: WalkingBadguy(pos, d, "images/creatures/igel/igel.sprite", "walking-left", "walking-right")
{
walk_speed = WALKSPEED;
- max_drop_height = 0;
+ max_drop_height = 16;
}
void
}
bool
-Igel::collision_squished(Player& )
+Igel::collision_squished(GameObject& )
{
// this will hurt
return false;
virtual Igel* clone() const { return new Igel(*this); }
protected:
- bool collision_squished(Player& player);
+ bool collision_squished(GameObject& object);
void be_normal(); /**< switch to state STATE_NORMAL */
void turn_around(); /**< reverse direction, assumes we are in STATE_NORMAL */
bool can_see(const MovingObject& o); /**< check if we can see o */
}
bool
-Mole::collision_squished(Player& )
+Mole::collision_squished(GameObject& )
{
set_state(DEAD);
sound_manager->play("sounds/squish.wav", get_pos());
void kill_fall();
HitResponse collision_badguy(BadGuy& , const CollisionHit& );
- bool collision_squished(Player& player);
+ bool collision_squished(GameObject& object);
void activate();
void write(lisp::Writer& );
: WalkingBadguy(reader, "images/creatures/mr_bomb/mr_bomb.sprite", "left", "right")
{
walk_speed = 80;
- max_drop_height = 0;
+ max_drop_height = 16;
grabbed = false;
//Check if we need another sprite
: WalkingBadguy(pos, d, "images/creatures/mr_bomb/mr_bomb.sprite", "left", "right")
{
walk_speed = 80;
- max_drop_height = 0;
+ max_drop_height = 16;
grabbed = false;
}
}
bool
-MrBomb::collision_squished(Player& player)
+MrBomb::collision_squished(GameObject& object)
{
remove_me();
Sector::current()->add_object(new Bomb(get_pos(), dir, sprite_name ));
- kill_squished(player);
+ kill_squished(object);
return true;
}
virtual MrBomb* clone() const { return new MrBomb(*this); }
protected:
- bool collision_squished(Player& player);
+ bool collision_squished(GameObject& object);
private:
bool grabbed;
}
bool
-MrIceBlock::collision_squished(Player& player)
+MrIceBlock::collision_squished(GameObject& object)
{
switch(ice_state) {
case ICESTATE_KICKED:
set_state(ICESTATE_FLAT);
break;
case ICESTATE_FLAT:
- if(player.get_pos().x < get_pos().x) {
- dir = RIGHT;
- } else {
- dir = LEFT;
+ {
+ MovingObject* movingobject = dynamic_cast<MovingObject*>(&object);
+ if (movingobject && (movingobject->get_pos().x < get_pos().x)) {
+ dir = RIGHT;
+ } else {
+ dir = LEFT;
+ }
}
set_state(ICESTATE_KICKED);
break;
break;
}
- player.bounce(*this);
+ Player* player = dynamic_cast<Player*>(&object);
+ if (player) player->bounce(*this);
return true;
}
virtual MrIceBlock* clone() const { return new MrIceBlock(*this); }
protected:
- bool collision_squished(Player& player);
+ bool collision_squished(GameObject& object);
private:
enum IceState {
}
bool
-MrRocket::collision_squished(Player& player)
+MrRocket::collision_squished(GameObject& object)
{
sprite->set_action(dir == LEFT ? "squished-left" : "squished-right");
- kill_squished(player);
+ kill_squished(object);
kill_fall();
return true;
}
virtual MrRocket* clone() const { return new MrRocket(*this); }
protected:
- bool collision_squished(Player& player);
+ bool collision_squished(GameObject& object);
Timer collision_timer;
};
: WalkingBadguy(reader, "images/creatures/mr_tree/mr_tree.sprite","left","right")
{
walk_speed = WALKSPEED;
- max_drop_height = 0;
+ max_drop_height = 16;
sound_manager->preload("sounds/mr_tree.ogg");
}
}
bool
-MrTree::collision_squished(Player& player)
+MrTree::collision_squished(GameObject& object)
{
// replace with Stumpy
Vector stumpy_pos = get_pos();
// give Feedback
sound_manager->play("sounds/mr_tree.ogg", get_pos());
- player.bounce(*this);
+ Player* player = dynamic_cast<Player*>(&object);
+ if (player) player->bounce(*this);
// spawn some particles
// TODO: provide convenience function in MovingSprite or MovingObject?
virtual MrTree* clone() const { return new MrTree(*this); }
protected:
- bool collision_squished(Player& player);
+ bool collision_squished(GameObject& object);
};
}
bool
-PoisonIvy::collision_squished(Player& player)
+PoisonIvy::collision_squished(GameObject& object)
{
sprite->set_action(dir == LEFT ? "squished-left" : "squished-right");
// spawn some particles
Vector paccel = Vector(0, 100);
Sector::current()->add_object(new SpriteParticle("images/objects/particles/poisonivy.sprite", "default", ppos, ANCHOR_MIDDLE, pspeed, paccel, LAYER_OBJECTS-1));
}
- kill_squished(player);
+ kill_squished(object);
return true;
}
virtual PoisonIvy* clone() const { return new PoisonIvy(*this); }
protected:
- bool collision_squished(Player& player);
+ bool collision_squished(GameObject& object);
};
}
bool
-SkullyHop::collision_squished(Player& player)
+SkullyHop::collision_squished(GameObject& object)
{
sprite->set_action(dir == LEFT ? "squished-left" : "squished-right");
- kill_squished(player);
+ kill_squished(object);
return true;
}
void write(lisp::Writer& writer);
void collision_solid(const CollisionHit& hit);
HitResponse collision_badguy(BadGuy& badguy, const CollisionHit& hit);
- bool collision_squished(Player& player);
+ bool collision_squished(GameObject& object);
void active_update(float elapsed_time);
virtual SkullyHop* clone() const { return new SkullyHop(*this); }
}
bool
-Snail::collision_squished(Player& player)
+Snail::collision_squished(GameObject& object)
{
switch(state) {
case STATE_FLAT:
sound_manager->play("sounds/kick.wav", get_pos());
-
- if(player.get_pos().x < get_pos().x) {
- dir = RIGHT;
- } else {
- dir = LEFT;
+ {
+ MovingObject* movingobject = dynamic_cast<MovingObject*>(&object);
+ if (movingobject && (movingobject->get_pos().x < get_pos().x)) {
+ dir = RIGHT;
+ } else {
+ dir = LEFT;
+ }
}
be_kicked();
break;
}
- player.bounce(*this);
+ Player* player = dynamic_cast<Player*>(&object);
+ if (player) player->bounce(*this);
return true;
}
virtual Snail* clone() const { return new Snail(*this); }
protected:
- bool collision_squished(Player& player);
+ bool collision_squished(GameObject& object);
void be_normal(); /**< switch to state STATE_NORMAL */
void be_flat(); /**< switch to state STATE_FLAT */
void be_kicked(); /**< switch to state STATE_KICKED_DELAY */
}
bool
-SnowBall::collision_squished(Player& player)
+SnowBall::collision_squished(GameObject& object)
{
sprite->set_action(dir == LEFT ? "squished-left" : "squished-right");
- kill_squished(player);
+ kill_squished(object);
return true;
}
virtual SnowBall* clone() const { return new SnowBall(*this); }
protected:
- bool collision_squished(Player& player);
+ bool collision_squished(GameObject& object);
};
}
bool
-SpiderMite::collision_squished(Player& player)
+SpiderMite::collision_squished(GameObject& object)
{
sprite->set_action(dir == LEFT ? "squished-left" : "squished-right");
- kill_squished(player);
+ kill_squished(object);
return true;
}
FLY_DOWN
};
SpiderMiteMode mode;
- bool collision_squished(Player& player);
+ bool collision_squished(GameObject& object);
private:
Timer timer;
};
: WalkingBadguy(reader, "images/creatures/mr_tree/stumpy.sprite","left","right"), mystate(STATE_NORMAL)
{
walk_speed = WALKSPEED;
- max_drop_height = 0;
+ max_drop_height = 16;
sound_manager->preload("sounds/mr_tree.ogg");
sound_manager->preload("sounds/mr_treehit.ogg");
}
: WalkingBadguy(pos, d, "images/creatures/mr_tree/stumpy.sprite","left","right"), mystate(STATE_INVINCIBLE)
{
walk_speed = WALKSPEED;
- max_drop_height = 0;
+ max_drop_height = 16;
sound_manager->preload("sounds/mr_treehit.ogg");
invincible_timer.start(INVINCIBLE_TIME);
}
}
bool
-Stumpy::collision_squished(Player& player)
+Stumpy::collision_squished(GameObject& object)
{
// if we're still invincible, we ignore the hit
if (mystate == STATE_INVINCIBLE) {
sound_manager->play("sounds/mr_treehit.ogg", get_pos());
- player.bounce(*this);
+ Player* player = dynamic_cast<Player*>(&object);
+ if (player) player->bounce(*this);
return true;
}
if (mystate == STATE_NORMAL) {
sprite->set_action(dir == LEFT ? "squished-left" : "squished-right");
set_size(sprite->get_current_hitbox_width(), sprite->get_current_hitbox_height());
- kill_squished(player);
+ kill_squished(object);
// spawn some particles
// TODO: provide convenience function in MovingSprite or MovingObject?
for (int i = 0; i < 25; i++) {
Timer invincible_timer;
- bool collision_squished(Player& player);
+ bool collision_squished(GameObject& object);
};
#endif
}
bool
-Toad::collision_squished(Player& player)
+Toad::collision_squished(GameObject& object)
{
sprite->set_action(dir == LEFT ? "squished-left" : "squished-right");
- kill_squished(player);
+ kill_squished(object);
return true;
}
void write(lisp::Writer& writer);
void collision_solid(const CollisionHit& hit);
HitResponse collision_badguy(BadGuy& badguy, const CollisionHit& hit);
- bool collision_squished(Player& player);
+ bool collision_squished(GameObject& object);
void active_update(float elapsed_time);
virtual Toad* clone() const { return new Toad(*this); }
}
bool
-Totem::collision_squished(Player& player)
+Totem::collision_squished(GameObject& object)
{
if (carrying) carrying->jump_off();
if (carried_by) {
- player.bounce(*this);
+ Player* player = dynamic_cast<Player*>(&object);
+ if (player) player->bounce(*this);
jump_off();
}
sprite->set_action(dir == LEFT ? "squished-left" : "squished-right");
bbox.set_size(sprite->get_current_hitbox_width(), sprite->get_current_hitbox_height());
- kill_squished(player);
+ kill_squished(object);
return true;
}
Totem* carrying; /**< Totem we are currently carrying (or 0) */
Totem* carried_by; /**< Totem by which we are currently carried (or 0) */
- bool collision_squished(Player& player);
+ bool collision_squished(GameObject& object);
void kill_fall();
void jump_on(Totem* target); /**< jump on target */
update_on_ground_flag(hit);
- if (hit.top || hit.bottom) {
- physic.set_velocity_y(0);
+ if (hit.top) {
+ if (physic.get_velocity_y() < 0) physic.set_velocity_y(0);
+ }
+ if (hit.bottom) {
+ if (physic.get_velocity_y() > 0) physic.set_velocity_y(0);
}
- if ((hit.left && dir == LEFT) || (hit.right && dir == RIGHT)) {
+ if ((hit.left && (hit.slope_normal.y == 0) && (dir == LEFT)) || (hit.right && (hit.slope_normal.y == 0) && (dir == RIGHT))) {
turn_around();
}
: WalkingBadguy(reader, "images/creatures/walkingleaf/walkingleaf.sprite", "left", "right")
{
walk_speed = 60;
- max_drop_height = 0;
+ max_drop_height = 16;
}
WalkingLeaf::WalkingLeaf(const Vector& pos, Direction d)
: WalkingBadguy(pos, d, "images/creatures/walkingleaf/walkingleaf.sprite", "left", "right")
{
walk_speed = 60;
- max_drop_height = 0;
+ max_drop_height = 16;
}
bool
-WalkingLeaf::collision_squished(Player& player)
+WalkingLeaf::collision_squished(GameObject& object)
{
sprite->set_action(dir == LEFT ? "squished-left" : "squished-right");
- kill_squished(player);
+ kill_squished(object);
return true;
}
virtual WalkingLeaf* clone() const { return new WalkingLeaf(*this); }
protected:
- bool collision_squished(Player& player);
+ bool collision_squished(GameObject& object);
};
}
bool
-Yeti::collision_squished(Player& player)
+Yeti::collision_squished(GameObject& object)
{
- kill_squished(player);
+ kill_squished(object);
return true;
}
void
-Yeti::kill_squished(Player& player)
+Yeti::kill_squished(GameObject& object)
{
- player.bounce(*this);
- take_hit(player);
+ Player* player = dynamic_cast<Player*>(&object);
+ if (player) {
+ player->bounce(*this);
+ take_hit(*player);
+ }
}
void Yeti::take_hit(Player& )
void activate();
void active_update(float elapsed_time);
void collision_solid(const CollisionHit& hit);
- bool collision_squished(Player& player);
- void kill_squished(Player& player);
+ bool collision_squished(GameObject& object);
+ void kill_squished(GameObject& object);
void kill_fall();
virtual Yeti* clone() const { return new Yeti(*this); }
}
bool
-Zeekling::collision_squished(Player& player)
+Zeekling::collision_squished(GameObject& object)
{
sprite->set_action(dir == LEFT ? "squished-left" : "squished-right");
- kill_squished(player);
+ kill_squished(object);
kill_fall();
return true;
}
virtual Zeekling* clone() const { return new Zeekling(*this); }
protected:
- bool collision_squished(Player& player);
+ bool collision_squished(GameObject& object);
float speed;
Timer diveRecoverTimer;