(gravity 10.000000)
(background (image "arctis.jpg")
(speed 0.5))
- (music "supertux-2.ogg")
+ (music "theme.mod")
(spawnpoint
(name "main")
(x 100)
{
case SDL_KEYDOWN:
{
- SDLKey key = key = event.key.keysym.sym;
+ SDLKey key = event.key.keysym.sym;
SDLMod keymod;
char ch[2];
keymod = SDL_GetModState();
remove_listeners = entry;
}
-
-
+
// flags
enum {
/// the tile so you can stand on it
#include "math/vector.h"
#include "math/rectangle.h"
+class FlipLevelTransformer;
class Sector;
class CollisionGrid;
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)
class ObjectRemoveListener
{
public:
+ virtual ~ObjectRemoveListener()
+ { }
+
virtual void object_removed(GameObject* object) = 0;
};
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* )
#include "serializable.h"
#include "resources.h"
#include "sector.h"
+#include "direction.h"
#include "object_factory.h"
#include "lisp/parser.h"
#include "lisp/lisp.h"
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,
#include "mrtree.h"
static const float WALKSPEED = 50;
+static const float WALKSPEED_SMALL = 30;
MrTree::MrTree(const lisp::Lisp& reader)
: mystate(STATE_BIG)
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
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) {
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);
}
}
}
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
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<ObjectWrapper*> moved_objects;
+
CollisionGridIterator iter(*this, Sector::current()->get_active_region());
while(ObjectWrapper* wrapper = iter.next_wrapper()) {
MovingObject* object = wrapper->object;
if(object->get_flags() & GameObject::FLAG_NO_COLLDET) {
object->bbox.move(object->movement);
object->movement = Vector(0, 0);
+ moved_objects.push_back(wrapper);
continue;
}
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<ObjectWrapper*>::iterator i = moved_objects.begin();
+ i != moved_objects.end(); ++i) {
+ move_object(*i);
}
}
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;
}
}
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 {
void add_object(MovingObject* object);
void remove_object(MovingObject* object);
- void move_object(MovingObject* object);
void check_collisions();
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<GridEntry*> GridEntries;
GridEntries grid;
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;
+++ /dev/null
-// $Id$
-//
-// SuperTux
-// Copyright (C) 2000 Bill Kendrick <bill@newbreedsoftware.com>
-// Copyright (C) 2004 Tobias Glaesser <tobi.web@gmx.de>
-//
-// 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 <config.h>
-
-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*/
-
--- /dev/null
+// $Id$
+//
+// SuperTux
+// Copyright (C) 2000 Bill Kendrick <bill@newbreedsoftware.com>
+// Copyright (C) 2004 Tobias Glaesser <tobi.web@gmx.de>
+//
+// 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*/
+
--- /dev/null
+#include <config.h>
+
+#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<TileMap*> (object);
+ if(tilemap) {
+ transform_tilemap(tilemap);
+ }
+ BadGuy* badguy = dynamic_cast<BadGuy*> (object);
+ if(badguy) {
+ transform_badguy(height, badguy);
+ } else {
+ MovingObject* mobject = dynamic_cast<MovingObject*> (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);
+}
+
--- /dev/null
+#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
+
#include <ctime>
#include <stdexcept>
-#include "SDL.h"
+#include <SDL.h>
#ifndef WIN32
#include <sys/types.h>
#include <ctype.h>
#endif
-#include "defines.h"
#include "app/globals.h"
#include "gameloop.h"
#include "video/screen.h"
#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"
#include "resources.h"
#include "app/gettext.h"
#include "worldmap.h"
-#include "intro.h"
#include "misc.h"
#include "statistics.h"
#include "timer.h"
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
{
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;
{
SDLKey key = event.key.keysym.sym;
- if(tux.key_event(key,DOWN))
+ if(tux.key_event(key, true))
break;
switch(key)
{
SDLKey key = event.key.keysym.sym;
- if(tux.key_event(key, UP))
+ if(tux.key_event(key, false))
break;
switch(key)
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:
{
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:
}
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;
void
GameSession::start_sequence(const std::string& sequencename)
{
- if(sequencename == "endsequence") {
+ if(sequencename == "endsequence" || sequencename == "fireworks") {
if(end_sequence)
return;
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 {
void check_end_conditions();
void start_timers();
void process_events();
+ void handle_cheats();
void levelintro();
void drawstatus(DrawingContext& context);
+++ /dev/null
-// $Id$
-//
-// SuperTux - A Jump'n Run
-// Copyright (C) 2000 Bill Kendrick <bill@newbreedsoftware.com>
-//
-// 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 <config.h>
-
-#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 );
-}
-
+++ /dev/null
-// $Id$
-//
-// SuperTux - A Jump'n Run
-// Copyright (C) 2000 Bill Kendrick <bill@newbreedsoftware.com>
-//
-// 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: */
#include "lisp/writer.h"
#include "level.h"
#include "math/physic.h"
-#include "scene.h"
#include "sector.h"
#include "tile.h"
#include "resources.h"
#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)
{
}
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;
}
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();
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");
}
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
{
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<Coin*> (*o);
}
return total_coins;
}
+
#ifndef SUPERTUX_LEVEL_H
#define SUPERTUX_LEVEL_H
-#include <map>
+#include <vector>
#include <string>
-using namespace SuperTux;
-
class Sector;
namespace lisp {
class Level
{
public:
- enum EndSequenceType{
- NONE_ENDSEQ_ANIM,
- FIREWORKS_ENDSEQ_ANIM
- };
-
std::string name;
std::string author;
int timelimit;
- typedef std::map<std::string, Sector*> Sectors;
+ typedef std::vector<Sector*> Sectors;
Sectors sectors;
- EndSequenceType end_sequence_type;
public:
Level();
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; }
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();
--- /dev/null
+#include <config.h>
+
+#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));
+ }
+}
+
--- /dev/null
+#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
+
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<std::string>::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<std::string>::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 <int> vector;
- vector.push_back(tiles_board->selected_id());
+ // check for events in buttons
+ else if(tiles_board->event(event))
+ {
+ std::vector <int> 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 <int> 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 <int> 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<TileMap*> (*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<TileMap*> (*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<Background*> (*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<Background*> (*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<TileMap*> (*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<TileMap*> (*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()
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*
#ifndef SUPERTUX_LEVELEDITOR_H
#define SUPERTUX_LEVELEDITOR_H
-#include "SDL.h"
-
#include <set>
#include <string>
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();
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;
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;
#include "special/game_object.h"
#include "serializable.h"
+using namespace SuperTux;
+
class DisplayManager;
namespace lisp {
#include "flower.h"
#include "oneup.h"
#include "star.h"
+#include "player_status.h"
#include "badguy/badguy.h"
#include "coin.h"
#include "object_factory.h"
: 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;
}
void
Block::start_bounce()
{
+ original_y = bbox.p1.y;
bouncing = true;
bounce_dir = -BOUNCY_BRICK_SPEED;
bounce_offset = 0;
#include <math.h>
#include "bullet.h"
-#include "defines.h"
#include "resources.h"
#include "camera.h"
#include "sector.h"
/****** 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) {
{
Player* player = sector->player;
- if(player->dying)
+ if(player->is_dying())
return;
if(auto_t - elapsed_time >= 0) {
#include <vector>
#include <cassert>
-#include "defines.h"
#include "math/vector.h"
#include "special/game_object.h"
#include "video/drawing_context.h"
#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"
#include <math.h>
#include "flower.h"
-#include "defines.h"
#include "resources.h"
#include "camera.h"
#include "sector.h"
#include "video/surface.h"
#include "timer.h"
-#include "scene.h"
#include "math/physic.h"
#include "special/game_object.h"
#include "special/moving_object.h"
#include <math.h>
#include "growup.h"
-#include "defines.h"
#include "resources.h"
#include "camera.h"
#include "sector.h"
#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"
#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"
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
duck = false;
dead = false;
- dying = DYING_NOT;
+ dying = false;
last_ground_y = 0;
fall_mode = ON_GROUND;
jumping = false;
on_ground_flag = false;
grabbed_object = 0;
- player_input_init(&input);
-
+ input.reset();
physic.reset();
}
-int
-Player::key_event(SDLKey key, int state)
+bool
+Player::key_event(SDLKey key, bool state)
{
idle_timer.start(IDLE_TIME, true);
}
else if(key == keymap.up)
{
- if(state == UP)
- input.old_up = UP;
+ if(state == false)
+ input.old_up = false;
input.up = state;
/* Up key also opens activates stuff */
input.activate = state;
}
else if(key == keymap.power)
{
- if (state == UP)
- input.old_fire = UP;
+ if(state == false)
+ input.old_fire = false;
input.fire = state;
return true;
}
else if(key == keymap.jump)
{
- if (state == UP)
- input.old_jump = UP;
+ if(state == false)
+ input.old_jump = false;
input.jump = state;
return true;
}
move(Vector(100, 170));
duck = false;
- dying = DYING_NOT;
+ dying = false;
- player_input_init(&input);
+ input.reset();
on_ground_flag = false;
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);
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
}
// 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);
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())
{
{
// Flapping, Ricardo's version
// similar to SM3 Fox
- if(input.jump == DOWN && input.old_jump == UP && can_flap &&
- flaps_nb < 3)
+ if(input.jump && !input.old_jump && can_flap && flaps_nb < 3)
{
physic.set_velocity_y(350);
physic.set_velocity_x(physic.get_velocity_x() * 35);
else if(flapping_mode == MAREK_FLAP)
{
// Flapping, Marek's version
- if (input.jump == DOWN && can_flap)
+ if (input.jump && can_flap)
{
if (!flapping_timer.started())
{
else if(flapping_mode == RYAN_FLAP)
{
// Flapping, Ryan's version
- if (input.jump == DOWN && can_flap)
+ if (input.jump && can_flap)
{
if (!flapping_timer.started())
{
#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
get_pos().y + bbox.get_height() + 64))
&& jumping == false
&& can_jump == false
- && input.jump == DOWN
- && input.old_jump == UP)
+ && input.jump && !input.old_jump)
{
can_jump = true;
}
#endif
+ // FIXME: why the heck is this here and not somewhere where the keys are
+ // checked?!?
input.old_jump = input.jump;
}
handle_horizontal_input();
/* Jump/jumping? */
- if (on_ground() && input.jump == UP)
+ if (on_ground() && !input.jump)
can_jump = true;
handle_vertical_input();
/* Shoot! */
- if (input.fire == DOWN && input.old_fire == UP && got_power != NONE_POWER) {
+ if (input.fire && !input.old_fire && 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));
}
/* 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)
{
Player::collision(GameObject& other, const CollisionHit& hit)
{
Portable* portable = dynamic_cast<Portable*> (&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;
TriggerBase* trigger = dynamic_cast<TriggerBase*> (&other);
if(trigger) {
- if(input.up == DOWN && input.old_up == UP)
+ if(input.up && !input.old_up)
trigger->event(*this, TriggerBase::EVENT_ACTIVATE);
}
physic.set_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;
}
#define SUPERTUX_PLAYER_H
#include <vector>
-#include "SDL.h"
+#include <SDL.h>
#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;
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];
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;
Player();
virtual ~Player();
- int key_event(SDLKey key, int state);
+ bool key_event(SDLKey key, bool state);
void level_begin();
void handle_input();
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);
#include <math.h>
#include "specialriser.h"
-#include "defines.h"
#include "resources.h"
#include "camera.h"
#include "sector.h"
#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"
TileMap::TileMap()
: solid(false), speed(1), width(0), height(0), layer(LAYER_TILES),
- vertical_flip(false)
+ drawing_effect(0)
{
tilemanager = tile_manager;
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;
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;
{
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));
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
{
*/
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; }
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<uint32_t> tiles;
int width, height;
int layer;
- bool vertical_flip;
+ int drawing_effect;
};
#endif /*SUPERTUX_TILEMAP_H*/
class Factory
{
public:
+ virtual ~Factory()
+ { }
+
/** Creates a new gameobject from a lisp node.
* Remember to delete the objects later
*/
--- /dev/null
+// $Id$
+//
+// SuperTux - A Jump'n Run
+// Copyright (C) 2003 Tobias Glaesser <tobi.web@gmx.de>
+//
+// 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 <config.h>
+
+#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);
+}
+
--- /dev/null
+// $Id$
+//
+// SuperTux - A Jump'n Run
+// Copyright (C) 2003 Tobias Glaesser <tobi.web@gmx.de>
+//
+// 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
#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"
+++ /dev/null
-// $Id$
-//
-// SuperTux - A Jump'n Run
-// Copyright (C) 2003 Tobias Glaesser <tobi.web@gmx.de>
-//
-// 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 <config.h>
-
-#include <cstdlib>
-
-#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 //
-
+++ /dev/null
-// $Id$
-//
-// SuperTux - A Jump'n Run
-// Copyright (C) 2003 Tobias Glaesser <tobi.web@gmx.de>
-//
-// 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*/
#include "app/globals.h"
#include "sector.h"
+#include "player_status.h"
#include "object/gameobjs.h"
#include "object/camera.h"
#include "object/background.h"
#include "badguy/spike.h"
#include "trigger/sequence_trigger.h"
+//#define USE_GRID
+
Sector* Sector::_current = 0;
Sector::Sector()
void
Sector::collision_handler()
{
-#if 0
+#ifdef USE_GRID
grid->check_collisions();
#else
for(std::vector<GameObject*>::iterator i = gameobjects.begin();
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;
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<BadGuy*> (*i);
if(badguy)
total_badguys++;
- }
-#endif
+ }
+
return total_badguys;
}
#include <string>
#include <vector>
+#include "direction.h"
#include "math/vector.h"
#include "audio/musicref.h"
#include "video/drawing_context.h"
-#include "defines.h"
using namespace SuperTux;
class Bullet;
class CollisionGrid;
-struct SpawnPoint
+class SpawnPoint
{
+public:
std::string name;
Vector pos;
};
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; }
public: // TODO make this private again
typedef std::vector<GameObject*> GameObjects;
GameObjects gameobjects;
+ typedef std::vector<SpawnPoint*> SpawnPoints;
+ SpawnPoints spawnpoints;
Rectangle get_active_region();
/// container for newly created objects, they'll be added in Sector::action
GameObjects gameobjects_new;
- typedef std::vector<SpawnPoint*> SpawnPoints;
- SpawnPoints spawnpoints;
-
int currentmusic;
CollisionGrid* grid;
#ifndef SUPERTUX_SERIALIZABLE_H
#define SUPERTUX_SERIALIZABLE_H
-using namespace SuperTux;
-
namespace lisp {
class Writer;
}
class Serializable
{
public:
+ virtual ~Serializable()
+ { }
+
virtual void write(lisp::Writer& writer) = 0;
};
#include <exception>
#include <locale.h>
-#include "defines.h"
#include "app/globals.h"
#include "app/setup.h"
-#include "intro.h"
#include "title.h"
#include "gameloop.h"
#include "leveleditor.h"
#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"
#include "tile.h"
#include "tile_manager.h"
#include "resources.h"
-#include "scene.h"
TileManager::TileManager(const std::string& filename)
{
{
return tiles.size();
}
+
+ int get_default_width() const
+ {
+ return 32;
+ }
+
+ int get_default_height() const
+ {
+ return 32;
+ }
};
#endif
#include <ctype.h>
#endif
-#include "defines.h"
#include "app/globals.h"
#include "title.h"
#include "video/screen.h"
#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"
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
#include "worldmap.h"
#include "resources.h"
#include "misc.h"
-#include "scene.h"
+#include "player_status.h"
#define map_message_TIME 2.8
if(filename == "")
return;
- std::cout << "savegame: " << filename << std::endl;
-
std::ofstream file(filename.c_str(), std::ios::out);
lisp::Writer writer(file);
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");
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);
}