+// $Id$
//
-// C Implementation: player/tux
+// SuperTux - A Jump'n Run
+// Copyright (C) 2003 Tobias Glaesser <tobi.web@gmx.de>
//
-// Description:
-//
-//
-// Author: Tobias Glaesser <tobi.web@gmx.de> & Bill Kendrick, (C) 2004
-//
-// Copyright: See COPYING file that comes with this distribution
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
#include <math.h>
#include "gameloop.h"
Surface* bigcape_right[2];
Surface* bigcape_left[2];
+PlayerKeymap keymap;
+
+PlayerKeymap::PlayerKeymap()
+{
+ keymap.jump = SDLK_UP;
+ keymap.duck = SDLK_DOWN;
+ keymap.left = SDLK_LEFT;
+ keymap.right = SDLK_RIGHT;
+ keymap.fire = SDLK_LCTRL;
+}
+
void player_input_init(player_input_type* pplayer_input)
{
pplayer_input->down = UP;
void
Player::init()
{
+ Level* plevel = World::current()->get_level();
+
base.width = 32;
base.height = 32;
size = SMALL;
got_coffee = false;
- // FIXME: Make the start position configurable via the levelfile
- base.x = 100;
- base.y = 170;
+ base.x = plevel->start_pos_x;
+ base.y = plevel->start_pos_y;
base.xm = 0;
base.ym = 0;
previous_base = old_base = base;
player_input_init(&input);
- keymap.jump = SDLK_UP;
- keymap.duck = SDLK_DOWN;
- keymap.left = SDLK_LEFT;
- keymap.right = SDLK_RIGHT;
- keymap.fire = SDLK_LCTRL;
-
invincible_timer.init(true);
skidding_timer.init(true);
safe_timer.init(true);
previous_base = base;
physic.apply(frame_ratio, base.x, base.y);
- if(dying == DYING_NOT) {
+ if(dying == DYING_NOT)
+ {
+ base_type target = base;
+
collision_swept_object_map(&old_base, &base);
+
+ // Don't accelerate Tux if he is running against a wall
+ if (target.x != base.x)
+ {
+ physic.set_velocity_x(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 += frame_ratio * WALK_SPEED * (dir ? 1 : -1);
- previous_base = old_base = base;
+ && collision_object_map(&base)) {
+ base.x += frame_ratio * WALK_SPEED * (dir ? 1 : -1);
+ previous_base = old_base = base;
}
keep_in_bounds();
- }
+ }
if (dying == DYING_NOT)
{
if(under_solid())
{
// fall down
- physic.set_velocity(physic.get_velocity_x(), 0);
+ physic.set_velocity_y(0);
jumped_in_solid = true;
}
}
if (physic.get_velocity_y() < 0)
{
base.y = (int)(((int)base.y / 32) * 32);
- physic.set_velocity(physic.get_velocity_x(), 0);
+ physic.set_velocity_y(0);
}
physic.enable_gravity(false);
if (get_current_music() == HERRING_MUSIC && !invincible_timer.check())
{
/*
- no, we are no more invincible
- or we were not in invincible mode
- but are we in hurry ?
- */
+ no, we are no more invincible
+ or we were not in invincible mode
+ but are we in hurry ?
+ */
// FIXME: Move this to gamesession
if (GameSession::current()->time_left.get_left() < TIME_WARNING)
/* yes, we are in hurry
stop the herring_song, prepare to play the correct
fast level_song !
- */
+ */
set_current_music(HURRYUP_MUSIC);
}
else
float ay = physic.get_acceleration_y();
float dirsign = 0;
- if(!duck && input.left == DOWN && input.right == UP) {
+ if(input.left == DOWN && input.right == UP && (!duck || physic.get_velocity_y() != 0)) {
dir = LEFT;
dirsign = -1;
- } else if(!duck && input.left == UP && input.right == DOWN) {
+ } else if(input.left == UP && input.right == DOWN && (!duck || physic.get_velocity_y() != 0)) {
dir = RIGHT;
dirsign = 1;
}
{
if(input.up == DOWN)
{
- if (on_ground() && !duck)
+ if (on_ground())
{
// jump
- physic.set_velocity(physic.get_velocity_x(), 5.5);
+ if (physic.get_velocity_x() > MAX_WALK_XM)
+ physic.set_velocity_y(5.8);
+ else
+ physic.set_velocity_y(5.2);
+
--base.y;
jumping = true;
if (size == SMALL)
{
jumping = false;
if(physic.get_velocity_y() > 0) {
- physic.set_velocity(physic.get_velocity_x(), 0);
+ physic.set_velocity_y(0);
}
}
}
}
/* Duck! */
- if (input.down == DOWN && size == BIG && !duck)
+ if (input.down == DOWN && size == BIG && !duck && physic.get_velocity_y() == 0)
{
duck = true;
base.height = 32;
// changing base size confuses collision otherwise
old_base = previous_base = base;
}
- else if(input.down == UP && size == BIG && duck)
+ else if(input.down == UP && size == BIG && duck && physic.get_velocity_y() == 0)
{
duck = false;
base.y -= 32;
/* Hurt player if he touches a badguy */
if (!pbad_c->dying && !dying &&
!safe_timer.started() &&
- pbad_c->mode != HELD)
+ pbad_c->mode != BadGuy::HELD)
{
- if (pbad_c->mode == FLAT && input.fire == DOWN)
+ if (pbad_c->mode == BadGuy::FLAT && input.fire == DOWN)
{
- pbad_c->mode = HELD;
+ pbad_c->mode = BadGuy::HELD;
pbad_c->base.y-=8;
}
- else if (pbad_c->mode == FLAT)
+ else if (pbad_c->mode == BadGuy::FLAT)
{
// Don't get hurt if we're kicking a flat badguy!
}
- else if (pbad_c->mode == KICK)
+ else if (pbad_c->mode == BadGuy::KICK)
{
/* Hurt if you get hit by kicked laptop: */
if (!invincible_timer.started())