sound_manager->preload("sounds/hurt.wav");
sound_manager->preload("sounds/skid.wav");
sound_manager->preload("sounds/flip.wav");
+ sound_manager->preload("sounds/invincible.wav");
init();
}
dead = false;
dying = false;
+ peeking = AUTO;
last_ground_y = 0;
fall_mode = ON_GROUND;
jumping = false;
on_ground_flag = false;
grabbed_object = NULL;
- floor_normal = Vector(0,-1);
-
physic.reset();
}
Rect bbox2 = bbox;
bbox2.move(Vector(0, bbox.get_height() - new_height));
bbox2.set_height(new_height);
- if (!Sector::current()->is_free_space(bbox2)) return false;
+ if (!Sector::current()->is_free_space(bbox2))
+ return false;
+
// adjust bbox accordingly
// note that we use members of moving_object for this, so we can run this during CD, too
set_pos(bbox2.p1);
set_width(31.8);
}
- // on downward slopes, adjust vertical velocity to match slope angle
+ // on downward slopes, adjust vertical velocity so tux walks smoothly down
if (on_ground()) {
- if (floor_normal.y != 0) {
- if ((floor_normal.x * physic.get_velocity_x()) > 0) {
- // we overdo it a little, just to be on the safe side
- physic.set_velocity_y(-physic.get_velocity_x() * (floor_normal.x / floor_normal.y) * 2);
+ if(floor_normal.y != 0) {
+ if ((floor_normal.x * physic.get_velocity_x()) >= 0) {
+ physic.set_velocity_y(250);
}
}
}
}
on_ground_flag = false;
+
+ // when invincible, spawn particles
+ if (invincible_timer.started() && !dying)
+ {
+ if (systemRandom.rand(0, 2) == 0) {
+ float px = systemRandom.randf(bbox.p1.x+0, bbox.p2.x-0);
+ float py = systemRandom.randf(bbox.p1.y+0, bbox.p2.y-0);
+ Vector ppos = Vector(px, py);
+ Vector pspeed = Vector(0, 0);
+ Vector paccel = Vector(0, 0);
+ // draw bright sparkle when there is lots of time left, dark sparkle when invincibility is about to end
+ if (invincible_timer.get_timeleft() > TUX_INVINCIBLE_TIME_WARNING) {
+ // make every other a longer sparkle to make trail a bit fuzzy
+ if (size_t(game_time*20)%2) {
+ Sector::current()->add_object(new SpriteParticle("images/objects/particles/sparkle.sprite", "small", ppos, ANCHOR_MIDDLE, pspeed, paccel, LAYER_OBJECTS+1+5));
+ } else {
+ Sector::current()->add_object(new SpriteParticle("images/objects/particles/sparkle.sprite", "medium", ppos, ANCHOR_MIDDLE, pspeed, paccel, LAYER_OBJECTS+1+5));
+ }
+ } else {
+ Sector::current()->add_object(new SpriteParticle("images/objects/particles/sparkle.sprite", "dark", ppos, ANCHOR_MIDDLE, pspeed, paccel, LAYER_OBJECTS+1+5));
+ }
+ }
+ }
+
}
bool
}
/* When Down is not held anymore, disable butt jump */
- if(butt_jump && !controller->hold(Controller::DOWN)) butt_jump = false;
-
- /** jumping is only allowed if we're about to touch ground soon and if the
- * button has been up in between the last jump
- */
- // FIXME
-#if 0
- if ( (issolid(get_pos().x + bbox.get_width() / 2,
- get_pos().y + bbox.get_height() + 64) ||
- issolid(get_pos().x + 1, get_pos().y + bbox.get_height() + 64) ||
- issolid(get_pos().x + bbox.get_width() - 1,
- get_pos().y + bbox.get_height() + 64))
- && jumping == false
- && can_jump == false
- && input.jump && !input.old_jump)
- {
- can_jump = true;
- }
-#endif
+ if(butt_jump && !controller->hold(Controller::DOWN))
+ butt_jump = false;
}
void
grabbed_object = NULL;
}
}
+
+ /* Peeking */
+ if( controller->released( Controller::PEEK_LEFT ) ) {
+ peeking = AUTO;
+ }
+ if( controller->released( Controller::PEEK_RIGHT ) ) {
+ peeking = AUTO;
+ }
+ if( controller->pressed( Controller::PEEK_LEFT ) ) {
+ peeking = LEFT;
+ }
+ if( controller->pressed( Controller::PEEK_RIGHT ) ) {
+ peeking = RIGHT;
+ }
/* Handle horizontal movement: */
if (!backflipping) handle_horizontal_input();
player_status->add_coins(count);
}
-void
+bool
Player::add_bonus(const std::string& bonustype)
{
+ BonusType type = NO_BONUS;
+
if(bonustype == "grow") {
- add_bonus(GROWUP_BONUS);
+ type = GROWUP_BONUS;
} else if(bonustype == "fireflower") {
- add_bonus(FIRE_BONUS);
+ type = FIRE_BONUS;
} else if(bonustype == "iceflower") {
- add_bonus(ICE_BONUS);
+ type = ICE_BONUS;
} else if(bonustype == "none") {
- add_bonus(NO_BONUS);
+ type = NO_BONUS;
} else {
std::ostringstream msg;
msg << "Unknown bonus type " << bonustype;
throw std::runtime_error(msg.str());
}
+
+ return add_bonus(type);
}
-void
+bool
Player::add_bonus(BonusType type, bool animate)
{
// always ignore NO_BONUS
if (type == NO_BONUS) {
- return;
+ return true;
}
// ignore GROWUP_BONUS if we're already big
if (type == GROWUP_BONUS) {
- if (player_status->bonus == GROWUP_BONUS) return;
- if (player_status->bonus == FIRE_BONUS) return;
- if (player_status->bonus == ICE_BONUS) return;
+ if (player_status->bonus == GROWUP_BONUS)
+ return true;
+ if (player_status->bonus == FIRE_BONUS)
+ return true;
+ if (player_status->bonus == ICE_BONUS)
+ return true;
}
- set_bonus(type, animate);
+ return set_bonus(type, animate);
}
-void
+bool
Player::set_bonus(BonusType type, bool animate)
{
if(player_status->bonus == NO_BONUS) {
- if (!adjust_height(62.8)) return;
+ if (!adjust_height(62.8)) {
+ printf("can't adjust\n");
+ return false;
+ }
if(animate)
growing_timer.start(GROWING_TIME);
}
if (type == ICE_BONUS) player_status->max_ice_bullets++;
player_status->bonus = type;
+ return true;
}
void
Player::set_visible(bool visible)
{
this->visible = visible;
+ if( visible )
+ set_group(COLGROUP_MOVING);
+ else
+ set_group(COLGROUP_DISABLED);
}
bool
else
tux_body->draw(context, get_pos(), layer);
- // Draw blinking star overlay
- if (invincible_timer.started() &&
- (invincible_timer.get_timeleft() > TUX_INVINCIBLE_TIME_WARNING
- || size_t(game_time*20)%2)
- && !dying)
- {
- if (!is_big() || duck)
- smalltux_star->draw(context, get_pos(), layer + 5);
- else
- bigtux_star->draw(context, get_pos(), layer + 5);
- }
}
void
kill(false);
}
+void
+Player::collision_solid(const CollisionHit& hit)
+{
+ if(hit.bottom) {
+ if(physic.get_velocity_y() > 0)
+ physic.set_velocity_y(0);
+
+ on_ground_flag = true;
+ floor_normal = hit.slope_normal;
+ } else if(hit.top) {
+ if(physic.get_velocity_y() < 0)
+ physic.set_velocity_y(.2);
+ }
+
+ if(hit.left || hit.right) {
+ physic.set_velocity_x(0);
+ }
+
+ // crushed?
+ if(hit.crush) {
+ if(hit.left || hit.right) {
+ kill(true);
+ } else if(hit.top || hit.bottom) {
+ kill(false);
+ }
+ }
+}
+
HitResponse
-Player::collision(GameObject& other, const CollisionHit& hit)
+Player::collision(GameObject& other, const CollisionHit& )
{
Bullet* bullet = dynamic_cast<Bullet*> (&other);
if(bullet) {
assert(portable != NULL);
if(portable && grabbed_object == NULL
&& controller->hold(Controller::ACTION)
- && fabsf(hit.normal.x) > .9) {
+ /*&& fabsf(hit.normal.x) > .9*/) {
grabbed_object = portable;
grabbed_object->grab(*this, get_pos(), dir);
return CONTINUE;
}
}
-
- if(other.get_flags() & FLAG_SOLID) {
- /*
- printf("Col %p: HN: %3.1f %3.1f D %.1f P: %3.1f %3.1f M: %3.1f %3.1f\n",
- &other,
- hit.normal.x, hit.normal.y, hit.depth,
- get_pos().x, get_pos().y,
- movement.x, movement.y);
- */
-
- if(hit.normal.y < 0) { // landed on floor?
- if(physic.get_velocity_y() > 0)
- physic.set_velocity_y(0);
-
- on_ground_flag = true;
-
- // remember normal of this tile
- if (hit.normal.y > -0.9) {
- floor_normal.x = hit.normal.x;
- floor_normal.y = hit.normal.y;
- } else {
- // slowly adjust to unisolid tiles.
- // Necessary because our bounding box sometimes reaches through slopes and thus hits unisolid tiles
- floor_normal.x = (floor_normal.x * 0.9) + (hit.normal.x * 0.1);
- floor_normal.y = (floor_normal.y * 0.9) + (hit.normal.y * 0.1);
- }
-
- // hack platforms so that we stand normally on them when going down...
- Platform* platform = dynamic_cast<Platform*> (&other);
- if(platform != NULL) {
- if(platform->get_speed().y > 0)
- physic.set_velocity_y(platform->get_speed().y);
- //physic.set_velocity_x(platform->get_speed().x);
- }
- } else if(hit.normal.y > 0) { // bumped against the roof
- physic.set_velocity_y(-.1);
-
- // hack platform so that we are not glued to it from below
- Platform* platform = dynamic_cast<Platform*> (&other);
- if(platform != NULL) {
- physic.set_velocity_y(platform->get_speed().y);
- }
- }
-
- if(fabsf(hit.normal.x) > .9) { // hit on the side?
- physic.set_velocity_x(0);
- }
-
- MovingObject* omov = dynamic_cast<MovingObject*> (&other);
- if(omov != NULL) {
- Vector mov = movement - omov->get_movement();
- /*
- printf("W %p - HITN: %3.1f %3.1f D:%3.1f TM: %3.1f %3.1f TD: %3.1f %3.1f PM: %3.2f %3.1f\n",
- omov,
- hit.normal.x, hit.normal.y,
- hit.depth,
- movement.x, movement.y,
- dest.p1.x, dest.p1.y,
- omov->get_movement().x, omov->get_movement().y);
- */
- }
-
- return CONTINUE;
- }
#ifdef DEBUG
assert(dynamic_cast<MovingObject*> (&other) != NULL);
if(dying || deactivated)
return;
- if(!completely && safe_timer.started() || invincible_timer.started())
+ if(!completely && (safe_timer.started() || invincible_timer.started()))
return;
sound_manager->play("sounds/hurt.wav");