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");
}
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);
}
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) {
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")
#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);
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);
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
enum Direction { LEFT = 0, RIGHT = 1 };
-#endif /*SUPERTUX_DEFINES_H*/
-
+#endif
// 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
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];
std::cout << "Non MovingObjetc grabbed?!?\n";
#endif
}
+ grabbed_object->ungrab(*this, dir);
grabbed_object = 0;
}
}
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);
}
}
}
void
+Player::kick()
+{
+ kick_timer.start(KICK_TIME);
+}
+
+void
Player::draw(DrawingContext& context)
{
TuxBodyParts* tux_body;
return FORCE_MOVE;
}
- Portable* portable = dynamic_cast<Portable*> (&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<Portable*> (&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) {
{
return player_status;
}
+ // set kick animation
+ void kick();
void bounce(BadGuy& badguy);
#define __PORTABLE_H__
#include "moving_object.hpp"
+#include "direction.hpp"
/**
* An object that inherits from this object is considered "portable" and can
/**
* 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
}
void
-Rock::grab(MovingObject& , const Vector& pos)
+Rock::grab(MovingObject& , const Vector& pos, Direction)
{
movement = pos - get_pos();
grabbed = true;
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;