From e3bb6e46812f108f093e9ad0751a945c34b18cd3 Mon Sep 17 00:00:00 2001 From: Matthias Braun Date: Mon, 20 Dec 2004 21:24:28 +0000 Subject: [PATCH] implemented a new object factory mechanism which is now really independent of the objects SVN-Revision: 2262 --- data/levels/world1/level3.stl | 3 +- lib/lisp/parser.cpp | 2 - src/badguy/badguy.h | 1 + src/badguy/bomb.cpp | 1 + src/badguy/bouncing_snowball.cpp | 2 + src/badguy/dispenser.cpp | 1 + src/badguy/flame.cpp | 2 + src/badguy/flyingsnowball.cpp | 1 + src/badguy/jumpy.cpp | 2 + src/badguy/mrbomb.cpp | 2 + src/badguy/mriceblock.cpp | 1 + src/badguy/nolok_01.cpp | 1 + src/badguy/snowball.cpp | 1 + src/badguy/spike.cpp | 2 + src/badguy/spiky.cpp | 1 + src/gameobjs_bridge.cpp | 231 --------------------------------------- src/gameobjs_bridge.h | 72 ------------ src/leveleditor.cpp | 33 ++++-- src/misc.h | 2 - src/object/background.cpp | 2 + src/object/block.cpp | 4 + src/object/camera.cpp | 2 + src/object/coin.cpp | 10 ++ src/object/coin.h | 2 + src/object/invisible_block.cpp | 2 + src/object/platform.cpp | 3 + src/object/rock.cpp | 3 + src/object/tilemap.cpp | 3 + src/object_factory.cpp | 39 +++++++ src/object_factory.h | 77 +++++++++++++ src/resources.cpp | 1 - src/sector.cpp | 39 ++----- src/trigger/door.cpp | 2 + src/trigger/sequence_trigger.cpp | 3 + 34 files changed, 206 insertions(+), 347 deletions(-) delete mode 100644 src/gameobjs_bridge.cpp delete mode 100644 src/gameobjs_bridge.h create mode 100644 src/object_factory.cpp create mode 100644 src/object_factory.h diff --git a/data/levels/world1/level3.stl b/data/levels/world1/level3.stl index 4eb2f3cfd..0fca345bc 100644 --- a/data/levels/world1/level3.stl +++ b/data/levels/world1/level3.stl @@ -121,7 +121,6 @@ (snowball (x 10932) (y 408)) (snowball (x 9969) (y 410)) ) - ) - +) ;; EOF ;; diff --git a/lib/lisp/parser.cpp b/lib/lisp/parser.cpp index 875a4b201..08c5aa78f 100644 --- a/lib/lisp/parser.cpp +++ b/lib/lisp/parser.cpp @@ -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 { diff --git a/src/badguy/badguy.h b/src/badguy/badguy.h index cddb825ff..075b02558 100644 --- a/src/badguy/badguy.h +++ b/src/badguy/badguy.h @@ -11,6 +11,7 @@ #include "serializable.h" #include "resources.h" #include "sector.h" +#include "object_factory.h" #include "lisp/parser.h" #include "lisp/lisp.h" #include "lisp/writer.h" diff --git a/src/badguy/bomb.cpp b/src/badguy/bomb.cpp index 66e834802..9495abc92 100644 --- a/src/badguy/bomb.cpp +++ b/src/badguy/bomb.cpp @@ -74,3 +74,4 @@ void Bomb::kill_fall() { } + diff --git a/src/badguy/bouncing_snowball.cpp b/src/badguy/bouncing_snowball.cpp index 912e52375..edbe4d793 100644 --- a/src/badguy/bouncing_snowball.cpp +++ b/src/badguy/bouncing_snowball.cpp @@ -81,3 +81,5 @@ BouncingSnowball::collision_badguy(BadGuy& , const CollisionHit& hit) return CONTINUE; } +IMPLEMENT_FACTORY(BouncingSnowball, "bouncingsnowball") + diff --git a/src/badguy/dispenser.cpp b/src/badguy/dispenser.cpp index f3445b3f7..0a92074dc 100644 --- a/src/badguy/dispenser.cpp +++ b/src/badguy/dispenser.cpp @@ -92,3 +92,4 @@ Dispenser::launch_badguy() } } +IMPLEMENT_FACTORY(Dispenser, "dispenser") diff --git a/src/badguy/flame.cpp b/src/badguy/flame.cpp index 853ca5e64..e9d7f4989 100644 --- a/src/badguy/flame.cpp +++ b/src/badguy/flame.cpp @@ -42,3 +42,5 @@ Flame::kill_fall() { } +IMPLEMENT_FACTORY(Flame, "flame") + diff --git a/src/badguy/flyingsnowball.cpp b/src/badguy/flyingsnowball.cpp index e07179a76..94caec91e 100644 --- a/src/badguy/flyingsnowball.cpp +++ b/src/badguy/flyingsnowball.cpp @@ -80,3 +80,4 @@ FlyingSnowBall::active_action(float elapsed_time) sprite->set_action(dir == LEFT ? "left" : "right"); } +IMPLEMENT_FACTORY(FlyingSnowBall, "flyingsnowball") diff --git a/src/badguy/jumpy.cpp b/src/badguy/jumpy.cpp index 779d81e90..4d32164ac 100644 --- a/src/badguy/jumpy.cpp +++ b/src/badguy/jumpy.cpp @@ -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") diff --git a/src/badguy/mrbomb.cpp b/src/badguy/mrbomb.cpp index 215284299..5b6395599 100644 --- a/src/badguy/mrbomb.cpp +++ b/src/badguy/mrbomb.cpp @@ -77,3 +77,5 @@ MrBomb::collision_badguy(BadGuy& , const CollisionHit& hit) return CONTINUE; } + +IMPLEMENT_FACTORY(MrBomb, "mrbomb") diff --git a/src/badguy/mriceblock.cpp b/src/badguy/mriceblock.cpp index 6a76d6908..4e1b1745a 100644 --- a/src/badguy/mriceblock.cpp +++ b/src/badguy/mriceblock.cpp @@ -165,3 +165,4 @@ MrIceBlock::collision_squished(Player& player) return true; } +IMPLEMENT_FACTORY(MrIceBlock, "mriceblock") diff --git a/src/badguy/nolok_01.cpp b/src/badguy/nolok_01.cpp index 1a5768fe6..f5a1c9409 100644 --- a/src/badguy/nolok_01.cpp +++ b/src/badguy/nolok_01.cpp @@ -106,3 +106,4 @@ Nolok_01::collision_solid(GameObject& , const CollisionHit& hit) return CONTINUE; } +IMPLEMENT_FACTORY(Nolok_01, "nolok01") diff --git a/src/badguy/snowball.cpp b/src/badguy/snowball.cpp index 75f68b450..5f65eaa0e 100644 --- a/src/badguy/snowball.cpp +++ b/src/badguy/snowball.cpp @@ -76,3 +76,4 @@ SnowBall::collision_badguy(BadGuy& , const CollisionHit& hit) return CONTINUE; } +IMPLEMENT_FACTORY(SnowBall, "snowball") diff --git a/src/badguy/spike.cpp b/src/badguy/spike.cpp index bc3145050..5d046eea4 100644 --- a/src/badguy/spike.cpp +++ b/src/badguy/spike.cpp @@ -62,3 +62,5 @@ void Spike::active_action(float ) { } + +IMPLEMENT_FACTORY(Spike, "spike") diff --git a/src/badguy/spiky.cpp b/src/badguy/spiky.cpp index 49d7e4c57..a4007b7c5 100644 --- a/src/badguy/spiky.cpp +++ b/src/badguy/spiky.cpp @@ -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 index c94076cc9..000000000 --- a/src/gameobjs_bridge.cpp +++ /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 index 3f30ee653..000000000 --- a/src/gameobjs_bridge.h +++ /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 - -//#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*/ diff --git a/src/leveleditor.cpp b/src/leveleditor.cpp index 5ac945cb9..fc1eb2676 100644 --- a/src/leveleditor.cpp +++ b/src/leveleditor.cpp @@ -34,11 +34,11 @@ #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) { diff --git a/src/misc.h b/src/misc.h index e00508710..33902f0f4 100644 --- a/src/misc.h +++ b/src/misc.h @@ -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 - diff --git a/src/object/background.cpp b/src/object/background.cpp index 15333dd20..50b01d09a 100644 --- a/src/object/background.cpp +++ b/src/object/background.cpp @@ -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"); diff --git a/src/object/block.cpp b/src/object/block.cpp index ccede815c..b3c6fccb6 100644 --- a/src/object/block.cpp +++ b/src/object/block.cpp @@ -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") diff --git a/src/object/camera.cpp b/src/object/camera.cpp index 367030aa5..246207f55 100644 --- a/src/object/camera.cpp +++ b/src/object/camera.cpp @@ -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(); } + diff --git a/src/object/coin.cpp b/src/object/coin.cpp index 359b4522d..c0910183e 100644 --- a/src/object/coin.cpp +++ b/src/object/coin.cpp @@ -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"); diff --git a/src/object/coin.h b/src/object/coin.h index fd827ed51..02fbe57fa 100644 --- a/src/object/coin.h +++ b/src/object/coin.h @@ -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); diff --git a/src/object/invisible_block.cpp b/src/object/invisible_block.cpp index 4db8c934d..f9e274869 100644 --- a/src/object/invisible_block.cpp +++ b/src/object/invisible_block.cpp @@ -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"); diff --git a/src/object/platform.cpp b/src/object/platform.cpp index f418596ba..69c6c0df2 100644 --- a/src/object/platform.cpp +++ b/src/object/platform.cpp @@ -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"); diff --git a/src/object/rock.cpp b/src/object/rock.cpp index 2b45e609d..b79a7543d 100644 --- a/src/object/rock.cpp +++ b/src/object/rock.cpp @@ -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") + diff --git a/src/object/tilemap.cpp b/src/object/tilemap.cpp index 4046813b4..fb0cb63d7 100644 --- a/src/object/tilemap.cpp +++ b/src/object/tilemap.cpp @@ -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 index 000000000..9ce2686a6 --- /dev/null +++ b/src/object_factory.cpp @@ -0,0 +1,39 @@ +// $Id$ +// +// SuperTux - A Jump'n Run +// Copyright (C) 2004 Ricardo Cruz +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +#include + +#include +#include + +#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 index 000000000..7cb3f8f02 --- /dev/null +++ b/src/object_factory.h @@ -0,0 +1,77 @@ +// $Id$ +// +// SuperTux - A Jump'n Run +// Copyright (C) 2004 Ricardo Cruz +// +// 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 +#include + +#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 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 diff --git a/src/resources.cpp b/src/resources.cpp index c5b084246..3cacedebb 100644 --- a/src/resources.cpp +++ b/src/resources.cpp @@ -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); diff --git a/src/sector.cpp b/src/sector.cpp index 310d64f30..96f7f3491 100644 --- a/src/sector.cpp +++ b/src/sector.cpp @@ -44,30 +44,17 @@ #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; } diff --git a/src/trigger/door.cpp b/src/trigger/door.cpp index f49371246..446f2faa9 100644 --- a/src/trigger/door.cpp +++ b/src/trigger/door.cpp @@ -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"); diff --git a/src/trigger/sequence_trigger.cpp b/src/trigger/sequence_trigger.cpp index 91f9c9868..f9bccd190 100644 --- a/src/trigger/sequence_trigger.cpp +++ b/src/trigger/sequence_trigger.cpp @@ -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") -- 2.11.0