implemented a new object factory mechanism which is now really independent of the...
authorMatthias Braun <matze@braunis.de>
Mon, 20 Dec 2004 21:24:28 +0000 (21:24 +0000)
committerMatthias Braun <matze@braunis.de>
Mon, 20 Dec 2004 21:24:28 +0000 (21:24 +0000)
SVN-Revision: 2262

34 files changed:
data/levels/world1/level3.stl
lib/lisp/parser.cpp
src/badguy/badguy.h
src/badguy/bomb.cpp
src/badguy/bouncing_snowball.cpp
src/badguy/dispenser.cpp
src/badguy/flame.cpp
src/badguy/flyingsnowball.cpp
src/badguy/jumpy.cpp
src/badguy/mrbomb.cpp
src/badguy/mriceblock.cpp
src/badguy/nolok_01.cpp
src/badguy/snowball.cpp
src/badguy/spike.cpp
src/badguy/spiky.cpp
src/gameobjs_bridge.cpp [deleted file]
src/gameobjs_bridge.h [deleted file]
src/leveleditor.cpp
src/misc.h
src/object/background.cpp
src/object/block.cpp
src/object/camera.cpp
src/object/coin.cpp
src/object/coin.h
src/object/invisible_block.cpp
src/object/platform.cpp
src/object/rock.cpp
src/object/tilemap.cpp
src/object_factory.cpp [new file with mode: 0644]
src/object_factory.h [new file with mode: 0644]
src/resources.cpp
src/sector.cpp
src/trigger/door.cpp
src/trigger/sequence_trigger.cpp

index 4eb2f3c..0fca345 100644 (file)
     (snowball  (x 10932) (y 408))
     (snowball  (x 9969) (y 410))
   )
-   )
-
+)
 
 ;; EOF ;;
index 875a4b2..08c5aa7 100644 (file)
@@ -119,8 +119,6 @@ Parser::read()
         result = new Lisp(Lisp::TYPE_STRING);
         if(dictionary) {
           std::string translation = dictionary->translate(lexer->getString());
-          std::cout << "Translated '" << lexer->getString() << "' -> '" 
-            << translation << "'\n";
           result->v.string = new char[translation.size()+1];
           memcpy(result->v.string, translation.c_str(), translation.size()+1);
         } else {
index cddb825..075b025 100644 (file)
@@ -11,6 +11,7 @@
 #include "serializable.h"
 #include "resources.h"
 #include "sector.h"
+#include "object_factory.h"
 #include "lisp/parser.h"
 #include "lisp/lisp.h"
 #include "lisp/writer.h"
index 66e8348..9495abc 100644 (file)
@@ -74,3 +74,4 @@ void
 Bomb::kill_fall()
 {
 }
+
index 912e523..edbe4d7 100644 (file)
@@ -81,3 +81,5 @@ BouncingSnowball::collision_badguy(BadGuy& , const CollisionHit& hit)
   return CONTINUE;
 }
 
+IMPLEMENT_FACTORY(BouncingSnowball, "bouncingsnowball")
+
index f3445b3..0a92074 100644 (file)
@@ -92,3 +92,4 @@ Dispenser::launch_badguy()
   }
 }
 
+IMPLEMENT_FACTORY(Dispenser, "dispenser")
index 853ca5e..e9d7f49 100644 (file)
@@ -42,3 +42,5 @@ Flame::kill_fall()
 {
 }
 
+IMPLEMENT_FACTORY(Flame, "flame")
+
index e07179a..94caec9 100644 (file)
@@ -80,3 +80,4 @@ FlyingSnowBall::active_action(float elapsed_time)
   sprite->set_action(dir == LEFT ? "left" : "right");
 }
 
+IMPLEMENT_FACTORY(FlyingSnowBall, "flyingsnowball")
index 779d81e..4d32164 100644 (file)
@@ -58,3 +58,5 @@ Jumpy::active_action(float elapsed_time)
     //FIXME: add middle and up here
   sprite->set_action(dir == LEFT ? "left-down" : "right-down");
 }
+
+IMPLEMENT_FACTORY(Jumpy, "jumpy")
index 2152842..5b63955 100644 (file)
@@ -77,3 +77,5 @@ MrBomb::collision_badguy(BadGuy& , const CollisionHit& hit)
 
   return CONTINUE;
 }
+
+IMPLEMENT_FACTORY(MrBomb, "mrbomb")
index 6a76d69..4e1b174 100644 (file)
@@ -165,3 +165,4 @@ MrIceBlock::collision_squished(Player& player)
   return true;
 }
 
+IMPLEMENT_FACTORY(MrIceBlock, "mriceblock")
index 1a5768f..f5a1c94 100644 (file)
@@ -106,3 +106,4 @@ Nolok_01::collision_solid(GameObject& , const CollisionHit& hit)
   return CONTINUE;
 }
 
+IMPLEMENT_FACTORY(Nolok_01, "nolok01")
index 75f68b4..5f65eaa 100644 (file)
@@ -76,3 +76,4 @@ SnowBall::collision_badguy(BadGuy& , const CollisionHit& hit)
   return CONTINUE;
 }
 
+IMPLEMENT_FACTORY(SnowBall, "snowball")
index bc31450..5d046ee 100644 (file)
@@ -62,3 +62,5 @@ void
 Spike::active_action(float )
 {
 }
+
+IMPLEMENT_FACTORY(Spike, "spike")
index 49d7e4c..a4007b7 100644 (file)
@@ -56,3 +56,4 @@ Spiky::collision_badguy(BadGuy& , const CollisionHit& hit)
   return CONTINUE;
 }
 
+IMPLEMENT_FACTORY(Spiky, "spiky")
diff --git a/src/gameobjs_bridge.cpp b/src/gameobjs_bridge.cpp
deleted file mode 100644 (file)
index c94076c..0000000
+++ /dev/null
@@ -1,231 +0,0 @@
-/***************************************************************************
-                          gameobjs_bridge.cpp  -  description
-                             -------------------
-    begin                : Dec, 19 2004
-    copyright            : (C) 2004 by Ricardo Cruz
-    email                : rick2@aeiou.pt
- ***************************************************************************/
-
-/***************************************************************************
- *                                                                         *
- *   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.                                   *
- *                                                                         *
- ***************************************************************************/
-
-#include "gameobjs_bridge.h"
-
-#include "object/coin.h"
-#include "object/block.h"
-#include "object/invisible_block.h"
-#include "object/platform.h"
-#include "object/bullet.h"
-#include "object/rock.h"
-#include "badguy/jumpy.h"
-#include "badguy/snowball.h"
-#include "badguy/bouncing_snowball.h"
-#include "badguy/flame.h"
-#include "badguy/flyingsnowball.h"
-#include "badguy/mriceblock.h"
-#include "badguy/mrbomb.h"
-#include "badguy/dispenser.h"
-#include "badguy/spike.h"
-#include "badguy/spiky.h"
-#include "badguy/nolok_01.h"
-#include "trigger/door.h"
-#include "trigger/sequence_trigger.h"
-#include "trigger/secretarea_trigger.h"
-
-std::string object_type_to_string(int kind)
-{
-switch(kind)
-  {
-  // Game Objects
-  case COIN_OBJECT:
-    return "coin";
-  case INVISIBLE_BLOCK_OBJECT:
-    return "invisible-block";
-  case PLATFORM_OBJECT:
-    return "platform";
-  case ROCK_OBJECT:
-    return "rock";
-  // Bad Guys
-  case JUMPY_BADGUY:
-    return "jumpy";
-  case SNOWBALL_BADGUY:
-    return "snowball";
-  case BOUNCING_SNOWBALL_BADGUY:
-    return "bouncingsnowball";
-  case FLAME_BADGUY:
-    return "flame";
-  case FLYING_SNOWBALL_BADGUY:
-    return "flyingsnowball";
-  case MRICEBLOCK_BADGUY:
-    return "mriceblock";
-  case MRBOMB_BADGUY:
-    return "mrbomb";
-  case DISPENSER_BADGUY:
-    return "dispenser";
-  case SPIKE_BADGUY:
-    return "spike";
-  case SPIKY_BADGUY:
-    return "spiky";
-  case NOLOK_01_BADGUY:
-    return "nolok_01";
-  // Triggers
-  case DOOR_TRIGGER:
-    return "door";
-  default:
-    std::cerr << "Warning: object not recognized.\n";
-    return "";  // should not happen
-  }
-return "";  // avoids warnings
-}
-
-GameObjectsType object_name_to_type(const std::string& name)
-{
-// Game Objects
-if(name == "coin")
-  return COIN_OBJECT;
-else if(name == "invisible-block")
-  return INVISIBLE_BLOCK_OBJECT;
-else if(name == "platform")
-  return PLATFORM_OBJECT;
-else if(name == "rock")
-  return ROCK_OBJECT;
-// Bad Guys
-else if(name == "jumpy")
-  return JUMPY_BADGUY;
-else if(name == "snowball")
-  return SNOWBALL_BADGUY;
-else if(name == "bouncingsnowball")
-  return BOUNCING_SNOWBALL_BADGUY;
-else if(name == "flame")
-  return FLAME_BADGUY;
-else if(name == "flyingsnowball")
-  return FLYING_SNOWBALL_BADGUY;
-else if(name == "mriceblock")
-  return MRICEBLOCK_BADGUY;
-else if(name == "mrbomb")
-  return MRBOMB_BADGUY;
-else if(name == "dispenser")
-  return DISPENSER_BADGUY;
-else if(name == "spike")
-  return SPIKE_BADGUY;
-else if(name == "spiky")
-  return SPIKY_BADGUY;
-else if(name == "nolok_01")
-  return NOLOK_01_BADGUY;
-// Triggers
-else if(name == "door")
-  return DOOR_TRIGGER;
-
-// Object not recognized
-return NOT_RECOGNIZED_GAMEOBJECT;
-}
-
-bool is_object(const std::string& name)
-{
-if(object_name_to_type(name) == NOT_RECOGNIZED_GAMEOBJECT)
-  return false;
-return true;
-}
-
-GameObject* create_object(GameObjectsType kind, const lisp::Lisp& reader)
-{
-switch(kind)
-  {
-  // Game Objects
-  case COIN_OBJECT:
-  case INVISIBLE_BLOCK_OBJECT:
-    std::cerr << "Error: This object doesn't yet supported a Lisp argument.\n";
-    return NULL;
-//    return new Coin(reader);
-//    return new InvisibleBlock(reader);
-  case PLATFORM_OBJECT:
-    return new Platform(reader);
-  case ROCK_OBJECT:
-    return new Rock(reader);
-  // Bad Guys
-  case JUMPY_BADGUY:
-    return new Jumpy(reader);
-  case SNOWBALL_BADGUY:
-    return new SnowBall(reader);
-  case BOUNCING_SNOWBALL_BADGUY:
-    return new BouncingSnowball(reader);
-  case FLAME_BADGUY:
-    return new Flame(reader);
-  case FLYING_SNOWBALL_BADGUY:
-    return new FlyingSnowBall(reader);
-  case MRICEBLOCK_BADGUY:
-    return new MrIceBlock(reader);
-  case MRBOMB_BADGUY:
-    return new MrBomb(reader);
-  case DISPENSER_BADGUY:
-    return new Dispenser(reader);
-  case SPIKE_BADGUY:
-    return new Spike(reader);
-  case SPIKY_BADGUY:
-    return new Spiky(reader);
-  case NOLOK_01_BADGUY:
-    return new Nolok_01(reader);
-  // Triggers
-  case DOOR_TRIGGER:
-    return new Door(reader);
-  default:
-    std::cerr << "Warning: object not recognized.\n";
-    return NULL;  // object not recognized
-  }
-return NULL;  // avoids warnings
-}
-
-GameObject* create_object(GameObjectsType kind, const Vector& pos)
-{
-switch(kind)
-  {
-  // Game Objects
-  case COIN_OBJECT:
-    return new Coin(pos);
-  case INVISIBLE_BLOCK_OBJECT:
-    return new InvisibleBlock(pos);
-  case PLATFORM_OBJECT:
-  case ROCK_OBJECT:
-  case JUMPY_BADGUY:
-  case FLAME_BADGUY:
-  case DISPENSER_BADGUY:
-  case SPIKY_BADGUY:
-    std::cerr << "Error: This object doesn't yet support a position argument.\n";
-    return NULL;
-//    return new Platform(pos);
-//    return new Rock(pos);
-  // Bad Guys
-//    return new Jumpy(pos.x,pos.y,LEFT);
-//    return new Flame(pos.x,pos.y,LEFT);
-//    return new Dispenser(pos.x,pos.y,LEFT);
-//    return new Spiky(pos.x,pos.y,LEFT);
-  case SNOWBALL_BADGUY:
-    return new SnowBall(pos.x,pos.y,LEFT);
-  case BOUNCING_SNOWBALL_BADGUY:
-    return new BouncingSnowball(pos.x,pos.y,LEFT);
-  case FLYING_SNOWBALL_BADGUY:
-    return new FlyingSnowBall(pos.x,pos.y);
-  case MRICEBLOCK_BADGUY:
-    return new MrIceBlock(pos.x,pos.y,LEFT);
-  case MRBOMB_BADGUY:
-    return new MrBomb(pos.x,pos.y,LEFT);
-  case SPIKE_BADGUY:
-    return new Spike(pos,Spike::WEST);
-  case NOLOK_01_BADGUY:
-    return new Nolok_01(pos.x,pos.y);
-  // Triggers
-  case DOOR_TRIGGER:
-    return new Door((int)pos.x,(int)pos.y,"","");
-  default:
-    std::cerr << "Warning: object not recognized.\n";
-    return NULL;  // object not recognized
-  }
-return NULL;  // avoids warnings
-}
diff --git a/src/gameobjs_bridge.h b/src/gameobjs_bridge.h
deleted file mode 100644 (file)
index 3f30ee6..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/***************************************************************************
-                          gameobjs_bridge.h  -  description
-                             -------------------
-    begin                : Dec, 19 2004
-    copyright            : (C) 2004 by Ricardo Cruz
-    email                : rick2@aeiou.pt
- ***************************************************************************/
-
-/***************************************************************************
- *                                                                         *
- *   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.                                   *
- *                                                                         *
- ***************************************************************************/
-
-#ifndef GAMEOBJS_BRIDGE_H
-#define GAMEOBJS_BRIDGE_H
-
-#include <string>
-
-//#include "lisp/parser.h"
-#include "lisp/lisp.h"
-//#include "lisp/writer.h"
-//#include "lisp/list_iterator.h"
-
-//class GameObject;
-#include "object/gameobjs.h"
-
-
-/** This is just a set of functions aim to provide a common way
-    to create new game objects. Game objects that ain't really
-    interactive don't fit in here. */
-
-enum GameObjectsType {
-  // Game Objects
-  COIN_OBJECT,
-  INVISIBLE_BLOCK_OBJECT,
-  PLATFORM_OBJECT,
-  ROCK_OBJECT,
-  // Bad Guys
-  JUMPY_BADGUY,
-  SNOWBALL_BADGUY,
-  BOUNCING_SNOWBALL_BADGUY,
-  FLAME_BADGUY,
-  FLYING_SNOWBALL_BADGUY,
-  MRICEBLOCK_BADGUY,
-  MRBOMB_BADGUY,
-  DISPENSER_BADGUY,
-  SPIKE_BADGUY,
-  SPIKY_BADGUY,
-  NOLOK_01_BADGUY,
-  // Triggers
-  DOOR_TRIGGER,
-
-  TOTAL_GAMEOBJECTS,
-  NOT_RECOGNIZED_GAMEOBJECT
-  };
-
-/* Objects identifiers. */
-std::string object_type_to_string(int kind);
-GameObjectsType object_name_to_type(const std::string& name);
-
-bool is_object(const std::string& name);
-
-/* Calls to return a pointer to a created GameObjects.
-   Don't forget to delete them! */
-GameObject* create_object(GameObjectsType kind, const lisp::Lisp& reader);
-GameObject* create_object(GameObjectsType kind, const Vector& pos);
-
-#endif /*GAMEOBJS_BRIDGE_H*/
index 5ac945c..fc1eb26 100644 (file)
 #include "tile_manager.h"
 #include "sector.h"
 #include "gameloop.h"
+#include "object_factory.h"
 #include "object/gameobjs.h"
 #include "object/camera.h"
 #include "object/tilemap.h"
 #include "object/background.h"
-#include "gameobjs_bridge.h"
 
 LevelEditor::LevelEditor()
 {
@@ -119,13 +119,14 @@ LevelEditor::LevelEditor()
     }
   gameobjs_first_id = id;
 
-  for(id = 0; id < TOTAL_GAMEOBJECTS; id++)
-    {
+  for(Factories::iterator i = object_factories->begin();
+      i != object_factories->end(); ++i) {
+    
 //    Surface *img = badguy.get_image();
 // FIXME: get image from object. Using the rubber in the meanwhile.
-    tiles_board->add_button(Button(img_rubber_bt, object_type_to_string(id),
-                            SDLKey(SDLK_1+id)), id+gameobjs_first_id);
-    }
+    tiles_board->add_button(Button(img_rubber_bt, i->first,
+                            SDLKey(SDLK_1+id)), id++);
+  }
 
   tiles_layer = new ButtonGroup(Vector(12, screen->h-64), Vector(80,20), Vector(1,3));
   tiles_layer->add_button(Button(img_foreground_bt, _("Edtit foreground tiles"),
@@ -844,7 +845,8 @@ void LevelEditor::change(int x, int y, int newtile, int layer)
   level_changed = true;
   
   if(zoom != 1)
-  {  // no need to do this for normal view (no zoom)
+  { 
+    // no need to do this for normal view (no zoom)
     x = (int)(x * (zoom*32) / 32);
     y = (int)(y * (zoom*32) / 32);
   }
@@ -854,9 +856,20 @@ void LevelEditor::change(int x, int y, int newtile, int layer)
     // remove an active tile or object that might be there
     change(x, y, 0, LAYER_TILES);
 
-    create_object((GameObjectsType)(newtile-gameobjs_first_id),Vector(x,y));
-
-    sector->update_game_objects();
+    int id = 0;
+    GameObject* object = 0;
+    for(Factories::iterator i = object_factories->begin(); i !=
+        object_factories->end(); ++i) {
+      if(id == newtile - gameobjs_first_id) {
+        object = i->second->create_object(Vector(x, y));
+        break;
+      }
+      id++;
+    }
+    if(object) {
+      sector->add_object(object);
+      sector->update_game_objects();
+    }
   } else if(cur_layer == LAYER_FOREGROUNDTILES) {
     foregrounds->change(x/32, y/32, newtile);
   } else if(cur_layer == LAYER_TILES) {
index e005087..33902f0 100644 (file)
@@ -14,7 +14,6 @@
 //  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_MISC_H
 #define SUPERTUX_MISC_H
 
@@ -51,4 +50,3 @@ void st_menu();
 void st_menu_free();
 
 #endif //SUPERTUX_MISC_H
-
index 15333dd..50b01d0 100644 (file)
@@ -25,6 +25,7 @@
 #include "video/drawing_context.h"
 #include "lisp/lisp.h"
 #include "lisp/writer.h"
+#include "object_factory.h"
 
 Background::Background()
   : type(INVALID), layer(LAYER_BACKGROUND0), image(0)
@@ -128,3 +129,4 @@ Background::draw(DrawingContext& context)
   }
 }
 
+IMPLEMENT_FACTORY(Background, "background");
index ccede81..b3c6fcc 100644 (file)
@@ -15,6 +15,7 @@
 #include "star.h"
 #include "badguy/badguy.h"
 #include "coin.h"
+#include "object_factory.h"
 
 static const float BOUNCY_BRICK_MAX_OFFSET=8;
 static const float BOUNCY_BRICK_SPEED=90;
@@ -164,6 +165,8 @@ BonusBlock::try_open()
   sprite->set_action("empty");
 }
 
+//IMPLEMENT_FACTORY(BonusBlock, "bonusblock")
+
 //---------------------------------------------------------------------------
 
 Brick::Brick(const Vector& pos, int data)
@@ -222,3 +225,4 @@ Brick::try_break(bool playerhit)
   }
 }
 
+//IMPLEMENT_FACTORY(Brick, "brick")
index 367030a..246207f 100644 (file)
@@ -32,6 +32,7 @@
 #include "gameloop.h"
 #include "app/globals.h"
 #include "sector.h"
+#include "object_factory.h"
 
 using namespace SuperTux;
 
@@ -289,3 +290,4 @@ Camera::scroll_autoscroll(float elapsed_time)
 
   keep_in_bounds();
 }
+
index 359b452..c091018 100644 (file)
@@ -9,6 +9,7 @@
 #include "scene.h"
 #include "gameobjs.h"
 #include "statistics.h"
+#include "object_factory.h"
 
 Coin::Coin(const Vector& pos)
 {
@@ -17,6 +18,14 @@ Coin::Coin(const Vector& pos)
   sprite = sprite_manager->create("coin");
 }
 
+Coin::Coin(const lisp::Lisp& reader)
+{
+  reader.get("x", bbox.p1.x);
+  reader.get("y", bbox.p1.y);
+  bbox.set_size(32, 32);
+  sprite = sprite_manager->create("coin");
+}
+
 Coin::~Coin()
 {
   delete sprite;
@@ -53,3 +62,4 @@ Coin::collision(GameObject& other, const CollisionHit& )
   return ABORT_MOVE;
 }
 
+IMPLEMENT_FACTORY(Coin, "coin");
index fd827ed..02fbe57 100644 (file)
@@ -2,6 +2,7 @@
 #define __COIN_H__
 
 #include "special/moving_object.h"
+#include "lisp/lisp.h"
 
 namespace SuperTux {
   class Sprite;
@@ -13,6 +14,7 @@ class Coin : public MovingObject
 {
 public:
   Coin(const Vector& pos);
+  Coin(const lisp::Lisp& reader);
   ~Coin();
 
   HitResponse collision(GameObject& other, const CollisionHit& hit);
index 4db8c93..f9e2748 100644 (file)
@@ -5,6 +5,7 @@
 #include "special/sprite.h"
 #include "special/sprite_manager.h"
 #include "video/drawing_context.h"
+#include "object_factory.h"
 
 InvisibleBlock::InvisibleBlock(const Vector& pos)
   : Block(pos, sprite_manager->create("invisibleblock")), visible(false)
@@ -32,3 +33,4 @@ InvisibleBlock::hit(Player& )
   visible = true;
 }
 
+//IMPLEMENT_FACTORY(InvisibleBlock, "invisible_block");
index f418596..69c6c0d 100644 (file)
@@ -7,6 +7,7 @@
 #include "special/sprite_manager.h"
 #include "lisp/lisp.h"
 #include "lisp/writer.h"
+#include "object_factory.h"
 
 Platform::Platform(const lisp::Lisp& reader)
 {
@@ -74,3 +75,5 @@ Platform::draw(DrawingContext& context)
 {
   sprite->draw(context, get_pos(), LAYER_OBJECTS);
 }
+
+IMPLEMENT_FACTORY(Platform, "flying_platform");
index 2b45e60..b79a754 100644 (file)
@@ -6,6 +6,7 @@
 #include "lisp/writer.h"
 #include "video/drawing_context.h"
 #include "resources.h"
+#include "object_factory.h"
 
 Rock::Rock(const lisp::Lisp& reader)
 {
@@ -73,3 +74,5 @@ Rock::grab(MovingObject& , const Vector& pos)
   grabbed = true;
 }
 
+IMPLEMENT_FACTORY(Rock, "rock")
+
index 4046813..fb0cb63 100644 (file)
@@ -33,6 +33,7 @@
 #include "app/globals.h"
 #include "lisp/lisp.h"
 #include "lisp/writer.h"
+#include "object_factory.h"
 
 TileMap::TileMap()
   : solid(false), speed(1), width(0), height(0), layer(LAYER_TILES),
@@ -277,3 +278,5 @@ TileMap::change_at(const Vector& pos, uint32_t newtile)
 {
   change(int(pos.x)/32, int(pos.y)/32, newtile);
 }
+
+IMPLEMENT_FACTORY(TileMap, "tilemap");
diff --git a/src/object_factory.cpp b/src/object_factory.cpp
new file mode 100644 (file)
index 0000000..9ce2686
--- /dev/null
@@ -0,0 +1,39 @@
+//  $Id$
+//
+//  SuperTux -  A Jump'n Run
+//  Copyright (C) 2004 Ricardo Cruz <rick2@aeiou.pt>
+//
+//  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 <sstream>
+#include <stdexcept>
+
+#include "object_factory.h"
+
+Factories* object_factories = 0;
+
+GameObject* create_object(const std::string& name, const lisp::Lisp& reader)
+{
+  Factories::iterator i = object_factories->find(name);
+  if(i == object_factories->end()) {
+    std::stringstream msg;
+    msg << "No factory for object '" << name << "' found.";
+    throw std::runtime_error(msg.str());
+  }
+
+  return i->second->create_object(reader);
+}
+
diff --git a/src/object_factory.h b/src/object_factory.h
new file mode 100644 (file)
index 0000000..7cb3f8f
--- /dev/null
@@ -0,0 +1,77 @@
+//  $Id$
+//
+//  SuperTux -  A Jump'n Run
+//  Copyright (C) 2004 Ricardo Cruz <rick2@aeiou.pt>
+//
+//  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 OBJECT_FACTORY_H
+#define OBJECT_FACTORY_H
+
+#include <string>
+#include <map>
+
+#include "lisp/lisp.h"
+#include "special/game_object.h"
+#include "math/vector.h"
+
+using namespace SuperTux;
+
+class Factory
+{
+public:
+  /** Creates a new gameobject from a lisp node.
+   * Remember to delete the objects later
+   */
+  virtual GameObject* create_object(const lisp::Lisp& reader) = 0;
+
+  // hack for now will be removed later
+  virtual GameObject* create_object(const Vector& )
+  {
+    return 0;
+  }
+};
+
+typedef std::map<std::string, Factory*> Factories;
+extern Factories* object_factories;
+
+GameObject* create_object(const std::string& name, const lisp::Lisp& reader);
+GameObject* create_object(const std::string& name, const Vector& pos);
+
+/** comment from Matze:
+ * Yes I know macros are evil, but in this specific case they save
+ * A LOT of typing and evil code duplication.
+ * I'll happily acceppt alternatives if someone can present me one that does
+ * not involve typing 4 or more lines for each object class
+ */
+#define IMPLEMENT_FACTORY(CLASS, NAME)                            \
+class INTERN_##CLASS##Factory : public Factory                    \
+{                                                                 \
+public:                                                           \
+  INTERN_##CLASS##Factory()                                       \
+  {                                                               \
+    if(object_factories == 0)                                     \
+      object_factories = new Factories;                           \
+                                                                  \
+    object_factories->insert(std::make_pair(NAME, this));         \
+  }                                                               \
+                                                                  \
+  virtual GameObject* create_object(const lisp::Lisp& reader)     \
+  {                                                               \
+    return new CLASS(reader);                                     \
+  }                                                               \
+};                                                                \
+static INTERN_##CLASS##Factory factory_##CLASS;
+
+#endif
index c5b0842..3cacede 100644 (file)
@@ -154,7 +154,6 @@ void loadshared()
                          true);
 
   /* Sound effects: */
-
   for (i = 0; i < NUM_SOUNDS; i++)
     SoundManager::get()->add_sound(SoundManager::get
                       ()->load_sound(datadir + soundfilenames[i]),i);
index 310d64f..96f7f34 100644 (file)
 #include "statistics.h"
 #include "collision_grid.h"
 #include "collision_grid_iterator.h"
+#include "object_factory.h"
 #include "special/collision.h"
 #include "math/rectangle.h"
 #include "math/aatriangle.h"
 #include "object/coin.h"
 #include "object/block.h"
 #include "object/invisible_block.h"
-#include "object/platform.h"
 #include "object/bullet.h"
-#include "object/rock.h"
 #include "badguy/jumpy.h"
-#include "badguy/snowball.h"
-#include "badguy/bouncing_snowball.h"
-#include "badguy/flame.h"
-#include "badguy/flyingsnowball.h"
-#include "badguy/mriceblock.h"
-#include "badguy/mrbomb.h"
-#include "badguy/dispenser.h"
 #include "badguy/spike.h"
-#include "badguy/spiky.h"
-#include "badguy/nolok_01.h"
-#include "trigger/door.h"
 #include "trigger/sequence_trigger.h"
-#include "trigger/secretarea_trigger.h"
-#include "gameobjs_bridge.h"
 
 Sector* Sector::_current = 0;
 
@@ -105,14 +92,10 @@ Sector::~Sector()
 GameObject*
 Sector::parse_object(const std::string& name, const lisp::Lisp& reader)
 {
-  if(name == "background") {
-    return new Background(reader);
-  } else if(name == "camera") {
+  if(name == "camera") {
     Camera* camera = new Camera(this);
     camera->parse(reader);
     return camera;
-  } else if(name == "tilemap") {
-    return  new TileMap(reader);
   } else if(name == "particles-snow") {
     SnowParticleSystem* partsys = new SnowParticleSystem();
     partsys->parse(reader);
@@ -121,14 +104,16 @@ Sector::parse_object(const std::string& name, const lisp::Lisp& reader)
     CloudParticleSystem* partsys = new CloudParticleSystem();
     partsys->parse(reader);
     return partsys;
-  } else if(name == "secretarea") {
-    return new SecretAreaTrigger(reader);
-  } else if(name == "sequencetrigger") {
-    return new SequenceTrigger(reader);
-  } else if(is_object(name)) {
-    return create_object(object_name_to_type(name), reader);
-  } else
-    std::cerr << "Unknown object type '" << name << "'.\n";
+  } else if(name == "money") { // for compatibility with old maps
+    return new Jumpy(reader);
+  } 
+
+  try {
+    return create_object(name, reader);
+  } catch(std::exception& e) {
+    std::cerr << e.what() << "\n";
+  }
+  
   return 0;
 }
 
index f493712..446f2fa 100644 (file)
@@ -21,6 +21,7 @@
 #include "door.h"
 #include "gameloop.h"
 #include "resources.h"
+#include "object_factory.h"
 #include "special/sprite.h"
 #include "special/sprite_manager.h"
 #include "video/drawing_context.h"
@@ -96,3 +97,4 @@ Door::event(Player& , EventType type)
   }
 }
 
+IMPLEMENT_FACTORY(Door, "door");
index 91f9c98..f9bccd1 100644 (file)
@@ -4,6 +4,7 @@
 #include "gameloop.h"
 #include "lisp/lisp.h"
 #include "lisp/writer.h"
+#include "object_factory.h"
 
 SequenceTrigger::SequenceTrigger(const lisp::Lisp& reader)
 {
@@ -49,3 +50,5 @@ SequenceTrigger::event(Player& , EventType type)
     GameSession::current()->start_sequence(sequence_name);
   }
 }
+
+IMPLEMENT_FACTORY(SequenceTrigger, "sequencetrigger")