static const float Y_OFFSCREEN_DISTANCE = 1200;
BadGuy::BadGuy(const Vector& pos, const std::string& sprite_name, int layer)
- : MovingSprite(pos, sprite_name, layer, COLGROUP_DISABLED), countMe(true), dir(LEFT), start_dir(AUTO), state(STATE_INIT)
+ : MovingSprite(pos, sprite_name, layer, COLGROUP_DISABLED), countMe(true), dir(LEFT), start_dir(AUTO), state(STATE_INIT), on_ground_flag(false)
{
start_position = bbox.p1;
}
BadGuy::BadGuy(const Vector& pos, Direction direction, const std::string& sprite_name, int layer)
- : MovingSprite(pos, sprite_name, layer, COLGROUP_DISABLED), countMe(true), dir(direction), start_dir(direction), state(STATE_INIT)
+ : MovingSprite(pos, sprite_name, layer, COLGROUP_DISABLED), countMe(true), dir(direction), start_dir(direction), state(STATE_INIT), on_ground_flag(false)
{
start_position = bbox.p1;
}
BadGuy::BadGuy(const lisp::Lisp& reader, const std::string& sprite_name, int layer)
- : MovingSprite(reader, sprite_name, layer, COLGROUP_DISABLED), countMe(true), dir(LEFT), start_dir(AUTO), state(STATE_INIT)
+ : MovingSprite(reader, sprite_name, layer, COLGROUP_DISABLED), countMe(true), dir(LEFT), start_dir(AUTO), state(STATE_INIT), on_ground_flag(false)
{
start_position = bbox.p1;
movement = physic.get_movement(elapsed_time);
break;
}
+
+ on_ground_flag = false;
}
Direction
}
void
-BadGuy::collision_solid(const CollisionHit& )
+BadGuy::collision_solid(const CollisionHit& hit)
{
+ update_on_ground_flag(hit);
}
HitResponse
return 0;
}
+
+void
+BadGuy::update_on_ground_flag(const CollisionHit& hit)
+{
+ if (hit.bottom) on_ground_flag = true;
+}
+
+bool
+BadGuy::on_ground()
+{
+ return on_ground_flag;
+}
+
*/
Direction str2dir( std::string dir_str );
+ /**
+ * Update on_ground_flag judging by solid collision @c hit.
+ * This gets called from the base implementation of collision_solid, so call this when overriding collision_solid's default behaviour.
+ */
+ void update_on_ground_flag(const CollisionHit& hit);
+
+ /**
+ * Returns true if we touched ground in the past frame
+ * This only works if update_on_ground_flag() gets called in collision_solid.
+ */
+ bool on_ground();
+
private:
void try_activate();
State state;
Timer state_timer;
+ bool on_ground_flag;
};
#endif
switch (state) {
case STATE_NORMAL:
- if (might_fall()) {
+ if (on_ground() && might_fall()) {
// turn around when we are at a ledge
turn_around();
}
void
Igel::collision_solid(const CollisionHit& hit)
{
+ update_on_ground_flag(hit);
+
if(hit.top || hit.bottom) { // floor or roof
physic.set_velocity_y(0);
return;
void
MrBomb::active_update(float elapsed_time)
{
- if (might_fall())
+ if (on_ground() && might_fall())
{
dir = (dir == LEFT ? RIGHT : LEFT);
sprite->set_action(dir == LEFT ? "left" : "right");
void
MrBomb::collision_solid(const CollisionHit& hit)
{
+ update_on_ground_flag(hit);
+
if(hit.bottom || hit.top) {
physic.set_velocity_y(0);
}
set_state(ICESTATE_NORMAL);
}
- if (ice_state == ICESTATE_NORMAL && might_fall(601))
+ if (ice_state == ICESTATE_NORMAL && on_ground() && might_fall(601))
{
dir = (dir == LEFT ? RIGHT : LEFT);
sprite->set_action(dir == LEFT ? "left" : "right");
void
MrIceBlock::collision_solid(const CollisionHit& hit)
{
+ update_on_ground_flag(hit);
+
if(hit.top || hit.bottom) { // floor or roof
physic.set_velocity_y(0);
return;
case ICESTATE_NORMAL:
if(hit.right && dir == RIGHT) {
dir = LEFT;
+ sprite->set_action(dir == LEFT ? "left" : "right");
+ physic.set_velocity_x(-physic.get_velocity_x());
} else if(hit.left && dir == LEFT) {
dir = RIGHT;
+ sprite->set_action(dir == LEFT ? "left" : "right");
+ physic.set_velocity_x(-physic.get_velocity_x());
}
- sprite->set_action(dir == LEFT ? "left" : "right");
- physic.set_velocity_x(-physic.get_velocity_x());
break;
case ICESTATE_KICKED: {
#if 0
activate();
}
- if (might_fall() && !recently_changed_direction )
+ if (on_ground() && might_fall() && !recently_changed_direction )
{
recently_changed_direction = true;
dir = (dir == LEFT ? RIGHT : LEFT);
void
MrTree::collision_solid(const CollisionHit& hit)
{
+ update_on_ground_flag(hit);
+
if(hit.top || hit.bottom) {
physic.set_velocity_y(0);
} else {
switch (state) {
case STATE_NORMAL:
- if (might_fall(601)) {
+ if (on_ground() && might_fall(601)) {
if( recently_changed_direction ) break;
recently_changed_direction = true;
- dir = (dir == LEFT ? RIGHT : LEFT);
- sprite->set_action(dir == LEFT ? "left" : "right");
- physic.set_velocity_x(-physic.get_velocity_x());
+ dir = (dir == LEFT ? RIGHT : LEFT);
+ sprite->set_action(dir == LEFT ? "left" : "right");
+ physic.set_velocity_x(-physic.get_velocity_x());
}
break;
void
Snail::collision_solid(const CollisionHit& hit)
{
+ update_on_ground_flag(hit);
+
if(hit.top || hit.bottom) { // floor or roof
physic.set_velocity_y(0);
{
BadGuy::active_update(elapsed_time);
- if (might_fall(601))
+ if (on_ground() && might_fall(601))
{
dir = (dir == LEFT ? RIGHT : LEFT);
sprite->set_action(dir == LEFT ? "left" : "right");
void
Spiky::collision_solid(const CollisionHit& hit)
{
+ update_on_ground_flag(hit);
+
if(hit.top || hit.bottom) { // hit floor or roof?
physic.set_velocity_y(0);
} else { // hit right or left
BadGuy::active_update(elapsed_time);
if (!carried_by) {
- if (might_fall())
+ if (on_ground() && might_fall())
{
dir = (dir == LEFT ? RIGHT : LEFT);
activate();
void
Totem::collision_solid(const CollisionHit& hit)
{
+ update_on_ground_flag(hit);
+
// if we are being carried around, pass event to bottom of stack and ignore it
if (carried_by) {
carried_by->collision_solid(hit);