From: Matthias Braun Date: Mon, 9 Jan 2006 22:46:54 +0000 (+0000) Subject: more work on MrIceBlock, you can carry him around and kick him again X-Git-Url: https://git.verplant.org/?a=commitdiff_plain;h=7ffe0f4a7fe4ee1d4041a684638d07557676624c;p=supertux.git more work on MrIceBlock, you can carry him around and kick him again SVN-Revision: 2977 --- diff --git a/src/badguy/mriceblock.cpp b/src/badguy/mriceblock.cpp index 052584869..7da4bf33d 100644 --- a/src/badguy/mriceblock.cpp +++ b/src/badguy/mriceblock.cpp @@ -62,7 +62,10 @@ MrIceBlock::write(lisp::Writer& writer) void MrIceBlock::activate() { - if (set_direction) {dir = initial_direction;} + if (set_direction) { + dir = initial_direction; + } + physic.set_velocity_x(dir == LEFT ? -WALKSPEED : WALKSPEED); sprite->set_action(dir == LEFT ? "left" : "right"); } @@ -70,11 +73,13 @@ MrIceBlock::activate() void MrIceBlock::active_update(float elapsed_time) { + if(ice_state == ICESTATE_GRABBED) + return; + if(ice_state == ICESTATE_FLAT && flat_timer.check()) { - ice_state = ICESTATE_NORMAL; - physic.set_velocity_x(dir == LEFT ? -WALKSPEED : WALKSPEED); - sprite->set_action(dir == LEFT ? "left" : "right"); + set_state(ICESTATE_NORMAL); } + BadGuy::active_update(elapsed_time); } @@ -111,12 +116,48 @@ MrIceBlock::collision_solid(GameObject& object, const CollisionHit& hit) case ICESTATE_FLAT: physic.set_velocity_x(0); break; + case ICESTATE_GRABBED: + return FORCE_MOVE; } return CONTINUE; } HitResponse +MrIceBlock::collision(GameObject& object, const CollisionHit& hit) +{ + if(ice_state == ICESTATE_GRABBED) + return FORCE_MOVE; + + return BadGuy::collision(object, hit); +} + +HitResponse +MrIceBlock::collision_player(Player& player, const CollisionHit& hit) +{ + if(ice_state == ICESTATE_GRABBED) + return FORCE_MOVE; + + // handle kicks from left or right side + if(ice_state == ICESTATE_FLAT && get_state() == STATE_ACTIVE) { + // hit from left side + if(hit.normal.x > 0.7) { + dir = RIGHT; + player.kick(); + set_state(ICESTATE_KICKED); + return FORCE_MOVE; + } else if(hit.normal.x < -0.7) { + dir = LEFT; + player.kick(); + set_state(ICESTATE_KICKED); + return FORCE_MOVE; + } + } + + return BadGuy::collision_player(player, hit); +} + +HitResponse MrIceBlock::collision_badguy(BadGuy& badguy, const CollisionHit& hit) { switch(ice_state) { @@ -151,32 +192,86 @@ MrIceBlock::collision_squished(Player& player) return true; } - // flatten + set_state(ICESTATE_FLAT); + break; + case ICESTATE_FLAT: + if(player.get_pos().x < get_pos().x) { + dir = RIGHT; + } else { + dir = LEFT; + } + set_state(ICESTATE_KICKED); + break; + case ICESTATE_GRABBED: + assert(false); + break; + } + + player.bounce(*this); + return true; +} + +void +MrIceBlock::set_state(IceState state) +{ + if(ice_state == state) + return; + + if(state == ICESTATE_FLAT) + flags |= FLAG_PORTABLE; + else + flags &= ~FLAG_PORTABLE; + + if(ice_state == ICESTATE_KICKED) { + bbox.set_size(31.8, 31.8); + } + + switch(state) { + case ICESTATE_NORMAL: + physic.set_velocity_x(dir == LEFT ? -WALKSPEED : WALKSPEED); + sprite->set_action(dir == LEFT ? "left" : "right"); + break; + case ICESTATE_FLAT: sound_manager->play("sounds/stomp.wav", get_pos()); physic.set_velocity_x(0); physic.set_velocity_y(0); sprite->set_action(dir == LEFT ? "flat-left" : "flat-right"); flat_timer.start(4); - ice_state = ICESTATE_FLAT; break; - case ICESTATE_FLAT: - // kick + case ICESTATE_KICKED: sound_manager->play("sounds/kick.wav", get_pos()); - if(player.get_pos().x < get_pos().x) { - dir = RIGHT; - } else { - dir = LEFT; - } physic.set_velocity_x(dir == LEFT ? -KICKSPEED : KICKSPEED); sprite->set_action(dir == LEFT ? "flat-left" : "flat-right"); - ice_state = ICESTATE_KICKED; + // we should slide above 1 block holes now... + bbox.set_size(32.5, 31.8); + break; + case ICESTATE_GRABBED: + flat_timer.stop(); break; + default: + assert(false); } + ice_state = state; +} - player.bounce(*this); - return true; +void +MrIceBlock::grab(MovingObject&, const Vector& pos, Direction dir) +{ + movement = pos - get_pos(); + this->dir = dir; + sprite->set_action(dir == LEFT ? "flat-left" : "flat-right"); + set_state(ICESTATE_GRABBED); + set_group(COLGROUP_DISABLED); +} + +void +MrIceBlock::ungrab(MovingObject& , Direction dir) +{ + this->dir = dir; + set_state(ICESTATE_KICKED); + set_group(COLGROUP_MOVING); } IMPLEMENT_FACTORY(MrIceBlock, "mriceblock") diff --git a/src/badguy/mriceblock.hpp b/src/badguy/mriceblock.hpp index 4031e0d2c..bd0ff53dc 100644 --- a/src/badguy/mriceblock.hpp +++ b/src/badguy/mriceblock.hpp @@ -22,8 +22,9 @@ #define __MRICEBLOCK_H__ #include "badguy.hpp" +#include "object/portable.hpp" -class MrIceBlock : public BadGuy +class MrIceBlock : public BadGuy, public Portable { public: MrIceBlock(const lisp::Lisp& reader); @@ -31,10 +32,15 @@ public: void activate(); void write(lisp::Writer& writer); + HitResponse collision(GameObject& object, const CollisionHit& hit); HitResponse collision_solid(GameObject& object, const CollisionHit& hit); HitResponse collision_badguy(BadGuy& badguy, const CollisionHit& hit); + HitResponse collision_player(Player& player, const CollisionHit& hit); void active_update(float elapsed_time); + + void grab(MovingObject& object, const Vector& pos, Direction dir); + void ungrab(MovingObject& object, Direction dir); protected: bool collision_squished(Player& player); @@ -43,13 +49,17 @@ private: enum IceState { ICESTATE_NORMAL, ICESTATE_FLAT, + ICESTATE_GRABBED, ICESTATE_KICKED }; + + void set_state(IceState state); + IceState ice_state; Timer flat_timer; int squishcount; bool set_direction; - Direction initial_direction; + Direction initial_direction; }; #endif diff --git a/src/direction.hpp b/src/direction.hpp index 5ecc417bc..ac32a21ef 100644 --- a/src/direction.hpp +++ b/src/direction.hpp @@ -23,5 +23,4 @@ enum Direction { LEFT = 0, RIGHT = 1 }; -#endif /*SUPERTUX_DEFINES_H*/ - +#endif diff --git a/src/game_object.hpp b/src/game_object.hpp index 6e0c4eed4..a1734ab45 100644 --- a/src/game_object.hpp +++ b/src/game_object.hpp @@ -78,7 +78,9 @@ public: // flags enum { /// the tile so you can stand on it - FLAG_SOLID = 0x0001, + FLAG_SOLID = (1 << 0), + /// the object can be carried around (inherits from Portable) + FLAG_PORTABLE = (1 << 1) }; int get_flags() const diff --git a/src/object/player.cpp b/src/object/player.cpp index 043a770f0..884059f73 100644 --- a/src/object/player.cpp +++ b/src/object/player.cpp @@ -57,6 +57,8 @@ static const float MAX_WALK_XM = 230; static const float MAX_RUN_XM = 320; static const float WALK_SPEED = 100; +static const float KICK_TIME = .3; + // growing animation Surface* growingtux_left[GROWING_FRAMES]; Surface* growingtux_right[GROWING_FRAMES]; @@ -177,6 +179,7 @@ Player::update(float elapsed_time) std::cout << "Non MovingObjetc grabbed?!?\n"; #endif } + grabbed_object->ungrab(*this, dir); grabbed_object = 0; } } @@ -201,7 +204,7 @@ Player::update(float elapsed_time) Vector pos = get_pos() + Vector(dir == LEFT ? -16 : 16, bbox.get_height()*0.66666 - 32); - grabbed_object->grab(*this, pos); + grabbed_object->grab(*this, pos, dir); } } @@ -520,6 +523,12 @@ Player::set_bonus(BonusType type, bool animate) } void +Player::kick() +{ + kick_timer.start(KICK_TIME); +} + +void Player::draw(DrawingContext& context) { TuxBodyParts* tux_body; @@ -682,11 +691,13 @@ Player::collision(GameObject& other, const CollisionHit& hit) return FORCE_MOVE; } - Portable* portable = dynamic_cast (&other); - if(portable && grabbed_object == 0 && controller->hold(Controller::ACTION) - && fabsf(hit.normal.x) > .9) { - grabbed_object = portable; - return CONTINUE; + if(other.get_flags() & FLAG_PORTABLE) { + Portable* portable = dynamic_cast (&other); + if(portable && grabbed_object == 0 && controller->hold(Controller::ACTION) + && fabsf(hit.normal.x) > .9) { + grabbed_object = portable; + return CONTINUE; + } } if(other.get_flags() & FLAG_SOLID) { diff --git a/src/object/player.hpp b/src/object/player.hpp index 253364d72..b24718671 100644 --- a/src/object/player.hpp +++ b/src/object/player.hpp @@ -144,6 +144,8 @@ public: { return player_status; } + // set kick animation + void kick(); void bounce(BadGuy& badguy); diff --git a/src/object/portable.hpp b/src/object/portable.hpp index ae7199b64..265f0a043 100644 --- a/src/object/portable.hpp +++ b/src/object/portable.hpp @@ -21,6 +21,7 @@ #define __PORTABLE_H__ #include "moving_object.hpp" +#include "direction.hpp" /** * An object that inherits from this object is considered "portable" and can @@ -37,7 +38,10 @@ public: /** * called each frame when the object has been grabbed. */ - virtual void grab(MovingObject& object, const Vector& pos) = 0; + virtual void grab(MovingObject& object, const Vector& pos, Direction dir) = 0; + + virtual void ungrab(MovingObject& , Direction ) + {} }; #endif diff --git a/src/object/rock.cpp b/src/object/rock.cpp index df1371c89..b6ad844f8 100644 --- a/src/object/rock.cpp +++ b/src/object/rock.cpp @@ -91,7 +91,7 @@ Rock::collision(GameObject& object, const CollisionHit& ) } void -Rock::grab(MovingObject& , const Vector& pos) +Rock::grab(MovingObject& , const Vector& pos, Direction) { movement = pos - get_pos(); grabbed = true; diff --git a/src/object/rock.hpp b/src/object/rock.hpp index 9e48d1b24..1ddce97a5 100644 --- a/src/object/rock.hpp +++ b/src/object/rock.hpp @@ -39,7 +39,7 @@ public: void draw(DrawingContext& context); void write(lisp::Writer& writer); - void grab(MovingObject& object, const Vector& pos); + void grab(MovingObject& object, const Vector& pos, Direction dir); private: bool grabbed;