#include "app/globals.h"
#include "app/gettext.h"
+#include "special/sprite_manager.h"
#include "player.h"
-#include "defines.h"
-#include "scene.h"
#include "tile.h"
#include "special/sprite.h"
#include "sector.h"
#include "object/tilemap.h"
#include "object/camera.h"
#include "object/gameobjs.h"
+#include "object/portable.h"
#include "trigger/trigger_base.h"
static const int TILES_FOR_BUTTJUMP = 3;
Surface* tux_life = 0;
-Sprite* smalltux_gameover = 0;
-Sprite* smalltux_star = 0;
-Sprite* bigtux_star = 0;
-
TuxBodyParts* small_tux = 0;
TuxBodyParts* big_tux = 0;
TuxBodyParts* fire_tux = 0;
keymap.jump = SDLK_SPACE;
}
-void player_input_init(player_input_type* pplayer_input)
+PlayerInputType::PlayerInputType()
{
- pplayer_input->up = UP;
- pplayer_input->old_up = UP;
- pplayer_input->down = UP;
- pplayer_input->fire = UP;
- pplayer_input->left = UP;
- pplayer_input->old_fire = UP;
- pplayer_input->right = UP;
- pplayer_input->jump = UP;
- pplayer_input->old_jump = UP;
- pplayer_input->activate = UP;
+ reset();
+}
+
+void
+PlayerInputType::reset()
+{
+ up = false;
+ old_up = false;
+ down = false;
+ fire = false;
+ old_fire = false;
+ left = false;
+ right = false;
+ jump = false;
+ old_jump = false;
+ activate = false;
}
void
feet->draw(context, pos, layer-2, drawing_effect);
}
-Player::Player()
+Player::Player(PlayerStatus* _player_status)
+ : player_status(_player_status), grabbed_object(0)
{
+ smalltux_gameover = sprite_manager->create("smalltux-gameover");
+ smalltux_star = sprite_manager->create("smalltux-star");
+ bigtux_star = sprite_manager->create("bigtux-star");
init();
}
Player::~Player()
{
+ delete smalltux_gameover;
+ delete smalltux_star;
+ delete bigtux_star;
}
void
Player::init()
{
- holding_something = false;
-
- bbox.set_size(31.8, 31.8);
-
- size = SMALL;
- got_power = NONE_POWER;
+ if(is_big())
+ bbox.set_size(31.8, 63.8);
+ else
+ bbox.set_size(31.8, 31.8);
dir = RIGHT;
old_dir = dir;
duck = false;
dead = false;
- dying = DYING_NOT;
+ dying = false;
last_ground_y = 0;
fall_mode = ON_GROUND;
jumping = false;
flapping_velocity = 0;
// temporary to help player's choosing a flapping
- flapping_mode = MAREK_FLAP;
+ flapping_mode = NO_FLAP;
// Ricardo's flapping
flaps_nb = 0;
on_ground_flag = false;
+ grabbed_object = 0;
- player_input_init(&input);
-
+ input.reset();
physic.reset();
}
-int
-Player::key_event(SDLKey key, int state)
+bool
+Player::key_event(SDLKey key, bool state)
{
idle_timer.start(IDLE_TIME, true);
}
else if(key == keymap.up)
{
- if(state == UP)
- input.old_up = UP;
+ if(state == false)
+ input.old_up = false;
input.up = state;
/* Up key also opens activates stuff */
input.activate = state;
}
else if(key == keymap.power)
{
- if (state == UP)
- input.old_fire = UP;
+ if(state == false)
+ input.old_fire = false;
input.fire = state;
return true;
}
else if(key == keymap.jump)
{
- if (state == UP)
- input.old_jump = UP;
+ if(state == false)
+ input.old_jump = false;
input.jump = state;
return true;
}
}
void
-Player::level_begin()
-{
- move(Vector(100, 170));
- duck = false;
-
- dying = DYING_NOT;
-
- player_input_init(&input);
-
- on_ground_flag = false;
-
- physic.reset();
-}
-
-PlayerStatus&
-Player::get_status()
-{
- return player_status;
-}
-
-void
Player::action(float elapsed_time)
{
if(dying && dying_timer.check()) {
return;
}
- if (input.fire == UP)
- holding_something = false;
+ if(input.fire == false && grabbed_object) {
+ grabbed_object = 0;
+ // move the grabbed object a bit away from tux
+ Vector pos = get_pos() +
+ Vector(dir == LEFT ? -bbox.get_width() : bbox.get_width(),
+ bbox.get_height()*0.66666 - 32);
+ MovingObject* object = dynamic_cast<MovingObject*> (grabbed_object);
+ if(object) {
+ object->set_pos(pos);
+ } else {
+#ifdef DEBUG
+ std::cout << "Non MovingObjetc grabbed?!?\n";
+#endif
+ }
+ }
- if(dying == DYING_NOT)
+ if(!dying)
handle_input();
movement = physic.get_movement(elapsed_time);
+ on_ground_flag = false;
#if 0
- // special exception for cases where we're stuck under tiles after
- // being ducked. In this case we drift out
- if(!duck && on_ground() && old_base.x == base.x && old_base.y == base.y
- && collision_object_map(base))
- {
- base.x += elapsed_time * WALK_SPEED * (dir ? 1: -1);
- previous_base = old_base = base;
- }
-
- /* Reset score multiplier (for multi-hits): */
- if (!invincible_timer.started())
- {
- if(player_status.score_multiplier > player_status.max_score_multiplier)
- {
- player_status.max_score_multiplier = player_status.score_multiplier;
-
- // show a message
- char str[124];
- sprintf(str, _("New max combo: %d"), player_status.max_score_multiplier-1);
- Sector::current()->add_floating_text(base, str);
- }
- player_status.score_multiplier = 1;
- }
- }
-
- }
+ // special exception for cases where we're stuck under tiles after
+ // being ducked. In this case we drift out
+ if(!duck && on_ground() && old_base.x == base.x && old_base.y == base.y
+ && collision_object_map(base)) {
+ base.x += elapsed_time * WALK_SPEED * (dir ? 1: -1);
+ previous_base = old_base = base;
+ }
#endif
- on_ground_flag = false;
+ if(grabbed_object != 0) {
+ Vector pos = get_pos() +
+ Vector(dir == LEFT ? -16 : 16,
+ bbox.get_height()*0.66666 - 32);
+ grabbed_object->grab(*this, pos);
+ }
}
bool
return on_ground_flag;
}
+bool
+Player::is_big()
+{
+ if(player_status->bonus == NO_BONUS)
+ return false;
+
+ return true;
+}
+
void
Player::handle_horizontal_input()
{
float ay = physic.get_acceleration_y();
float dirsign = 0;
- if(input.left == DOWN && input.right == UP && (!duck || physic.get_velocity_y() != 0)) {
+ if(!duck || physic.get_velocity_y() != 0) {
+ if(input.left && !input.right) {
old_dir = dir;
dir = LEFT;
dirsign = -1;
- } else if(input.left == UP && input.right == DOWN && (!duck || physic.get_velocity_y() != 0)) {
+ } else if(!input.left && input.right) {
old_dir = dir;
dir = RIGHT;
dirsign = 1;
+ }
}
- if (input.fire == UP) {
- ax = dirsign * WALK_ACCELERATION_X;
- // limit speed
- if(vx >= MAX_WALK_XM && dirsign > 0) {
- vx = MAX_WALK_XM;
- ax = 0;
- } else if(vx <= -MAX_WALK_XM && dirsign < 0) {
- vx = -MAX_WALK_XM;
- ax = 0;
- }
+ if (!input.fire) {
+ ax = dirsign * WALK_ACCELERATION_X;
+ // limit speed
+ if(vx >= MAX_WALK_XM && dirsign > 0) {
+ vx = MAX_WALK_XM;
+ ax = 0;
+ } else if(vx <= -MAX_WALK_XM && dirsign < 0) {
+ vx = -MAX_WALK_XM;
+ ax = 0;
+ }
} else {
- ax = dirsign * RUN_ACCELERATION_X;
- // limit speed
- if(vx >= MAX_RUN_XM && dirsign > 0) {
- vx = MAX_RUN_XM;
- ax = 0;
- } else if(vx <= -MAX_RUN_XM && dirsign < 0) {
- vx = -MAX_RUN_XM;
- ax = 0;
- }
+ ax = dirsign * RUN_ACCELERATION_X;
+ // limit speed
+ if(vx >= MAX_RUN_XM && dirsign > 0) {
+ vx = MAX_RUN_XM;
+ ax = 0;
+ } else if(vx <= -MAX_RUN_XM && dirsign < 0) {
+ vx = -MAX_RUN_XM;
+ ax = 0;
+ }
}
// we can reach WALK_SPEED without any acceleration
}
// changing directions?
- if(on_ground() && ((vx < 0 && dirsign >0) || (vx>0 && dirsign<0)))
- {
- // let's skid!
- if(fabs(vx)>SKID_XM && !skidding_timer.started())
- {
- skidding_timer.start(SKID_TIME);
- SoundManager::get()->play_sound(IDToSound(SND_SKID));
- // dust some partcles
- Sector::current()->add_object(
- new Particles(
- Vector(bbox.p1.x + (dir == RIGHT ? bbox.get_width() : 0),
- bbox.p2.y),
- dir == RIGHT ? 270+20 : 90-40, dir == RIGHT ? 270+40 : 90-20,
- Vector(280,-260), Vector(0,0.030), 3, Color(100,100,100), 3, .8,
- LAYER_OBJECTS+1));
-
- ax *= 2.5;
- }
- else
- {
- ax *= 2;
- }
+ if(on_ground() && ((vx < 0 && dirsign >0) || (vx>0 && dirsign<0))) {
+ // let's skid!
+ if(fabs(vx)>SKID_XM && !skidding_timer.started()) {
+ skidding_timer.start(SKID_TIME);
+ SoundManager::get()->play_sound(IDToSound(SND_SKID));
+ // dust some partcles
+ Sector::current()->add_object(
+ new Particles(
+ Vector(bbox.p1.x + (dir == RIGHT ? bbox.get_width() : 0),
+ bbox.p2.y),
+ dir == RIGHT ? 270+20 : 90-40, dir == RIGHT ? 270+40 : 90-20,
+ Vector(280,-260), Vector(0,0.030), 3, Color(100,100,100), 3, .8,
+ LAYER_OBJECTS+1));
+
+ ax *= 2.5;
+ } else {
+ ax *= 2;
}
+ }
// we get slower when not pressing any keys
if(dirsign == 0) {
- if(fabs(vx) < WALK_SPEED) {
- vx = 0;
- ax = 0;
- } else if(vx < 0) {
- ax = WALK_ACCELERATION_X * 1.5;
- } else {
- ax = WALK_ACCELERATION_X * -1.5;
- }
+ if(fabs(vx) < WALK_SPEED) {
+ vx = 0;
+ ax = 0;
+ } else if(vx < 0) {
+ ax = WALK_ACCELERATION_X * 1.5;
+ } else {
+ ax = WALK_ACCELERATION_X * -1.5;
+ }
}
#if 0
}
// Press jump key
- if(input.jump == DOWN && can_jump && on_ground())
+ if(input.jump && can_jump && on_ground())
{
if(duck) { // only jump a little bit when in duck mode {
physic.set_velocity_y(300);
can_jump = false;
can_flap = false;
flaps_nb = 0; // Ricardo's flapping
- if (size == SMALL)
- SoundManager::get()->play_sound(IDToSound(SND_JUMP));
- else
+ if (is_big())
SoundManager::get()->play_sound(IDToSound(SND_BIGJUMP));
+ else
+ SoundManager::get()->play_sound(IDToSound(SND_JUMP));
}
// Let go of jump key
- else if(input.jump == UP)
+ else if(!input.jump)
{
if (!flapping && !duck && !falling_from_flap && !on_ground())
{
{
// Flapping, Ricardo's version
// similar to SM3 Fox
- if(input.jump == DOWN && input.old_jump == UP && can_flap &&
- flaps_nb < 3)
+ if(input.jump && !input.old_jump && can_flap && flaps_nb < 3)
{
physic.set_velocity_y(350);
physic.set_velocity_x(physic.get_velocity_x() * 35);
else if(flapping_mode == MAREK_FLAP)
{
// Flapping, Marek's version
- if (input.jump == DOWN && can_flap)
+ if (input.jump && can_flap)
{
if (!flapping_timer.started())
{
else if(flapping_mode == RYAN_FLAP)
{
// Flapping, Ryan's version
- if (input.jump == DOWN && can_flap)
+ if (input.jump && can_flap)
{
if (!flapping_timer.started())
{
}
}
- // Hover
- //(disabled by default, use cheat code "hover" to toggle on/off)
- //TODO: needs some tweaking, especially when used together with double jump and jumping off badguys
- if (enable_hover && input.jump == DOWN && !jumping && !butt_jump && physic.get_velocity_y() <= 0)
- {
- physic.set_velocity_y(-100);
- }
-
-#if 0
/* In case the player has pressed Down while in a certain range of air,
enable butt jump action */
- if (input.down == DOWN && !butt_jump && !duck)
- if(tiles_on_air(TILES_FOR_BUTTJUMP) && jumping)
+ if (input.down && !butt_jump && !duck)
+ //if(tiles_on_air(TILES_FOR_BUTTJUMP) && jumping)
butt_jump = true;
-#endif
/* When Down is not held anymore, disable butt jump */
- if(butt_jump && input.down == UP)
+ if(butt_jump && !input.down)
butt_jump = false;
+#if 0
// Do butt jump
- if (butt_jump && on_ground() && size == BIG)
+ if (butt_jump && on_ground() && is_big())
{
// Add a smoke cloud
if (duck)
butt_jump = false;
-#if 0
// Break bricks beneath Tux
if(Sector::current()->trybreakbrick(
Vector(base.x + 1, base.y + base.height), false)
physic.set_velocity_y(2);
butt_jump = true;
}
-#endif
-#if 0
// Kill nearby badguys
std::vector<GameObject*> gameobjects = Sector::current()->gameobjects;
for (std::vector<GameObject*>::iterator i = gameobjects.begin();
}
}
}
-#endif
}
+#endif
/** jumping is only allowed if we're about to touch ground soon and if the
* button has been up in between the last jump
get_pos().y + bbox.get_height() + 64))
&& jumping == false
&& can_jump == false
- && input.jump == DOWN
- && input.old_jump == UP)
+ && input.jump && !input.old_jump)
{
can_jump = true;
}
#endif
+ // FIXME: why the heck is this here and not somewhere where the keys are
+ // checked?!?
input.old_jump = input.jump;
}
handle_horizontal_input();
/* Jump/jumping? */
- if (on_ground() && input.jump == UP)
+ if (on_ground() && !input.jump)
can_jump = true;
handle_vertical_input();
/* Shoot! */
- if (input.fire == DOWN && input.old_fire == UP && got_power != NONE_POWER) {
+ if (input.fire && !input.old_fire && player_status->bonus == FIRE_BONUS) {
if(Sector::current()->add_bullet(
- get_pos() + Vector(0, bbox.get_height()/2),
+// get_pos() + Vector(0, bbox.get_height()/2),
+ get_pos() + ((dir == LEFT)? Vector(0, bbox.get_height()/2)
+ : Vector(32, bbox.get_height()/2)),
physic.get_velocity_x(), dir))
shooting_timer.start(SHOOTING_TIME);
- input.old_fire = DOWN;
+ // FIXME: why the heck is this here
+ input.old_fire = false;
}
/* Duck! */
- if (input.down == DOWN && size == BIG && !duck
+ if (input.down && is_big() && !duck
&& physic.get_velocity_y() == 0 && on_ground())
{
duck = true;
bbox.move(Vector(0, 32));
bbox.set_height(31.8);
}
- else if(input.down == UP && size == BIG && duck)
+ else if(!input.down && is_big() && duck)
{
// try if we can really unduck
bbox.move(Vector(0, -32));
}
void
-Player::grow(bool animate)
+Player::set_bonus(BonusType type, bool animate)
{
- if(size == BIG)
+ if(player_status->bonus == type)
return;
- size = BIG;
- bbox.set_height(63.8);
- bbox.move(Vector(0, -32));
-
- if(animate)
- growing_timer.start(GROWING_TIME);
-}
-
-void
-Player::grabdistros()
-{
+ if(player_status->bonus == NO_BONUS) {
+ bbox.set_height(63.8);
+ bbox.move(Vector(0, -32));
+ if(animate)
+ growing_timer.start(GROWING_TIME);
+ }
+
+ player_status->bonus = type;
}
void
{
TuxBodyParts* tux_body;
- if (size == SMALL)
- tux_body = small_tux;
- else if (got_power == FIRE_POWER)
+ if (player_status->bonus == GROWUP_BONUS)
+ tux_body = big_tux;
+ else if (player_status->bonus == FIRE_BONUS)
tux_body = fire_tux;
- else if (got_power == ICE_POWER)
+ else if (player_status->bonus == ICE_BONUS)
tux_body = ice_tux;
else
- tux_body = big_tux;
+ tux_body = small_tux;
int layer = LAYER_OBJECTS + 10;
/* Set Tux sprite action */
- if (duck && size == BIG)
+ if (duck && is_big())
{
if(dir == LEFT)
tux_body->set_action("duck-left");
else // dir == RIGHT
tux_body->set_action("kick-right");
}
- else if (butt_jump && size == BIG)
+ else if (butt_jump && is_big())
{
if(dir == LEFT)
tux_body->set_action("buttjump-left");
if(idle_timer.check())
{
- if(size == BIG)
+ if(is_big())
{
if(dir == LEFT)
tux_body->head->set_action("idle-left", 1);
}
// Tux is holding something
- if ((holding_something && physic.get_velocity_y() == 0) ||
+ if ((grabbed_object != 0 && physic.get_velocity_y() == 0) ||
(shooting_timer.get_timeleft() > 0 && !shooting_timer.check()))
{
if (duck)
}
/* Draw Tux */
- if (dying == DYING_SQUISHED) {
- smalltux_gameover->draw(context, get_pos(), LAYER_FOREGROUNDTILES+1);
+ if(dying) {
+ smalltux_gameover->draw(context, get_pos(), layer);
} else if(growing_timer.get_timeleft() > 0) {
- if(size == SMALL)
+ if(!is_big())
{
if (dir == RIGHT)
context.draw_surface(growingtux_right[GROWING_FRAMES-1 -
|| size_t(global_time*20)%2)
&& !dying)
{
- if (size == SMALL || duck)
+ if (!is_big() || duck)
smalltux_star->draw(context, get_pos(), layer + 5);
else
bigtux_star->draw(context, get_pos(), layer + 5);
HitResponse
Player::collision(GameObject& other, const CollisionHit& hit)
{
+ Portable* portable = dynamic_cast<Portable*> (&other);
+ if(portable && grabbed_object == 0 && input.fire
+ && fabsf(hit.normal.x) > .9) {
+ grabbed_object = portable;
+ return CONTINUE;
+ }
+
if(other.get_flags() & FLAG_SOLID) {
if(hit.normal.y < 0) { // landed on floor?
if (physic.get_velocity_y() < 0)
TriggerBase* trigger = dynamic_cast<TriggerBase*> (&other);
if(trigger) {
- if(input.up == DOWN && input.old_up == UP)
+ if(input.up && !input.old_up)
trigger->event(*this, TriggerBase::EVENT_ACTIVATE);
}
physic.set_velocity_x(0);
- if (mode == SHRINK && size == BIG)
+ if (mode == SHRINK && is_big())
{
- if (got_power != NONE_POWER)
+ if (player_status->bonus == FIRE_BONUS
+ || player_status->bonus == ICE_BONUS)
{
safe_timer.start(TUX_SAFE_TIME);
- got_power = NONE_POWER;
+ player_status->bonus = GROWUP_BONUS;
}
- else
+ else
{
growing_timer.start(GROWING_TIME);
safe_timer.start(TUX_SAFE_TIME + GROWING_TIME);
- size = SMALL;
bbox.set_height(31.8);
duck = false;
+ player_status->bonus = NO_BONUS;
}
}
else
physic.enable_gravity(true);
physic.set_acceleration(0, 0);
physic.set_velocity(0, 700);
- --player_status.lives;
- dying = DYING_SQUISHED;
+ player_status->lives -= 1;
+ player_status->bonus = NO_BONUS;
+ dying = true;
dying_timer.start(3.0);
flags |= FLAG_NO_COLLDET;
}
}
-/* Remove Tux's power ups */
-void
-Player::remove_powerups()
-{
- got_power = NONE_POWER;
- size = SMALL;
- bbox.set_height(31.8);
-}
-
void
Player::move(const Vector& vector)
{
bbox.set_pos(vector);
+ if(is_big())
+ bbox.set_size(31.8, 63.8);
+ else
+ bbox.set_size(31.8, 31.8);
+ on_ground_flag = false;
+ duck = false;
+ last_ground_y = vector.y;
+
+ input.reset();
+ physic.reset();
}
void
bbox.set_pos(Vector(camera->get_translation().x, get_pos().y));
adjust = true;
}
- if(get_pos().x >= camera->get_translation().x + screen->w - bbox.get_width())
+ if(get_pos().x >= camera->get_translation().x + SCREEN_WIDTH - bbox.get_width())
{
bbox.set_pos(Vector(
- camera->get_translation().x + screen->w - bbox.get_width(),
+ camera->get_translation().x + SCREEN_WIDTH - bbox.get_width(),
get_pos().y));
adjust = true;
}