#define SUPERTUX_GAMEOBJECT_H
#include <string>
+#include "refcounter.hpp"
class DrawingContext;
class ObjectRemoveListener;
* functions.
* - a 32bit bitset for flags...
*/
-class GameObject
+class GameObject : public RefCounter
{
public:
GameObject();
/** returns true if the object is not scheduled to be removed yet */
bool is_valid() const
- {
- return !wants_to_die;
- }
+ {
+ return !wants_to_die;
+ }
+
/** schedules this object to be removed at the end of the frame */
void remove_me()
{
wants_to_die = true;
}
+
/** registers a remove listener which will be called if the object
* gets removed/destroyed
*/
max_score_multiplier(1)
{
reset();
- key_brass.reset(sprite_manager->create("images/objects/keys/key_brass.sprite"));
- key_iron.reset(sprite_manager->create("images/objects/keys/key_iron.sprite"));
- key_bronze.reset(sprite_manager->create("images/objects/keys/key_bronze.sprite"));
- key_silver.reset(sprite_manager->create("images/objects/keys/key_silver.sprite"));
- key_gold.reset(sprite_manager->create("images/objects/keys/key_gold.sprite"));
- key_brass->set_action("outline");
- key_iron->set_action("outline");
- key_bronze->set_action("outline");
- key_silver->set_action("outline");
- key_gold->set_action("outline");
tux_life.reset(sprite_manager->create("images/creatures/tux_small/tux-life.sprite"));
void PlayerStatus::reset()
{
coins = START_COINS;
- keys = 0;
bonus = NO_BONUS;
score_multiplier = 1;
max_score_multiplier = 1;
}
void
-PlayerStatus::set_keys(int new_key)
-{
- keys |= new_key;
- key_brass->set_action(keys & KEY_BRASS ? "display" : "outline");
- key_iron->set_action(keys & KEY_IRON ? "display" : "outline");
- key_bronze->set_action(keys & KEY_BRONZE ? "display" : "outline");
- key_silver->set_action(keys & KEY_SILVER ? "display" : "outline");
- key_gold->set_action(keys & KEY_GOLD ? "display" : "outline");
-}
-
-void
PlayerStatus::write(lisp::Writer& writer)
{
switch(bonus) {
writer.write_int("fireflowers", max_fire_bullets);
writer.write_int("iceflowers", max_ice_bullets);
- writer.write_bool("key-brass", keys & KEY_BRASS);
- writer.write_bool("key-iron", keys & KEY_IRON);
- writer.write_bool("key-bronze", keys & KEY_BRONZE);
- writer.write_bool("key-silver", keys & KEY_SILVER);
- writer.write_bool("key-gold", keys & KEY_GOLD);
-
writer.write_int("coins", coins);
writer.write_int("max-score-multiplier", max_score_multiplier);
}
lisp.get("fireflowers", max_fire_bullets);
lisp.get("iceflowers", max_ice_bullets);
- bool val = false;
- if(lisp.get("key-brass", val) && val == true)
- set_keys(KEY_BRASS);
- if(lisp.get("key-iron", val) && val == true)
- set_keys(KEY_IRON);
- if(lisp.get("key-bronze", val) && val == true)
- set_keys(KEY_BRONZE);
- if(lisp.get("key-silver", val) && val == true)
- set_keys(KEY_SILVER);
- if(lisp.get("key-gold", val) && val == true)
- set_keys(KEY_GOLD);
-
lisp.get("coins", coins);
lisp.get("max-score-multiplier", max_score_multiplier);
}
void
-PlayerStatus::draw_keys(DrawingContext& context)
-{
- const float SPACING = 10;
- float x,y;
- x = BORDER_X; y = BORDER_Y;
- key_brass->draw(context, Vector(x, y), LAYER_FOREGROUND1);
- x += key_brass->get_width() + SPACING;
- key_iron->draw(context, Vector(x, y), LAYER_FOREGROUND1);
- x += key_iron->get_width() + SPACING;
- key_bronze->draw(context, Vector(x, y), LAYER_FOREGROUND1);
- x += key_bronze->get_width() + SPACING;
- key_silver->draw(context, Vector(x, y), LAYER_FOREGROUND1);
- x += key_silver->get_width() + SPACING;
- key_gold->draw(context, Vector(x, y), LAYER_FOREGROUND1);
- x += key_gold->get_width() + SPACING;
-}
-
-void
PlayerStatus::draw(DrawingContext& context)
{
context.push_transform();
context.draw_text(white_text, coinstext, Vector(SCREEN_WIDTH - white_text->get_text_width(coinstext) - gold_text->get_text_width(" 99999") - BORDER_X, BORDER_Y), LEFT_ALLIGN, LAYER_FOREGROUND1);
context.draw_text(gold_text, str, Vector(SCREEN_WIDTH - BORDER_X, BORDER_Y), RIGHT_ALLIGN, LAYER_FOREGROUND1);
- //draw_keys(context);
-
context.pop_transform();
}
bonus = other.bonus;
score_multiplier = other.score_multiplier;
max_score_multiplier = other.max_score_multiplier;
- keys = other.keys;
}
bool
~PlayerStatus();
void reset();
void add_coins(int count);
- void set_keys(int new_key);
void write(lisp::Writer& writer);
void read(const lisp::Lisp& lisp);
void draw(DrawingContext& context);
- void draw_keys(DrawingContext& context);
bool consoleCommand(std::string command, std::vector<std::string> arguments); /**< callback from Console; return false if command was unknown, true otherwise */
void operator= (const PlayerStatus& other);
- enum {
- KEY_BRASS = 0x001,
- KEY_IRON = 0x002,
- KEY_BRONZE = 0x004,
- KEY_SILVER = 0x008,
- KEY_GOLD = 0x010,
- };
-
private:
// don't use this
PlayerStatus(const PlayerStatus& other);
- int keys;
-
std::auto_ptr<Sprite> tux_life;
- std::auto_ptr<Sprite> key_iron;
- std::auto_ptr<Sprite> key_brass;
- std::auto_ptr<Sprite> key_bronze;
- std::auto_ptr<Sprite> key_silver;
- std::auto_ptr<Sprite> key_gold;
};
// global player state
--- /dev/null
+// $Id: main.cpp 3385 2006-04-23 13:08:57Z matzebraun $
+//
+// SuperTux
+// Copyright (C) 2006 Matthias Braun <matze@braunis.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 __REF_HPP__
+#define __REF_HPP__
+
+/** This class behaves like a pointer to a refcounted object, but increments the
+ * reference count when new objects are assigned and decrements the refcounter
+ * when it's lifetime has experied. (similar to std::auto_ptr)
+ */
+template<typename T>
+class Ref
+{
+public:
+ Ref(T* object = 0)
+ : object(object)
+ {
+ if(object)
+ object->ref();
+ }
+ Ref(const Ref<T>& other)
+ : object(other.object)
+ {
+ if(object)
+ object->ref();
+ }
+ ~Ref()
+ {
+ if(object)
+ object->unref();
+ }
+
+ void operator= (const Ref<T>& other)
+ {
+ *this = other.get();
+ }
+
+ void operator= (T* object)
+ {
+ if(object)
+ object->ref();
+ if(this->object)
+ this->object->unref();
+ this->object = object;
+ }
+
+ T* operator ->() const
+ {
+ return object;
+ }
+
+ T& operator* () const
+ {
+ return *object;
+ }
+
+ operator const T* () const
+ {
+ return object;
+ }
+
+ T* get() const
+ {
+ return object;
+ }
+
+private:
+ T* object;
+};
+
+#endif
+
--- /dev/null
+// $Id: refcounter.hpp 1195 2006-01-07 10:37:52Z grumbel $
+//
+// Windstille - A Jump'n Shoot Game
+// Copyright (C) 2005 Matthias Braun <matze@braunis.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 __REFCOUNTER_HPP__
+#define __REFCOUNTER_HPP__
+
+#include <assert.h>
+
+/**
+ * A base class that provides reference counting facilities
+ */
+class RefCounter
+{
+public:
+ RefCounter()
+ : refcount(0)
+ { }
+
+ /** increases reference count */
+ void ref()
+ {
+ refcount++;
+ }
+ /** decreases reference count. Destroys the object if the reference count
+ * reaches 0
+ */
+ void unref()
+ {
+ refcount--;
+ if(refcount <= 0) {
+ delete this;
+ return;
+ }
+ }
+
+protected:
+ virtual ~RefCounter()
+ {
+ assert(refcount == 0);
+ }
+
+private:
+ int refcount;
+};
+
+#endif
// 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 <assert.h>
{
using namespace WorldMapNS;
- floating_image = new _FloatingImage(spritefile);
+ floating_image = new _FloatingImage(spritefile);
if(Sector::current() != NULL) {
- Sector::current()->add_object(floating_image);
+ Sector::current()->add_object(floating_image.get());
} else if(WorldMap::current() != NULL) {
- WorldMap::current()->add_object(floating_image);
+ WorldMap::current()->add_object(floating_image.get());
} else {
- delete floating_image;
throw new std::runtime_error("Neither sector nor worldmap active");
}
}
FloatingImage::~FloatingImage()
{
floating_image->remove_me();
- // no delete here, Sector will do that
}
void
#ifndef SCRIPTING_API
#define __suspend
#include <string>
+#include "ref.hpp"
class FloatingImage;
typedef FloatingImage _FloatingImage;
#ifndef SCRIPTING_API
private:
- _FloatingImage* floating_image;
+ Ref<_FloatingImage> floating_image;
#endif
};
sq_pop(vm, 1);
}
-void add_key(int new_key)
-{
- player_status->set_keys(new_key);
-}
-
void debug_collrects(bool enable)
{
Sector::show_collrects = enable;
namespace Scripting
{
-//TODO: Get this from PlayerStatus (update MiniSwig!)
-static const int KEY_BRASS = 0x001;
-static const int KEY_IRON = 0x002;
-static const int KEY_BRONZE = 0x004;
-static const int KEY_SILVER = 0x008;
-static const int KEY_GOLD = 0x010;
-
/**
* Display the value of the argument. This is usefull for inspecting tables.
*/
void save_state();
/**
- * Add a key to the inventory
- */
-void add_key(int new_key);
-
-/**
* enable/disable drawing of collision rectangles
*/
void debug_collrects(bool enable);
}
-static int add_key_wrapper(HSQUIRRELVM vm)
-{
- int arg0;
- if(SQ_FAILED(sq_getinteger(vm, 2, &arg0))) {
- sq_throwerror(vm, _SC("Argument 1 not an integer"));
- return SQ_ERROR;
- }
-
- try {
- Scripting::add_key(arg0);
-
- return 0;
-
- } catch(std::exception& e) {
- sq_throwerror(vm, e.what());
- return SQ_ERROR;
- } catch(...) {
- sq_throwerror(vm, _SC("Unexpected exception while executing function 'add_key'"));
- return SQ_ERROR;
- }
-
-}
-
static int debug_collrects_wrapper(HSQUIRRELVM vm)
{
SQBool arg0;
{
using namespace Wrapper;
- sq_pushstring(v, "KEY_BRASS", -1);
- sq_pushinteger(v, 1);
- if(SQ_FAILED(sq_createslot(v, -3))) {
- throw SquirrelError(v, "Couldn't register constant 'KEY_BRASS'");
- }
-
- sq_pushstring(v, "KEY_IRON", -1);
- sq_pushinteger(v, 2);
- if(SQ_FAILED(sq_createslot(v, -3))) {
- throw SquirrelError(v, "Couldn't register constant 'KEY_IRON'");
- }
-
- sq_pushstring(v, "KEY_BRONZE", -1);
- sq_pushinteger(v, 4);
- if(SQ_FAILED(sq_createslot(v, -3))) {
- throw SquirrelError(v, "Couldn't register constant 'KEY_BRONZE'");
- }
-
- sq_pushstring(v, "KEY_SILVER", -1);
- sq_pushinteger(v, 8);
- if(SQ_FAILED(sq_createslot(v, -3))) {
- throw SquirrelError(v, "Couldn't register constant 'KEY_SILVER'");
- }
-
- sq_pushstring(v, "KEY_GOLD", -1);
- sq_pushinteger(v, 16);
- if(SQ_FAILED(sq_createslot(v, -3))) {
- throw SquirrelError(v, "Couldn't register constant 'KEY_GOLD'");
- }
-
sq_pushstring(v, "ANCHOR_TOP", -1);
sq_pushinteger(v, 16);
if(SQ_FAILED(sq_createslot(v, -3))) {
throw SquirrelError(v, "Couldn't register function 'save_state'");
}
- sq_pushstring(v, "add_key", -1);
- sq_newclosure(v, &add_key_wrapper, 0);
- if(SQ_FAILED(sq_createslot(v, -3))) {
- throw SquirrelError(v, "Couldn't register function 'add_key'");
- }
-
sq_pushstring(v, "debug_collrects", -1);
sq_newclosure(v, &debug_collrects_wrapper, 0);
if(SQ_FAILED(sq_createslot(v, -3))) {
update_game_objects();
assert(gameobjects_new.size() == 0);
- for(GameObjects::iterator i = gameobjects.begin(); i != gameobjects.end();
- ++i) {
- before_object_remove(*i);
- delete *i;
+ for(GameObjects::iterator i = gameobjects.begin();
+ i != gameobjects.end(); ++i) {
+ GameObject* object = *i;
+ before_object_remove(object);
+ object->unref();
}
for(SpawnPoints::iterator i = spawnpoints.begin(); i != spawnpoints.end();
}
#endif
+ object->ref();
gameobjects_new.push_back(object);
}
before_object_remove(object);
- delete *i;
+ object->unref();
i = gameobjects.erase(i);
}
current_ = NULL;
for(GameObjects::iterator i = game_objects.begin();
- i != game_objects.end(); ++i)
- delete *i;
+ i != game_objects.end(); ++i) {
+ GameObject* object = *i;
+ object->unref();
+ }
for(SpawnPoints::iterator i = spawn_points.begin();
i != spawn_points.end(); ++i) {
solids = tilemap;
}
+ object->ref();
game_objects.push_back(object);
}
} else if(iter.item() == "level") {
LevelTile* level = new LevelTile(levels_path, iter.lisp());
levels.push_back(level);
- game_objects.push_back(level);
+ add_object(level);
} else if(iter.item() == "special-tile") {
SpecialTile* special_tile = new SpecialTile(iter.lisp());
special_tiles.push_back(special_tile);
- game_objects.push_back(special_tile);
+ add_object(special_tile);
} else if(iter.item() == "sprite-change") {
SpriteChange* sprite_change = new SpriteChange(iter.lisp());
sprite_changes.push_back(sprite_change);
- game_objects.push_back(sprite_change);
+ add_object(sprite_change);
} else if(iter.item() == "name") {
// skip
} else {
}
// update GameObjects
- for(GameObjects::iterator i = game_objects.begin();
- i != game_objects.end(); ++i) {
- GameObject* object = *i;
+ for(size_t i = 0; i < game_objects.size(); ++i) {
+ GameObject* object = game_objects[i];
object->update(delta);
}
i != game_objects.end(); ) {
GameObject* object = *i;
if(!object->is_valid()) {
- delete object;
+ object->unref();
i = game_objects.erase(i);
} else {
++i;