(snowball (x 10932) (y 408))
(snowball (x 9969) (y 410))
)
- )
-
+)
;; EOF ;;
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 {
#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"
return CONTINUE;
}
+IMPLEMENT_FACTORY(BouncingSnowball, "bouncingsnowball")
+
}
}
+IMPLEMENT_FACTORY(Dispenser, "dispenser")
{
}
+IMPLEMENT_FACTORY(Flame, "flame")
+
sprite->set_action(dir == LEFT ? "left" : "right");
}
+IMPLEMENT_FACTORY(FlyingSnowBall, "flyingsnowball")
//FIXME: add middle and up here
sprite->set_action(dir == LEFT ? "left-down" : "right-down");
}
+
+IMPLEMENT_FACTORY(Jumpy, "jumpy")
return CONTINUE;
}
+
+IMPLEMENT_FACTORY(MrBomb, "mrbomb")
return true;
}
+IMPLEMENT_FACTORY(MrIceBlock, "mriceblock")
return CONTINUE;
}
+IMPLEMENT_FACTORY(Nolok_01, "nolok01")
return CONTINUE;
}
+IMPLEMENT_FACTORY(SnowBall, "snowball")
Spike::active_action(float )
{
}
+
+IMPLEMENT_FACTORY(Spike, "spike")
return CONTINUE;
}
+IMPLEMENT_FACTORY(Spiky, "spiky")
+++ /dev/null
-
-/***************************************************************************
- 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
-}
+++ /dev/null
-/***************************************************************************
- 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*/
#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()
{
}
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"),
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);
}
// 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) {
// 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
void st_menu_free();
#endif //SUPERTUX_MISC_H
-
#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)
}
}
+IMPLEMENT_FACTORY(Background, "background");
#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;
sprite->set_action("empty");
}
+//IMPLEMENT_FACTORY(BonusBlock, "bonusblock")
+
//---------------------------------------------------------------------------
Brick::Brick(const Vector& pos, int data)
}
}
+//IMPLEMENT_FACTORY(Brick, "brick")
#include "gameloop.h"
#include "app/globals.h"
#include "sector.h"
+#include "object_factory.h"
using namespace SuperTux;
keep_in_bounds();
}
+
#include "scene.h"
#include "gameobjs.h"
#include "statistics.h"
+#include "object_factory.h"
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;
return ABORT_MOVE;
}
+IMPLEMENT_FACTORY(Coin, "coin");
#define __COIN_H__
#include "special/moving_object.h"
+#include "lisp/lisp.h"
namespace SuperTux {
class Sprite;
{
public:
Coin(const Vector& pos);
+ Coin(const lisp::Lisp& reader);
~Coin();
HitResponse collision(GameObject& other, const CollisionHit& hit);
#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)
visible = true;
}
+//IMPLEMENT_FACTORY(InvisibleBlock, "invisible_block");
#include "special/sprite_manager.h"
#include "lisp/lisp.h"
#include "lisp/writer.h"
+#include "object_factory.h"
Platform::Platform(const lisp::Lisp& reader)
{
{
sprite->draw(context, get_pos(), LAYER_OBJECTS);
}
+
+IMPLEMENT_FACTORY(Platform, "flying_platform");
#include "lisp/writer.h"
#include "video/drawing_context.h"
#include "resources.h"
+#include "object_factory.h"
Rock::Rock(const lisp::Lisp& reader)
{
grabbed = true;
}
+IMPLEMENT_FACTORY(Rock, "rock")
+
#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),
{
change(int(pos.x)/32, int(pos.y)/32, newtile);
}
+
+IMPLEMENT_FACTORY(TileMap, "tilemap");
--- /dev/null
+// $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);
+}
+
--- /dev/null
+// $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
true);
/* Sound effects: */
-
for (i = 0; i < NUM_SOUNDS; i++)
SoundManager::get()->add_sound(SoundManager::get
()->load_sound(datadir + soundfilenames[i]),i);
#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;
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);
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;
}
#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"
}
}
+IMPLEMENT_FACTORY(Door, "door");
#include "gameloop.h"
#include "lisp/lisp.h"
#include "lisp/writer.h"
+#include "object_factory.h"
SequenceTrigger::SequenceTrigger(const lisp::Lisp& reader)
{
GameSession::current()->start_sequence(sequence_name);
}
}
+
+IMPLEMENT_FACTORY(SequenceTrigger, "sequencetrigger")