Had a bit of time today and worked on supertux:
authorMatthias Braun <matze@braunis.de>
Fri, 25 Mar 2005 20:39:56 +0000 (20:39 +0000)
committerMatthias Braun <matze@braunis.de>
Fri, 25 Mar 2005 20:39:56 +0000 (20:39 +0000)
- Commited some old changes I had lying around here
  (improved mrtree images? and improvement to the collision grid which still
   isn't enabled by default)
- Did a bit more cleanups (eleminated defines.h and renamed scene.* to
    player_status.* as that is waht ti really contained)
- Cleaned up PlayerStatus code a bit (refactored loading/saving out of worldmap
    into PlayerStatus)
- Implemented LevelTransformer interface and did a first test with a flip level
  transformer
- Removed explicit LevelEndSequence attribute (can be done by placing aprorpiate
    SequenceTrigger objects)

SVN-Revision: 2293

63 files changed:
data/images/shared/mrtree-small-left-0.png
data/images/shared/mrtree-small-left-1.png
data/images/shared/mrtree-small-left-2.png
data/images/shared/mrtree-squished-left.png
data/images/shared/mrtree-walk-left-0.png
data/images/shared/mrtree-walk-left-1.png
data/images/shared/mrtree-walk-left-2.png
data/levels/test/bonusblock.stl
lib/gui/menu.cpp
lib/special/game_object.h
lib/special/moving_object.h
lib/special/object_remove_listener.h
lib/utils/configfile.h
src/badguy/badguy.h
src/badguy/mrtree.cpp
src/collision_grid.cpp
src/collision_grid.h
src/collision_grid_iterator.h
src/defines.h [deleted file]
src/direction.h [new file with mode: 0644]
src/flip_level_transformer.cpp [new file with mode: 0644]
src/flip_level_transformer.h [new file with mode: 0644]
src/gameloop.cpp
src/gameloop.h
src/intro.cpp [deleted file]
src/intro.h [deleted file]
src/level.cpp
src/level.h
src/level_transformer.cpp [new file with mode: 0644]
src/level_transformer.h [new file with mode: 0644]
src/leveleditor.cpp
src/leveleditor.h
src/object/background.h
src/object/block.cpp
src/object/bullet.cpp
src/object/camera.cpp
src/object/camera.h
src/object/coin.cpp
src/object/flower.cpp
src/object/gameobjs.h
src/object/growup.cpp
src/object/oneup.cpp
src/object/player.cpp
src/object/player.h
src/object/specialriser.cpp
src/object/star.cpp
src/object/tilemap.cpp
src/object/tilemap.h
src/object_factory.h
src/player_status.cpp [new file with mode: 0644]
src/player_status.h [new file with mode: 0644]
src/resources.cpp
src/scene.cpp [deleted file]
src/scene.h [deleted file]
src/sector.cpp
src/sector.h
src/serializable.h
src/supertux.cpp
src/tile.cpp
src/tile_manager.cpp
src/tile_manager.h
src/title.cpp
src/worldmap.cpp

index 4842eaf..9bfec1f 100644 (file)
Binary files a/data/images/shared/mrtree-small-left-0.png and b/data/images/shared/mrtree-small-left-0.png differ
index f111008..a773cc8 100644 (file)
Binary files a/data/images/shared/mrtree-small-left-1.png and b/data/images/shared/mrtree-small-left-1.png differ
index 618fd91..63abe69 100644 (file)
Binary files a/data/images/shared/mrtree-small-left-2.png and b/data/images/shared/mrtree-small-left-2.png differ
index b9655be..c86f51a 100644 (file)
Binary files a/data/images/shared/mrtree-squished-left.png and b/data/images/shared/mrtree-squished-left.png differ
index f39c658..035547c 100644 (file)
Binary files a/data/images/shared/mrtree-walk-left-0.png and b/data/images/shared/mrtree-walk-left-0.png differ
index d1bde10..d814da5 100644 (file)
Binary files a/data/images/shared/mrtree-walk-left-1.png and b/data/images/shared/mrtree-walk-left-1.png differ
index 6abbe65..e762155 100644 (file)
Binary files a/data/images/shared/mrtree-walk-left-2.png and b/data/images/shared/mrtree-walk-left-2.png differ
index d392e93..7db7426 100644 (file)
@@ -9,7 +9,7 @@
     (gravity 10.000000)
     (background (image "arctis.jpg")
                 (speed 0.5))
-    (music "supertux-2.ogg")
+    (music "theme.mod")
     (spawnpoint
       (name "main")
       (x 100)
index ba7b749..57643ef 100644 (file)
@@ -746,7 +746,7 @@ Menu::event(SDL_Event& event)
     {
     case SDL_KEYDOWN:
       {
-        SDLKey key = key = event.key.keysym.sym;
+        SDLKey key = event.key.keysym.sym;
         SDLMod keymod;
         char ch[2];
         keymod = SDL_GetModState();
index b235c01..a657d49 100644 (file)
@@ -80,8 +80,7 @@ namespace SuperTux
 
         remove_listeners = entry;
       }
-        
-
+      
       // flags
       enum {
         /// the tile so you can stand on it
index b5c4764..0ac6844 100644 (file)
@@ -25,6 +25,7 @@
 #include "math/vector.h"
 #include "math/rectangle.h"
 
+class FlipLevelTransformer;
 class Sector;
 class CollisionGrid;
 
@@ -65,6 +66,7 @@ namespace SuperTux
     protected:
       friend class Sector;
       friend class CollisionGrid;
+      friend class FlipLevelTransformer;
       
       /** The bounding box of the object (as used for collision detection, this
        * isn't necessarily the bounding box for graphics)
index fdcb769..502db1c 100644 (file)
@@ -9,6 +9,9 @@ class GameObject;
 class ObjectRemoveListener
 {
 public:
+  virtual ~ObjectRemoveListener()
+  { }
+
   virtual void object_removed(GameObject* object) = 0;
 };
 
index 5c2de64..90862da 100644 (file)
@@ -27,7 +27,9 @@ namespace SuperTux {
 FILE * opendata(const std::string& filename, const char * mode);
 
 class Config {
-  public:
+public:
+  virtual ~Config()
+  { }
   void load ();
   void save ();
   virtual void customload(const lisp::Lisp* )
index c7c24e1..92bd010 100644 (file)
@@ -11,6 +11,7 @@
 #include "serializable.h"
 #include "resources.h"
 #include "sector.h"
+#include "direction.h"
 #include "object_factory.h"
 #include "lisp/parser.h"
 #include "lisp/lisp.h"
@@ -35,6 +36,15 @@ public:
 
   virtual void kill_fall();
 
+  Vector get_start_position() const
+  {
+    return start_position;
+  }
+  void set_start_position(const Vector& vec)
+  {
+    start_position = vec;
+  }
+
 protected:
   enum State {
     STATE_INIT,
index efe080d..d944717 100644 (file)
@@ -3,6 +3,7 @@
 #include "mrtree.h"
 
 static const float WALKSPEED = 50;
+static const float WALKSPEED_SMALL = 30;
 
 MrTree::MrTree(const lisp::Lisp& reader)
   : mystate(STATE_BIG)
@@ -27,11 +28,13 @@ MrTree::write(lisp::Writer& writer)
 void
 MrTree::activate()
 {
-  physic.set_velocity_x(dir == LEFT ? -WALKSPEED : WALKSPEED);
-  if(mystate == STATE_BIG)
+  if(mystate == STATE_BIG) {
+    physic.set_velocity_x(dir == LEFT ? -WALKSPEED : WALKSPEED);
     sprite->set_action(dir == LEFT ? "left" : "right");
-  else
+  } else {
+    physic.set_velocity_x(dir == LEFT ? -WALKSPEED_SMALL : WALKSPEED_SMALL);
     sprite->set_action(dir == LEFT ? "small-left" : "small-right");
+  }
 }
 
 bool
index c3b2769..311fc78 100644 (file)
@@ -78,7 +78,14 @@ CollisionGrid::remove_object(MovingObject* object)
       break;
     }
   }
+#ifdef DEBUG
   assert(wrapper != 0);
+#else
+  if(wrapper == 0) {
+       std::cerr << "Tried to remove nonexistant object!\n";
+       return;
+  }
+#endif
   
   const Rectangle& bbox = wrapper->dest;
   for(float y = bbox.p1.y; y < bbox.p2.y; y += cell_height) {
@@ -90,7 +97,7 @@ CollisionGrid::remove_object(MovingObject* object)
         std::cerr << "Object out of range: " << gridx << ", " << gridy << "\n";
         continue;
       }
-      remove_object_from_gridcell(gridy*cells_x + gridx, object);
+      remove_object_from_gridcell(gridy*cells_x + gridx, wrapper);
     }
   }
 
@@ -98,11 +105,13 @@ CollisionGrid::remove_object(MovingObject* object)
 }
 
 void
-CollisionGrid::move_object(MovingObject* object)
+CollisionGrid::move_object(ObjectWrapper* wrapper)
 {
-  const Rectangle& bbox = object->bbox;
-  for(float y = bbox.p1.y; y < bbox.p2.y; y += cell_height) {
-    for(float x = bbox.p1.x; x < bbox.p2.x; x += cell_width) {
+  // FIXME not optimal yet... should leave the gridcells untouched that don't
+  // need to be changed.
+  const Rectangle& obbox = wrapper->dest;
+  for(float y = obbox.p1.y; y < obbox.p2.y; y += cell_height) {
+    for(float x = obbox.p1.x; x < obbox.p2.x; x += cell_width) {
       int gridx = int(x / cell_width);
       int gridy = int(y / cell_height);
       if(gridx < 0 || gridy < 0 
@@ -110,14 +119,36 @@ CollisionGrid::move_object(MovingObject* object)
         std::cerr << "Object out of range: " << gridx << ", " << gridy << "\n";
         continue;
       }
-      // TODO
+      remove_object_from_gridcell(gridy*cells_x + gridx, wrapper);
     }
   }
+
+  const Rectangle& nbbox = wrapper->object->bbox;
+  for(float y = nbbox.p1.y; y < nbbox.p2.y; y += cell_height) {
+    for(float x = nbbox.p1.x; x < nbbox.p2.x; x += cell_width) {
+      int gridx = int(x / cell_width);
+      int gridy = int(y / cell_height);
+      if(gridx < 0 || gridy < 0 
+          || gridx >= int(cells_x) || gridy >= int(cells_y)) {
+        std::cerr << "Object out of range: " << gridx << ", " << gridy << "\n";
+        continue;
+      }
+
+      GridEntry* entry = new GridEntry;
+      entry->object_wrapper = wrapper;
+      entry->next = grid[gridy*cells_x + gridx];
+      grid[gridy*cells_x + gridx] = entry;
+    }
+  }
+
+  wrapper->dest = nbbox;
 }
 
 void
 CollisionGrid::check_collisions()
 {
+  std::vector<ObjectWrapper*> moved_objects;
+  
   CollisionGridIterator iter(*this, Sector::current()->get_active_region());
   while(ObjectWrapper* wrapper = iter.next_wrapper()) {
     MovingObject* object = wrapper->object;
@@ -126,6 +157,7 @@ CollisionGrid::check_collisions()
     if(object->get_flags() & GameObject::FLAG_NO_COLLDET) {
       object->bbox.move(object->movement);
       object->movement = Vector(0, 0);
+      moved_objects.push_back(wrapper);
       continue;
     }
 
@@ -134,8 +166,16 @@ CollisionGrid::check_collisions()
     
     collide_object(wrapper);
 
-    object->bbox.move(object->get_movement());
-    object->movement = Vector(0, 0);
+    if(object->movement != Vector(0, 0)) {
+      object->bbox.move(object->movement);
+      object->movement = Vector(0, 0);
+      moved_objects.push_back(wrapper);
+    }
+  }
+
+  for(std::vector<ObjectWrapper*>::iterator i = moved_objects.begin();
+      i != moved_objects.end(); ++i) {
+    move_object(*i);
   }
 }
 
@@ -145,13 +185,13 @@ CollisionGrid::collide_object(ObjectWrapper* wrapper)
   iterator_timestamp++;
 
   const Rectangle& bbox = wrapper->object->bbox;
-  for(float y = bbox.p1.y; y < bbox.p2.y; y += cell_height) {
-    for(float x = bbox.p1.x; x < bbox.p2.x; x += cell_width) {
+  for(float y = bbox.p1.y - cell_height; y < bbox.p2.y + cell_height; y += cell_height) {
+    for(float x = bbox.p1.x - cell_width; x < bbox.p2.x + cell_width; x += cell_width) {
       int gridx = int(x / cell_width);
       int gridy = int(y / cell_height);
       if(gridx < 0 || gridy < 0 
           || gridx >= int(cells_x) || gridy >= int(cells_y)) {
-        std::cerr << "Object out of range: " << gridx << ", " << gridy << "\n";
+        //std::cerr << "Object out of range: " << gridx << ", " << gridy << "\n";
         continue;
       }
   
@@ -209,13 +249,13 @@ CollisionGrid::collide_object_object(ObjectWrapper* wrapper,
 }
 
 void
-CollisionGrid::remove_object_from_gridcell(int gridcell, MovingObject* object)
+CollisionGrid::remove_object_from_gridcell(int gridcell, ObjectWrapper* wrapper)
 {
   GridEntry* lastentry = 0;
   GridEntry* entry = grid[gridcell];
 
   while(entry) {
-    if(entry->object_wrapper->object == object) {
+    if(entry->object_wrapper == wrapper) {
       if(lastentry == 0) {
         grid[gridcell] = entry->next;
       } else {
index 8a507d1..7822c31 100644 (file)
@@ -20,7 +20,6 @@ public:
 
   void add_object(MovingObject* object);
   void remove_object(MovingObject* object);
-  void move_object(MovingObject* object);
 
   void check_collisions();
 
@@ -47,9 +46,10 @@ private:
     ObjectWrapper* object_wrapper;
   };
 
-  void remove_object_from_gridcell(int gridcell, MovingObject* object);
+  void remove_object_from_gridcell(int gridcell, ObjectWrapper* wrapper);
   void collide_object(ObjectWrapper* wrapper);
   void collide_object_object(ObjectWrapper* wrapper, ObjectWrapper* wrapper2);
+  void move_object(ObjectWrapper* wrapper);
   
   typedef std::vector<GridEntry*> GridEntries;
   GridEntries grid;
index 9e22f62..efed0b4 100644 (file)
@@ -13,20 +13,20 @@ public:
   CollisionGridIterator(CollisionGrid& newgrid, const Rectangle& bbox)
     : grid(newgrid)
   {
-    start_x = int(bbox.p1.x / grid.cell_width);
+    start_x = int(bbox.p1.x / grid.cell_width) - 2;
     if(start_x < 0)
       start_x = 0;
     x = start_x;
         
-    y = int(bbox.p1.y / grid.cell_height);
+    y = int(bbox.p1.y / grid.cell_height) - 2;
     if(y < 0)
       y = 0;
     
-    end_x = int(bbox.p2.x / grid.cell_width) + 1;
+    end_x = int(bbox.p2.x / grid.cell_width) + 2;
     if(end_x > (int) grid.cells_x)
       end_x = grid.cells_x;
     
-    end_y = int(bbox.p2.y / grid.cell_height) + 1;
+    end_y = int(bbox.p2.y / grid.cell_height) + 2;
     if(end_y > (int) grid.cells_y)
       end_y = grid.cells_y;
 
diff --git a/src/defines.h b/src/defines.h
deleted file mode 100644 (file)
index c408b68..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-//  $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*/
-
diff --git a/src/direction.h b/src/direction.h
new file mode 100644 (file)
index 0000000..5ecc417
--- /dev/null
@@ -0,0 +1,27 @@
+//  $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*/
+
diff --git a/src/flip_level_transformer.cpp b/src/flip_level_transformer.cpp
new file mode 100644 (file)
index 0000000..db5a693
--- /dev/null
@@ -0,0 +1,78 @@
+#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);
+}
+
diff --git a/src/flip_level_transformer.h b/src/flip_level_transformer.h
new file mode 100644 (file)
index 0000000..f3cc842
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef __FLIP_LEVEL_TRANSFORMER_H__
+#define __FLIP_LEVEL_TRANSFORMER_H__
+
+#include "level_transformer.h"
+
+class TileMap;
+class BadGuy;
+class SpawnPoint;
+namespace SuperTux {
+class MovingObject;
+}
+
+using namespace SuperTux;
+
+/** Vertically or horizontally flip a level */
+class FlipLevelTransformer : public LevelTransformer
+{
+public:
+  virtual void transform_sector(Sector* sector);
+
+private:
+  void transform_tilemap(TileMap* tilemap);
+  void transform_moving_object(float height, MovingObject* object);
+  void transform_badguy(float height, BadGuy* badguy);
+  void transform_spawnpoint(float height, SpawnPoint* spawnpoint);
+};
+
+#endif
+
index 275c42f..3a33cdb 100644 (file)
 #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"
@@ -47,8 +46,8 @@
 #include "gui/menu.h"
 #include "sector.h"
 #include "level.h"
-#include "scene.h"
 #include "tile.h"
+#include "player_status.h"
 #include "object/particlesystem.h"
 #include "object/background.h"
 #include "object/tilemap.h"
@@ -59,7 +58,6 @@
 #include "resources.h"
 #include "app/gettext.h"
 #include "worldmap.h"
-#include "intro.h"
 #include "misc.h"
 #include "statistics.h"
 #include "timer.h"
@@ -225,32 +223,18 @@ GameSession::start_timers()
 void
 GameSession::on_escape_press()
 {
-  if(currentsector->player->dying || end_sequence != NO_ENDSEQUENCE)
+  if(currentsector->player->is_dying() || end_sequence != NO_ENDSEQUENCE)
     return;   // don't let the player open the menu, when he is dying
   
   if(game_pause)
     return;
 
-  if(st_gl_mode == ST_GL_TEST)
-    {
-      exit_status = ES_LEVEL_ABORT;
-    }
-  else if (!Menu::current())
-    {
-      /* Tell Tux that the keys are all down, otherwise
-        it could have nasty bugs, like going allways to the right
-        or whatever that key does */
-      Player& tux = *(currentsector->player);
-      tux.key_event((SDLKey)keymap.up, UP);
-      tux.key_event((SDLKey)keymap.down, UP);
-      tux.key_event((SDLKey)keymap.left, UP);
-      tux.key_event((SDLKey)keymap.right, UP);
-      tux.key_event((SDLKey)keymap.jump, UP);
-      tux.key_event((SDLKey)keymap.power, UP);
-
-      Menu::set_current(game_menu);
-      Ticks::pause_start();
-    }
+  if(st_gl_mode == ST_GL_TEST) {
+    exit_status = ES_LEVEL_ABORT;
+  } else if (!Menu::current()) {
+    Menu::set_current(game_menu);
+    Ticks::pause_start();
+  }
 }
 
 void
@@ -260,15 +244,15 @@ GameSession::process_events()
     {
       Player& tux = *currentsector->player;
          
-      tux.input.fire  = UP;
-      tux.input.left  = UP;
-      tux.input.right = DOWN;
-      tux.input.down  = UP
+      tux.input.fire  = false;
+      tux.input.left  = false;
+      tux.input.right = true;
+      tux.input.down  = false
 
       if (int(last_x_pos) == int(tux.get_pos().x))
-        tux.input.up    = DOWN
+        tux.input.up    = true
       else
-        tux.input.up    = UP; 
+        tux.input.up    = false;
 
       last_x_pos = tux.get_pos().x;
 
@@ -339,7 +323,7 @@ GameSession::process_events()
                   {
                     SDLKey key = event.key.keysym.sym;
             
-                    if(tux.key_event(key,DOWN))
+                    if(tux.key_event(key, true))
                       break;
 
                     switch(key)
@@ -356,7 +340,7 @@ GameSession::process_events()
                   {
                     SDLKey key = event.key.keysym.sym;
 
-                    if(tux.key_event(key, UP))
+                    if(tux.key_event(key, false))
                       break;
 
                     switch(key)
@@ -407,93 +391,7 @@ GameSession::process_events()
                           ch[1] = '\0';
                           }
                         last_keys.append(ch);  // add to cheat keys
-
-                        // Cheating words (the goal of this is really for debugging,
-                        // but could be used for some cheating, nothing wrong with that)
-                        if(compare_last(last_keys, "grow"))
-                          {
-                          tux.grow(false);
-                          last_keys.clear();
-                          }
-                        if(compare_last(last_keys, "fire"))
-                          {
-                          tux.grow(false);
-                          tux.got_power = tux.FIRE_POWER;
-                          last_keys.clear();
-                          }
-                        if(compare_last(last_keys, "ice"))
-                          {
-                          tux.grow(false);
-                          tux.got_power = tux.ICE_POWER;
-                          last_keys.clear();
-                          }
-                        if(compare_last(last_keys, "lifeup"))
-                          {
-                          player_status.lives++;
-                          last_keys.clear();
-                          }
-                        if(compare_last(last_keys, "lifedown"))
-                          {
-                          player_status.lives--;
-                          last_keys.clear();
-                          }
-                        if(compare_last(last_keys, "grease"))
-                          {
-                          tux.physic.set_velocity_x(tux.physic.get_velocity_x()*3);
-                          last_keys.clear();
-                          }
-                        if(compare_last(last_keys, "invincible"))
-                          {    // be invincle for the rest of the level
-                          tux.invincible_timer.start(10000);
-                          last_keys.clear();
-                          }
-                        if(compare_last(last_keys, "shrink"))
-                          {    // remove powerups
-                          tux.kill(tux.SHRINK);
-                          last_keys.clear();
-                          }
-                        if(compare_last(last_keys, "kill"))
-                          {    // kill Tux, but without losing a life
-                          player_status.lives++;
-                          tux.kill(tux.KILL);
-                          last_keys.clear();
-                          }
-                        if(compare_last(last_keys, "grid"))
-                          {    // toggle debug grid
-                          debug_grid = !debug_grid;
-                          last_keys.clear();
-                          }
-                        if(compare_last(last_keys, "hover"))
-                          {    // toggle hover ability on/off
-                          tux.enable_hover = !tux.enable_hover;
-                          last_keys.clear();
-                          }
-                        if(compare_last(last_keys, "gotoend"))
-                          {    // goes to the end of the level
-                          tux.move(Vector(
-                              (currentsector->solids->get_width()*32) 
-                                - (screen->w*2),
-                                0));
-                          currentsector->camera->reset(
-                              Vector(tux.get_pos().x, tux.get_pos().y));
-                          last_keys.clear();
-                          }
-                        // temporary to help player's choosing a flapping
-                        if(compare_last(last_keys, "marek"))
-                          {
-                          tux.flapping_mode = Player::MAREK_FLAP;
-                          last_keys.clear();
-                          }
-                        if(compare_last(last_keys, "ricardo"))
-                          {
-                          tux.flapping_mode = Player::RICARDO_FLAP;
-                          last_keys.clear();
-                          }
-                        if(compare_last(last_keys, "ryan"))
-                          {
-                          tux.flapping_mode = Player::RYAN_FLAP;
-                          last_keys.clear();
-                          }
+                        handle_cheats();
                   break;
 
                 case SDL_JOYAXISMOTION:
@@ -501,74 +399,75 @@ GameSession::process_events()
                     {
                       if (event.jaxis.value < -joystick_keymap.dead_zone)
                         {
-                          tux.input.left  = DOWN;
-                          tux.input.right = UP;
+                          tux.input.left  = true;
+                          tux.input.right = false;
                         }
                       else if (event.jaxis.value > joystick_keymap.dead_zone)
                         {
-                          tux.input.left  = UP;
-                          tux.input.right = DOWN;
+                          tux.input.left  = false;
+                          tux.input.right = true;
                         }
                       else
                         {
-                          tux.input.left  = DOWN;
-                          tux.input.right = DOWN;
+                          tux.input.left  = false;
+                          tux.input.right = false;
                         }
                     }
                   else if (event.jaxis.axis == joystick_keymap.y_axis)
                     {
                       if (event.jaxis.value > joystick_keymap.dead_zone)
                         {
-                        tux.input.up = DOWN;
-                        tux.input.down = UP;
+                        tux.input.up = true;
+                        tux.input.down = false;
                         }
                       else if (event.jaxis.value < -joystick_keymap.dead_zone)
                         {
-                        tux.input.up = UP;
-                        tux.input.down = DOWN;
+                        tux.input.up = false;
+                        tux.input.down = true;
                         }
                       else
                         {
-                        tux.input.up = DOWN;
-                        tux.input.down = DOWN;
+                        tux.input.up = false;
+                        tux.input.down = false;
                         }
                     }
                   break;
 
                 case SDL_JOYHATMOTION:
                   if(event.jhat.value & SDL_HAT_UP) {
-                    tux.input.up = DOWN;
-                    tux.input.down = UP;
+                    tux.input.up = true;
+                    tux.input.down = false;
                   } else if(event.jhat.value & SDL_HAT_DOWN) {
-                    tux.input.up = UP;
-                    tux.input.down = DOWN;
+                    tux.input.up = false;
+                    tux.input.down = true;
                   } else if(event.jhat.value & SDL_HAT_LEFT) {
-                    tux.input.left = DOWN;
-                    tux.input.right = UP;
+                    tux.input.left = true;
+                    tux.input.right = false;
                   } else if(event.jhat.value & SDL_HAT_RIGHT) {
-                    tux.input.left = UP;
-                    tux.input.right = DOWN;
+                    tux.input.left = false;
+                    tux.input.right = true;
                   } else if(event.jhat.value == SDL_HAT_CENTERED) {
-                    tux.input.left = UP;
-                    tux.input.right = UP;
-                    tux.input.up = UP;
-                    tux.input.down = UP;
+                    tux.input.left = false;
+                    tux.input.right = false;
+                    tux.input.up = false;
+                    tux.input.down = false;
                   }
                   break;
             
                 case SDL_JOYBUTTONDOWN:
+                  // FIXME: I assume we have to set old_jump and stuff here?!?
                   if (event.jbutton.button == joystick_keymap.a_button)
-                    tux.input.jump = DOWN;
+                    tux.input.jump = true;
                   else if (event.jbutton.button == joystick_keymap.b_button)
-                    tux.input.fire = DOWN;
+                    tux.input.fire = true;
                   else if (event.jbutton.button == joystick_keymap.start_button)
                     on_escape_press();
                   break;
                 case SDL_JOYBUTTONUP:
                   if (event.jbutton.button == joystick_keymap.a_button)
-                    tux.input.jump = UP;
+                    tux.input.jump = false;
                   else if (event.jbutton.button == joystick_keymap.b_button)
-                    tux.input.fire = UP;
+                    tux.input.fire = false;
                   break;
 
                 default:
@@ -580,6 +479,93 @@ GameSession::process_events()
 }
 
 void
+GameSession::handle_cheats()
+{
+  Player& tux = *currentsector->player;
+  
+  // Cheating words (the goal of this is really for debugging,
+  // but could be used for some cheating, nothing wrong with that)
+  if(compare_last(last_keys, "grow")) {
+    tux.grow(false);
+    last_keys.clear();
+  }
+  if(compare_last(last_keys, "fire")) {
+    tux.grow(false);
+    tux.got_power = tux.FIRE_POWER;
+    last_keys.clear();
+  }
+  if(compare_last(last_keys, "ice")) {
+    tux.grow(false);
+    tux.got_power = tux.ICE_POWER;
+    last_keys.clear();
+  }
+  if(compare_last(last_keys, "lifeup")) {
+    player_status.lives++;
+    last_keys.clear();
+  }
+  if(compare_last(last_keys, "lifedown")) {
+    player_status.lives--;
+    last_keys.clear();
+  }
+  if(compare_last(last_keys, "grease")) {
+    tux.physic.set_velocity_x(tux.physic.get_velocity_x()*3);
+    last_keys.clear();
+  }
+  if(compare_last(last_keys, "invincible")) {
+    // be invincle for the rest of the level
+    tux.invincible_timer.start(10000);
+    last_keys.clear();
+  }
+  if(compare_last(last_keys, "shrink")) {
+    // remove powerups
+    tux.kill(tux.SHRINK);
+    last_keys.clear();
+  }
+  if(compare_last(last_keys, "kill")) {
+    // kill Tux, but without losing a life
+    player_status.lives++;
+    tux.kill(tux.KILL);
+    last_keys.clear();
+  }
+  if(compare_last(last_keys, "grid")) {
+    // toggle debug grid
+    debug_grid = !debug_grid;
+    last_keys.clear();
+  }
+  if(compare_last(last_keys, "hover")) {
+    // toggle hover ability on/off
+    tux.enable_hover = !tux.enable_hover;
+    last_keys.clear();
+  }
+  if(compare_last(last_keys, "gotoend")) {
+    // goes to the end of the level
+    tux.move(Vector(
+          (currentsector->solids->get_width()*32) - (screen->w*2), 0));
+    currentsector->camera->reset(
+        Vector(tux.get_pos().x, tux.get_pos().y));
+    last_keys.clear();
+  }
+  if(compare_last(last_keys, "finish")) {
+    // finish current sector
+    exit_status = ES_LEVEL_FINISHED;
+    // don't add points to stats though...
+  }
+  // temporary to help player's choosing a flapping
+  if(compare_last(last_keys, "marek")) {
+    tux.flapping_mode = Player::MAREK_FLAP;
+    last_keys.clear();
+  }
+  if(compare_last(last_keys, "ricardo")) {
+    tux.flapping_mode = Player::RICARDO_FLAP;
+    last_keys.clear();
+  }
+  if(compare_last(last_keys, "ryan")) {
+    tux.flapping_mode = Player::RYAN_FLAP;
+    last_keys.clear();
+  }
+}
+
+void
 GameSession::check_end_conditions()
 {
   Player* tux = currentsector->player;
@@ -811,7 +797,7 @@ GameSession::respawn(const std::string& sector, const std::string& spawnpoint)
 void
 GameSession::start_sequence(const std::string& sequencename)
 {
-  if(sequencename == "endsequence") {
+  if(sequencename == "endsequence" || sequencename == "fireworks") {
     if(end_sequence)
       return;
     
@@ -825,7 +811,7 @@ GameSession::start_sequence(const std::string& sequencename)
     global_stats.set_points(TIME_NEEDED_STAT,
         int(time_left.get_period() - time_left.get_timeleft()));
 
-    if(level->get_end_sequence_type() == Level::FIREWORKS_ENDSEQ_ANIM) {
+    if(sequencename == "fireworks") {
       currentsector->add_object(new Fireworks());
     }
   } else {
index a63a24b..ea1df56 100644 (file)
@@ -129,6 +129,7 @@ private:
   void check_end_conditions();
   void start_timers();
   void process_events();
+  void handle_cheats();
 
   void levelintro();
   void drawstatus(DrawingContext& context);
diff --git a/src/intro.cpp b/src/intro.cpp
deleted file mode 100644 (file)
index d23e600..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-//  $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 );
-}
-
diff --git a/src/intro.h b/src/intro.h
deleted file mode 100644 (file)
index 87b34e2..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-//  $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: */
index 8e572a0..21ce9eb 100644 (file)
@@ -38,7 +38,6 @@
 #include "lisp/writer.h"
 #include "level.h"
 #include "math/physic.h"
-#include "scene.h"
 #include "sector.h"
 #include "tile.h"
 #include "resources.h"
 #include "object/tilemap.h"
 #include "object/coin.h"
 
+// test
+#include "flip_level_transformer.h"
+
 using namespace std;
 
 Level::Level()
-  : name("noname"), author("mr. x"), timelimit(500),
-    end_sequence_type(NONE_ENDSEQ_ANIM) 
+  : name("noname"), author("Mr. X"), timelimit(500)
 {
 }
 
@@ -70,6 +71,13 @@ Level::load(const std::string& filepath)
     level->get("version", version);
     if(version == 1) {
       load_old_format(*level);
+
+#if 0
+      // test for now
+      FlipLevelTransformer* transformer = new FlipLevelTransformer();  
+      transformer->transform(this);
+#endif
+     
       return;
     }
 
@@ -91,20 +99,12 @@ Level::load(const std::string& filepath)
         Sector* sector = new Sector;
         sector->parse(*(iter.lisp()));
         add_sector(sector);
-      } else if(token == "end-sequence-animation") {
-        std::string endsequencename;
-        iter.value()->get(endsequencename);
-        if(endsequencename == "fireworks") {
-          end_sequence_type = FIREWORKS_ENDSEQ_ANIM;
-        } else {
-          std::cout << "Unknown endsequence type: '" << endsequencename <<
-            "'.\n";
-        }
       } else {
         std::cerr << "Unknown token '" << token << "' in level file.\n";
         continue;
       }
     }
+    
   } catch(std::exception& e) {
     std::stringstream msg;
     msg << "Problem when reading level '" << filepath << "': " << e.what();
@@ -144,12 +144,11 @@ Level::save(const std::string& filename)
   writer->write_string("name", name, true);
   writer->write_string("author", author);
   writer->write_int("time", timelimit);
-  writer->write_string("end-sequence-animation",
-      end_sequence_type == FIREWORKS_ENDSEQ_ANIM ? "fireworks" : "none");
 
   for(Sectors::iterator i = sectors.begin(); i != sectors.end(); ++i) {
+    Sector* sector = *i;
     writer->start_list("sector");
-    i->second->write(*writer);
+    sector->write(*writer);
     writer->end_list("sector");
   }
 
@@ -162,63 +161,41 @@ Level::save(const std::string& filename)
 Level::~Level()
 {
   for(Sectors::iterator i = sectors.begin(); i != sectors.end(); ++i)
-    delete i->second;
+    delete *i;
 }
 
 void
 Level::add_sector(Sector* sector)
 {
-  sectors.insert(std::make_pair(sector->get_name(), sector));       
+  Sector* test = get_sector(sector->get_name());
+  if(test != 0) {
+    throw std::runtime_error("Trying to add 2 sectors with same name");
+  }
+  sectors.push_back(sector);
 }
 
 Sector*
 Level::get_sector(const std::string& name)
 {
-  Sectors::iterator i = sectors.find(name);
-  if(i == sectors.end())
-    return 0;
+  for(Sectors::iterator i = sectors.begin(); i != sectors.end(); ++i) {
+    Sector* sector = *i;
+    if(sector->get_name() == name)
+      return sector;
+  }
 
-  return i->second;
+  return 0;
 }
 
-Sector*
-Level::get_next_sector(const Sector* sector)
+size_t
+Level::get_sector_count()
 {
-  for(Sectors::iterator i = sectors.begin(); i != sectors.end(); ++i)
-    {
-    if(i->second == sector)
-      {
-      i++;
-      if(i == sectors.end())
-        return NULL;
-      return i->second;
-      }
-    }
-  std::cerr << "Warning: Sector not found on level\n";
-  return NULL;
+  return sectors.size();
 }
 
 Sector*
-Level::get_previous_sector(const Sector* sector)
+Level::get_sector(size_t num)
 {
-  for(Sectors::iterator i = sectors.begin(); i != sectors.end(); ++i)
-    {
-    if(i->second == sector)
-      {
-      if(i == sectors.begin())
-        return NULL;
-      i--;
-      return i->second;
-      }
-    }
-  std::cerr << "Warning: Sector not found on level\n";
-  return NULL;
-}
-
-int
-Level::get_total_sectors()
-{
-return sectors.size();
+  return sectors.at(num);
 }
 
 int
@@ -226,16 +203,17 @@ Level::get_total_badguys()
 {
   int total_badguys = 0;
   for(Sectors::iterator i = sectors.begin(); i != sectors.end(); ++i)
-    total_badguys += i->second->get_total_badguys();
+    total_badguys += (*i)->get_total_badguys();
   return total_badguys;
 }
 
 int
 Level::get_total_coins()
 {
+  // FIXME not really correct as coins can also be inside blocks...
   int total_coins = 0;
   for(Sectors::iterator i = sectors.begin(); i != sectors.end(); ++i) {
-    Sector* sector = i->second;
+    Sector* sector = *i;
     for(Sector::GameObjects::iterator o = sector->gameobjects.begin();
         o != sector->gameobjects.end(); ++o) {
       Coin* coin = dynamic_cast<Coin*> (*o);
@@ -245,3 +223,4 @@ Level::get_total_coins()
   }
   return total_coins;
 }
+
index 7eb0248..555138a 100644 (file)
 #ifndef SUPERTUX_LEVEL_H
 #define SUPERTUX_LEVEL_H
 
-#include <map>
+#include <vector>
 #include <string>
 
-using namespace SuperTux;
-
 class Sector;
 
 namespace lisp {
@@ -35,17 +33,11 @@ class Lisp;
 class Level
 {
 public:
-  enum EndSequenceType{
-    NONE_ENDSEQ_ANIM,
-    FIREWORKS_ENDSEQ_ANIM
-  };
-
   std::string name;
   std::string author;
   int timelimit;
-  typedef std::map<std::string, Sector*> Sectors;
+  typedef std::vector<Sector*> Sectors;
   Sectors sectors;
-  EndSequenceType end_sequence_type;
 
 public:
   Level();
@@ -55,9 +47,6 @@ public:
   void load(const std::string& filename);
   void save(const std::string& filename);
 
-  EndSequenceType get_end_sequence_type() const
-  { return end_sequence_type; }
-
   const std::string& get_name() const
   { return name; }
 
@@ -68,10 +57,8 @@ public:
 
   Sector* get_sector(const std::string& name);
 
-  Sector* get_next_sector(const Sector* sector);
-  Sector* get_previous_sector(const Sector* sector);
-
-  int get_total_sectors();
+  size_t get_sector_count();
+  Sector* get_sector(size_t num);
 
   int get_total_badguys();
   int get_total_coins();
diff --git a/src/level_transformer.cpp b/src/level_transformer.cpp
new file mode 100644 (file)
index 0000000..4735dd2
--- /dev/null
@@ -0,0 +1,17 @@
+#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));
+  }
+}
+
diff --git a/src/level_transformer.h b/src/level_transformer.h
new file mode 100644 (file)
index 0000000..c587acf
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef __LEVEL_TRANSFORMER_H__
+#define __LEVEL_TRANSFORMER_H__
+
+class Level;
+class Sector;
+
+/**
+ * This class is an abstract interface for algorithms that transform levels in
+ * some way before they are played.
+ */
+class LevelTransformer
+{
+public:
+  virtual ~LevelTransformer();
+  
+  /** transform a complete Level, the standard implementation just calls
+   * transformSector on each sector in the level. 
+   */
+  virtual void transform(Level* level);
+
+  virtual void transform_sector(Sector* sector) = 0;
+};
+
+#endif
+
index 1f1692d..9ae0dc1 100644 (file)
@@ -201,622 +201,625 @@ delete img_next_sector_bt;
 
 void LevelEditor::run(const std::string filename)
 {
-SoundManager::get()->halt_music();
-Menu::set_current(0);
+  SoundManager::get()->halt_music();
+  Menu::set_current(0);
 
-DrawingContext context;
+  DrawingContext context;
 
-if(!filename.empty())
-  {
-  level_nb = -1;
-  load_level(filename);
-  }
-else
-  Menu::set_current(main_menu);
+  if(!filename.empty())
+    {
+    level_nb = -1;
+    load_level(filename);
+    }
+  else
+    Menu::set_current(main_menu);
 
-mouse_cursor->set_state(MC_NORMAL);
+  mouse_cursor->set_state(MC_NORMAL);
 
-done = false;
-while(!done)
-  {
-  events();
-  action();
-  draw(context);
-  }
+  done = false;
+  while(!done)
+    {
+    events();
+    action();
+    draw(context);
+    }
 
-if(level_changed)
-  if(confirm_dialog(NULL, _("Level not saved. Wanna to?")))
-    save_level();
+  if(level_changed)
+    if(confirm_dialog(NULL, _("Level not saved. Wanna to?")))
+      save_level();
 }
 
 void LevelEditor::events()
 {
-mouse_moved = false;
+  mouse_moved = false;
 
-while(SDL_PollEvent(&event))
-  {
-  Menu* menu = Menu::current();
-  if(menu)
+  SDL_Event event;
+  while(SDL_PollEvent(&event))
     {
-    menu->event(event);
-    menu->action();
-    if(menu == main_menu)
+    Menu* menu = Menu::current();
+    if(menu)
       {
-      switch (main_menu->check())
+      menu->event(event);
+      menu->action();
+      if(menu == main_menu)
         {
-        case MN_ID_RETURN:
-          Menu::set_current(0);
-          break;
-        case MN_ID_QUIT:
-          done = true;
-          break;
+        switch (main_menu->check())
+          {
+          case MN_ID_RETURN:
+            Menu::set_current(0);
+            break;
+          case MN_ID_QUIT:
+            done = true;
+            break;
+          }
         }
-      }
-    else if(menu == create_subset_menu)
-      {
-      // activate or deactivate Create button if any filename as been specified
-      if(create_subset_menu->get_item_by_id(MN_ID_FILENAME_SUBSET).input[0] == '\0')
-        create_subset_menu->get_item_by_id(MN_ID_CREATE_SUBSET).kind = MN_DEACTIVE;
-      else
-        create_subset_menu->get_item_by_id(MN_ID_CREATE_SUBSET).kind = MN_ACTION;
-
-      if(create_subset_menu->check() == MN_ID_CREATE_SUBSET)
-        {   // applying settings:
-        std::string subset_name = create_subset_menu->get_item_by_id(MN_ID_FILENAME_SUBSET).input;
-        LevelSubset::create(subset_name);
-
-        delete level_subset;
-        level_subset = new LevelSubset();
-        level_subset->load(create_subset_menu->get_item_by_id(MN_ID_FILENAME_SUBSET).input);
-
-        level_subset->title = create_subset_menu->get_item_by_id(MN_ID_TITLE_SUBSET).input;
-        level_subset->description = create_subset_menu->get_item_by_id(MN_ID_DESCRIPTION_SUBSET).input;
-        //FIXME: generate better level filenames
-        level_subset->add_level(subset_name+'/'+"new_level.stl");
-        Level* newlevel = new Level();
-        newlevel->add_sector(create_sector("main", 25, 19));
-        newlevel->save(level_subset->get_level_filename(0));
-        level_subset->save();
-        
-        load_level(0);
-
-        create_subset_menu->get_item_by_id(MN_ID_FILENAME_SUBSET).change_input("");
-        create_subset_menu->get_item_by_id(MN_ID_TITLE_SUBSET).change_input("");
-        create_subset_menu->get_item_by_id(MN_ID_DESCRIPTION_SUBSET).change_input("");
+      else if(menu == create_subset_menu)
+        {
+        // activate or deactivate Create button if any filename as been specified
+        if(create_subset_menu->get_item_by_id(MN_ID_FILENAME_SUBSET).input[0] == '\0')
+          create_subset_menu->get_item_by_id(MN_ID_CREATE_SUBSET).kind = MN_DEACTIVE;
+        else
+          create_subset_menu->get_item_by_id(MN_ID_CREATE_SUBSET).kind = MN_ACTION;
+
+        if(create_subset_menu->check() == MN_ID_CREATE_SUBSET)
+          {   // applying settings:
+          std::string subset_name = create_subset_menu->get_item_by_id(MN_ID_FILENAME_SUBSET).input;
+          LevelSubset::create(subset_name);
+
+          delete level_subset;
+          level_subset = new LevelSubset();
+          level_subset->load(create_subset_menu->get_item_by_id(MN_ID_FILENAME_SUBSET).input);
+
+          level_subset->title = create_subset_menu->get_item_by_id(MN_ID_TITLE_SUBSET).input;
+          level_subset->description = create_subset_menu->get_item_by_id(MN_ID_DESCRIPTION_SUBSET).input;
+          //FIXME: generate better level filenames
+          level_subset->add_level(subset_name+'/'+"new_level.stl");
+          Level* newlevel = new Level();
+          newlevel->add_sector(create_sector("main", 25, 19));
+          newlevel->save(level_subset->get_level_filename(0));
+          level_subset->save();
+          
+          load_level(0);
+
+          create_subset_menu->get_item_by_id(MN_ID_FILENAME_SUBSET).change_input("");
+          create_subset_menu->get_item_by_id(MN_ID_TITLE_SUBSET).change_input("");
+          create_subset_menu->get_item_by_id(MN_ID_DESCRIPTION_SUBSET).change_input("");
+          }
         }
-      }
-    else if(menu == subset_menu)
-      {
-      int i = subset_menu->check();
-      if(i >= 0)
+      else if(menu == subset_menu)
         {
-        std::set<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()
@@ -907,111 +910,111 @@ void LevelEditor::change(int x, int y, int newtile, int layer)
 
 void LevelEditor::show_help()
 {
-DrawingContext context;
-
-bool show_grid_t = show_grid;
-show_grid = false;
-mouse_cursor->set_state(MC_HIDE);
-
-
-char str[1024];
-const char *text1[] = {
-         _("This is the built-in level editor. Its aim is to be intuitive\n"
-         "and simple to use, so it should be pretty straightforward.\n"
-         "\n"
-         "To open a level, first you'll have to select a level subset from\n"
-         "the menu (or create your own).\n"
-         "A level subset is basically a collection of levels.\n"
-         "They can then be played from the Contrib menu.\n"
-         "\n"
-         "To access the menu from the level editor, just press Esc.\n"
-         "\n"
-         "You are currently looking at the level. To scroll it, just\n"
-         "press the right mouse button and drag the mouse. It will move like\n"
-         "a strategy game.\n"
-         "You can also use the arrow keys and Page Up/Down.\n"
-         "\n"
-         "'+' and '-' keys can be used to zoom the level in/out.\n"
-         "\n"
-         "You probably already noticed those floating groups of buttons.\n"
-         "Each one serves a different purpose. To select a certain button\n"
-         "just press the Left mouse button on it. A few buttons have key\n"
-         "shortcuts. You can find them by pressing the Right mouse button on\n"
-         "a button. That will also show what that button does.\n"
-         "Groups of buttons can also be moved around by just dragging them,\n"
-         "while pressing the Left mouse button.\n"
-         "\n"
-         "Let's learn a bit of what each group of buttons does, shall we?\n"
-         "\n"
-         "To starting putting tiles and objects around use the bigger group\n"
-         "of buttons. Each button is a different tile. To put it on the level,\n"
-         "just press it and then left click in the level.\n"
-         "You can also copy tiles from the level by using the middle mouse button.\n"
-         "Use the mouse wheel to scroll that group of buttons. You will find\n"
-         "enemies and game objects in the bottom.\n")
-                };
-
-const char *text2[] = {
-         _("The Foreground/Interactive/Background buttons may be used to\n"
-         "see and edit the respective layer. Levels have three tiles layers:\n"
-         "Foreground - tiles are drawn on top of everything and have no contact\n"
-         "with the player.\n"
-         "Interactive - these are the tiles that have contact with the player.\n"
-         "Background - tiles are drawn underneath everything and have no contact\n"
-         "with the player.\n"
-         "The unselected layers will be drawn semi-transparently.\n"
-         "\n"
-         "Last, but not least, the group of buttons that's left serves\n"
-         "to do related actions with the level.\n"
-         "From left to right:\n"
-         "Mini arrows - can be used to choose other sectors.\n"
-         "Sectors are mini-levels, so to speak, that can be accessed using a door.\n"
-         "Big arrows - choose other level in the same level subset.\n"
-         "Diskette - save the level\n"
-         "Tux - test the level\n"
-         "Tools - set a few settings for the level, including resizing it.\n"
-         "\n"
-         "We have reached the end of this Howto.\n"
-         "\n"
-         "Don't forget to send us a few cool levels. :)\n"
-         "\n"
-         "Enjoy,\n"
-         "  SuperTux development team\n"
-         "\n"
-         "PS: If you are looking for something more powerful, you might like to\n"
-         "try FlexLay. FlexLay is a level editor that supports several games,\n"
-         "including SuperTux. It is an independent project.\n"
-         "Webpage: http://pingus.seul.org/~grumbel/flexlay/")
-                };
-
-const char **text[] = { text1, text2 };
-
-
-bool done;
-for(unsigned int i = 0; i < sizeof(text) / sizeof(text[0]); i++)
-  {
-  draw(context);
+  DrawingContext context;
+
+  bool show_grid_t = show_grid;
+  show_grid = false;
+  mouse_cursor->set_state(MC_HIDE);
+
+
+  char str[1024];
+  const char *text1[] = {
+           _("This is the built-in level editor. Its aim is to be intuitive\n"
+           "and simple to use, so it should be pretty straightforward.\n"
+           "\n"
+           "To open a level, first you'll have to select a level subset from\n"
+           "the menu (or create your own).\n"
+           "A level subset is basically a collection of levels.\n"
+           "They can then be played from the Contrib menu.\n"
+           "\n"
+           "To access the menu from the level editor, just press Esc.\n"
+           "\n"
+           "You are currently looking at the level. To scroll it, just\n"
+           "press the right mouse button and drag the mouse. It will move like\n"
+           "a strategy game.\n"
+           "You can also use the arrow keys and Page Up/Down.\n"
+           "\n"
+           "'+' and '-' keys can be used to zoom the level in/out.\n"
+           "\n"
+           "You probably already noticed those floating groups of buttons.\n"
+           "Each one serves a different purpose. To select a certain button\n"
+           "just press the Left mouse button on it. A few buttons have key\n"
+           "shortcuts. You can find them by pressing the Right mouse button on\n"
+           "a button. That will also show what that button does.\n"
+           "Groups of buttons can also be moved around by just dragging them,\n"
+           "while pressing the Left mouse button.\n"
+           "\n"
+           "Let's learn a bit of what each group of buttons does, shall we?\n"
+           "\n"
+           "To starting putting tiles and objects around use the bigger group\n"
+           "of buttons. Each button is a different tile. To put it on the level,\n"
+           "just press it and then left click in the level.\n"
+           "You can also copy tiles from the level by using the middle mouse button.\n"
+           "Use the mouse wheel to scroll that group of buttons. You will find\n"
+           "enemies and game objects in the bottom.\n")
+                  };
+
+  const char *text2[] = {
+           _("The Foreground/Interactive/Background buttons may be used to\n"
+           "see and edit the respective layer. Levels have three tiles layers:\n"
+           "Foreground - tiles are drawn on top of everything and have no contact\n"
+           "with the player.\n"
+           "Interactive - these are the tiles that have contact with the player.\n"
+           "Background - tiles are drawn underneath everything and have no contact\n"
+           "with the player.\n"
+           "The unselected layers will be drawn semi-transparently.\n"
+           "\n"
+           "Last, but not least, the group of buttons that's left serves\n"
+           "to do related actions with the level.\n"
+           "From left to right:\n"
+           "Mini arrows - can be used to choose other sectors.\n"
+           "Sectors are mini-levels, so to speak, that can be accessed using a door.\n"
+           "Big arrows - choose other level in the same level subset.\n"
+           "Diskette - save the level\n"
+           "Tux - test the level\n"
+           "Tools - set a few settings for the level, including resizing it.\n"
+           "\n"
+           "We have reached the end of this Howto.\n"
+           "\n"
+           "Don't forget to send us a few cool levels. :)\n"
+           "\n"
+           "Enjoy,\n"
+           "  SuperTux development team\n"
+           "\n"
+           "PS: If you are looking for something more powerful, you might like to\n"
+           "try FlexLay. FlexLay is a level editor that supports several games,\n"
+           "including SuperTux. It is an independent project.\n"
+           "Webpage: http://pingus.seul.org/~grumbel/flexlay/")
+                  };
+
+  const char **text[] = { text1, text2 };
+
+
+  bool done;
+  for(unsigned int i = 0; i < sizeof(text) / sizeof(text[0]); i++)
+    {
+    draw(context);
 
-  context.draw_text(blue_text, _("- Level Editor's Help -"), Vector(screen->w/2, 60), CENTER_ALLIGN, LAYER_GUI);
+    context.draw_text(blue_text, _("- Level Editor's Help -"), Vector(screen->w/2, 60), CENTER_ALLIGN, LAYER_GUI);
 
-  context.draw_text(white_small_text, *text[i], Vector(20, 120), LEFT_ALLIGN, LAYER_GUI);
+    context.draw_text(white_small_text, *text[i], Vector(20, 120), LEFT_ALLIGN, LAYER_GUI);
 
-  sprintf(str,_("Press any key to continue - Page %d/%d"), i+1, sizeof(text) / sizeof(text[0]));
-  context.draw_text(gold_text, str, Vector(screen->w/2, screen->h-60), CENTER_ALLIGN, LAYER_GUI);
+    sprintf(str,_("Press any key to continue - Page %d/%d"), i+1, sizeof(text) / sizeof(text[0]));
+    context.draw_text(gold_text, str, Vector(screen->w/2, screen->h-60), CENTER_ALLIGN, LAYER_GUI);
 
-  context.do_drawing();
+    context.do_drawing();
 
-  done = false;
+    done = false;
 
-  while(!done)
-    {
-    done = wait_for_event(event);
-    SDL_Delay(50);
+    while(!done) {
+      SDL_Event event;
+      done = wait_for_event(event);
+      SDL_Delay(50);
     }
   }
 
-show_grid = show_grid_t;
-mouse_cursor->set_state(MC_NORMAL);
+  show_grid = show_grid_t;
+  mouse_cursor->set_state(MC_NORMAL);
 }
 
 Sector*
index 5fef880..912f8ea 100644 (file)
@@ -18,8 +18,6 @@
 #ifndef SUPERTUX_LEVELEDITOR_H
 #define SUPERTUX_LEVELEDITOR_H
 
-#include "SDL.h"
-
 #include <set>
 #include <string>
 
@@ -91,8 +89,7 @@ private:
   void load_level_subset(std::string filename);
   void load_level(std::string filename);
   void load_level(int nb);
-  void load_sector(std::string name);
-  void load_sector(Sector* sector);
+  void load_sector(size_t num);
 
   void save_level();
   void test_level();
@@ -108,6 +105,7 @@ private:
   Level* level;
   std::string level_filename;
 
+  size_t sectornum; // number of current sector
   Sector* sector;  // current sector
   TileMap *solids, *foregrounds, *backgrounds;
   std::string sector_name;
@@ -122,13 +120,13 @@ private:
   Menu* settings_menu;
 
   bool left_button, middle_button, mouse_moved;
+  int mouse_x, mouse_y;
   bool done;
   bool show_grid;
 
   Vector scroll;
   float zoom;
 
-  SDL_Event event;
   Timer2 level_name_timer;
 
   Surface *img_background_bt, *img_foreground_bt, *img_interactive_bt;
index 0bc3ca1..dd849b4 100644 (file)
@@ -25,6 +25,8 @@
 #include "special/game_object.h"
 #include "serializable.h"
 
+using namespace SuperTux;
+
 class DisplayManager;
 
 namespace lisp {
index b3c6fcc..3bd3209 100644 (file)
@@ -13,6 +13,7 @@
 #include "flower.h"
 #include "oneup.h"
 #include "star.h"
+#include "player_status.h"
 #include "badguy/badguy.h"
 #include "coin.h"
 #include "object_factory.h"
@@ -25,7 +26,7 @@ Block::Block(const Vector& pos, Sprite* newsprite)
   : sprite(newsprite), bouncing(false), bounce_dir(0), bounce_offset(0)
 {
   bbox.set_pos(pos);
-  bbox.set_size(32, 32);
+  bbox.set_size(32, 32.1);
   flags |= FLAG_SOLID;
   original_y = pos.y;
 }
@@ -88,6 +89,7 @@ Block::draw(DrawingContext& context)
 void
 Block::start_bounce()
 {
+  original_y = bbox.p1.y;
   bouncing = true;
   bounce_dir = -BOUNCY_BRICK_SPEED;
   bounce_offset = 0;
index bceed3c..e80491a 100644 (file)
@@ -2,7 +2,6 @@
 
 #include <math.h>
 #include "bullet.h"
-#include "defines.h"
 #include "resources.h"
 #include "camera.h"
 #include "sector.h"
index 246207f..1b60386 100644 (file)
@@ -178,7 +178,7 @@ Camera::scroll_normal(float elapsed_time)
   /****** Vertical Scrolling part ******/
   bool do_y_scrolling = true;
 
-  if(player->dying || sector->solids->get_height() == 19)
+  if(player->is_dying() || sector->solids->get_height() == 19)
     do_y_scrolling = false;
 
   if(do_y_scrolling) {
@@ -260,7 +260,7 @@ Camera::scroll_autoscroll(float elapsed_time)
 {
   Player* player = sector->player;
   
-  if(player->dying)
+  if(player->is_dying())
     return;
 
   if(auto_t - elapsed_time >= 0) {
index 45351b6..028671a 100644 (file)
@@ -23,7 +23,6 @@
 #include <vector>
 #include <cassert>
 
-#include "defines.h"
 #include "math/vector.h"
 #include "special/game_object.h"
 #include "video/drawing_context.h"
index c091018..c9b38ba 100644 (file)
@@ -6,7 +6,7 @@
 #include "special/sprite_manager.h"
 #include "player.h"
 #include "sector.h"
-#include "scene.h"
+#include "player_status.h"
 #include "gameobjs.h"
 #include "statistics.h"
 #include "object_factory.h"
index 435be07..d480555 100644 (file)
@@ -2,7 +2,6 @@
 
 #include <math.h>
 #include "flower.h"
-#include "defines.h"
 #include "resources.h"
 #include "camera.h"
 #include "sector.h"
index 6b884d7..d5c9583 100644 (file)
@@ -23,7 +23,6 @@
 
 #include "video/surface.h"
 #include "timer.h"
-#include "scene.h"
 #include "math/physic.h"
 #include "special/game_object.h"
 #include "special/moving_object.h"
index deaaff1..4ed6e72 100644 (file)
@@ -2,7 +2,6 @@
 
 #include <math.h>
 #include "growup.h"
-#include "defines.h"
 #include "resources.h"
 #include "camera.h"
 #include "sector.h"
index a576bcf..324f838 100644 (file)
@@ -3,7 +3,7 @@
 #include "oneup.h"
 #include "resources.h"
 #include "player.h"
-#include "scene.h"
+#include "player_status.h"
 #include "sector.h"
 #include "special/sprite_manager.h"
 #include "video/drawing_context.h"
index ec97165..93fd5c4 100644 (file)
@@ -27,9 +27,8 @@
 #include "app/gettext.h"
 #include "special/sprite_manager.h"
 #include "player.h"
-#include "defines.h"
-#include "scene.h"
 #include "tile.h"
+#include "player_status.h"
 #include "special/sprite.h"
 #include "sector.h"
 #include "resources.h"
@@ -79,18 +78,24 @@ PlayerKeymap::PlayerKeymap()
   keymap.jump  = SDLK_SPACE;
 }
 
-void player_input_init(player_input_type* pplayer_input)
+PlayerInputType::PlayerInputType()
 {
-  pplayer_input->up = UP;
-  pplayer_input->old_up = UP;
-  pplayer_input->down = UP;
-  pplayer_input->fire = UP;
-  pplayer_input->left = UP;
-  pplayer_input->old_fire = UP;
-  pplayer_input->right = UP;
-  pplayer_input->jump = UP;
-  pplayer_input->old_jump = UP;
-  pplayer_input->activate = UP;
+  reset();
+}
+
+void
+PlayerInputType::reset()
+{
+  up = false;
+  old_up = false;
+  down = false;
+  fire = false;
+  old_fire = false;
+  left = false;
+  right = false;
+  jump = false;
+  old_jump = false;
+  activate = false;
 }
 
 void
@@ -149,7 +154,7 @@ Player::init()
   duck = false;
   dead = false;
 
-  dying   = DYING_NOT;
+  dying = false;
   last_ground_y = 0;
   fall_mode = ON_GROUND;
   jumping = false;
@@ -171,13 +176,12 @@ Player::init()
   on_ground_flag = false;
   grabbed_object = 0;
 
-  player_input_init(&input);
-
+  input.reset();
   physic.reset();
 }
 
-int
-Player::key_event(SDLKey key, int state)
+bool
+Player::key_event(SDLKey key, bool state)
 {
   idle_timer.start(IDLE_TIME, true);
 
@@ -193,8 +197,8 @@ Player::key_event(SDLKey key, int state)
     }
   else if(key == keymap.up)
     {
-      if(state == UP)
-        input.old_up = UP;
+      if(state == false)
+        input.old_up = false;
       input.up = state;
       /* Up key also opens activates stuff */
       input.activate = state;
@@ -207,16 +211,16 @@ Player::key_event(SDLKey key, int state)
     }
   else if(key == keymap.power)
     {
-      if (state == UP)
-        input.old_fire = UP;
+      if(state == false)
+        input.old_fire = false;
       input.fire = state;
 
       return true;
     }
   else if(key == keymap.jump)
     {
-      if (state == UP)
-        input.old_jump = UP;
+      if(state == false)
+        input.old_jump = false;
       input.jump = state;
       return true;
     }
@@ -230,9 +234,9 @@ Player::level_begin()
   move(Vector(100, 170));
   duck = false;
 
-  dying = DYING_NOT;
+  dying = false;
 
-  player_input_init(&input);
+  input.reset();
 
   on_ground_flag = false;
 
@@ -253,11 +257,11 @@ Player::action(float elapsed_time)
     return;
   }
 
-  if(input.fire == UP)
+  if(input.fire == false)
     grabbed_object = 0;
 
 
-  if(dying == DYING_NOT)
+  if(!dying)
     handle_input();
 
   movement = physic.get_movement(elapsed_time);
@@ -296,36 +300,38 @@ Player::handle_horizontal_input()
   float ay = physic.get_acceleration_y();
 
   float dirsign = 0;
-  if(input.left == DOWN && input.right == UP && (!duck || physic.get_velocity_y() != 0)) {
+  if(!duck || physic.get_velocity_y() != 0) {
+    if(input.left && !input.right) {
       old_dir = dir;
       dir = LEFT;
       dirsign = -1;
-  } else if(input.left == UP && input.right == DOWN && (!duck || physic.get_velocity_y() != 0)) {
+    } else if(!input.left && input.right) {
       old_dir = dir;
       dir = RIGHT;
       dirsign = 1;
+    }
   }
 
-  if (input.fire == UP) {
-      ax = dirsign * WALK_ACCELERATION_X;
-      // limit speed
-      if(vx >= MAX_WALK_XM && dirsign > 0) {
-        vx = MAX_WALK_XM;
-        ax = 0;
-      } else if(vx <= -MAX_WALK_XM && dirsign < 0) {
-        vx = -MAX_WALK_XM;
-        ax = 0;
-      }
+  if (!input.fire) {
+    ax = dirsign * WALK_ACCELERATION_X;
+    // limit speed
+    if(vx >= MAX_WALK_XM && dirsign > 0) {
+      vx = MAX_WALK_XM;
+      ax = 0;
+    } else if(vx <= -MAX_WALK_XM && dirsign < 0) {
+      vx = -MAX_WALK_XM;
+      ax = 0;
+    }
   } else {
-      ax = dirsign * RUN_ACCELERATION_X;
-      // limit speed
-      if(vx >= MAX_RUN_XM && dirsign > 0) {
-        vx = MAX_RUN_XM;
-        ax = 0;
-      } else if(vx <= -MAX_RUN_XM && dirsign < 0) {
-        vx = -MAX_RUN_XM;
-        ax = 0;
-      }
+    ax = dirsign * RUN_ACCELERATION_X;
+    // limit speed
+    if(vx >= MAX_RUN_XM && dirsign > 0) {
+      vx = MAX_RUN_XM;
+      ax = 0;
+    } else if(vx <= -MAX_RUN_XM && dirsign < 0) {
+      vx = -MAX_RUN_XM;
+      ax = 0;
+    }
   }
 
   // we can reach WALK_SPEED without any acceleration
@@ -419,7 +425,7 @@ Player::handle_vertical_input()
   }
 
   // Press jump key
-  if(input.jump == DOWN && can_jump && on_ground())
+  if(input.jump && can_jump && on_ground())
     {
       if(duck) { // only jump a little bit when in duck mode {
         physic.set_velocity_y(300);
@@ -443,7 +449,7 @@ Player::handle_vertical_input()
         SoundManager::get()->play_sound(IDToSound(SND_BIGJUMP));
     }
   // Let go of jump key
-  else if(input.jump == UP)
+  else if(!input.jump)
     {
       if (!flapping && !duck && !falling_from_flap && !on_ground())
          {
@@ -461,8 +467,7 @@ Player::handle_vertical_input()
    {
    // Flapping, Ricardo's version
    // similar to SM3 Fox
-   if(input.jump == DOWN && input.old_jump == UP && can_flap &&
-     flaps_nb < 3)
+   if(input.jump && !input.old_jump && can_flap && flaps_nb < 3)
      {
        physic.set_velocity_y(350);
        physic.set_velocity_x(physic.get_velocity_x() * 35);
@@ -472,7 +477,7 @@ Player::handle_vertical_input()
   else if(flapping_mode == MAREK_FLAP)
    {
    // Flapping, Marek's version
-   if (input.jump == DOWN && can_flap)
+   if (input.jump && can_flap)
      {
          if (!flapping_timer.started())
             {
@@ -504,7 +509,7 @@ Player::handle_vertical_input()
   else if(flapping_mode == RYAN_FLAP)
    {
    // Flapping, Ryan's version
-   if (input.jump == DOWN && can_flap)
+   if (input.jump && can_flap)
      {
          if (!flapping_timer.started())
             {
@@ -549,13 +554,13 @@ Player::handle_vertical_input()
 #if 0
    /* In case the player has pressed Down while in a certain range of air,
       enable butt jump action */
-  if (input.down == DOWN && !butt_jump && !duck)
+  if (input.down && !butt_jump && !duck)
     if(tiles_on_air(TILES_FOR_BUTTJUMP) && jumping)
       butt_jump = true;
 #endif
 
    /* When Down is not held anymore, disable butt jump */
-  if(butt_jump && input.down == UP)
+  if(butt_jump && !input.down)
     butt_jump = false;
 
   // Do butt jump
@@ -617,13 +622,14 @@ Player::handle_vertical_input()
           get_pos().y + bbox.get_height() + 64))
        && jumping  == false
        && can_jump == false
-       && input.jump == DOWN
-       && input.old_jump == UP)
+       && input.jump && !input.old_jump)
     {
       can_jump = true;
     }
 #endif
 
+  // FIXME: why the heck is this here and not somewhere where the keys are
+  // checked?!?
   input.old_jump = input.jump;
 }
 
@@ -634,30 +640,31 @@ Player::handle_input()
   handle_horizontal_input();
 
   /* Jump/jumping? */
-  if (on_ground() && input.jump == UP)
+  if (on_ground() && !input.jump)
     can_jump = true;
   handle_vertical_input();
 
   /* Shoot! */
-  if (input.fire == DOWN && input.old_fire == UP && got_power != NONE_POWER) {
+  if (input.fire && !input.old_fire && got_power != NONE_POWER) {
     if(Sector::current()->add_bullet(
 //           get_pos() + Vector(0, bbox.get_height()/2),
           get_pos() + ((dir == LEFT)? Vector(0, bbox.get_height()/2) 
           : Vector(32, bbox.get_height()/2)),
           physic.get_velocity_x(), dir))
       shooting_timer.start(SHOOTING_TIME);
-    input.old_fire = DOWN;
+    // FIXME: why the heck is this here
+    input.old_fire = false;
   }
 
   /* Duck! */
-  if (input.down == DOWN && size == BIG && !duck 
+  if (input.down && size == BIG && !duck 
       && physic.get_velocity_y() == 0 && on_ground())
     {
       duck = true;
       bbox.move(Vector(0, 32));
       bbox.set_height(31.8);
     }
-  else if(input.down == UP && size == BIG && duck)
+  else if(!input.down && size == BIG && duck)
     {
       // try if we can really unduck
       bbox.move(Vector(0, -32));
@@ -794,8 +801,8 @@ Player::draw(DrawingContext& context)
     }
 
   /* Draw Tux */
-  if (dying == DYING_SQUISHED) {
-    smalltux_gameover->draw(context, get_pos(), LAYER_FOREGROUNDTILES+1);
+  if(dying) {
+    smalltux_gameover->draw(context, get_pos(), layer);
   } else if(growing_timer.get_timeleft() > 0) {
     if(size == SMALL)
       {
@@ -848,7 +855,7 @@ HitResponse
 Player::collision(GameObject& other, const CollisionHit& hit)
 {
   Portable* portable = dynamic_cast<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;
@@ -872,7 +879,7 @@ Player::collision(GameObject& other, const CollisionHit& hit)
 
   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);
   }
 
@@ -923,7 +930,7 @@ Player::kill(HurtMode mode)
       physic.set_acceleration(0, 0);
       physic.set_velocity(0, 700);
       --player_status.lives;
-      dying = DYING_SQUISHED;
+      dying = true;
       dying_timer.start(3.0);
       flags |= FLAG_NO_COLLDET;
     }
index 0a179a4..91e14b5 100644 (file)
 #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;
 
@@ -61,28 +61,33 @@ public:
 
 extern PlayerKeymap keymap;
 
-struct player_input_type
+/** Contains a field of booleans that indicate wheter a button is pressed or
+ * released. The old_ fields contain the state of the button at the previous
+ * frame.
+ */
+struct PlayerInputType
 {
-  int right;
-  int left;
-  int up;
-  int old_up;
-  int down;
-  int fire;
-  int old_fire;
-  int activate;
-  int jump;
-  int old_jump;
+public:
+  PlayerInputType();
+  void reset();
+
+  bool left;
+  bool right;
+  bool up;
+  bool old_up;
+  bool down;
+  bool fire;
+  bool old_fire;
+  bool activate;
+  bool jump;
+  bool old_jump;
 };
 
-void player_input_init(player_input_type* pplayer_input);
-
 class Camera;
 class PlayerStatus;
 
 extern Surface* tux_life;
 
-
 #define GROWING_TIME 1.0
 #define GROWING_FRAMES 7
 extern Surface* growingtux_left[GROWING_FRAMES];
@@ -124,12 +129,15 @@ public:
   enum Power { NONE_POWER, FIRE_POWER, ICE_POWER };
   enum FallMode { ON_GROUND, JUMPING, TRAMPOLINE_JUMP, FALLING };
 
-  player_input_type  input;
+  PlayerInputType input;
   int got_power;
   int size;
   bool duck;
   bool dead;
-  DyingType dying;
+
+private:
+  bool dying;
+public:
 
   Direction dir;
   Direction old_dir;
@@ -170,7 +178,7 @@ public:
   Player();
   virtual ~Player();
   
-  int  key_event(SDLKey key, int state);
+  bool key_event(SDLKey key, bool state);
   void level_begin();
   void handle_input();
 
@@ -183,7 +191,11 @@ public:
   void make_invincible();
   bool is_invincible() const
   {
-      return invincible_timer.started();
+    return invincible_timer.started();
+  }
+  bool is_dying() const
+  {
+    return dying;
   }
   
   void kill(HurtMode mode);
index 8d84f6a..af0440e 100644 (file)
@@ -2,7 +2,6 @@
 
 #include <math.h>
 #include "specialriser.h"
-#include "defines.h"
 #include "resources.h"
 #include "camera.h"
 #include "sector.h"
index 522c08a..8bf4a4d 100644 (file)
@@ -3,7 +3,7 @@
 #include "star.h"
 #include "resources.h"
 #include "player.h"
-#include "scene.h"
+#include "player_status.h"
 #include "special/sprite_manager.h"
 #include "video/drawing_context.h"
 
index fb0cb63..59557d1 100644 (file)
@@ -37,7 +37,7 @@
 
 TileMap::TileMap()
   : solid(false), speed(1), width(0), height(0), layer(LAYER_TILES),
-    vertical_flip(false)
+    drawing_effect(0)
 {
   tilemanager = tile_manager;
 
@@ -47,7 +47,7 @@ TileMap::TileMap()
 
 TileMap::TileMap(const lisp::Lisp& reader)
   : solid(false), speed(1), width(0), height(0), layer(LAYER_TILES),
-    vertical_flip(false)
+    drawing_effect(0)
 {
   tilemanager = tile_manager;
 
@@ -87,7 +87,7 @@ TileMap::TileMap(const lisp::Lisp& reader)
 
 TileMap::TileMap(int layer_, bool solid_, size_t width_, size_t height_)
   : solid(solid_), speed(1), width(0), height(0), layer(layer_),
-    vertical_flip(false)
+    drawing_effect(0)
 {
   tilemanager = tile_manager;
   
@@ -136,8 +136,8 @@ TileMap::draw(DrawingContext& context)
 {
   context.push_transform();
 
-  if(vertical_flip)
-    context.set_drawing_effect(VERTICAL_FLIP); 
+  if(drawing_effect != 0)
+    context.set_drawing_effect(drawing_effect); 
   float trans_x = roundf(context.get_translation().x);
   float trans_y = roundf(context.get_translation().y);
   context.set_translation(Vector(trans_x * speed, trans_y * speed));
@@ -234,19 +234,6 @@ TileMap::resize(int new_width, int new_height)
   width = new_width;
 }
 
-void
-TileMap::do_vertical_flip()
-{
-  // remap tiles vertically flipped
-  for(int y = 0; y < height / 2; ++y) {
-    for(int x = 0; x < width; ++x) {
-      std::swap(tiles[y*width + x], tiles[(((height-1)*width) - (y*width)) + x]);
-    }
-  }
-
-  vertical_flip = true;
-}
-
 const Tile*
 TileMap::get_tile(int x, int y) const
 {
index ecf8d10..2c1960a 100644 (file)
@@ -61,10 +61,6 @@ public:
    */
   void resize(int newwidth, int newheight);
 
-  /** Flip the all tile map vertically. The purpose of this is to let
-      player to play the same level in a different way :) */
-  void do_vertical_flip();
-
   size_t get_width() const
   { return width; }
 
@@ -86,6 +82,16 @@ public:
 
   void change_at(const Vector& pos, uint32_t newtile);
 
+  TileManager* get_tilemanager() const
+  {
+    return tilemanager;
+  }
+
+  void set_drawing_effect(int effect)
+  {
+    drawing_effect = effect;
+  }
+
 private:
   std::vector<uint32_t> tiles;
   
@@ -96,7 +102,7 @@ private:
   int width, height;
   int layer;
 
-  bool vertical_flip;
+  int drawing_effect;
 };
 
 #endif /*SUPERTUX_TILEMAP_H*/
index c9a57e0..7ff6028 100644 (file)
@@ -31,6 +31,9 @@ using namespace SuperTux;
 class Factory
 {
 public:
+  virtual ~Factory()
+  { }
+    
   /** Creates a new gameobject from a lisp node.
    * Remember to delete the objects later
    */
diff --git a/src/player_status.cpp b/src/player_status.cpp
new file mode 100644 (file)
index 0000000..ba8b633
--- /dev/null
@@ -0,0 +1,114 @@
+//  $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);
+}
+
diff --git a/src/player_status.h b/src/player_status.h
new file mode 100644 (file)
index 0000000..760ae92
--- /dev/null
@@ -0,0 +1,53 @@
+//  $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
index fc8c038..f2c3c0a 100644 (file)
@@ -24,7 +24,6 @@
 #include "app/setup.h"
 #include "gui/menu.h"
 #include "gui/button.h"
-#include "scene.h"
 #include "resources.h"
 #include "tile_manager.h"
 #include "object/gameobjs.h"
diff --git a/src/scene.cpp b/src/scene.cpp
deleted file mode 100644 (file)
index 429abd0..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-//  $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 //
-
diff --git a/src/scene.h b/src/scene.h
deleted file mode 100644 (file)
index b8d5596..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-//  $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*/
index 655eb22..4037f35 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "app/globals.h"
 #include "sector.h"
+#include "player_status.h"
 #include "object/gameobjs.h"
 #include "object/camera.h"
 #include "object/background.h"
@@ -56,6 +57,8 @@
 #include "badguy/spike.h"
 #include "trigger/sequence_trigger.h"
 
+//#define USE_GRID
+
 Sector* Sector::_current = 0;
 
 Sector::Sector()
@@ -694,7 +697,7 @@ Sector::collision_object(MovingObject* object1, MovingObject* object2)
 void
 Sector::collision_handler()
 {
-#if 0
+#ifdef USE_GRID
   grid->check_collisions();
 #else
   for(std::vector<GameObject*>::iterator i = gameobjects.begin();
@@ -738,6 +741,10 @@ Sector::collision_handler()
 bool
 Sector::add_bullet(const Vector& pos, float xm, Direction dir)
 {
+  // TODO remove this function and move these checks elsewhere...
+  static const size_t MAX_FIRE_BULLETS = 2;
+  static const size_t MAX_ICE_BULLETS = 1;
+    
   if(player->got_power == Player::FIRE_POWER) {
     if(bullets.size() > MAX_FIRE_BULLETS-1)
       return false;
@@ -826,14 +833,13 @@ int
 Sector::get_total_badguys()
 {
   int total_badguys = 0;
-#if 0
-  for(GameObjects::iterator i = gameobjects_new.begin(); i != gameobjects_new.end(); ++i)
-    {
+  for(GameObjects::iterator i = gameobjects.begin();
+      i != gameobjects.end(); ++i) {
     BadGuy* badguy = dynamic_cast<BadGuy*> (*i);
     if(badguy)
       total_badguys++;
-    }
-#endif
+  }
+
   return total_badguys;
 }
 
index 5f31dc9..39b13bc 100644 (file)
 #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;
 
@@ -46,8 +46,9 @@ class TileMap;
 class Bullet;
 class CollisionGrid;
 
-struct SpawnPoint
+class SpawnPoint
 {
+public:
   std::string name;
   Vector pos;
 };
@@ -100,7 +101,7 @@ public:
   bool add_smoke_cloud(const Vector& pos);
   void add_floating_text(const Vector& pos, const std::string& text);
                                                                                 
-  /** @evil@ but can#t always be avoided in current design... */
+  /** @evil@ but can't always be avoided in current design... */
   static Sector* current()
   { return _current; }
 
@@ -138,6 +139,8 @@ private:
 public: // TODO make this private again
   typedef std::vector<GameObject*> GameObjects;
   GameObjects gameobjects;
+  typedef std::vector<SpawnPoint*> SpawnPoints;
+  SpawnPoints spawnpoints;                       
 
   Rectangle get_active_region();
 
@@ -147,9 +150,6 @@ private:
   /// container for newly created objects, they'll be added in Sector::action
   GameObjects gameobjects_new;
   
-  typedef std::vector<SpawnPoint*> SpawnPoints;
-  SpawnPoints spawnpoints;
-
   int currentmusic;
 
   CollisionGrid* grid;
index 3fc7020..06a8234 100644 (file)
@@ -19,8 +19,6 @@
 #ifndef SUPERTUX_SERIALIZABLE_H
 #define SUPERTUX_SERIALIZABLE_H
 
-using namespace SuperTux;
-
 namespace lisp {
 class Writer;
 }
@@ -28,6 +26,9 @@ class Writer;
 class Serializable
 {
 public:
+  virtual ~Serializable()
+  { }
+    
   virtual void write(lisp::Writer& writer) = 0;
 };
 
index 81856f6..06cbbe7 100644 (file)
 #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"
index a57d304..0edef84 100644 (file)
@@ -27,8 +27,8 @@
 #include "app/globals.h"
 #include "lisp/lisp.h"
 #include "tile.h"
-#include "scene.h"
 #include "resources.h"
+#include "timer.h"
 #include "math/vector.h"
 #include "video/drawing_context.h"
 
index f2c95e0..e3a5b59 100644 (file)
@@ -31,7 +31,6 @@
 #include "tile.h"
 #include "tile_manager.h"
 #include "resources.h"
-#include "scene.h"
 
 TileManager::TileManager(const std::string& filename)
 {
index db8a70c..961e077 100644 (file)
@@ -81,6 +81,16 @@ public:
   {
     return tiles.size();
   }
+
+  int get_default_width() const
+  {
+    return 32;
+  }
+
+  int get_default_height() const
+  {
+    return 32;
+  }
 };
 
 #endif
index 3f0f3a5..514479d 100644 (file)
@@ -36,7 +36,6 @@
 #include <ctype.h>
 #endif
 
-#include "defines.h"
 #include "app/globals.h"
 #include "title.h"
 #include "video/screen.h"
@@ -52,7 +51,7 @@
 #include "gameloop.h"
 #include "worldmap.h"
 #include "leveleditor.h"
-#include "scene.h"
+#include "player_status.h"
 #include "tile.h"
 #include "sector.h"
 #include "object/tilemap.h"
@@ -246,16 +245,16 @@ void draw_demo(float elapsed_time)
 
   world->play_music(LEVEL_MUSIC);
   
-  tux->key_event((SDLKey) keymap.right,DOWN);
+  tux->key_event((SDLKey) keymap.right, true);
   
   if(random_timer.check()) {
     random_timer.start(float(rand() % 3000 + 3000) / 1000.);
     walking = !walking;
   } else {
       if(walking)
-        tux->key_event((SDLKey) keymap.jump,UP);
+        tux->key_event((SDLKey) keymap.jump, false);
       else
-        tux->key_event((SDLKey) keymap.jump,DOWN);
+        tux->key_event((SDLKey) keymap.jump, true);
   }
 
   // Wrap around at the end of the level back to the beginnig
index af67421..80a21d7 100644 (file)
@@ -43,7 +43,7 @@
 #include "worldmap.h"
 #include "resources.h"
 #include "misc.h"
-#include "scene.h"
+#include "player_status.h"
 
 #define map_message_TIME 2.8
 
@@ -1087,8 +1087,6 @@ WorldMap::savegame(const std::string& filename)
   if(filename == "")
     return;
 
-  std::cout << "savegame: " << filename << std::endl;
-
   std::ofstream file(filename.c_str(), std::ios::out);
   lisp::Writer writer(file);
 
@@ -1111,16 +1109,14 @@ WorldMap::savegame(const std::string& filename)
       std::string(name + " - " + nb_solved_levels_str+"/"+total_levels_str));
   writer.write_string("map", map_filename);
   writer.write_bool("intro-displayed", intro_displayed);
-  writer.write_int("lives", player_status.lives);
-  writer.write_int("distros", player_status.lives);
-  writer.write_int("max-score-multiplier", player_status.max_score_multiplier);
 
   writer.start_list("tux");
 
   writer.write_float("x", tux->get_tile_pos().x);
   writer.write_float("y", tux->get_tile_pos().y);
   writer.write_string("back", direction_to_string(tux->back_direction));
-  writer.write_string("bonus", bonus_to_string(player_status.bonus));
+  player_status.write(writer);
+  writer.write_string("back", direction_to_string(tux->back_direction));
 
   writer.end_list("tux");
 
@@ -1169,21 +1165,19 @@ WorldMap::loadgame(const std::string& filename)
     savegame->get("distros", player_status.distros);
     savegame->get("max-score-multiplier", player_status.max_score_multiplier);
     if (player_status.lives < 0)
-      player_status.lives = START_LIVES;
+      player_status.reset();
 
     const lisp::Lisp* tux_lisp = savegame->get_lisp("tux");
     if(tux)
     {
       Vector p;
       std::string back_str = "none";
-      std::string bonus_str = "none";
 
       tux_lisp->get("x", p.x);
       tux_lisp->get("y", p.y);
       tux_lisp->get("back", back_str);
-      tux_lisp->get("bonus", bonus_str);
+      player_status.read(*tux_lisp);
       
-      player_status.bonus = string_to_bonus(bonus_str);
       tux->back_direction = string_to_direction(back_str);      
       tux->set_tile_pos(p);
     }