From: Matthias Braun Date: Fri, 25 Mar 2005 20:39:56 +0000 (+0000) Subject: Had a bit of time today and worked on supertux: X-Git-Url: https://git.verplant.org/?a=commitdiff_plain;h=9599042661b468aae7bd34dca05441c0ebc93ad7;p=supertux.git Had a bit of time today and worked on supertux: - Commited some old changes I had lying around here (improved mrtree images? and improvement to the collision grid which still isn't enabled by default) - Did a bit more cleanups (eleminated defines.h and renamed scene.* to player_status.* as that is waht ti really contained) - Cleaned up PlayerStatus code a bit (refactored loading/saving out of worldmap into PlayerStatus) - Implemented LevelTransformer interface and did a first test with a flip level transformer - Removed explicit LevelEndSequence attribute (can be done by placing aprorpiate SequenceTrigger objects) SVN-Revision: 2293 --- diff --git a/data/images/shared/mrtree-small-left-0.png b/data/images/shared/mrtree-small-left-0.png index 4842eaf8d..9bfec1f4a 100644 Binary files a/data/images/shared/mrtree-small-left-0.png and b/data/images/shared/mrtree-small-left-0.png differ diff --git a/data/images/shared/mrtree-small-left-1.png b/data/images/shared/mrtree-small-left-1.png index f1110088b..a773cc81a 100644 Binary files a/data/images/shared/mrtree-small-left-1.png and b/data/images/shared/mrtree-small-left-1.png differ diff --git a/data/images/shared/mrtree-small-left-2.png b/data/images/shared/mrtree-small-left-2.png index 618fd916d..63abe698d 100644 Binary files a/data/images/shared/mrtree-small-left-2.png and b/data/images/shared/mrtree-small-left-2.png differ diff --git a/data/images/shared/mrtree-squished-left.png b/data/images/shared/mrtree-squished-left.png index b9655be1d..c86f51a9f 100644 Binary files a/data/images/shared/mrtree-squished-left.png and b/data/images/shared/mrtree-squished-left.png differ diff --git a/data/images/shared/mrtree-walk-left-0.png b/data/images/shared/mrtree-walk-left-0.png index f39c65880..035547c85 100644 Binary files a/data/images/shared/mrtree-walk-left-0.png and b/data/images/shared/mrtree-walk-left-0.png differ diff --git a/data/images/shared/mrtree-walk-left-1.png b/data/images/shared/mrtree-walk-left-1.png index d1bde106a..d814da558 100644 Binary files a/data/images/shared/mrtree-walk-left-1.png and b/data/images/shared/mrtree-walk-left-1.png differ diff --git a/data/images/shared/mrtree-walk-left-2.png b/data/images/shared/mrtree-walk-left-2.png index 6abbe6593..e76215505 100644 Binary files a/data/images/shared/mrtree-walk-left-2.png and b/data/images/shared/mrtree-walk-left-2.png differ diff --git a/data/levels/test/bonusblock.stl b/data/levels/test/bonusblock.stl index d392e932b..7db74262c 100644 --- a/data/levels/test/bonusblock.stl +++ b/data/levels/test/bonusblock.stl @@ -9,7 +9,7 @@ (gravity 10.000000) (background (image "arctis.jpg") (speed 0.5)) - (music "supertux-2.ogg") + (music "theme.mod") (spawnpoint (name "main") (x 100) diff --git a/lib/gui/menu.cpp b/lib/gui/menu.cpp index ba7b749a6..57643efdd 100644 --- a/lib/gui/menu.cpp +++ b/lib/gui/menu.cpp @@ -746,7 +746,7 @@ Menu::event(SDL_Event& event) { case SDL_KEYDOWN: { - SDLKey key = key = event.key.keysym.sym; + SDLKey key = event.key.keysym.sym; SDLMod keymod; char ch[2]; keymod = SDL_GetModState(); diff --git a/lib/special/game_object.h b/lib/special/game_object.h index b235c01ac..a657d4984 100644 --- a/lib/special/game_object.h +++ b/lib/special/game_object.h @@ -80,8 +80,7 @@ namespace SuperTux remove_listeners = entry; } - - + // flags enum { /// the tile so you can stand on it diff --git a/lib/special/moving_object.h b/lib/special/moving_object.h index b5c476496..0ac684421 100644 --- a/lib/special/moving_object.h +++ b/lib/special/moving_object.h @@ -25,6 +25,7 @@ #include "math/vector.h" #include "math/rectangle.h" +class FlipLevelTransformer; class Sector; class CollisionGrid; @@ -65,6 +66,7 @@ namespace SuperTux protected: friend class Sector; friend class CollisionGrid; + friend class FlipLevelTransformer; /** The bounding box of the object (as used for collision detection, this * isn't necessarily the bounding box for graphics) diff --git a/lib/special/object_remove_listener.h b/lib/special/object_remove_listener.h index fdcb769bc..502db1ce5 100644 --- a/lib/special/object_remove_listener.h +++ b/lib/special/object_remove_listener.h @@ -9,6 +9,9 @@ class GameObject; class ObjectRemoveListener { public: + virtual ~ObjectRemoveListener() + { } + virtual void object_removed(GameObject* object) = 0; }; diff --git a/lib/utils/configfile.h b/lib/utils/configfile.h index 5c2de647c..90862da82 100644 --- a/lib/utils/configfile.h +++ b/lib/utils/configfile.h @@ -27,7 +27,9 @@ namespace SuperTux { FILE * opendata(const std::string& filename, const char * mode); class Config { - public: +public: + virtual ~Config() + { } void load (); void save (); virtual void customload(const lisp::Lisp* ) diff --git a/src/badguy/badguy.h b/src/badguy/badguy.h index c7c24e101..92bd0104e 100644 --- a/src/badguy/badguy.h +++ b/src/badguy/badguy.h @@ -11,6 +11,7 @@ #include "serializable.h" #include "resources.h" #include "sector.h" +#include "direction.h" #include "object_factory.h" #include "lisp/parser.h" #include "lisp/lisp.h" @@ -35,6 +36,15 @@ public: virtual void kill_fall(); + Vector get_start_position() const + { + return start_position; + } + void set_start_position(const Vector& vec) + { + start_position = vec; + } + protected: enum State { STATE_INIT, diff --git a/src/badguy/mrtree.cpp b/src/badguy/mrtree.cpp index efe080de9..d94471790 100644 --- a/src/badguy/mrtree.cpp +++ b/src/badguy/mrtree.cpp @@ -3,6 +3,7 @@ #include "mrtree.h" static const float WALKSPEED = 50; +static const float WALKSPEED_SMALL = 30; MrTree::MrTree(const lisp::Lisp& reader) : mystate(STATE_BIG) @@ -27,11 +28,13 @@ MrTree::write(lisp::Writer& writer) void MrTree::activate() { - physic.set_velocity_x(dir == LEFT ? -WALKSPEED : WALKSPEED); - if(mystate == STATE_BIG) + if(mystate == STATE_BIG) { + physic.set_velocity_x(dir == LEFT ? -WALKSPEED : WALKSPEED); sprite->set_action(dir == LEFT ? "left" : "right"); - else + } else { + physic.set_velocity_x(dir == LEFT ? -WALKSPEED_SMALL : WALKSPEED_SMALL); sprite->set_action(dir == LEFT ? "small-left" : "small-right"); + } } bool diff --git a/src/collision_grid.cpp b/src/collision_grid.cpp index c3b27698b..311fc78af 100644 --- a/src/collision_grid.cpp +++ b/src/collision_grid.cpp @@ -78,7 +78,14 @@ CollisionGrid::remove_object(MovingObject* object) break; } } +#ifdef DEBUG assert(wrapper != 0); +#else + if(wrapper == 0) { + std::cerr << "Tried to remove nonexistant object!\n"; + return; + } +#endif const Rectangle& bbox = wrapper->dest; for(float y = bbox.p1.y; y < bbox.p2.y; y += cell_height) { @@ -90,7 +97,7 @@ CollisionGrid::remove_object(MovingObject* object) std::cerr << "Object out of range: " << gridx << ", " << gridy << "\n"; continue; } - remove_object_from_gridcell(gridy*cells_x + gridx, object); + remove_object_from_gridcell(gridy*cells_x + gridx, wrapper); } } @@ -98,11 +105,13 @@ CollisionGrid::remove_object(MovingObject* object) } void -CollisionGrid::move_object(MovingObject* object) +CollisionGrid::move_object(ObjectWrapper* wrapper) { - const Rectangle& bbox = object->bbox; - for(float y = bbox.p1.y; y < bbox.p2.y; y += cell_height) { - for(float x = bbox.p1.x; x < bbox.p2.x; x += cell_width) { + // FIXME not optimal yet... should leave the gridcells untouched that don't + // need to be changed. + const Rectangle& obbox = wrapper->dest; + for(float y = obbox.p1.y; y < obbox.p2.y; y += cell_height) { + for(float x = obbox.p1.x; x < obbox.p2.x; x += cell_width) { int gridx = int(x / cell_width); int gridy = int(y / cell_height); if(gridx < 0 || gridy < 0 @@ -110,14 +119,36 @@ CollisionGrid::move_object(MovingObject* object) std::cerr << "Object out of range: " << gridx << ", " << gridy << "\n"; continue; } - // TODO + remove_object_from_gridcell(gridy*cells_x + gridx, wrapper); } } + + const Rectangle& nbbox = wrapper->object->bbox; + for(float y = nbbox.p1.y; y < nbbox.p2.y; y += cell_height) { + for(float x = nbbox.p1.x; x < nbbox.p2.x; x += cell_width) { + int gridx = int(x / cell_width); + int gridy = int(y / cell_height); + if(gridx < 0 || gridy < 0 + || gridx >= int(cells_x) || gridy >= int(cells_y)) { + std::cerr << "Object out of range: " << gridx << ", " << gridy << "\n"; + continue; + } + + GridEntry* entry = new GridEntry; + entry->object_wrapper = wrapper; + entry->next = grid[gridy*cells_x + gridx]; + grid[gridy*cells_x + gridx] = entry; + } + } + + wrapper->dest = nbbox; } void CollisionGrid::check_collisions() { + std::vector moved_objects; + CollisionGridIterator iter(*this, Sector::current()->get_active_region()); while(ObjectWrapper* wrapper = iter.next_wrapper()) { MovingObject* object = wrapper->object; @@ -126,6 +157,7 @@ CollisionGrid::check_collisions() if(object->get_flags() & GameObject::FLAG_NO_COLLDET) { object->bbox.move(object->movement); object->movement = Vector(0, 0); + moved_objects.push_back(wrapper); continue; } @@ -134,8 +166,16 @@ CollisionGrid::check_collisions() collide_object(wrapper); - object->bbox.move(object->get_movement()); - object->movement = Vector(0, 0); + if(object->movement != Vector(0, 0)) { + object->bbox.move(object->movement); + object->movement = Vector(0, 0); + moved_objects.push_back(wrapper); + } + } + + for(std::vector::iterator i = moved_objects.begin(); + i != moved_objects.end(); ++i) { + move_object(*i); } } @@ -145,13 +185,13 @@ CollisionGrid::collide_object(ObjectWrapper* wrapper) iterator_timestamp++; const Rectangle& bbox = wrapper->object->bbox; - for(float y = bbox.p1.y; y < bbox.p2.y; y += cell_height) { - for(float x = bbox.p1.x; x < bbox.p2.x; x += cell_width) { + for(float y = bbox.p1.y - cell_height; y < bbox.p2.y + cell_height; y += cell_height) { + for(float x = bbox.p1.x - cell_width; x < bbox.p2.x + cell_width; x += cell_width) { int gridx = int(x / cell_width); int gridy = int(y / cell_height); if(gridx < 0 || gridy < 0 || gridx >= int(cells_x) || gridy >= int(cells_y)) { - std::cerr << "Object out of range: " << gridx << ", " << gridy << "\n"; + //std::cerr << "Object out of range: " << gridx << ", " << gridy << "\n"; continue; } @@ -209,13 +249,13 @@ CollisionGrid::collide_object_object(ObjectWrapper* wrapper, } void -CollisionGrid::remove_object_from_gridcell(int gridcell, MovingObject* object) +CollisionGrid::remove_object_from_gridcell(int gridcell, ObjectWrapper* wrapper) { GridEntry* lastentry = 0; GridEntry* entry = grid[gridcell]; while(entry) { - if(entry->object_wrapper->object == object) { + if(entry->object_wrapper == wrapper) { if(lastentry == 0) { grid[gridcell] = entry->next; } else { diff --git a/src/collision_grid.h b/src/collision_grid.h index 8a507d142..7822c31e3 100644 --- a/src/collision_grid.h +++ b/src/collision_grid.h @@ -20,7 +20,6 @@ public: void add_object(MovingObject* object); void remove_object(MovingObject* object); - void move_object(MovingObject* object); void check_collisions(); @@ -47,9 +46,10 @@ private: ObjectWrapper* object_wrapper; }; - void remove_object_from_gridcell(int gridcell, MovingObject* object); + void remove_object_from_gridcell(int gridcell, ObjectWrapper* wrapper); void collide_object(ObjectWrapper* wrapper); void collide_object_object(ObjectWrapper* wrapper, ObjectWrapper* wrapper2); + void move_object(ObjectWrapper* wrapper); typedef std::vector GridEntries; GridEntries grid; diff --git a/src/collision_grid_iterator.h b/src/collision_grid_iterator.h index 9e22f629f..efed0b4ef 100644 --- a/src/collision_grid_iterator.h +++ b/src/collision_grid_iterator.h @@ -13,20 +13,20 @@ public: CollisionGridIterator(CollisionGrid& newgrid, const Rectangle& bbox) : grid(newgrid) { - start_x = int(bbox.p1.x / grid.cell_width); + start_x = int(bbox.p1.x / grid.cell_width) - 2; if(start_x < 0) start_x = 0; x = start_x; - y = int(bbox.p1.y / grid.cell_height); + y = int(bbox.p1.y / grid.cell_height) - 2; if(y < 0) y = 0; - end_x = int(bbox.p2.x / grid.cell_width) + 1; + end_x = int(bbox.p2.x / grid.cell_width) + 2; if(end_x > (int) grid.cells_x) end_x = grid.cells_x; - end_y = int(bbox.p2.y / grid.cell_height) + 1; + end_y = int(bbox.p2.y / grid.cell_height) + 2; if(end_y > (int) grid.cells_y) end_y = grid.cells_y; diff --git a/src/defines.h b/src/defines.h deleted file mode 100644 index c408b688a..000000000 --- a/src/defines.h +++ /dev/null @@ -1,50 +0,0 @@ -// $Id$ -// -// SuperTux -// Copyright (C) 2000 Bill Kendrick -// Copyright (C) 2004 Tobias Glaesser -// -// 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. -#ifndef SUPERTUX_DEFINES_H -#define SUPERTUX_DEFINES_H - -#include - -enum Direction { LEFT = 0, RIGHT = 1 }; - -/* keyboard/joystick states: */ -#define UP 0 -#define DOWN 1 - -/* Dying types: */ -enum DyingType { - DYING_NOT = 0, - DYING_SQUISHED = 1, - DYING_FALLING = 2 -}; - -/* Speed constraints: */ -#define MAX_LIVES 99 - -/* gameplay related defines */ -#define START_LIVES 4 - -#define MAX_FIRE_BULLETS 2 -#define MAX_ICE_BULLETS 1 -#define FROZEN_TIME 3.0 - -#endif /*SUPERTUX_DEFINES_H*/ - diff --git a/src/direction.h b/src/direction.h new file mode 100644 index 000000000..5ecc417bc --- /dev/null +++ b/src/direction.h @@ -0,0 +1,27 @@ +// $Id$ +// +// SuperTux +// Copyright (C) 2000 Bill Kendrick +// Copyright (C) 2004 Tobias Glaesser +// +// 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. +#ifndef SUPERTUX_DIRECTION_H +#define SUPERTUX_DIRECTION_H + +enum Direction { LEFT = 0, RIGHT = 1 }; + +#endif /*SUPERTUX_DEFINES_H*/ + diff --git a/src/flip_level_transformer.cpp b/src/flip_level_transformer.cpp new file mode 100644 index 000000000..db5a693a4 --- /dev/null +++ b/src/flip_level_transformer.cpp @@ -0,0 +1,78 @@ +#include + +#include "flip_level_transformer.h" +#include "object/tilemap.h" +#include "badguy/badguy.h" +#include "sector.h" +#include "tile_manager.h" + +void +FlipLevelTransformer::transform_sector(Sector* sector) +{ + float height = sector->solids->get_height() + * sector->solids->get_tilemanager()->get_default_height(); + + for(Sector::GameObjects::iterator i = sector->gameobjects.begin(); + i != sector->gameobjects.end(); ++i) { + GameObject* object = *i; + + TileMap* tilemap = dynamic_cast (object); + if(tilemap) { + transform_tilemap(tilemap); + } + BadGuy* badguy = dynamic_cast (object); + if(badguy) { + transform_badguy(height, badguy); + } else { + MovingObject* mobject = dynamic_cast (object); + if(mobject) { + transform_moving_object(height, mobject); + } + } + } + for(Sector::SpawnPoints::iterator i = sector->spawnpoints.begin(); + i != sector->spawnpoints.end(); ++i) { + transform_spawnpoint(height, *i); + } +} + +void +FlipLevelTransformer::transform_tilemap(TileMap* tilemap) +{ + for(size_t x = 0; x < tilemap->get_width(); ++x) { + for(size_t y = 0; y < tilemap->get_height()/2; ++y) { + // swap tiles + int y2 = tilemap->get_height()-1-y; + const Tile* t1 = tilemap->get_tile(x, y); + const Tile* t2 = tilemap->get_tile(x, y2); + tilemap->change(x, y, t2->getID()); + tilemap->change(x, y2, t1->getID()); + } + } + tilemap->set_drawing_effect(VERTICAL_FLIP); +} + +void +FlipLevelTransformer::transform_badguy(float height, BadGuy* badguy) +{ + Vector pos = badguy->get_start_position(); + pos.y = height - pos.y; + badguy->set_start_position(pos); +} + +void +FlipLevelTransformer::transform_spawnpoint(float height, SpawnPoint* spawn) +{ + Vector pos = spawn->pos; + pos.y = height - pos.y; + spawn->pos = pos; +} + +void +FlipLevelTransformer::transform_moving_object(float height, MovingObject*object) +{ + Vector pos = object->bbox.p1; + pos.y = height - pos.y; + object->bbox.set_pos(pos); +} + diff --git a/src/flip_level_transformer.h b/src/flip_level_transformer.h new file mode 100644 index 000000000..f3cc8422f --- /dev/null +++ b/src/flip_level_transformer.h @@ -0,0 +1,29 @@ +#ifndef __FLIP_LEVEL_TRANSFORMER_H__ +#define __FLIP_LEVEL_TRANSFORMER_H__ + +#include "level_transformer.h" + +class TileMap; +class BadGuy; +class SpawnPoint; +namespace SuperTux { +class MovingObject; +} + +using namespace SuperTux; + +/** Vertically or horizontally flip a level */ +class FlipLevelTransformer : public LevelTransformer +{ +public: + virtual void transform_sector(Sector* sector); + +private: + void transform_tilemap(TileMap* tilemap); + void transform_moving_object(float height, MovingObject* object); + void transform_badguy(float height, BadGuy* badguy); + void transform_spawnpoint(float height, SpawnPoint* spawnpoint); +}; + +#endif + diff --git a/src/gameloop.cpp b/src/gameloop.cpp index 275c42fa6..3a33cdbbc 100644 --- a/src/gameloop.cpp +++ b/src/gameloop.cpp @@ -32,14 +32,13 @@ #include #include -#include "SDL.h" +#include #ifndef WIN32 #include #include #endif -#include "defines.h" #include "app/globals.h" #include "gameloop.h" #include "video/screen.h" @@ -47,8 +46,8 @@ #include "gui/menu.h" #include "sector.h" #include "level.h" -#include "scene.h" #include "tile.h" +#include "player_status.h" #include "object/particlesystem.h" #include "object/background.h" #include "object/tilemap.h" @@ -59,7 +58,6 @@ #include "resources.h" #include "app/gettext.h" #include "worldmap.h" -#include "intro.h" #include "misc.h" #include "statistics.h" #include "timer.h" @@ -225,32 +223,18 @@ GameSession::start_timers() void GameSession::on_escape_press() { - if(currentsector->player->dying || end_sequence != NO_ENDSEQUENCE) + if(currentsector->player->is_dying() || end_sequence != NO_ENDSEQUENCE) return; // don't let the player open the menu, when he is dying if(game_pause) return; - if(st_gl_mode == ST_GL_TEST) - { - exit_status = ES_LEVEL_ABORT; - } - else if (!Menu::current()) - { - /* Tell Tux that the keys are all down, otherwise - it could have nasty bugs, like going allways to the right - or whatever that key does */ - Player& tux = *(currentsector->player); - tux.key_event((SDLKey)keymap.up, UP); - tux.key_event((SDLKey)keymap.down, UP); - tux.key_event((SDLKey)keymap.left, UP); - tux.key_event((SDLKey)keymap.right, UP); - tux.key_event((SDLKey)keymap.jump, UP); - tux.key_event((SDLKey)keymap.power, UP); - - Menu::set_current(game_menu); - Ticks::pause_start(); - } + if(st_gl_mode == ST_GL_TEST) { + exit_status = ES_LEVEL_ABORT; + } else if (!Menu::current()) { + Menu::set_current(game_menu); + Ticks::pause_start(); + } } void @@ -260,15 +244,15 @@ GameSession::process_events() { Player& tux = *currentsector->player; - tux.input.fire = UP; - tux.input.left = UP; - tux.input.right = DOWN; - tux.input.down = UP; + tux.input.fire = false; + tux.input.left = false; + tux.input.right = true; + tux.input.down = false; if (int(last_x_pos) == int(tux.get_pos().x)) - tux.input.up = DOWN; + tux.input.up = true; else - tux.input.up = UP; + tux.input.up = false; last_x_pos = tux.get_pos().x; @@ -339,7 +323,7 @@ GameSession::process_events() { SDLKey key = event.key.keysym.sym; - if(tux.key_event(key,DOWN)) + if(tux.key_event(key, true)) break; switch(key) @@ -356,7 +340,7 @@ GameSession::process_events() { SDLKey key = event.key.keysym.sym; - if(tux.key_event(key, UP)) + if(tux.key_event(key, false)) break; switch(key) @@ -407,93 +391,7 @@ GameSession::process_events() ch[1] = '\0'; } last_keys.append(ch); // add to cheat keys - - // Cheating words (the goal of this is really for debugging, - // but could be used for some cheating, nothing wrong with that) - if(compare_last(last_keys, "grow")) - { - tux.grow(false); - last_keys.clear(); - } - if(compare_last(last_keys, "fire")) - { - tux.grow(false); - tux.got_power = tux.FIRE_POWER; - last_keys.clear(); - } - if(compare_last(last_keys, "ice")) - { - tux.grow(false); - tux.got_power = tux.ICE_POWER; - last_keys.clear(); - } - if(compare_last(last_keys, "lifeup")) - { - player_status.lives++; - last_keys.clear(); - } - if(compare_last(last_keys, "lifedown")) - { - player_status.lives--; - last_keys.clear(); - } - if(compare_last(last_keys, "grease")) - { - tux.physic.set_velocity_x(tux.physic.get_velocity_x()*3); - last_keys.clear(); - } - if(compare_last(last_keys, "invincible")) - { // be invincle for the rest of the level - tux.invincible_timer.start(10000); - last_keys.clear(); - } - if(compare_last(last_keys, "shrink")) - { // remove powerups - tux.kill(tux.SHRINK); - last_keys.clear(); - } - if(compare_last(last_keys, "kill")) - { // kill Tux, but without losing a life - player_status.lives++; - tux.kill(tux.KILL); - last_keys.clear(); - } - if(compare_last(last_keys, "grid")) - { // toggle debug grid - debug_grid = !debug_grid; - last_keys.clear(); - } - if(compare_last(last_keys, "hover")) - { // toggle hover ability on/off - tux.enable_hover = !tux.enable_hover; - last_keys.clear(); - } - if(compare_last(last_keys, "gotoend")) - { // goes to the end of the level - tux.move(Vector( - (currentsector->solids->get_width()*32) - - (screen->w*2), - 0)); - currentsector->camera->reset( - Vector(tux.get_pos().x, tux.get_pos().y)); - last_keys.clear(); - } - // temporary to help player's choosing a flapping - if(compare_last(last_keys, "marek")) - { - tux.flapping_mode = Player::MAREK_FLAP; - last_keys.clear(); - } - if(compare_last(last_keys, "ricardo")) - { - tux.flapping_mode = Player::RICARDO_FLAP; - last_keys.clear(); - } - if(compare_last(last_keys, "ryan")) - { - tux.flapping_mode = Player::RYAN_FLAP; - last_keys.clear(); - } + handle_cheats(); break; case SDL_JOYAXISMOTION: @@ -501,74 +399,75 @@ GameSession::process_events() { if (event.jaxis.value < -joystick_keymap.dead_zone) { - tux.input.left = DOWN; - tux.input.right = UP; + tux.input.left = true; + tux.input.right = false; } else if (event.jaxis.value > joystick_keymap.dead_zone) { - tux.input.left = UP; - tux.input.right = DOWN; + tux.input.left = false; + tux.input.right = true; } else { - tux.input.left = DOWN; - tux.input.right = DOWN; + tux.input.left = false; + tux.input.right = false; } } else if (event.jaxis.axis == joystick_keymap.y_axis) { if (event.jaxis.value > joystick_keymap.dead_zone) { - tux.input.up = DOWN; - tux.input.down = UP; + tux.input.up = true; + tux.input.down = false; } else if (event.jaxis.value < -joystick_keymap.dead_zone) { - tux.input.up = UP; - tux.input.down = DOWN; + tux.input.up = false; + tux.input.down = true; } else { - tux.input.up = DOWN; - tux.input.down = DOWN; + tux.input.up = false; + tux.input.down = false; } } break; case SDL_JOYHATMOTION: if(event.jhat.value & SDL_HAT_UP) { - tux.input.up = DOWN; - tux.input.down = UP; + tux.input.up = true; + tux.input.down = false; } else if(event.jhat.value & SDL_HAT_DOWN) { - tux.input.up = UP; - tux.input.down = DOWN; + tux.input.up = false; + tux.input.down = true; } else if(event.jhat.value & SDL_HAT_LEFT) { - tux.input.left = DOWN; - tux.input.right = UP; + tux.input.left = true; + tux.input.right = false; } else if(event.jhat.value & SDL_HAT_RIGHT) { - tux.input.left = UP; - tux.input.right = DOWN; + tux.input.left = false; + tux.input.right = true; } else if(event.jhat.value == SDL_HAT_CENTERED) { - tux.input.left = UP; - tux.input.right = UP; - tux.input.up = UP; - tux.input.down = UP; + tux.input.left = false; + tux.input.right = false; + tux.input.up = false; + tux.input.down = false; } break; case SDL_JOYBUTTONDOWN: + // FIXME: I assume we have to set old_jump and stuff here?!? if (event.jbutton.button == joystick_keymap.a_button) - tux.input.jump = DOWN; + tux.input.jump = true; else if (event.jbutton.button == joystick_keymap.b_button) - tux.input.fire = DOWN; + tux.input.fire = true; else if (event.jbutton.button == joystick_keymap.start_button) on_escape_press(); break; case SDL_JOYBUTTONUP: if (event.jbutton.button == joystick_keymap.a_button) - tux.input.jump = UP; + tux.input.jump = false; else if (event.jbutton.button == joystick_keymap.b_button) - tux.input.fire = UP; + tux.input.fire = false; break; default: @@ -580,6 +479,93 @@ GameSession::process_events() } void +GameSession::handle_cheats() +{ + Player& tux = *currentsector->player; + + // Cheating words (the goal of this is really for debugging, + // but could be used for some cheating, nothing wrong with that) + if(compare_last(last_keys, "grow")) { + tux.grow(false); + last_keys.clear(); + } + if(compare_last(last_keys, "fire")) { + tux.grow(false); + tux.got_power = tux.FIRE_POWER; + last_keys.clear(); + } + if(compare_last(last_keys, "ice")) { + tux.grow(false); + tux.got_power = tux.ICE_POWER; + last_keys.clear(); + } + if(compare_last(last_keys, "lifeup")) { + player_status.lives++; + last_keys.clear(); + } + if(compare_last(last_keys, "lifedown")) { + player_status.lives--; + last_keys.clear(); + } + if(compare_last(last_keys, "grease")) { + tux.physic.set_velocity_x(tux.physic.get_velocity_x()*3); + last_keys.clear(); + } + if(compare_last(last_keys, "invincible")) { + // be invincle for the rest of the level + tux.invincible_timer.start(10000); + last_keys.clear(); + } + if(compare_last(last_keys, "shrink")) { + // remove powerups + tux.kill(tux.SHRINK); + last_keys.clear(); + } + if(compare_last(last_keys, "kill")) { + // kill Tux, but without losing a life + player_status.lives++; + tux.kill(tux.KILL); + last_keys.clear(); + } + if(compare_last(last_keys, "grid")) { + // toggle debug grid + debug_grid = !debug_grid; + last_keys.clear(); + } + if(compare_last(last_keys, "hover")) { + // toggle hover ability on/off + tux.enable_hover = !tux.enable_hover; + last_keys.clear(); + } + if(compare_last(last_keys, "gotoend")) { + // goes to the end of the level + tux.move(Vector( + (currentsector->solids->get_width()*32) - (screen->w*2), 0)); + currentsector->camera->reset( + Vector(tux.get_pos().x, tux.get_pos().y)); + last_keys.clear(); + } + if(compare_last(last_keys, "finish")) { + // finish current sector + exit_status = ES_LEVEL_FINISHED; + // don't add points to stats though... + } + // temporary to help player's choosing a flapping + if(compare_last(last_keys, "marek")) { + tux.flapping_mode = Player::MAREK_FLAP; + last_keys.clear(); + } + if(compare_last(last_keys, "ricardo")) { + tux.flapping_mode = Player::RICARDO_FLAP; + last_keys.clear(); + } + if(compare_last(last_keys, "ryan")) { + tux.flapping_mode = Player::RYAN_FLAP; + last_keys.clear(); + } +} + +void GameSession::check_end_conditions() { Player* tux = currentsector->player; @@ -811,7 +797,7 @@ GameSession::respawn(const std::string& sector, const std::string& spawnpoint) void GameSession::start_sequence(const std::string& sequencename) { - if(sequencename == "endsequence") { + if(sequencename == "endsequence" || sequencename == "fireworks") { if(end_sequence) return; @@ -825,7 +811,7 @@ GameSession::start_sequence(const std::string& sequencename) global_stats.set_points(TIME_NEEDED_STAT, int(time_left.get_period() - time_left.get_timeleft())); - if(level->get_end_sequence_type() == Level::FIREWORKS_ENDSEQ_ANIM) { + if(sequencename == "fireworks") { currentsector->add_object(new Fireworks()); } } else { diff --git a/src/gameloop.h b/src/gameloop.h index a63a24b05..ea1df562a 100644 --- a/src/gameloop.h +++ b/src/gameloop.h @@ -129,6 +129,7 @@ private: void check_end_conditions(); void start_timers(); void process_events(); + void handle_cheats(); void levelintro(); void drawstatus(DrawingContext& context); diff --git a/src/intro.cpp b/src/intro.cpp deleted file mode 100644 index d23e600d7..000000000 --- a/src/intro.cpp +++ /dev/null @@ -1,34 +0,0 @@ -// $Id$ -// -// SuperTux - A Jump'n Run -// Copyright (C) 2000 Bill Kendrick -// -// 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 - -#include "intro.h" -#include "app/globals.h" -#include "defines.h" -#include "video/font.h" -#include "video/screen.h" -#include "resources.h" - -using namespace SuperTux; - -void draw_intro() -{ - display_text_file("intro.txt", 1, white_big_text , white_text, white_small_text, blue_text ); -} - diff --git a/src/intro.h b/src/intro.h deleted file mode 100644 index 87b34e22f..000000000 --- a/src/intro.h +++ /dev/null @@ -1,29 +0,0 @@ -// $Id$ -// -// SuperTux - A Jump'n Run -// Copyright (C) 2000 Bill Kendrick -// -// 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. - -#ifndef SUPERTUX_INTRO_H -#define SUPERTUX_INTRO_H - -void draw_intro(); - -#endif /*SUPERTUX_INTRO_H*/ - -/* Local Variables: */ -/* mode:c++ */ -/* End: */ diff --git a/src/level.cpp b/src/level.cpp index 8e572a05e..21ce9eb53 100644 --- a/src/level.cpp +++ b/src/level.cpp @@ -38,7 +38,6 @@ #include "lisp/writer.h" #include "level.h" #include "math/physic.h" -#include "scene.h" #include "sector.h" #include "tile.h" #include "resources.h" @@ -47,11 +46,13 @@ #include "object/tilemap.h" #include "object/coin.h" +// test +#include "flip_level_transformer.h" + using namespace std; Level::Level() - : name("noname"), author("mr. x"), timelimit(500), - end_sequence_type(NONE_ENDSEQ_ANIM) + : name("noname"), author("Mr. X"), timelimit(500) { } @@ -70,6 +71,13 @@ Level::load(const std::string& filepath) level->get("version", version); if(version == 1) { load_old_format(*level); + +#if 0 + // test for now + FlipLevelTransformer* transformer = new FlipLevelTransformer(); + transformer->transform(this); +#endif + return; } @@ -91,20 +99,12 @@ Level::load(const std::string& filepath) Sector* sector = new Sector; sector->parse(*(iter.lisp())); add_sector(sector); - } else if(token == "end-sequence-animation") { - std::string endsequencename; - iter.value()->get(endsequencename); - if(endsequencename == "fireworks") { - end_sequence_type = FIREWORKS_ENDSEQ_ANIM; - } else { - std::cout << "Unknown endsequence type: '" << endsequencename << - "'.\n"; - } } else { std::cerr << "Unknown token '" << token << "' in level file.\n"; continue; } } + } catch(std::exception& e) { std::stringstream msg; msg << "Problem when reading level '" << filepath << "': " << e.what(); @@ -144,12 +144,11 @@ Level::save(const std::string& filename) writer->write_string("name", name, true); writer->write_string("author", author); writer->write_int("time", timelimit); - writer->write_string("end-sequence-animation", - end_sequence_type == FIREWORKS_ENDSEQ_ANIM ? "fireworks" : "none"); for(Sectors::iterator i = sectors.begin(); i != sectors.end(); ++i) { + Sector* sector = *i; writer->start_list("sector"); - i->second->write(*writer); + sector->write(*writer); writer->end_list("sector"); } @@ -162,63 +161,41 @@ Level::save(const std::string& filename) Level::~Level() { for(Sectors::iterator i = sectors.begin(); i != sectors.end(); ++i) - delete i->second; + delete *i; } void Level::add_sector(Sector* sector) { - sectors.insert(std::make_pair(sector->get_name(), sector)); + Sector* test = get_sector(sector->get_name()); + if(test != 0) { + throw std::runtime_error("Trying to add 2 sectors with same name"); + } + sectors.push_back(sector); } Sector* Level::get_sector(const std::string& name) { - Sectors::iterator i = sectors.find(name); - if(i == sectors.end()) - return 0; + for(Sectors::iterator i = sectors.begin(); i != sectors.end(); ++i) { + Sector* sector = *i; + if(sector->get_name() == name) + return sector; + } - return i->second; + return 0; } -Sector* -Level::get_next_sector(const Sector* sector) +size_t +Level::get_sector_count() { - for(Sectors::iterator i = sectors.begin(); i != sectors.end(); ++i) - { - if(i->second == sector) - { - i++; - if(i == sectors.end()) - return NULL; - return i->second; - } - } - std::cerr << "Warning: Sector not found on level\n"; - return NULL; + return sectors.size(); } Sector* -Level::get_previous_sector(const Sector* sector) +Level::get_sector(size_t num) { - for(Sectors::iterator i = sectors.begin(); i != sectors.end(); ++i) - { - if(i->second == sector) - { - if(i == sectors.begin()) - return NULL; - i--; - return i->second; - } - } - std::cerr << "Warning: Sector not found on level\n"; - return NULL; -} - -int -Level::get_total_sectors() -{ -return sectors.size(); + return sectors.at(num); } int @@ -226,16 +203,17 @@ Level::get_total_badguys() { int total_badguys = 0; for(Sectors::iterator i = sectors.begin(); i != sectors.end(); ++i) - total_badguys += i->second->get_total_badguys(); + total_badguys += (*i)->get_total_badguys(); return total_badguys; } int Level::get_total_coins() { + // FIXME not really correct as coins can also be inside blocks... int total_coins = 0; for(Sectors::iterator i = sectors.begin(); i != sectors.end(); ++i) { - Sector* sector = i->second; + Sector* sector = *i; for(Sector::GameObjects::iterator o = sector->gameobjects.begin(); o != sector->gameobjects.end(); ++o) { Coin* coin = dynamic_cast (*o); @@ -245,3 +223,4 @@ Level::get_total_coins() } return total_coins; } + diff --git a/src/level.h b/src/level.h index 7eb024807..555138ae1 100644 --- a/src/level.h +++ b/src/level.h @@ -21,11 +21,9 @@ #ifndef SUPERTUX_LEVEL_H #define SUPERTUX_LEVEL_H -#include +#include #include -using namespace SuperTux; - class Sector; namespace lisp { @@ -35,17 +33,11 @@ class Lisp; class Level { public: - enum EndSequenceType{ - NONE_ENDSEQ_ANIM, - FIREWORKS_ENDSEQ_ANIM - }; - std::string name; std::string author; int timelimit; - typedef std::map Sectors; + typedef std::vector Sectors; Sectors sectors; - EndSequenceType end_sequence_type; public: Level(); @@ -55,9 +47,6 @@ public: void load(const std::string& filename); void save(const std::string& filename); - EndSequenceType get_end_sequence_type() const - { return end_sequence_type; } - const std::string& get_name() const { return name; } @@ -68,10 +57,8 @@ public: Sector* get_sector(const std::string& name); - Sector* get_next_sector(const Sector* sector); - Sector* get_previous_sector(const Sector* sector); - - int get_total_sectors(); + size_t get_sector_count(); + Sector* get_sector(size_t num); int get_total_badguys(); int get_total_coins(); diff --git a/src/level_transformer.cpp b/src/level_transformer.cpp new file mode 100644 index 000000000..4735dd247 --- /dev/null +++ b/src/level_transformer.cpp @@ -0,0 +1,17 @@ +#include + +#include "level_transformer.h" +#include "level.h" + +LevelTransformer::~LevelTransformer() +{ +} + +void +LevelTransformer::transform(Level* level) +{ + for(size_t i = 0; i < level->get_sector_count(); ++i) { + transform_sector(level->get_sector(i)); + } +} + diff --git a/src/level_transformer.h b/src/level_transformer.h new file mode 100644 index 000000000..c587acf9e --- /dev/null +++ b/src/level_transformer.h @@ -0,0 +1,25 @@ +#ifndef __LEVEL_TRANSFORMER_H__ +#define __LEVEL_TRANSFORMER_H__ + +class Level; +class Sector; + +/** + * This class is an abstract interface for algorithms that transform levels in + * some way before they are played. + */ +class LevelTransformer +{ +public: + virtual ~LevelTransformer(); + + /** transform a complete Level, the standard implementation just calls + * transformSector on each sector in the level. + */ + virtual void transform(Level* level); + + virtual void transform_sector(Sector* sector) = 0; +}; + +#endif + diff --git a/src/leveleditor.cpp b/src/leveleditor.cpp index 1f1692def..9ae0dc173 100644 --- a/src/leveleditor.cpp +++ b/src/leveleditor.cpp @@ -201,622 +201,625 @@ delete img_next_sector_bt; void LevelEditor::run(const std::string filename) { -SoundManager::get()->halt_music(); -Menu::set_current(0); + SoundManager::get()->halt_music(); + Menu::set_current(0); -DrawingContext context; + DrawingContext context; -if(!filename.empty()) - { - level_nb = -1; - load_level(filename); - } -else - Menu::set_current(main_menu); + if(!filename.empty()) + { + level_nb = -1; + load_level(filename); + } + else + Menu::set_current(main_menu); -mouse_cursor->set_state(MC_NORMAL); + mouse_cursor->set_state(MC_NORMAL); -done = false; -while(!done) - { - events(); - action(); - draw(context); - } + done = false; + while(!done) + { + events(); + action(); + draw(context); + } -if(level_changed) - if(confirm_dialog(NULL, _("Level not saved. Wanna to?"))) - save_level(); + if(level_changed) + if(confirm_dialog(NULL, _("Level not saved. Wanna to?"))) + save_level(); } void LevelEditor::events() { -mouse_moved = false; + mouse_moved = false; -while(SDL_PollEvent(&event)) - { - Menu* menu = Menu::current(); - if(menu) + SDL_Event event; + while(SDL_PollEvent(&event)) { - menu->event(event); - menu->action(); - if(menu == main_menu) + Menu* menu = Menu::current(); + if(menu) { - switch (main_menu->check()) + menu->event(event); + menu->action(); + if(menu == main_menu) { - case MN_ID_RETURN: - Menu::set_current(0); - break; - case MN_ID_QUIT: - done = true; - break; + switch (main_menu->check()) + { + case MN_ID_RETURN: + Menu::set_current(0); + break; + case MN_ID_QUIT: + done = true; + break; + } } - } - else if(menu == create_subset_menu) - { - // activate or deactivate Create button if any filename as been specified - if(create_subset_menu->get_item_by_id(MN_ID_FILENAME_SUBSET).input[0] == '\0') - create_subset_menu->get_item_by_id(MN_ID_CREATE_SUBSET).kind = MN_DEACTIVE; - else - create_subset_menu->get_item_by_id(MN_ID_CREATE_SUBSET).kind = MN_ACTION; - - if(create_subset_menu->check() == MN_ID_CREATE_SUBSET) - { // applying settings: - std::string subset_name = create_subset_menu->get_item_by_id(MN_ID_FILENAME_SUBSET).input; - LevelSubset::create(subset_name); - - delete level_subset; - level_subset = new LevelSubset(); - level_subset->load(create_subset_menu->get_item_by_id(MN_ID_FILENAME_SUBSET).input); - - level_subset->title = create_subset_menu->get_item_by_id(MN_ID_TITLE_SUBSET).input; - level_subset->description = create_subset_menu->get_item_by_id(MN_ID_DESCRIPTION_SUBSET).input; - //FIXME: generate better level filenames - level_subset->add_level(subset_name+'/'+"new_level.stl"); - Level* newlevel = new Level(); - newlevel->add_sector(create_sector("main", 25, 19)); - newlevel->save(level_subset->get_level_filename(0)); - level_subset->save(); - - load_level(0); - - create_subset_menu->get_item_by_id(MN_ID_FILENAME_SUBSET).change_input(""); - create_subset_menu->get_item_by_id(MN_ID_TITLE_SUBSET).change_input(""); - create_subset_menu->get_item_by_id(MN_ID_DESCRIPTION_SUBSET).change_input(""); + else if(menu == create_subset_menu) + { + // activate or deactivate Create button if any filename as been specified + if(create_subset_menu->get_item_by_id(MN_ID_FILENAME_SUBSET).input[0] == '\0') + create_subset_menu->get_item_by_id(MN_ID_CREATE_SUBSET).kind = MN_DEACTIVE; + else + create_subset_menu->get_item_by_id(MN_ID_CREATE_SUBSET).kind = MN_ACTION; + + if(create_subset_menu->check() == MN_ID_CREATE_SUBSET) + { // applying settings: + std::string subset_name = create_subset_menu->get_item_by_id(MN_ID_FILENAME_SUBSET).input; + LevelSubset::create(subset_name); + + delete level_subset; + level_subset = new LevelSubset(); + level_subset->load(create_subset_menu->get_item_by_id(MN_ID_FILENAME_SUBSET).input); + + level_subset->title = create_subset_menu->get_item_by_id(MN_ID_TITLE_SUBSET).input; + level_subset->description = create_subset_menu->get_item_by_id(MN_ID_DESCRIPTION_SUBSET).input; + //FIXME: generate better level filenames + level_subset->add_level(subset_name+'/'+"new_level.stl"); + Level* newlevel = new Level(); + newlevel->add_sector(create_sector("main", 25, 19)); + newlevel->save(level_subset->get_level_filename(0)); + level_subset->save(); + + load_level(0); + + create_subset_menu->get_item_by_id(MN_ID_FILENAME_SUBSET).change_input(""); + create_subset_menu->get_item_by_id(MN_ID_TITLE_SUBSET).change_input(""); + create_subset_menu->get_item_by_id(MN_ID_DESCRIPTION_SUBSET).change_input(""); + } } - } - else if(menu == subset_menu) - { - int i = subset_menu->check(); - if(i >= 0) + else if(menu == subset_menu) { - std::set::iterator it = level_subsets.begin(); - for(int t = 0; t < i; t++) - it++; - load_level_subset(*it); - Menu::set_current(0); + int i = subset_menu->check(); + if(i >= 0) + { + std::set::iterator it = level_subsets.begin(); + for(int t = 0; t < i; t++) + it++; + load_level_subset(*it); + Menu::set_current(0); + } } - } - else if(menu == settings_menu) - { - if(settings_menu->check() == MN_ID_APPLY_SETTINGS) - { // applying settings: - level_changed = true; + else if(menu == settings_menu) + { + if(settings_menu->check() == MN_ID_APPLY_SETTINGS) + { // applying settings: + level_changed = true; - level->name = settings_menu->get_item_by_id(MN_ID_NAME).input; - level->author = settings_menu->get_item_by_id(MN_ID_AUTHOR).input; + level->name = settings_menu->get_item_by_id(MN_ID_NAME).input; + level->author = settings_menu->get_item_by_id(MN_ID_AUTHOR).input; - solids->resize(atoi(settings_menu->get_item_by_id(MN_ID_WIDTH).input.c_str()), - atoi(settings_menu->get_item_by_id(MN_ID_HEIGHT).input.c_str())); - foregrounds->resize(atoi(settings_menu->get_item_by_id(MN_ID_WIDTH).input.c_str()), - atoi(settings_menu->get_item_by_id(MN_ID_HEIGHT).input.c_str())); - backgrounds->resize(atoi(settings_menu->get_item_by_id(MN_ID_WIDTH).input.c_str()), - atoi(settings_menu->get_item_by_id(MN_ID_HEIGHT).input.c_str())); + solids->resize(atoi(settings_menu->get_item_by_id(MN_ID_WIDTH).input.c_str()), + atoi(settings_menu->get_item_by_id(MN_ID_HEIGHT).input.c_str())); + foregrounds->resize(atoi(settings_menu->get_item_by_id(MN_ID_WIDTH).input.c_str()), + atoi(settings_menu->get_item_by_id(MN_ID_HEIGHT).input.c_str())); + backgrounds->resize(atoi(settings_menu->get_item_by_id(MN_ID_WIDTH).input.c_str()), + atoi(settings_menu->get_item_by_id(MN_ID_HEIGHT).input.c_str())); - Menu::set_current(0); + Menu::set_current(0); + } } } - } - // check for events in buttons - else if(tiles_board->event(event)) - { - std::vector vector; - vector.push_back(tiles_board->selected_id()); + // check for events in buttons + else if(tiles_board->event(event)) + { + std::vector vector; + vector.push_back(tiles_board->selected_id()); - selection.clear(); - selection.push_back(vector); - continue; - } - else if(tiles_layer->event(event)) - { - cur_layer = tiles_layer->selected_id(); - continue; - } - else if(level_options->event(event)) - { - switch(level_options->selected_id()) + selection.clear(); + selection.push_back(vector); + continue; + } + else if(tiles_layer->event(event)) { - case BT_LEVEL_SAVE: - save_level(); - break; - case BT_LEVEL_TEST: - test_level(); - break; - case BT_LEVEL_SETUP: - Menu::set_current(settings_menu); - break; - case BT_NEXT_LEVEL: - if(level_nb + 1 < level_subset->get_num_levels()) - load_level(level_nb + 1); - else - { - char str[1024]; - sprintf(str,_("Level %d doesn't exist. Create it?"), level_nb + 2); - if(confirm_dialog(NULL, str)) - { - level_subset->add_level("new_level.stl"); - Level* newlevel = new Level(); - newlevel->add_sector(create_sector("main", 25, 19)); - newlevel->save(level_subset->get_level_filename(level_nb + 1)); - level_subset->save(); + cur_layer = tiles_layer->selected_id(); + continue; + } + else if(level_options->event(event)) + { + switch(level_options->selected_id()) + { + case BT_LEVEL_SAVE: + save_level(); + break; + case BT_LEVEL_TEST: + test_level(); + break; + case BT_LEVEL_SETUP: + Menu::set_current(settings_menu); + break; + case BT_NEXT_LEVEL: + if(level_nb + 1 < level_subset->get_num_levels()) load_level(level_nb + 1); + else + { + char str[1024]; + sprintf(str,_("Level %d doesn't exist. Create it?"), level_nb + 2); + if(confirm_dialog(NULL, str)) + { + level_subset->add_level("new_level.stl"); + Level* newlevel = new Level(); + newlevel->add_sector(create_sector("main", 25, 19)); + newlevel->save(level_subset->get_level_filename(level_nb + 1)); + level_subset->save(); + load_level(level_nb + 1); + } } - } - break; - case BT_PREVIOUS_LEVEL: - if(level_nb - 1 >= 0) - load_level(level_nb - 1); - break; - case BT_NEXT_SECTOR: -std::cerr << "next sector.\n"; -std::cerr << "total sectors: " << level->get_total_sectors() << std::endl; - load_sector(level->get_next_sector(sector)); - break; - case BT_PREVIOUS_SECTOR: -std::cerr << "previous sector.\n"; - load_sector(level->get_previous_sector(sector)); - break; + break; + case BT_PREVIOUS_LEVEL: + if(level_nb - 1 >= 0) + load_level(level_nb - 1); + break; + case BT_NEXT_SECTOR: + std::cerr << "next sector.\n"; + load_sector(sectornum+1); + break; + case BT_PREVIOUS_SECTOR: + std::cerr << "previous sector.\n"; + if(sectornum > 0) + load_sector(sectornum-1); + break; + } + level_options->set_unselected(); + continue; } - level_options->set_unselected(); - continue; - } - else - { - switch(event.type) + else { - case SDL_MOUSEMOTION: - mouse_moved = true; - if(SDL_GetMouseState(NULL, NULL)&SDL_BUTTON(SDL_BUTTON_RIGHT)) - { // movement like in strategy games - scroll.x += -1 * event.motion.xrel; - scroll.y += -1 * event.motion.yrel; - } - break; - - case SDL_MOUSEBUTTONDOWN: - mouse_moved = true; - if(event.button.button == SDL_BUTTON_LEFT) - left_button = true; - else if(event.button.button == SDL_BUTTON_MIDDLE) - { - middle_button = true; - selection_ini = Vector(event.button.x, event.button.y); - } - break; - - case SDL_MOUSEBUTTONUP: - mouse_moved = true; - if(event.button.button == SDL_BUTTON_LEFT) - left_button = false; - else if(event.button.button == SDL_BUTTON_MIDDLE) - { - middle_button = false; - selection_end = Vector(event.button.x, event.button.y); + switch(event.type) + { + case SDL_MOUSEMOTION: + mouse_moved = true; + mouse_x = event.motion.x; + mouse_y = event.motion.y; + if(SDL_GetMouseState(NULL, NULL)&SDL_BUTTON(SDL_BUTTON_RIGHT)) + { // movement like in strategy games + scroll.x += -1 * event.motion.xrel; + scroll.y += -1 * event.motion.yrel; + } + break; - if(selection_end.x < selection_ini.x) + case SDL_MOUSEBUTTONDOWN: + mouse_moved = true; + mouse_x = event.motion.x; + mouse_y = event.motion.y; + if(event.button.button == SDL_BUTTON_LEFT) + left_button = true; + else if(event.button.button == SDL_BUTTON_MIDDLE) { - float t = selection_ini.x; - selection_ini.x = selection_end.x; - selection_end.x = t; + middle_button = true; + selection_ini = Vector(event.button.x, event.button.y); } - if(selection_end.y < selection_ini.y) + break; + + case SDL_MOUSEBUTTONUP: + mouse_moved = true; + mouse_x = event.motion.x; + mouse_y = event.motion.y; + if(event.button.button == SDL_BUTTON_LEFT) + left_button = false; + else if(event.button.button == SDL_BUTTON_MIDDLE) { - float t = selection_ini.y; - selection_ini.y = selection_end.y; - selection_end.y = t; - } + middle_button = false; + selection_end = Vector(event.button.x, event.button.y); - selection.clear(); - std::vector vector; + if(selection_end.x < selection_ini.x) + { + float t = selection_ini.x; + selection_ini.x = selection_end.x; + selection_end.x = t; + } + if(selection_end.y < selection_ini.y) + { + float t = selection_ini.y; + selection_ini.y = selection_end.y; + selection_end.y = t; + } - TileMap* tilemap = 0; - if(cur_layer == LAYER_FOREGROUNDTILES) - tilemap = foregrounds; - else if(cur_layer == LAYER_TILES) - tilemap = solids; - else if(cur_layer == LAYER_BACKGROUNDTILES) - tilemap = backgrounds; + selection.clear(); + std::vector vector; - for(int x = 0; x < (int)((selection_end.x - selection_ini.x)*zoom / 32) + 1; x++) - { - vector.clear(); - for(int y = 0; y < (int)((selection_end.y - selection_ini.y)*zoom / 32) + 1; y++) + TileMap* tilemap = 0; + if(cur_layer == LAYER_FOREGROUNDTILES) + tilemap = foregrounds; + else if(cur_layer == LAYER_TILES) + tilemap = solids; + else if(cur_layer == LAYER_BACKGROUNDTILES) + tilemap = backgrounds; + + for(int x = 0; x < (int)((selection_end.x - selection_ini.x)*zoom / 32) + 1; x++) { - vector.push_back(tilemap->get_tile(x + - (int)(((selection_ini.x+scroll.x)*zoom)/32), - y + (int)(((selection_ini.y+scroll.y)*zoom)/32))->getID()); + vector.clear(); + for(int y = 0; y < (int)((selection_end.y - selection_ini.y)*zoom / 32) + 1; y++) + { + vector.push_back(tilemap->get_tile(x + + (int)(((selection_ini.x+scroll.x)*zoom)/32), + y + (int)(((selection_ini.y+scroll.y)*zoom)/32))->getID()); + } + selection.push_back(vector); } - selection.push_back(vector); } - } - break; + break; - case SDL_KEYDOWN: // key pressed - switch(event.key.keysym.sym) - { - case SDLK_ESCAPE: - Menu::set_current(main_menu); - break; - /* scrolling related events: */ - case SDLK_HOME: - scroll.x = 0; - break; - case SDLK_END: - scroll.x = sector->solids->get_height()*32 - screen->w; - break; - case SDLK_LEFT: - scroll.x -= 80; - break; - case SDLK_RIGHT: - scroll.x += 80; - break; - case SDLK_UP: - scroll.y -= 80; - break; - case SDLK_DOWN: - scroll.y += 80; - break; - case SDLK_PAGEUP: - scroll.x -= 450; - break; - case SDLK_PAGEDOWN: - scroll.x += 450; - break; - case SDLK_PLUS: - case SDLK_KP_PLUS: - zoom += 0.10; - break; - case SDLK_MINUS: - case SDLK_KP_MINUS: - zoom -= 0.10; - break; + case SDL_KEYDOWN: // key pressed + switch(event.key.keysym.sym) + { + case SDLK_ESCAPE: + Menu::set_current(main_menu); + break; + /* scrolling related events: */ + case SDLK_HOME: + scroll.x = 0; + break; + case SDLK_END: + scroll.x = sector->solids->get_height()*32 - screen->w; + break; + case SDLK_LEFT: + scroll.x -= 80; + break; + case SDLK_RIGHT: + scroll.x += 80; + break; + case SDLK_UP: + scroll.y -= 80; + break; + case SDLK_DOWN: + scroll.y += 80; + break; + case SDLK_PAGEUP: + scroll.x -= 450; + break; + case SDLK_PAGEDOWN: + scroll.x += 450; + break; + case SDLK_PLUS: + case SDLK_KP_PLUS: + zoom += 0.10; + break; + case SDLK_MINUS: + case SDLK_KP_MINUS: + zoom -= 0.10; + break; + + case SDLK_F1: + show_help(); + break; + case SDLK_F2: + show_grid = !show_grid; + break; + default: + break; + } + break; + + case SDL_QUIT: // window closed + done = true; + break; - case SDLK_F1: - show_help(); - break; - case SDLK_F2: - show_grid = !show_grid; - break; default: break; - } - break; - - case SDL_QUIT: // window closed - done = true; - break; - - default: - break; + } } } - } } void LevelEditor::action() { -mouse_cursor->set_state(MC_NORMAL); -if(tiles_board->is_hover() || tiles_layer->is_hover() || level_options->is_hover()) - mouse_cursor->set_state(MC_LINK); + mouse_cursor->set_state(MC_NORMAL); + if(tiles_board->is_hover() || tiles_layer->is_hover() || level_options->is_hover()) + mouse_cursor->set_state(MC_LINK); -if(sector) - { - // don't scroll before the start or after the level's end - float width = sector->solids->get_width() * 32; - float height = sector->solids->get_height() * 32; - - if(scroll.x < -screen->w/2) - scroll.x = -screen->w/2; - if(scroll.x > width - screen->w/2) - scroll.x = width - screen->w/2; - if(scroll.y < -screen->h/2) - scroll.y = -screen->h/2; - if(scroll.y > height - screen->h/2) - scroll.y = height - screen->h/2; - - // set camera translation, since BadGuys like it - sector->camera->set_scrolling((int)scroll.x, (int)scroll.y); - - if(left_button && mouse_moved) - for(unsigned int x = 0; x < selection.size(); x++) - for(unsigned int y = 0; y < selection[x].size(); y++) - change((int)(scroll.x + event.button.x) + (x*32), - (int)(scroll.y + event.button.y) + (y*32), selection[x][y], - cur_layer); - } + if(sector) + { + // don't scroll before the start or after the level's end + float width = sector->solids->get_width() * 32; + float height = sector->solids->get_height() * 32; + + if(scroll.x < -screen->w/2) + scroll.x = -screen->w/2; + if(scroll.x > width - screen->w/2) + scroll.x = width - screen->w/2; + if(scroll.y < -screen->h/2) + scroll.y = -screen->h/2; + if(scroll.y > height - screen->h/2) + scroll.y = height - screen->h/2; + + // set camera translation, since BadGuys like it + sector->camera->set_scrolling((int)scroll.x, (int)scroll.y); + + if(left_button && mouse_moved) + for(unsigned int x = 0; x < selection.size(); x++) + for(unsigned int y = 0; y < selection[x].size(); y++) + change((int)(scroll.x + mouse_x) + (x*32), + (int)(scroll.y + mouse_y) + (y*32), selection[x][y], + cur_layer); + } } #define FADING_TIME .6 void LevelEditor::draw(DrawingContext& context) { -context.draw_text(white_text, _("Level Editor"), Vector(10, 5), LEFT_ALLIGN, LAYER_GUI); -mouse_cursor->draw(context); + context.draw_text(white_text, _("Level Editor"), Vector(10, 5), LEFT_ALLIGN, LAYER_GUI); + mouse_cursor->draw(context); -// draw a filled background -context.draw_filled_rect(Vector(0,0), Vector(screen->w,screen->h), Color(60,60,60), LAYER_BACKGROUND0-1); - -if(level_name_timer.check()) - { - context.push_transform(); - if(level_name_timer.get_timeleft() < FADING_TIME) - context.set_alpha(int(level_name_timer.get_timeleft() * 255 / FADING_TIME)); + // draw a filled background + context.draw_filled_rect(Vector(0,0), Vector(screen->w,screen->h), Color(60,60,60), LAYER_BACKGROUND0-1); - context.draw_text(gold_text, level->name, Vector(screen->w/2, 30), CENTER_ALLIGN, LAYER_GUI); - if(level_nb != -1) + if(level_name_timer.check()) { - char str[128]; - sprintf(str, "%i/%i", level_nb+1, level_subset->get_num_levels()); - context.draw_text(gold_text, str, Vector(screen->w/2, 50), CENTER_ALLIGN, LAYER_GUI); - } + context.push_transform(); + if(level_name_timer.get_timeleft() < FADING_TIME) + context.set_alpha(int(level_name_timer.get_timeleft() * 255 / FADING_TIME)); - context.pop_transform(); - } -if(sector) - context.draw_text(white_small_text, _("F1 for help"), Vector(5, 510), LEFT_ALLIGN, LAYER_GUI-10); -else - context.draw_text(white_small_text, _("Choose a level subset"), Vector(5, 510), LEFT_ALLIGN, LAYER_GUI-10); - -Menu* menu = Menu::current(); -if(menu) - menu->draw(context); -else - { - tiles_board->draw(context); - tiles_layer->draw(context); - level_options->draw(context); - } + context.draw_text(gold_text, level->name, Vector(screen->w/2, 30), CENTER_ALLIGN, LAYER_GUI); + if(level_nb != -1) + { + char str[128]; + sprintf(str, "%i/%i", level_nb+1, level_subset->get_num_levels()); + context.draw_text(gold_text, str, Vector(screen->w/2, 50), CENTER_ALLIGN, LAYER_GUI); + } -// draw selection -if(sector) - { - if(!middle_button) + context.pop_transform(); + } + if(sector) + context.draw_text(white_small_text, _("F1 for help"), Vector(5, 510), LEFT_ALLIGN, LAYER_GUI-10); + else + context.draw_text(white_small_text, _("Choose a level subset"), Vector(5, 510), LEFT_ALLIGN, LAYER_GUI-10); + + Menu* menu = Menu::current(); + if(menu) + menu->draw(context); + else { - context.set_drawing_effect(SEMI_TRANSPARENT); + tiles_board->draw(context); + tiles_layer->draw(context); + level_options->draw(context); + } - if(selection.size()) + // draw selection + if(sector) + { + if(!middle_button) { - if(selection[0][0] == 0 && selection.size() == 1) - context.draw_surface(img_rubber_bt, Vector(event.button.x - 8, - event.button.y - 8), LAYER_GUI-2); - else if(selection[0][0] >= gameobjs_first_id || selection[0][0] < 0) + context.set_drawing_effect(SEMI_TRANSPARENT); + + if(selection.size()) { -// FIXME: this should draw an object image near cursor -#if 0 - int id = selection[0][0]; - - if(id == OBJ_TRAMPOLINE) - context.draw_surface(img_trampoline[0].get_frame(0), Vector(event.button.x - 8, - event.button.y - 8), LAYER_GUI-2); - else if(id == OBJ_FLYING_PLATFORM) - context.draw_surface(img_flying_platform->get_frame(0), Vector(event.button.x - 8, - event.button.y - 8), LAYER_GUI-2); - else - if(id == OBJ_DOOR) - /*context.draw_surface(door->get_frame(0), Vector(event.button.x - 8, - event.button.y - 8), LAYER_GUI-2);*/ - ; - else + if(selection[0][0] == 0 && selection.size() == 1) + context.draw_surface(img_rubber_bt, Vector(mouse_x - 8, + mouse_y - 8), LAYER_GUI-2); + else if(selection[0][0] >= gameobjs_first_id || selection[0][0] < 0) { - BadGuyKind kind = BadGuyKind((-id)-1); - BadGuy badguy(kind, 0,0); - badguy.activate(LEFT); - Surface *img = badguy.get_image(); + // FIXME: this should draw an object image near cursor + #if 0 + int id = selection[0][0]; + + if(id == OBJ_TRAMPOLINE) + context.draw_surface(img_trampoline[0].get_frame(0), Vector(mouse_x - 8, + mouse_y - 8), LAYER_GUI-2); + else if(id == OBJ_FLYING_PLATFORM) + context.draw_surface(img_flying_platform->get_frame(0), Vector(mouse_x - 8, + mouse_y - 8), LAYER_GUI-2); + else + if(id == OBJ_DOOR) + /*context.draw_surface(door->get_frame(0), Vector(mouse_x - 8, + mouse_y - 8), LAYER_GUI-2);*/ + ; + else + { + BadGuyKind kind = BadGuyKind((-id)-1); + BadGuy badguy(kind, 0,0); + badguy.activate(LEFT); + Surface *img = badguy.get_image(); - context.draw_surface(img, Vector(event.button.x - 8, - event.button.y - 8), LAYER_GUI-2); + context.draw_surface(img, Vector(mouse_x - 8, + mouse_y - 8), LAYER_GUI-2); + } + #endif } -#endif - } - else - { - for(unsigned int x = 0; x < selection.size(); x++) - for(unsigned int y = 0; y < selection[x].size(); y++) { - const Tile* tile = tile_manager->get(selection[x][y]); - tile->draw(context, - Vector(event.button.x + x*32 - 8, event.button.y + y*32 - 8), - LAYER_GUI-2); + else + { + for(unsigned int x = 0; x < selection.size(); x++) + for(unsigned int y = 0; y < selection[x].size(); y++) { + const Tile* tile = tile_manager->get(selection[x][y]); + tile->draw(context, + Vector(mouse_x + x*32 - 8, mouse_y + y*32 - 8), + LAYER_GUI-2); + } } } + context.set_drawing_effect(NONE_EFFECT); } - context.set_drawing_effect(NONE_EFFECT); - } - else - context.draw_filled_rect(Vector(std::min((int)selection_ini.x, (int)event.button.x)*zoom, - std::min((int)selection_ini.y, (int)event.button.y))*zoom, - Vector(abs(event.button.x - (int)selection_ini.x)*zoom, - abs(event.button.y - (int)selection_ini.y)*zoom), - Color(170,255,170,128), LAYER_GUI-2); + else + context.draw_filled_rect(Vector(std::min((int)selection_ini.x, mouse_x)*zoom, + std::min((int)selection_ini.y, mouse_y))*zoom, + Vector(abs(mouse_x - (int)selection_ini.x)*zoom, + abs(mouse_y - (int)selection_ini.y)*zoom), + Color(170,255,170,128), LAYER_GUI-2); - if(show_grid) - { - for(int x = 0; x < screen->w / (32*zoom); x++) + if(show_grid) { - int pos = (int)(x*32*zoom) - ((int)scroll.x % 32); - context.draw_filled_rect(Vector (pos, 0), Vector(1, screen->h), - Color(225, 225, 225), LAYER_GUI-50); - } - for(int y = 0; y < screen->h / (32*zoom); y++) - { - int pos = (int)(y*32*zoom) - ((int)scroll.y % 32); - context.draw_filled_rect(Vector (0, pos), Vector(screen->w, 1), - Color(225, 225, 225), LAYER_GUI-50); + for(int x = 0; x < screen->w / (32*zoom); x++) + { + int pos = (int)(x*32*zoom) - ((int)scroll.x % 32); + context.draw_filled_rect(Vector (pos, 0), Vector(1, screen->h), + Color(225, 225, 225), LAYER_GUI-50); + } + for(int y = 0; y < screen->h / (32*zoom); y++) + { + int pos = (int)(y*32*zoom) - ((int)scroll.y % 32); + context.draw_filled_rect(Vector (0, pos), Vector(screen->w, 1), + Color(225, 225, 225), LAYER_GUI-50); + } } - } - context.push_transform(); - context.set_translation(scroll); - context.set_zooming(zoom); + context.push_transform(); + context.set_translation(scroll); + context.set_zooming(zoom); - for(Sector::GameObjects::iterator i = sector->gameobjects.begin(); i != sector->gameobjects.end(); ++i) - { - TileMap* tilemap = dynamic_cast (*i); - if(tilemap) - { // draw the non-selected tiles semi-transparently - context.push_transform(); + for(Sector::GameObjects::iterator i = sector->gameobjects.begin(); i != sector->gameobjects.end(); ++i) + { + TileMap* tilemap = dynamic_cast (*i); + if(tilemap) + { // draw the non-selected tiles semi-transparently + context.push_transform(); - if(tilemap->get_layer() != cur_layer) - context.set_drawing_effect(SEMI_TRANSPARENT); - (*i)->draw(context); + if(tilemap->get_layer() != cur_layer) + context.set_drawing_effect(SEMI_TRANSPARENT); + (*i)->draw(context); - context.pop_transform(); - continue; - } - Background* background = dynamic_cast (*i); - if(background) - { // don't resize background - context.push_transform(); - context.set_zooming(1.0); - (*i)->draw(context); - context.pop_transform(); + context.pop_transform(); + continue; + } + Background* background = dynamic_cast (*i); + if(background) + { // don't resize background + context.push_transform(); + context.set_zooming(1.0); + (*i)->draw(context); + context.pop_transform(); + } + else + (*i)->draw(context); } - else - (*i)->draw(context); - } - context.pop_transform(); - } -else - context.draw_filled_rect(Vector(0,0), Vector(screen->w,screen->h),Color(0,0,0), LAYER_BACKGROUND0); + context.pop_transform(); + } + else + context.draw_filled_rect(Vector(0,0), Vector(screen->w,screen->h),Color(0,0,0), LAYER_BACKGROUND0); -context.do_drawing(); + context.do_drawing(); } void LevelEditor::load_level_subset(std::string filename) { -delete level_subset; -level_subset = new LevelSubset(); -level_subset->load(filename.c_str()); -load_level(0); + delete level_subset; + level_subset = new LevelSubset(); + level_subset->load(filename.c_str()); + load_level(0); } void LevelEditor::load_level(std::string filename) { -if(level_changed) - { - if(confirm_dialog(NULL, _("Level not saved. Wanna to?"))) - save_level(); - else - return; - } - -level_filename = filename; + if(level_changed) + { + if(confirm_dialog(NULL, _("Level not saved. Wanna to?"))) + save_level(); + else + return; + } -delete level; -level = new Level(); -level->load(filename); + level_filename = filename; -load_sector("main"); -level_name_timer.start(3000); -scroll.x = scroll.y = 0; -level_changed = false; + delete level; + level = new Level(); + level->load(filename); + + sectornum = 0; + load_sector(0); + level_name_timer.start(3000); + scroll.x = scroll.y = 0; + level_changed = false; -settings_menu->get_item_by_id(MN_ID_NAME).change_input(level->name.c_str()); -settings_menu->get_item_by_id(MN_ID_AUTHOR).change_input(level->author.c_str()); + settings_menu->get_item_by_id(MN_ID_NAME).change_input(level->name.c_str()); + settings_menu->get_item_by_id(MN_ID_AUTHOR).change_input(level->author.c_str()); } void LevelEditor::load_level(int nb) { -if(level_changed) - { - if(confirm_dialog(NULL, _("Level not saved. Wanna to?"))) - save_level(); - else - return; - } - -level_nb = nb; -level_filename = level_subset->get_level_filename(level_nb); - -load_level(level_filename); -} + if(level_changed) + { + if(confirm_dialog(NULL, _("Level not saved. Wanna to?"))) + save_level(); + else + return; + } -void LevelEditor::load_sector(std::string name) -{ -sector_name = name; -sector = level->get_sector(sector_name); -if(!sector) - Termination::abort("Level has no " + sector_name + " sector.", ""); + level_nb = nb; + level_filename = level_subset->get_level_filename(level_nb); -load_sector(sector); + load_level(level_filename); } -void LevelEditor::load_sector(Sector* sector_) +void LevelEditor::load_sector(size_t num) { -if(sector_ == NULL) + assert(num <= level->get_sector_count()); + + if(num >= level->get_sector_count()) { - if(!confirm_dialog(NULL, _("No more sectors exist. Create another?"))) - return; - sector_ = create_sector("new_sector",25,19); - level->add_sector(sector_); + if(!confirm_dialog(NULL, _("No more sectors exist. Create another?"))) + return; + Sector* sector_ = create_sector("new_sector",25,19); + level->add_sector(sector_); + num = level->get_sector_count()-1; } -sector = sector_; + sector = level->get_sector(num); -/* Load sector stuff */ + /* Load sector stuff */ -sector->update_game_objects(); + sector->update_game_objects(); -foregrounds = solids = backgrounds = 0; -/* Point foregrounds, backgrounds, solids to its layer */ -for(Sector::GameObjects::iterator i = sector->gameobjects.begin(); i != sector->gameobjects.end(); i++) - { - TileMap* tilemap = dynamic_cast (*i); - if(tilemap) + foregrounds = solids = backgrounds = 0; + /* Point foregrounds, backgrounds, solids to its layer */ + for(Sector::GameObjects::iterator i = sector->gameobjects.begin(); i != sector->gameobjects.end(); i++) { - if(tilemap->get_layer() == LAYER_FOREGROUNDTILES) - foregrounds = tilemap; - else if(tilemap->get_layer() == LAYER_TILES) - solids = tilemap; - else if(tilemap->get_layer() == LAYER_BACKGROUNDTILES) - backgrounds = tilemap; + TileMap* tilemap = dynamic_cast (*i); + if(tilemap) + { + if(tilemap->get_layer() == LAYER_FOREGROUNDTILES) + foregrounds = tilemap; + else if(tilemap->get_layer() == LAYER_TILES) + solids = tilemap; + else if(tilemap->get_layer() == LAYER_BACKGROUNDTILES) + backgrounds = tilemap; + } } - } -if(!foregrounds) - { - TileMap* tilemap = new TileMap(LAYER_FOREGROUNDTILES, false, solids->get_width(), solids->get_height()); - sector->add_object(tilemap); - sector->update_game_objects(); - } -if(!backgrounds) - { - TileMap* tilemap = new TileMap(LAYER_BACKGROUNDTILES, false, solids->get_width(), solids->get_height()); - sector->add_object(tilemap); - sector->update_game_objects(); - } + if(!foregrounds) + { + TileMap* tilemap = new TileMap(LAYER_FOREGROUNDTILES, false, solids->get_width(), solids->get_height()); + sector->add_object(tilemap); + sector->update_game_objects(); + } + if(!backgrounds) + { + TileMap* tilemap = new TileMap(LAYER_BACKGROUNDTILES, false, solids->get_width(), solids->get_height()); + sector->add_object(tilemap); + sector->update_game_objects(); + } + + char str[64]; + sprintf(str, "%i", solids->get_width()); + settings_menu->get_item_by_id(MN_ID_WIDTH).change_input(str); + sprintf(str, "%i", solids->get_height()); + settings_menu->get_item_by_id(MN_ID_HEIGHT).change_input(str); -char str[64]; -sprintf(str, "%i", solids->get_width()); -settings_menu->get_item_by_id(MN_ID_WIDTH).change_input(str); -sprintf(str, "%i", solids->get_height()); -settings_menu->get_item_by_id(MN_ID_HEIGHT).change_input(str); + sectornum = num; } void LevelEditor::save_level() { -level->save(level_filename); -level_changed = false; + level->save(level_filename); + level_changed = false; } void LevelEditor::test_level() @@ -907,111 +910,111 @@ void LevelEditor::change(int x, int y, int newtile, int layer) void LevelEditor::show_help() { -DrawingContext context; - -bool show_grid_t = show_grid; -show_grid = false; -mouse_cursor->set_state(MC_HIDE); - - -char str[1024]; -const char *text1[] = { - _("This is the built-in level editor. Its aim is to be intuitive\n" - "and simple to use, so it should be pretty straightforward.\n" - "\n" - "To open a level, first you'll have to select a level subset from\n" - "the menu (or create your own).\n" - "A level subset is basically a collection of levels.\n" - "They can then be played from the Contrib menu.\n" - "\n" - "To access the menu from the level editor, just press Esc.\n" - "\n" - "You are currently looking at the level. To scroll it, just\n" - "press the right mouse button and drag the mouse. It will move like\n" - "a strategy game.\n" - "You can also use the arrow keys and Page Up/Down.\n" - "\n" - "'+' and '-' keys can be used to zoom the level in/out.\n" - "\n" - "You probably already noticed those floating groups of buttons.\n" - "Each one serves a different purpose. To select a certain button\n" - "just press the Left mouse button on it. A few buttons have key\n" - "shortcuts. You can find them by pressing the Right mouse button on\n" - "a button. That will also show what that button does.\n" - "Groups of buttons can also be moved around by just dragging them,\n" - "while pressing the Left mouse button.\n" - "\n" - "Let's learn a bit of what each group of buttons does, shall we?\n" - "\n" - "To starting putting tiles and objects around use the bigger group\n" - "of buttons. Each button is a different tile. To put it on the level,\n" - "just press it and then left click in the level.\n" - "You can also copy tiles from the level by using the middle mouse button.\n" - "Use the mouse wheel to scroll that group of buttons. You will find\n" - "enemies and game objects in the bottom.\n") - }; - -const char *text2[] = { - _("The Foreground/Interactive/Background buttons may be used to\n" - "see and edit the respective layer. Levels have three tiles layers:\n" - "Foreground - tiles are drawn on top of everything and have no contact\n" - "with the player.\n" - "Interactive - these are the tiles that have contact with the player.\n" - "Background - tiles are drawn underneath everything and have no contact\n" - "with the player.\n" - "The unselected layers will be drawn semi-transparently.\n" - "\n" - "Last, but not least, the group of buttons that's left serves\n" - "to do related actions with the level.\n" - "From left to right:\n" - "Mini arrows - can be used to choose other sectors.\n" - "Sectors are mini-levels, so to speak, that can be accessed using a door.\n" - "Big arrows - choose other level in the same level subset.\n" - "Diskette - save the level\n" - "Tux - test the level\n" - "Tools - set a few settings for the level, including resizing it.\n" - "\n" - "We have reached the end of this Howto.\n" - "\n" - "Don't forget to send us a few cool levels. :)\n" - "\n" - "Enjoy,\n" - " SuperTux development team\n" - "\n" - "PS: If you are looking for something more powerful, you might like to\n" - "try FlexLay. FlexLay is a level editor that supports several games,\n" - "including SuperTux. It is an independent project.\n" - "Webpage: http://pingus.seul.org/~grumbel/flexlay/") - }; - -const char **text[] = { text1, text2 }; - - -bool done; -for(unsigned int i = 0; i < sizeof(text) / sizeof(text[0]); i++) - { - draw(context); + DrawingContext context; + + bool show_grid_t = show_grid; + show_grid = false; + mouse_cursor->set_state(MC_HIDE); + + + char str[1024]; + const char *text1[] = { + _("This is the built-in level editor. Its aim is to be intuitive\n" + "and simple to use, so it should be pretty straightforward.\n" + "\n" + "To open a level, first you'll have to select a level subset from\n" + "the menu (or create your own).\n" + "A level subset is basically a collection of levels.\n" + "They can then be played from the Contrib menu.\n" + "\n" + "To access the menu from the level editor, just press Esc.\n" + "\n" + "You are currently looking at the level. To scroll it, just\n" + "press the right mouse button and drag the mouse. It will move like\n" + "a strategy game.\n" + "You can also use the arrow keys and Page Up/Down.\n" + "\n" + "'+' and '-' keys can be used to zoom the level in/out.\n" + "\n" + "You probably already noticed those floating groups of buttons.\n" + "Each one serves a different purpose. To select a certain button\n" + "just press the Left mouse button on it. A few buttons have key\n" + "shortcuts. You can find them by pressing the Right mouse button on\n" + "a button. That will also show what that button does.\n" + "Groups of buttons can also be moved around by just dragging them,\n" + "while pressing the Left mouse button.\n" + "\n" + "Let's learn a bit of what each group of buttons does, shall we?\n" + "\n" + "To starting putting tiles and objects around use the bigger group\n" + "of buttons. Each button is a different tile. To put it on the level,\n" + "just press it and then left click in the level.\n" + "You can also copy tiles from the level by using the middle mouse button.\n" + "Use the mouse wheel to scroll that group of buttons. You will find\n" + "enemies and game objects in the bottom.\n") + }; + + const char *text2[] = { + _("The Foreground/Interactive/Background buttons may be used to\n" + "see and edit the respective layer. Levels have three tiles layers:\n" + "Foreground - tiles are drawn on top of everything and have no contact\n" + "with the player.\n" + "Interactive - these are the tiles that have contact with the player.\n" + "Background - tiles are drawn underneath everything and have no contact\n" + "with the player.\n" + "The unselected layers will be drawn semi-transparently.\n" + "\n" + "Last, but not least, the group of buttons that's left serves\n" + "to do related actions with the level.\n" + "From left to right:\n" + "Mini arrows - can be used to choose other sectors.\n" + "Sectors are mini-levels, so to speak, that can be accessed using a door.\n" + "Big arrows - choose other level in the same level subset.\n" + "Diskette - save the level\n" + "Tux - test the level\n" + "Tools - set a few settings for the level, including resizing it.\n" + "\n" + "We have reached the end of this Howto.\n" + "\n" + "Don't forget to send us a few cool levels. :)\n" + "\n" + "Enjoy,\n" + " SuperTux development team\n" + "\n" + "PS: If you are looking for something more powerful, you might like to\n" + "try FlexLay. FlexLay is a level editor that supports several games,\n" + "including SuperTux. It is an independent project.\n" + "Webpage: http://pingus.seul.org/~grumbel/flexlay/") + }; + + const char **text[] = { text1, text2 }; + + + bool done; + for(unsigned int i = 0; i < sizeof(text) / sizeof(text[0]); i++) + { + draw(context); - context.draw_text(blue_text, _("- Level Editor's Help -"), Vector(screen->w/2, 60), CENTER_ALLIGN, LAYER_GUI); + context.draw_text(blue_text, _("- Level Editor's Help -"), Vector(screen->w/2, 60), CENTER_ALLIGN, LAYER_GUI); - context.draw_text(white_small_text, *text[i], Vector(20, 120), LEFT_ALLIGN, LAYER_GUI); + context.draw_text(white_small_text, *text[i], Vector(20, 120), LEFT_ALLIGN, LAYER_GUI); - sprintf(str,_("Press any key to continue - Page %d/%d"), i+1, sizeof(text) / sizeof(text[0])); - context.draw_text(gold_text, str, Vector(screen->w/2, screen->h-60), CENTER_ALLIGN, LAYER_GUI); + sprintf(str,_("Press any key to continue - Page %d/%d"), i+1, sizeof(text) / sizeof(text[0])); + context.draw_text(gold_text, str, Vector(screen->w/2, screen->h-60), CENTER_ALLIGN, LAYER_GUI); - context.do_drawing(); + context.do_drawing(); - done = false; + done = false; - while(!done) - { - done = wait_for_event(event); - SDL_Delay(50); + while(!done) { + SDL_Event event; + done = wait_for_event(event); + SDL_Delay(50); } } -show_grid = show_grid_t; -mouse_cursor->set_state(MC_NORMAL); + show_grid = show_grid_t; + mouse_cursor->set_state(MC_NORMAL); } Sector* diff --git a/src/leveleditor.h b/src/leveleditor.h index 5fef8801b..912f8ea33 100644 --- a/src/leveleditor.h +++ b/src/leveleditor.h @@ -18,8 +18,6 @@ #ifndef SUPERTUX_LEVELEDITOR_H #define SUPERTUX_LEVELEDITOR_H -#include "SDL.h" - #include #include @@ -91,8 +89,7 @@ private: void load_level_subset(std::string filename); void load_level(std::string filename); void load_level(int nb); - void load_sector(std::string name); - void load_sector(Sector* sector); + void load_sector(size_t num); void save_level(); void test_level(); @@ -108,6 +105,7 @@ private: Level* level; std::string level_filename; + size_t sectornum; // number of current sector Sector* sector; // current sector TileMap *solids, *foregrounds, *backgrounds; std::string sector_name; @@ -122,13 +120,13 @@ private: Menu* settings_menu; bool left_button, middle_button, mouse_moved; + int mouse_x, mouse_y; bool done; bool show_grid; Vector scroll; float zoom; - SDL_Event event; Timer2 level_name_timer; Surface *img_background_bt, *img_foreground_bt, *img_interactive_bt; diff --git a/src/object/background.h b/src/object/background.h index 0bc3ca199..dd849b40d 100644 --- a/src/object/background.h +++ b/src/object/background.h @@ -25,6 +25,8 @@ #include "special/game_object.h" #include "serializable.h" +using namespace SuperTux; + class DisplayManager; namespace lisp { diff --git a/src/object/block.cpp b/src/object/block.cpp index b3c6fccb6..3bd32096d 100644 --- a/src/object/block.cpp +++ b/src/object/block.cpp @@ -13,6 +13,7 @@ #include "flower.h" #include "oneup.h" #include "star.h" +#include "player_status.h" #include "badguy/badguy.h" #include "coin.h" #include "object_factory.h" @@ -25,7 +26,7 @@ Block::Block(const Vector& pos, Sprite* newsprite) : sprite(newsprite), bouncing(false), bounce_dir(0), bounce_offset(0) { bbox.set_pos(pos); - bbox.set_size(32, 32); + bbox.set_size(32, 32.1); flags |= FLAG_SOLID; original_y = pos.y; } @@ -88,6 +89,7 @@ Block::draw(DrawingContext& context) void Block::start_bounce() { + original_y = bbox.p1.y; bouncing = true; bounce_dir = -BOUNCY_BRICK_SPEED; bounce_offset = 0; diff --git a/src/object/bullet.cpp b/src/object/bullet.cpp index bceed3ccb..e80491a29 100644 --- a/src/object/bullet.cpp +++ b/src/object/bullet.cpp @@ -2,7 +2,6 @@ #include #include "bullet.h" -#include "defines.h" #include "resources.h" #include "camera.h" #include "sector.h" diff --git a/src/object/camera.cpp b/src/object/camera.cpp index 246207f55..1b6038673 100644 --- a/src/object/camera.cpp +++ b/src/object/camera.cpp @@ -178,7 +178,7 @@ Camera::scroll_normal(float elapsed_time) /****** Vertical Scrolling part ******/ bool do_y_scrolling = true; - if(player->dying || sector->solids->get_height() == 19) + if(player->is_dying() || sector->solids->get_height() == 19) do_y_scrolling = false; if(do_y_scrolling) { @@ -260,7 +260,7 @@ Camera::scroll_autoscroll(float elapsed_time) { Player* player = sector->player; - if(player->dying) + if(player->is_dying()) return; if(auto_t - elapsed_time >= 0) { diff --git a/src/object/camera.h b/src/object/camera.h index 45351b6af..028671add 100644 --- a/src/object/camera.h +++ b/src/object/camera.h @@ -23,7 +23,6 @@ #include #include -#include "defines.h" #include "math/vector.h" #include "special/game_object.h" #include "video/drawing_context.h" diff --git a/src/object/coin.cpp b/src/object/coin.cpp index c0910183e..c9b38ba54 100644 --- a/src/object/coin.cpp +++ b/src/object/coin.cpp @@ -6,7 +6,7 @@ #include "special/sprite_manager.h" #include "player.h" #include "sector.h" -#include "scene.h" +#include "player_status.h" #include "gameobjs.h" #include "statistics.h" #include "object_factory.h" diff --git a/src/object/flower.cpp b/src/object/flower.cpp index 435be0725..d4805553b 100644 --- a/src/object/flower.cpp +++ b/src/object/flower.cpp @@ -2,7 +2,6 @@ #include #include "flower.h" -#include "defines.h" #include "resources.h" #include "camera.h" #include "sector.h" diff --git a/src/object/gameobjs.h b/src/object/gameobjs.h index 6b884d737..d5c958365 100644 --- a/src/object/gameobjs.h +++ b/src/object/gameobjs.h @@ -23,7 +23,6 @@ #include "video/surface.h" #include "timer.h" -#include "scene.h" #include "math/physic.h" #include "special/game_object.h" #include "special/moving_object.h" diff --git a/src/object/growup.cpp b/src/object/growup.cpp index deaaff168..4ed6e7231 100644 --- a/src/object/growup.cpp +++ b/src/object/growup.cpp @@ -2,7 +2,6 @@ #include #include "growup.h" -#include "defines.h" #include "resources.h" #include "camera.h" #include "sector.h" diff --git a/src/object/oneup.cpp b/src/object/oneup.cpp index a576bcfe3..324f8381f 100644 --- a/src/object/oneup.cpp +++ b/src/object/oneup.cpp @@ -3,7 +3,7 @@ #include "oneup.h" #include "resources.h" #include "player.h" -#include "scene.h" +#include "player_status.h" #include "sector.h" #include "special/sprite_manager.h" #include "video/drawing_context.h" diff --git a/src/object/player.cpp b/src/object/player.cpp index ec971654f..93fd5c425 100644 --- a/src/object/player.cpp +++ b/src/object/player.cpp @@ -27,9 +27,8 @@ #include "app/gettext.h" #include "special/sprite_manager.h" #include "player.h" -#include "defines.h" -#include "scene.h" #include "tile.h" +#include "player_status.h" #include "special/sprite.h" #include "sector.h" #include "resources.h" @@ -79,18 +78,24 @@ PlayerKeymap::PlayerKeymap() 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 @@ -149,7 +154,7 @@ Player::init() duck = false; dead = false; - dying = DYING_NOT; + dying = false; last_ground_y = 0; fall_mode = ON_GROUND; jumping = false; @@ -171,13 +176,12 @@ Player::init() 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); @@ -193,8 +197,8 @@ Player::key_event(SDLKey key, int state) } 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; @@ -207,16 +211,16 @@ Player::key_event(SDLKey key, int 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; } @@ -230,9 +234,9 @@ Player::level_begin() move(Vector(100, 170)); duck = false; - dying = DYING_NOT; + dying = false; - player_input_init(&input); + input.reset(); on_ground_flag = false; @@ -253,11 +257,11 @@ Player::action(float elapsed_time) return; } - if(input.fire == UP) + if(input.fire == false) grabbed_object = 0; - if(dying == DYING_NOT) + if(!dying) handle_input(); movement = physic.get_movement(elapsed_time); @@ -296,36 +300,38 @@ 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 @@ -419,7 +425,7 @@ Player::handle_vertical_input() } // 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); @@ -443,7 +449,7 @@ Player::handle_vertical_input() SoundManager::get()->play_sound(IDToSound(SND_BIGJUMP)); } // Let go of jump key - else if(input.jump == UP) + else if(!input.jump) { if (!flapping && !duck && !falling_from_flap && !on_ground()) { @@ -461,8 +467,7 @@ Player::handle_vertical_input() { // 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); @@ -472,7 +477,7 @@ Player::handle_vertical_input() 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()) { @@ -504,7 +509,7 @@ Player::handle_vertical_input() 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()) { @@ -549,13 +554,13 @@ Player::handle_vertical_input() #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 (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; // Do butt jump @@ -617,13 +622,14 @@ Player::handle_vertical_input() 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; } @@ -634,30 +640,31 @@ Player::handle_input() 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 && got_power != NONE_POWER) { if(Sector::current()->add_bullet( // 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 && size == 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 && size == BIG && duck) { // try if we can really unduck bbox.move(Vector(0, -32)); @@ -794,8 +801,8 @@ Player::draw(DrawingContext& context) } /* 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) { @@ -848,7 +855,7 @@ HitResponse Player::collision(GameObject& other, const CollisionHit& hit) { Portable* portable = dynamic_cast (&other); - if(portable && grabbed_object == 0 && input.fire == DOWN + if(portable && grabbed_object == 0 && input.fire && fabsf(hit.normal.x) > .9) { grabbed_object = portable; return CONTINUE; @@ -872,7 +879,7 @@ Player::collision(GameObject& other, const CollisionHit& hit) TriggerBase* trigger = dynamic_cast (&other); if(trigger) { - if(input.up == DOWN && input.old_up == UP) + if(input.up && !input.old_up) trigger->event(*this, TriggerBase::EVENT_ACTIVATE); } @@ -923,7 +930,7 @@ Player::kill(HurtMode mode) physic.set_acceleration(0, 0); physic.set_velocity(0, 700); --player_status.lives; - dying = DYING_SQUISHED; + dying = true; dying_timer.start(3.0); flags |= FLAG_NO_COLLDET; } diff --git a/src/object/player.h b/src/object/player.h index 0a179a425..91e14b511 100644 --- a/src/object/player.h +++ b/src/object/player.h @@ -20,14 +20,14 @@ #define SUPERTUX_PLAYER_H #include -#include "SDL.h" +#include #include "timer.h" +#include "direction.h" #include "video/surface.h" #include "special/moving_object.h" #include "special/sprite.h" #include "math/physic.h" -#include "defines.h" using namespace SuperTux; @@ -61,28 +61,33 @@ public: extern PlayerKeymap keymap; -struct player_input_type +/** Contains a field of booleans that indicate wheter a button is pressed or + * released. The old_ fields contain the state of the button at the previous + * frame. + */ +struct PlayerInputType { - int right; - int left; - int up; - int old_up; - int down; - int fire; - int old_fire; - int activate; - int jump; - int old_jump; +public: + PlayerInputType(); + void reset(); + + bool left; + bool right; + bool up; + bool old_up; + bool down; + bool fire; + bool old_fire; + bool activate; + bool jump; + bool old_jump; }; -void player_input_init(player_input_type* pplayer_input); - class Camera; class PlayerStatus; extern Surface* tux_life; - #define GROWING_TIME 1.0 #define GROWING_FRAMES 7 extern Surface* growingtux_left[GROWING_FRAMES]; @@ -124,12 +129,15 @@ public: enum Power { NONE_POWER, FIRE_POWER, ICE_POWER }; enum FallMode { ON_GROUND, JUMPING, TRAMPOLINE_JUMP, FALLING }; - player_input_type input; + PlayerInputType input; int got_power; int size; bool duck; bool dead; - DyingType dying; + +private: + bool dying; +public: Direction dir; Direction old_dir; @@ -170,7 +178,7 @@ public: Player(); virtual ~Player(); - int key_event(SDLKey key, int state); + bool key_event(SDLKey key, bool state); void level_begin(); void handle_input(); @@ -183,7 +191,11 @@ public: void make_invincible(); bool is_invincible() const { - return invincible_timer.started(); + return invincible_timer.started(); + } + bool is_dying() const + { + return dying; } void kill(HurtMode mode); diff --git a/src/object/specialriser.cpp b/src/object/specialriser.cpp index 8d84f6af7..af0440efd 100644 --- a/src/object/specialriser.cpp +++ b/src/object/specialriser.cpp @@ -2,7 +2,6 @@ #include #include "specialriser.h" -#include "defines.h" #include "resources.h" #include "camera.h" #include "sector.h" diff --git a/src/object/star.cpp b/src/object/star.cpp index 522c08af4..8bf4a4d2f 100644 --- a/src/object/star.cpp +++ b/src/object/star.cpp @@ -3,7 +3,7 @@ #include "star.h" #include "resources.h" #include "player.h" -#include "scene.h" +#include "player_status.h" #include "special/sprite_manager.h" #include "video/drawing_context.h" diff --git a/src/object/tilemap.cpp b/src/object/tilemap.cpp index fb0cb63d7..59557d162 100644 --- a/src/object/tilemap.cpp +++ b/src/object/tilemap.cpp @@ -37,7 +37,7 @@ TileMap::TileMap() : solid(false), speed(1), width(0), height(0), layer(LAYER_TILES), - vertical_flip(false) + drawing_effect(0) { tilemanager = tile_manager; @@ -47,7 +47,7 @@ TileMap::TileMap() TileMap::TileMap(const lisp::Lisp& reader) : solid(false), speed(1), width(0), height(0), layer(LAYER_TILES), - vertical_flip(false) + drawing_effect(0) { tilemanager = tile_manager; @@ -87,7 +87,7 @@ TileMap::TileMap(const lisp::Lisp& reader) TileMap::TileMap(int layer_, bool solid_, size_t width_, size_t height_) : solid(solid_), speed(1), width(0), height(0), layer(layer_), - vertical_flip(false) + drawing_effect(0) { tilemanager = tile_manager; @@ -136,8 +136,8 @@ TileMap::draw(DrawingContext& context) { context.push_transform(); - if(vertical_flip) - context.set_drawing_effect(VERTICAL_FLIP); + if(drawing_effect != 0) + context.set_drawing_effect(drawing_effect); float trans_x = roundf(context.get_translation().x); float trans_y = roundf(context.get_translation().y); context.set_translation(Vector(trans_x * speed, trans_y * speed)); @@ -234,19 +234,6 @@ TileMap::resize(int new_width, int new_height) width = new_width; } -void -TileMap::do_vertical_flip() -{ - // remap tiles vertically flipped - for(int y = 0; y < height / 2; ++y) { - for(int x = 0; x < width; ++x) { - std::swap(tiles[y*width + x], tiles[(((height-1)*width) - (y*width)) + x]); - } - } - - vertical_flip = true; -} - const Tile* TileMap::get_tile(int x, int y) const { diff --git a/src/object/tilemap.h b/src/object/tilemap.h index ecf8d1030..2c1960a9f 100644 --- a/src/object/tilemap.h +++ b/src/object/tilemap.h @@ -61,10 +61,6 @@ public: */ void resize(int newwidth, int newheight); - /** Flip the all tile map vertically. The purpose of this is to let - player to play the same level in a different way :) */ - void do_vertical_flip(); - size_t get_width() const { return width; } @@ -86,6 +82,16 @@ public: void change_at(const Vector& pos, uint32_t newtile); + TileManager* get_tilemanager() const + { + return tilemanager; + } + + void set_drawing_effect(int effect) + { + drawing_effect = effect; + } + private: std::vector tiles; @@ -96,7 +102,7 @@ private: int width, height; int layer; - bool vertical_flip; + int drawing_effect; }; #endif /*SUPERTUX_TILEMAP_H*/ diff --git a/src/object_factory.h b/src/object_factory.h index c9a57e099..7ff6028f2 100644 --- a/src/object_factory.h +++ b/src/object_factory.h @@ -31,6 +31,9 @@ using namespace SuperTux; class Factory { public: + virtual ~Factory() + { } + /** Creates a new gameobject from a lisp node. * Remember to delete the objects later */ diff --git a/src/player_status.cpp b/src/player_status.cpp new file mode 100644 index 000000000..ba8b633c7 --- /dev/null +++ b/src/player_status.cpp @@ -0,0 +1,114 @@ +// $Id$ +// +// SuperTux - A Jump'n Run +// Copyright (C) 2003 Tobias Glaesser +// +// 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 + +#include "lisp/writer.h" +#include "lisp/lisp.h" +#include "player_status.h" +#include "resources.h" + +static const int START_LIVES = 4; +static const int MAX_LIVES = 99; + +PlayerStatus player_status; + +PlayerStatus::PlayerStatus() + : distros(0), + lives(START_LIVES), + bonus(NO_BONUS), + score_multiplier(1), + max_score_multiplier(1) +{ +} + +void PlayerStatus::reset() +{ + distros = 0; + lives = START_LIVES; + bonus = NO_BONUS; + score_multiplier = 1; + max_score_multiplier = 1; +} + +void +PlayerStatus::incLives() +{ + if(lives < MAX_LIVES) + ++lives; + SoundManager::get()->play_sound(IDToSound(SND_LIFEUP)); +} + +void +PlayerStatus::incCoins() +{ + distros++; + if(distros >= 100) { + incLives(); + distros = 0; + } + SoundManager::get()->play_sound(IDToSound(SND_DISTRO)); +} + +void +PlayerStatus::write(lisp::Writer& writer) +{ + switch(bonus) { + case PlayerStatus::NO_BONUS: + writer.write_string("bonus", "none"); + break; + case PlayerStatus::GROWUP_BONUS: + writer.write_string("bonus", "growup"); + break; + case PlayerStatus::FLOWER_BONUS: + writer.write_string("bonus", "fireflower"); + break; + default: + std::cerr << "Unknown bonus type.\n"; + writer.write_string("bonus", "none"); + } + + writer.write_int("lives", lives); + writer.write_int("distros", distros); + writer.write_int("max-score-multiplier", max_score_multiplier); +} + +void +PlayerStatus::read(const lisp::Lisp& lisp) +{ + reset(); + + std::string bonusname; + if(lisp.get("bonus", bonusname)) { + if(bonusname == "none") { + bonus = NO_BONUS; + } else if(bonusname == "growup") { + bonus = GROWUP_BONUS; + } else if(bonusname == "fireflower") { + bonus = FLOWER_BONUS; + } else { + std::cerr << "Unknown bonus '" << bonusname << "' in savefile.\n"; + bonus = NO_BONUS; + } + } + + lisp.get("lives", lives); + lisp.get("distros", distros); + lisp.get("max-score-multiplier", max_score_multiplier); +} + diff --git a/src/player_status.h b/src/player_status.h new file mode 100644 index 000000000..760ae9212 --- /dev/null +++ b/src/player_status.h @@ -0,0 +1,53 @@ +// $Id$ +// +// SuperTux - A Jump'n Run +// Copyright (C) 2003 Tobias Glaesser +// +// 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. +#ifndef SUPERTUX_PLAYERSTATUS_H +#define SUPERTUX_PLAYERSTATUS_H + +#include "lisp/lisp.h" +#include "timer.h" +#include "serializable.h" + +/** + * This class memorizes player status between different game sessions (for + * example when switching maps in the worldmap) + */ +class PlayerStatus : public Serializable +{ +public: + PlayerStatus(); + void reset(); + void incLives(); + void incCoins(); + + void write(lisp::Writer& writer); + void read(const lisp::Lisp& lisp); + + int distros; + int lives; + enum BonusType { NO_BONUS, GROWUP_BONUS, FLOWER_BONUS }; + BonusType bonus; + + int score_multiplier; + int max_score_multiplier; +}; + +// global player state +extern PlayerStatus player_status; + +#endif diff --git a/src/resources.cpp b/src/resources.cpp index fc8c038cb..f2c3c0a17 100644 --- a/src/resources.cpp +++ b/src/resources.cpp @@ -24,7 +24,6 @@ #include "app/setup.h" #include "gui/menu.h" #include "gui/button.h" -#include "scene.h" #include "resources.h" #include "tile_manager.h" #include "object/gameobjs.h" diff --git a/src/scene.cpp b/src/scene.cpp deleted file mode 100644 index 429abd07d..000000000 --- a/src/scene.cpp +++ /dev/null @@ -1,97 +0,0 @@ -// $Id$ -// -// SuperTux - A Jump'n Run -// Copyright (C) 2003 Tobias Glaesser -// -// 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 - -#include - -#include "scene.h" -#include "defines.h" -#include "resources.h" - -PlayerStatus player_status; - -PlayerStatus::PlayerStatus() - : distros(0), - lives(START_LIVES), - bonus(NO_BONUS), - score_multiplier(1), - max_score_multiplier(1) -{ -} - -void PlayerStatus::reset() -{ - distros = 0; - lives = START_LIVES; - bonus = NO_BONUS; - score_multiplier = 1; - max_score_multiplier = 1; -} - -void -PlayerStatus::incLives() -{ - if(lives < MAX_LIVES) - ++lives; - SoundManager::get()->play_sound(IDToSound(SND_LIFEUP)); -} - -void -PlayerStatus::incCoins() -{ - distros++; - if(distros >= 100) { - incLives(); - distros = 0; - } - SoundManager::get()->play_sound(IDToSound(SND_DISTRO)); -} - -std::string bonus_to_string(PlayerStatus::BonusType b) -{ - switch (b) - { - case PlayerStatus::NO_BONUS: - return "none"; - case PlayerStatus::GROWUP_BONUS: - return "growup"; - case PlayerStatus::FLOWER_BONUS: - return "iceflower"; - default: - return "none"; - } -} - -PlayerStatus::BonusType string_to_bonus(const std::string& str) -{ - if (str == "none") - return PlayerStatus::NO_BONUS; - else if (str == "growup") - return PlayerStatus::GROWUP_BONUS; - else if (str == "iceflower") - return PlayerStatus::FLOWER_BONUS; - else - return PlayerStatus::NO_BONUS; -} - -unsigned int global_frame_counter; - -// EOF // - diff --git a/src/scene.h b/src/scene.h deleted file mode 100644 index b8d55963c..000000000 --- a/src/scene.h +++ /dev/null @@ -1,50 +0,0 @@ -// $Id$ -// -// SuperTux - A Jump'n Run -// Copyright (C) 2003 Tobias Glaesser -// -// 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. - -#ifndef SUPERTUX_SCENE_H -#define SUPERTUX_SCENE_H - -#include "video/surface.h" -#include "timer.h" - -#define FRAME_RATE 10 // 100 Frames per second (10ms) - -// Player stats -struct PlayerStatus -{ - int distros; - int lives; - enum BonusType { NO_BONUS, GROWUP_BONUS, FLOWER_BONUS }; - BonusType bonus; - - int score_multiplier; - int max_score_multiplier; - - PlayerStatus(); - void reset(); - void incLives(); - void incCoins(); -}; - -std::string bonus_to_string(PlayerStatus::BonusType b); -PlayerStatus::BonusType string_to_bonus(const std::string& str); - -extern PlayerStatus player_status; - -#endif /*SUPERTUX_SCENE_H*/ diff --git a/src/sector.cpp b/src/sector.cpp index 655eb22a3..4037f35fb 100644 --- a/src/sector.cpp +++ b/src/sector.cpp @@ -28,6 +28,7 @@ #include "app/globals.h" #include "sector.h" +#include "player_status.h" #include "object/gameobjs.h" #include "object/camera.h" #include "object/background.h" @@ -56,6 +57,8 @@ #include "badguy/spike.h" #include "trigger/sequence_trigger.h" +//#define USE_GRID + Sector* Sector::_current = 0; Sector::Sector() @@ -694,7 +697,7 @@ Sector::collision_object(MovingObject* object1, MovingObject* object2) void Sector::collision_handler() { -#if 0 +#ifdef USE_GRID grid->check_collisions(); #else for(std::vector::iterator i = gameobjects.begin(); @@ -738,6 +741,10 @@ Sector::collision_handler() bool Sector::add_bullet(const Vector& pos, float xm, Direction dir) { + // TODO remove this function and move these checks elsewhere... + static const size_t MAX_FIRE_BULLETS = 2; + static const size_t MAX_ICE_BULLETS = 1; + if(player->got_power == Player::FIRE_POWER) { if(bullets.size() > MAX_FIRE_BULLETS-1) return false; @@ -826,14 +833,13 @@ int Sector::get_total_badguys() { int total_badguys = 0; -#if 0 - for(GameObjects::iterator i = gameobjects_new.begin(); i != gameobjects_new.end(); ++i) - { + for(GameObjects::iterator i = gameobjects.begin(); + i != gameobjects.end(); ++i) { BadGuy* badguy = dynamic_cast (*i); if(badguy) total_badguys++; - } -#endif + } + return total_badguys; } diff --git a/src/sector.h b/src/sector.h index 5f31dc96e..39b13bce4 100644 --- a/src/sector.h +++ b/src/sector.h @@ -23,10 +23,10 @@ #include #include +#include "direction.h" #include "math/vector.h" #include "audio/musicref.h" #include "video/drawing_context.h" -#include "defines.h" using namespace SuperTux; @@ -46,8 +46,9 @@ class TileMap; class Bullet; class CollisionGrid; -struct SpawnPoint +class SpawnPoint { +public: std::string name; Vector pos; }; @@ -100,7 +101,7 @@ public: bool add_smoke_cloud(const Vector& pos); void add_floating_text(const Vector& pos, const std::string& text); - /** @evil@ but can#t always be avoided in current design... */ + /** @evil@ but can't always be avoided in current design... */ static Sector* current() { return _current; } @@ -138,6 +139,8 @@ private: public: // TODO make this private again typedef std::vector GameObjects; GameObjects gameobjects; + typedef std::vector SpawnPoints; + SpawnPoints spawnpoints; Rectangle get_active_region(); @@ -147,9 +150,6 @@ private: /// container for newly created objects, they'll be added in Sector::action GameObjects gameobjects_new; - typedef std::vector SpawnPoints; - SpawnPoints spawnpoints; - int currentmusic; CollisionGrid* grid; diff --git a/src/serializable.h b/src/serializable.h index 3fc702004..06a8234e3 100644 --- a/src/serializable.h +++ b/src/serializable.h @@ -19,8 +19,6 @@ #ifndef SUPERTUX_SERIALIZABLE_H #define SUPERTUX_SERIALIZABLE_H -using namespace SuperTux; - namespace lisp { class Writer; } @@ -28,6 +26,9 @@ class Writer; class Serializable { public: + virtual ~Serializable() + { } + virtual void write(lisp::Writer& writer) = 0; }; diff --git a/src/supertux.cpp b/src/supertux.cpp index 81856f6e6..06cbbe733 100644 --- a/src/supertux.cpp +++ b/src/supertux.cpp @@ -25,10 +25,8 @@ #include #include -#include "defines.h" #include "app/globals.h" #include "app/setup.h" -#include "intro.h" #include "title.h" #include "gameloop.h" #include "leveleditor.h" diff --git a/src/tile.cpp b/src/tile.cpp index a57d3043f..0edef84d9 100644 --- a/src/tile.cpp +++ b/src/tile.cpp @@ -27,8 +27,8 @@ #include "app/globals.h" #include "lisp/lisp.h" #include "tile.h" -#include "scene.h" #include "resources.h" +#include "timer.h" #include "math/vector.h" #include "video/drawing_context.h" diff --git a/src/tile_manager.cpp b/src/tile_manager.cpp index f2c95e09d..e3a5b59a6 100644 --- a/src/tile_manager.cpp +++ b/src/tile_manager.cpp @@ -31,7 +31,6 @@ #include "tile.h" #include "tile_manager.h" #include "resources.h" -#include "scene.h" TileManager::TileManager(const std::string& filename) { diff --git a/src/tile_manager.h b/src/tile_manager.h index db8a70ccb..961e07751 100644 --- a/src/tile_manager.h +++ b/src/tile_manager.h @@ -81,6 +81,16 @@ public: { return tiles.size(); } + + int get_default_width() const + { + return 32; + } + + int get_default_height() const + { + return 32; + } }; #endif diff --git a/src/title.cpp b/src/title.cpp index 3f0f3a5e0..514479d77 100644 --- a/src/title.cpp +++ b/src/title.cpp @@ -36,7 +36,6 @@ #include #endif -#include "defines.h" #include "app/globals.h" #include "title.h" #include "video/screen.h" @@ -52,7 +51,7 @@ #include "gameloop.h" #include "worldmap.h" #include "leveleditor.h" -#include "scene.h" +#include "player_status.h" #include "tile.h" #include "sector.h" #include "object/tilemap.h" @@ -246,16 +245,16 @@ void draw_demo(float elapsed_time) world->play_music(LEVEL_MUSIC); - tux->key_event((SDLKey) keymap.right,DOWN); + tux->key_event((SDLKey) keymap.right, true); if(random_timer.check()) { random_timer.start(float(rand() % 3000 + 3000) / 1000.); walking = !walking; } else { if(walking) - tux->key_event((SDLKey) keymap.jump,UP); + tux->key_event((SDLKey) keymap.jump, false); else - tux->key_event((SDLKey) keymap.jump,DOWN); + tux->key_event((SDLKey) keymap.jump, true); } // Wrap around at the end of the level back to the beginnig diff --git a/src/worldmap.cpp b/src/worldmap.cpp index af6742148..80a21d773 100644 --- a/src/worldmap.cpp +++ b/src/worldmap.cpp @@ -43,7 +43,7 @@ #include "worldmap.h" #include "resources.h" #include "misc.h" -#include "scene.h" +#include "player_status.h" #define map_message_TIME 2.8 @@ -1087,8 +1087,6 @@ WorldMap::savegame(const std::string& filename) if(filename == "") return; - std::cout << "savegame: " << filename << std::endl; - std::ofstream file(filename.c_str(), std::ios::out); lisp::Writer writer(file); @@ -1111,16 +1109,14 @@ WorldMap::savegame(const std::string& filename) std::string(name + " - " + nb_solved_levels_str+"/"+total_levels_str)); writer.write_string("map", map_filename); writer.write_bool("intro-displayed", intro_displayed); - writer.write_int("lives", player_status.lives); - writer.write_int("distros", player_status.lives); - writer.write_int("max-score-multiplier", player_status.max_score_multiplier); writer.start_list("tux"); writer.write_float("x", tux->get_tile_pos().x); writer.write_float("y", tux->get_tile_pos().y); writer.write_string("back", direction_to_string(tux->back_direction)); - writer.write_string("bonus", bonus_to_string(player_status.bonus)); + player_status.write(writer); + writer.write_string("back", direction_to_string(tux->back_direction)); writer.end_list("tux"); @@ -1169,21 +1165,19 @@ WorldMap::loadgame(const std::string& filename) savegame->get("distros", player_status.distros); savegame->get("max-score-multiplier", player_status.max_score_multiplier); if (player_status.lives < 0) - player_status.lives = START_LIVES; + player_status.reset(); const lisp::Lisp* tux_lisp = savegame->get_lisp("tux"); if(tux) { Vector p; std::string back_str = "none"; - std::string bonus_str = "none"; tux_lisp->get("x", p.x); tux_lisp->get("y", p.y); tux_lisp->get("back", back_str); - tux_lisp->get("bonus", bonus_str); + player_status.read(*tux_lisp); - player_status.bonus = string_to_bonus(bonus_str); tux->back_direction = string_to_direction(back_str); tux->set_tile_pos(p); }