summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBjørn Lindeijer <bjorn@lindeijer.nl>2006-07-24 00:13:24 +0000
committerBjørn Lindeijer <bjorn@lindeijer.nl>2006-07-24 00:13:24 +0000
commit4789ebb11407eb9402c385f3cc6fa242d91214c2 (patch)
tree6bf5bed52073ae19ef4b5b08e7fe92af603f04d8
parent1b7ff9ad4160fd0ff79d2da658eca8d8c8abf815 (diff)
downloadmana-4789ebb11407eb9402c385f3cc6fa242d91214c2.tar.gz
mana-4789ebb11407eb9402c385f3cc6fa242d91214c2.tar.bz2
mana-4789ebb11407eb9402c385f3cc6fa242d91214c2.tar.xz
mana-4789ebb11407eb9402c385f3cc6fa242d91214c2.zip
Implemented caching of spritesets, including a lot of cleanups to the new
animation system. Action now refers to the Spriteset directly and AnimatedSprite refers to the current Action directly instead of using the std::map with a std::string constantly. Some methods and parameters are marked as const. The READ_PROP macro was replaced by static methods. Warnings are logged when unnamed actions are defined or when actions refer to undefined imagesets. Code is more tolerant towards missing actions.
-rw-r--r--ChangeLog20
-rw-r--r--NEWS8
-rw-r--r--src/Makefile.am6
-rw-r--r--src/animation.cpp320
-rw-r--r--src/animation.h100
-rw-r--r--src/being.cpp10
-rw-r--r--src/being.h2
-rw-r--r--src/engine.cpp25
-rw-r--r--src/floor_item.cpp3
-rw-r--r--src/gui/equipmentwindow.cpp7
-rw-r--r--src/gui/itemcontainer.cpp7
-rw-r--r--src/gui/playerbox.cpp2
-rw-r--r--src/log.cpp3
-rw-r--r--src/main.cpp21
-rw-r--r--src/resources/mapreader.cpp3
-rw-r--r--src/resources/resourcemanager.cpp74
-rw-r--r--src/resources/resourcemanager.h8
-rw-r--r--src/resources/spriteset.cpp (renamed from src/graphic/spriteset.cpp)9
-rw-r--r--src/resources/spriteset.h (renamed from src/graphic/spriteset.h)11
-rw-r--r--src/tileset.h4
20 files changed, 400 insertions, 243 deletions
diff --git a/ChangeLog b/ChangeLog
index ffd0f7f8..888a00c3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,23 @@
+2006-07-24 Bjørn Lindeijer <bjorn@lindeijer.nl>
+
+ * src/floor_item.cpp, src/animation.h, src/being.cpp, src/main.cpp,
+ src/gui/equipmentwindow.cpp, src/gui/playerbox.cpp,
+ src/gui/itemcontainer.cpp, src/engine.cpp, src/tileset.h,
+ src/animation.cpp, src/Makefile.am, src/resources/mapreader.cpp,
+ src/resources/resourcemanager.cpp, src/resources/spriteset.cpp,
+ src/resources/resourcemanager.h, src/resources/spriteset.h,
+ src/being.h, src/graphic/spriteset.cpp, src/graphic/spriteset.h,
+ data/graphics/sprites/npc.xml, data/graphics/sprites/weapons.xml:
+ Implemented caching of spritesets, including a lot of cleanups to the
+ new animation system. Action now refers to the Spriteset directly and
+ AnimatedSprite refers to the current Action directly instead of using
+ the std::map with a std::string constantly. Some methods and
+ parameters are marked as const. The READ_PROP macro was replaced by
+ static methods. Warnings are logged when unnamed actions are defined
+ or when actions refer to undefined imagesets. Code is more tolerant
+ towards missing actions.
+ * NEWS: Rearranged some items.
+
2006-07-21 Eugenio Favalli <elvenprogrammer@gmail.com>
* src/animation.cpp, src/animation.h: Removed unused code, fixed a
diff --git a/NEWS b/NEWS
index b30f1f89..b1d48891 100644
--- a/NEWS
+++ b/NEWS
@@ -1,16 +1,16 @@
0.0.20 (23 July 2006)
-- Reduced size of textures to stay within the OpenGL limits
- Added new hairstyle, and some fixes to the old ones
-- Fixed connection not being shut down completely in case of an error
-- Fixed min size of a window when resizing
- Added slider to set FPS limit
- Added visible equipments
- Added new maps and monsters
- Added female characters
-- Some fixes to monsters and player graphics
- Implemented a new animation system
- Updated the updating system
+- Reduced size of textures to stay within the limits of some OpenGL drivers
+- Fixed connection not being shut down completely in case of an error
+- Fixed min size of a window when resizing
- Fixed some maps issues
+- Some fixes to monsters and player graphics
- Minor bug fixes and lots of code cleanups
0.0.19 (6 March 2006)
diff --git a/src/Makefile.am b/src/Makefile.am
index c6db2ec6..1bb1d538 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,7 +1,5 @@
bin_PROGRAMS = tmw
-tmw_SOURCES = graphic/spriteset.cpp \
- graphic/imagerect.h \
- graphic/spriteset.h \
+tmw_SOURCES = graphic/imagerect.h \
gui/browserbox.cpp \
gui/browserbox.h \
gui/buddywindow.cpp \
@@ -177,6 +175,8 @@ tmw_SOURCES = graphic/spriteset.cpp \
resources/sdlimageloader.cpp \
resources/soundeffect.h \
resources/soundeffect.cpp \
+ resources/spriteset.h \
+ resources/spriteset.cpp \
resources/buddylist.h \
resources/buddylist.cpp \
utils/dtor.h \
diff --git a/src/animation.cpp b/src/animation.cpp
index 4dae04c4..313fd25c 100644
--- a/src/animation.cpp
+++ b/src/animation.cpp
@@ -23,21 +23,13 @@
#include "animation.h"
-#include <libxml/tree.h>
+#include <cassert>
#include "log.h"
-#include "graphic/spriteset.h"
-
#include "resources/image.h"
#include "resources/resourcemanager.h"
-
-#define READ_PROP(node, prop, name, target, cast) \
- prop = xmlGetProp(node, BAD_CAST name); \
- if (prop) { \
- target = cast((const char*)prop); \
- xmlFree(prop); \
- }
+#include "resources/spriteset.h"
Animation::Animation():
mTime(0)
@@ -65,7 +57,7 @@ Animation::update(unsigned int time)
}
int
-Animation::getCurrentPhase()
+Animation::getCurrentPhase() const
{
if (mAnimationPhases.empty())
{
@@ -78,7 +70,7 @@ Animation::getCurrentPhase()
}
void
-Animation::addPhase (int image, unsigned int delay, int offsetX, int offsetY)
+Animation::addPhase(int image, unsigned int delay, int offsetX, int offsetY)
{
//add new phase to animation list
AnimationPhase newPhase;
@@ -106,10 +98,9 @@ Animation::getLength()
return length;
}
-Action::Action()
- :mImageset("")
+Action::Action():
+ mSpriteset(NULL)
{
- //NOOP
}
Action::~Action()
@@ -121,28 +112,30 @@ Action::~Action()
mAnimations.clear();
}
-Animation *
-Action::getAnimation(std::string direction)
+Animation*
+Action::getAnimation(const std::string& direction) const
{
Animation *animation = NULL;
- AnimationIterator i = mAnimations.find(direction);
+ Animations::const_iterator i = mAnimations.find(direction);
+
+ // When the direction isn't defined, try the default
if (i == mAnimations.end())
{
- //when the direction isn't defined just use another one
- animation = mAnimations["default"];
+ i = mAnimations.find("default");
}
- else
+
+ if (i != mAnimations.end())
{
- animation = mAnimations[direction];
+ animation = i->second;
}
return animation;
}
void
-Action::setAnimation(std::string direction, Animation *animation)
+Action::setAnimation(const std::string& direction, Animation *animation)
{
- //set first direction as default direction
+ // Set first direction as default direction
if (mAnimations.empty())
{
mAnimations["default"] = animation;
@@ -152,18 +145,18 @@ Action::setAnimation(std::string direction, Animation *animation)
}
-AnimatedSprite::AnimatedSprite(std::string animationFile, int variant):
- mAction("stand"), mDirection("down"), mLastTime(0), mSpeed(1.0f)
+AnimatedSprite::AnimatedSprite(const std::string& animationFile, int variant):
+ mAction(NULL),
+ mDirection("down"),
+ mLastTime(0),
+ mSpeed(1.0f)
{
- int variant_num = 0;
- int variant_offset = 0;
int size;
ResourceManager *resman = ResourceManager::getInstance();
- char *data = (char*)resman->loadFile(
- animationFile.c_str(), size);
+ char *data = (char*)resman->loadFile(animationFile.c_str(), size);
if (!data) {
- logger->error("Animation: Could not find " + animationFile + " !");
+ logger->error("Animation: Could not find " + animationFile + "!");
}
xmlDocPtr doc = xmlParseMemory(data, size);
@@ -182,10 +175,9 @@ AnimatedSprite::AnimatedSprite(std::string animationFile, int variant):
return;
}
- //get the variant
- xmlChar *prop = NULL;
- READ_PROP(node, prop, "variants", variant_num, atoi);
- READ_PROP(node, prop, "variant_offset", variant_offset, atoi);
+ // Get the variant
+ int variant_num = getProperty(node, "variants", 0);
+ int variant_offset = getProperty(node, "variant_offset", 0);
if (variant_num > 0 && variant < variant_num )
{
@@ -200,16 +192,14 @@ AnimatedSprite::AnimatedSprite(std::string animationFile, int variant):
{
if (xmlStrEqual(node->name, BAD_CAST "imageset"))
{
- int width = 0, height = 0;
- std::string name = "", imageSrc = "";
- xmlChar *prop = NULL;
- READ_PROP(node, prop, "name", name, );
- READ_PROP(node, prop, "src", imageSrc, );
- READ_PROP(node, prop, "width", width, atoi);
- READ_PROP(node, prop, "height", height, atoi);
-
- Spriteset *spriteset = resman->createSpriteset(
- imageSrc, width, height);
+ int width = getProperty(node, "width", 0);
+ int height = getProperty(node, "height", 0);
+ std::string name = getProperty(node, "name", "");
+ std::string imageSrc = getProperty(node, "src", "");
+
+ Spriteset *spriteset =
+ resman->getSpriteset(imageSrc, width, height);
+
if (!spriteset)
{
logger->error("Couldn't load spriteset!");
@@ -222,59 +212,73 @@ AnimatedSprite::AnimatedSprite(std::string animationFile, int variant):
// get action
else if (xmlStrEqual(node->name, BAD_CAST "action"))
{
- std::string name = "", imageset = "";
- xmlChar *prop = NULL;
- READ_PROP(node, prop, "name", name, );
- READ_PROP(node, prop, "imageset", imageset, );
+ std::string name = getProperty(node, "name", "");
+ std::string imageset = getProperty(node, "imageset", "");
+
+ if (name.length() == 0)
+ {
+ logger->log("Warning: unnamed action in %s",
+ animationFile.c_str());
+ }
Action *action = new Action();
- mActions[name] = action;
- action->setImageset(imageset);
- //get animations
- for ( xmlNodePtr animationNode = node->xmlChildrenNode;
- animationNode != NULL;
- animationNode = animationNode->next)
+ if (mSpritesets.find(imageset) != mSpritesets.end())
+ {
+ action->setSpriteset(mSpritesets[imageset]);
+ mActions[name] = action;
+ }
+ else
+ {
+ logger->log("Warning: imageset \"%s\" not defined in %s",
+ imageset.c_str(),
+ animationFile.c_str());
+
+ // Discard action and skip loading animations
+ delete action;
+ continue;
+ }
+
+ // get animations
+ for (xmlNodePtr animationNode = node->xmlChildrenNode;
+ animationNode != NULL;
+ animationNode = animationNode->next)
{
if (xmlStrEqual(animationNode->name, BAD_CAST "animation"))
{
- std::string direction = "";
-
+ std::string direction =
+ getProperty(animationNode, "direction", "");
Animation *animation = new Animation();
- READ_PROP(animationNode, prop, "direction", direction, );
- //get animation phases
- for ( xmlNodePtr phaseNode = animationNode->xmlChildrenNode;
- phaseNode != NULL;
- phaseNode = phaseNode->next)
+ // Get animation phases
+ for (xmlNodePtr phaseNode = animationNode->xmlChildrenNode;
+ phaseNode != NULL;
+ phaseNode = phaseNode->next)
{
- int index = -1;
- int start = 0;
- int end = 0;
- int delay = 0;
- int offsetX = 0;
- int offsetY = 0;
+ int delay = getProperty(phaseNode, "delay", 0);
+
if (xmlStrEqual(phaseNode->name, BAD_CAST "frame"))
{
- READ_PROP(phaseNode, prop, "index", index, atoi);
- READ_PROP(phaseNode, prop, "delay", delay, atoi);
- READ_PROP(phaseNode, prop, "offsetX", offsetX, atoi);
- READ_PROP(phaseNode, prop, "offsetY", offsetY, atoi);
+ int index = getProperty(phaseNode, "index", -1);
+ int offsetX = getProperty(phaseNode, "offsetX", 0);
+ int offsetY = getProperty(phaseNode, "offsetY", 0);
+
offsetY = offsetY - mSpritesets[imageset]->getHeight() + 32;
offsetX = offsetX - mSpritesets[imageset]->getWidth() / 2 + 16;
- animation->addPhase(index + variant_offset, delay, offsetX, offsetY);
+ animation->addPhase(index + variant_offset, delay,
+ offsetX, offsetY);
}
- if (xmlStrEqual(phaseNode->name, BAD_CAST "sequence"))
+ else if (xmlStrEqual(phaseNode->name, BAD_CAST "sequence"))
{
- READ_PROP(phaseNode, prop, "start", start, atoi);
- READ_PROP(phaseNode, prop, "end", end, atoi);
- READ_PROP(phaseNode, prop, "delay", delay, atoi);
- offsetY = 0 - mSpritesets[imageset]->getHeight() + 32;
- offsetX = 0 - mSpritesets[imageset]->getWidth() / 2 + 16;
+ int start = getProperty(phaseNode, "start", 0);
+ int end = getProperty(phaseNode, "end", 0);
+ int offsetY = 0 - mSpritesets[imageset]->getHeight() + 32;
+ int offsetX = 0 - mSpritesets[imageset]->getWidth() / 2 + 16;
while (end >= start)
{
- animation->addPhase(start + variant_offset, delay, offsetX, offsetY);
+ animation->addPhase(start + variant_offset,
+ delay, offsetX, offsetY);
start++;
}
}
@@ -285,8 +289,7 @@ AnimatedSprite::AnimatedSprite(std::string animationFile, int variant):
} // if "<imageset>" else if "<action>"
} // for node
- //complete missing actions
- substituteAction("stand", "");
+ // Complete missing actions
substituteAction("walk", "stand");
substituteAction("walk", "run");
substituteAction("attack", "stand");
@@ -301,11 +304,44 @@ AnimatedSprite::AnimatedSprite(std::string animationFile, int variant):
substituteAction("hurt", "stand");
substituteAction("dead", "hurt");
+ // Play the stand animation by default
+ play("stand");
+
xmlFreeDoc(doc);
}
+int
+AnimatedSprite::getProperty(xmlNodePtr node, const char* name, int def)
+{
+ xmlChar *prop = xmlGetProp(node, BAD_CAST name);
+ if (prop) {
+ int val = atoi((char*)prop);
+ xmlFree(prop);
+ return val;
+ }
+ else {
+ return def;
+ }
+}
+
+std::string
+AnimatedSprite::getProperty(xmlNodePtr node, const char* name,
+ const std::string& def)
+{
+ xmlChar *prop = xmlGetProp(node, BAD_CAST name);
+ if (prop) {
+ std::string val = (char*)prop;
+ xmlFree(prop);
+ return val;
+ }
+ else {
+ return def;
+ }
+}
+
void
-AnimatedSprite::substituteAction(std::string complete, std::string with)
+AnimatedSprite::substituteAction(const std::string& complete,
+ const std::string& with)
{
if (mActions.find(complete) == mActions.end())
{
@@ -315,104 +351,106 @@ AnimatedSprite::substituteAction(std::string complete, std::string with)
AnimatedSprite::~AnimatedSprite()
{
- for (SpritesetIterator i = mSpritesets.begin(); i != mSpritesets.end(); i++)
+ for (SpritesetIterator i = mSpritesets.begin(); i != mSpritesets.end(); ++i)
{
- delete i->second;
+ i->second->decRef();
}
mSpritesets.clear();
}
void
-AnimatedSprite::play(std::string action)
+AnimatedSprite::play(const std::string& action)
{
- if (mAction != action)
+ Actions::iterator iAction;
+ iAction = mActions.find(action);
+
+ if (iAction == mActions.end())
+ {
+ logger->log("Warning: no action \"%s\" defined!", action.c_str());
+ mAction = NULL;
+ return;
+ }
+
+ if (mAction != iAction->second)
{
- mAction = action;
+ mAction = iAction->second;
+ mLastTime = 0;
}
- mLastTime = 0;
+
mSpeed = 1.0f;
}
void
-AnimatedSprite::play(std::string action, int time)
+AnimatedSprite::play(const std::string& action, int time)
{
- if (mAction != action)
+ play(action);
+
+ if (mAction != NULL)
{
- mAction = action;
+ Animation *animation = mAction->getAnimation(mDirection);
+ int animationLength = animation->getLength();
+ mSpeed = (float) animationLength / time;
}
- mLastTime = 0;
- int animationLength = 0;
- Action *nextAction = mActions[mAction];
- Animation *animation = nextAction->getAnimation(mDirection);
- animationLength = animation->getLength();
- mSpeed = (float)animationLength / time;
}
void
AnimatedSprite::update(int time)
{
- // avoid freaking out at first frame or when tick_time overflows
+ // Avoid freaking out at first frame or when tick_time overflows
if (time < mLastTime || mLastTime == 0) mLastTime = time;
- // if not enough time have passed yet, do nothing
+ // If not enough time have passed yet, do nothing
if (time > mLastTime)
{
- Action *action = mActions[mAction];
- Animation *animation = action->getAnimation(mDirection);
- animation->update((unsigned int)((time - mLastTime) * mSpeed));
- mLastTime = time;
+ if (mAction != NULL)
+ {
+ Animation *animation = mAction->getAnimation(mDirection);
+ animation->update((unsigned int)((time - mLastTime) * mSpeed));
+ mLastTime = time;
+ }
}
}
bool
-AnimatedSprite::draw(Graphics * graphics, Sint32 posX, Sint32 posY)
+AnimatedSprite::draw(Graphics* graphics, Sint32 posX, Sint32 posY) const
{
- Sint32 offsetX, offsetY;
- Action *action = mActions[mAction];
- Spriteset *spriteset = mSpritesets[action->getImageset()];
- Animation *animation = action->getAnimation(mDirection);
-
- if (animation->getCurrentPhase() >= 0)
- {
- Image *image = spriteset->get(animation->getCurrentPhase());
- offsetX = animation->getOffsetX();
- offsetY = animation->getOffsetY();
- return graphics->drawImage(image, posX + offsetX, posY + offsetY);
- }
- else
+ if (mAction != NULL)
{
- return false;
+ Animation *animation = mAction->getAnimation(mDirection);
+
+ if (animation->getCurrentPhase() >= 0)
+ {
+ Spriteset *spriteset = mAction->getSpriteset();
+ Image *image = spriteset->get(animation->getCurrentPhase());
+ Sint32 offsetX = animation->getOffsetX();
+ Sint32 offsetY = animation->getOffsetY();
+ return graphics->drawImage(image, posX + offsetX, posY + offsetY);
+ }
}
+
+ return false;
}
-Image *
-AnimatedSprite::getCurrentFrame()
+int
+AnimatedSprite::getWidth() const
{
- Action *action = mActions[mAction];
- Spriteset *spriteset = mSpritesets[action->getImageset()];
- Animation *animation = action->getAnimation(mDirection);
- if (animation->getCurrentPhase() >= 0)
+ if (mAction != NULL)
{
- return spriteset->get(animation->getCurrentPhase());
+ Spriteset *spriteset = mAction->getSpriteset();
+ return spriteset->getWidth();
}
- else
- {
- return NULL;
- }
-}
-int
-AnimatedSprite::getWidth()
-{
- Action *action = mActions[mAction];
- Spriteset *spriteset = mSpritesets[action->getImageset()];
- return spriteset->getWidth();
+ return 0;
}
int
-AnimatedSprite::getHeight()
+AnimatedSprite::getHeight() const
{
- Action *action = mActions[mAction];
- Spriteset *spriteset = mSpritesets[action->getImageset()];
- return spriteset->getHeight();
+ if (mAction != NULL)
+ {
+ Spriteset *spriteset = mAction->getSpriteset();
+ return spriteset->getHeight();
+ }
+
+ return 0;
}
diff --git a/src/animation.h b/src/animation.h
index 4f7d57a9..c5adb873 100644
--- a/src/animation.h
+++ b/src/animation.h
@@ -28,11 +28,16 @@
#include <map>
#include <string>
+#include <libxml/tree.h>
+
#include "graphics.h"
class Image;
class Spriteset;
+/**
+ * A single frame in an animation, with a delay and an offset.
+ */
struct AnimationPhase
{
int image;
@@ -41,19 +46,26 @@ struct AnimationPhase
int offsetY;
};
+/**
+ * An animation consists of several frames, each with their own delay and
+ * offset.
+ */
class Animation
{
public:
+ /**
+ * Constructor.
+ */
Animation();
void addPhase(int image, unsigned int delay, int offsetX, int offsetY);
void update(unsigned int time);
- int getCurrentPhase();
+ int getCurrentPhase() const;
- int getOffsetX() { return (*iCurrentPhase).offsetX; };
- int getOffsetY() { return (*iCurrentPhase).offsetY; };
+ int getOffsetX() const { return (*iCurrentPhase).offsetX; };
+ int getOffsetY() const { return (*iCurrentPhase).offsetY; };
int getLength();
@@ -63,23 +75,42 @@ class Animation
unsigned int mTime;
};
+/**
+ * An action consists of several animations, one for each direction.
+ */
class Action
{
public:
+ /**
+ * Constructor.
+ */
Action();
+ /**
+ * Destructor.
+ */
~Action();
- void setImageset(std::string imageset) { mImageset = imageset; }
+ /**
+ * Sets the spriteset used by this action.
+ */
+ void
+ setSpriteset(Spriteset *spriteset) { mSpriteset = spriteset; }
- std::string getImageset() { return mImageset; }
+ /**
+ * Returns the spriteset used by this action.
+ */
+ Spriteset*
+ getSpriteset() const { return mSpriteset; }
- void setAnimation(std::string direction, Animation *animation);
+ void
+ setAnimation(const std::string& direction, Animation *animation);
- Animation *getAnimation(std::string direction); // { return mAnimations[direction]; }
+ Animation*
+ getAnimation(const std::string& direction) const;
protected:
- std::string mImageset;
+ Spriteset *mSpriteset;
typedef std::map<std::string, Animation*> Animations;
typedef Animations::iterator AnimationIterator;
Animations mAnimations;
@@ -94,7 +125,7 @@ class AnimatedSprite
/**
* Constructor.
*/
- AnimatedSprite(std::string animationFile, int variant);
+ AnimatedSprite(const std::string& animationFile, int variant);
/**
* Destructor.
@@ -104,12 +135,14 @@ class AnimatedSprite
/**
* Sets a new action using the current direction.
*/
- void play(std::string action);
+ void
+ play(const std::string& action);
/**
* Plays an action in a specified time.
*/
- void play(std::string action, int time);
+ void
+ play(const std::string& action, int time);
/**
* Inform the animation of the passed time so that it can output the
@@ -119,45 +152,66 @@ class AnimatedSprite
/**
* Draw the current animation phase at the coordinates given in screen
- * pixels
- */
- bool draw(Graphics * graphics, Sint32 posX, Sint32 posY);
-
- /**
- * Draw the current animation phase.
+ * pixels.
*/
- Image *getCurrentFrame();
+ bool
+ draw(Graphics* graphics, Sint32 posX, Sint32 posY) const;
/**
* gets the width in pixels of the current animation phase.
*/
- int getWidth();
+ int
+ getWidth() const;
/**
* gets the height in pixels of the current animation phase.
*/
- int getHeight();
+ int
+ getHeight() const;
/**
* Sets the direction.
*/
- void setDirection(std::string direction) { mDirection = direction; }
+ void
+ setDirection(const std::string& direction)
+ {
+ mDirection = direction;
+ }
protected:
/**
* When there are no animations defined for the action "complete", its
* animations become a copy of those of the action "with".
*/
- void substituteAction(std::string complete, std::string with);
+ void
+ substituteAction(const std::string& complete,
+ const std::string& with);
typedef std::map<std::string, Spriteset*> Spritesets;
typedef Spritesets::iterator SpritesetIterator;
Spritesets mSpritesets;
typedef std::map<std::string, Action*> Actions;
Actions mActions;
- std::string mAction, mDirection;
+ Action *mAction;
+ std::string mDirection;
int mLastTime;
float mSpeed;
+
+ private:
+ /**
+ * Gets an integer property from an xmlNodePtr.
+ *
+ * TODO: Same function is present in MapReader. Should probably be
+ * TODO: shared in a static utility class.
+ */
+ static int
+ getProperty(xmlNodePtr node, const char* name, int def);
+
+ /**
+ * Gets a string property from an xmlNodePtr.
+ */
+ static std::string
+ getProperty(xmlNodePtr node, const char* name, const std::string& def);
};
#endif
diff --git a/src/being.cpp b/src/being.cpp
index d34ea43e..437023d4 100644
--- a/src/being.cpp
+++ b/src/being.cpp
@@ -28,7 +28,7 @@
#include "log.h"
#include "map.h"
-#include "graphic/spriteset.h"
+#include "resources/spriteset.h"
#include "gui/gui.h"
@@ -65,9 +65,12 @@ Being::Being(Uint32 id, Uint16 job, Map *map):
Being::~Being()
{
- for (int i =0; i < VECTOREND_SPRITE; i++)
+ for (int i = 0; i < VECTOREND_SPRITE; i++)
{
- delete mSprites[i];
+ if (mSprites[i] != NULL)
+ {
+ delete mSprites[i];
+ }
}
clearPath();
@@ -266,7 +269,6 @@ Being::setDirection(Uint8 direction)
{
if (mSprites[i] != NULL) mSprites[i]->setDirection(dir);
}
-
}
void
diff --git a/src/being.h b/src/being.h
index 6fac98b7..6d2bada6 100644
--- a/src/being.h
+++ b/src/being.h
@@ -371,7 +371,7 @@ class Being : public Sprite
bool mShowSpeech, mShowDamage;
Sint32 mPx, mPy; /**< Pixel coordinates */
- std::vector<AnimatedSprite *>mSprites;
+ std::vector<AnimatedSprite*> mSprites;
};
#endif
diff --git a/src/engine.cpp b/src/engine.cpp
index c5cf5c1a..b1fb9b4b 100644
--- a/src/engine.cpp
+++ b/src/engine.cpp
@@ -38,8 +38,6 @@
#include "map.h"
#include "sound.h"
-#include "graphic/spriteset.h"
-
#include "gui/gui.h"
#include "gui/minimap.h"
@@ -49,6 +47,7 @@
#include "resources/itemmanager.h"
#include "resources/mapreader.h"
#include "resources/resourcemanager.h"
+#include "resources/spriteset.h"
#include "utils/dtor.h"
#include "utils/tostring.h"
@@ -75,12 +74,12 @@ Engine::Engine(Network *network):
// Load the sprite sets
ResourceManager *resman = ResourceManager::getInstance();
- npcset = resman->createSpriteset("graphics/sprites/npcs.png", 50, 80);
- emotionset = resman->createSpriteset("graphics/sprites/emotions.png",
+ npcset = resman->getSpriteset("graphics/sprites/npcs.png", 50, 80);
+ emotionset = resman->getSpriteset("graphics/sprites/emotions.png",
30, 32);
for (int i = 0; i < 2; i++)
{
- Spriteset *tmp = ResourceManager::getInstance()->createSpriteset(
+ Spriteset *tmp = ResourceManager::getInstance()->getSpriteset(
"graphics/sprites/weapon" + toString(i) + ".png", 64, 64);
if (!tmp) {
logger->error("Unable to load weaponset");
@@ -88,11 +87,10 @@ Engine::Engine(Network *network):
weaponset.push_back(tmp);
}
}
- itemset = resman->createSpriteset("graphics/sprites/items.png", 32, 32);
+ itemset = resman->getSpriteset("graphics/sprites/items.png", 32, 32);
if (!npcset) logger->error("Unable to load NPC spriteset!");
if (!emotionset) logger->error("Unable to load emotions spriteset!");
- //if (!weaponset) logger->error("Unable to load weapon spriteset!");
if (!itemset) logger->error("Unable to load item spriteset!");
// Initialize item manager
@@ -102,11 +100,16 @@ Engine::Engine(Network *network):
Engine::~Engine()
{
// Delete sprite sets
- delete npcset;
- delete emotionset;
- for_each(weaponset.begin(), weaponset.end(), make_dtor(weaponset));
+ npcset->decRef();
+ emotionset->decRef();
+ itemset->decRef();
+
+ std::vector<Spriteset *>::iterator iter;
+ for (iter = weaponset.begin(); iter != weaponset.end(); ++iter)
+ {
+ (*iter)->decRef();
+ }
weaponset.clear();
- delete itemset;
delete itemDb;
diff --git a/src/floor_item.cpp b/src/floor_item.cpp
index 4573d646..1581b201 100644
--- a/src/floor_item.cpp
+++ b/src/floor_item.cpp
@@ -25,10 +25,9 @@
#include "map.h"
-#include "graphic/spriteset.h"
-
#include "resources/itemmanager.h"
#include "resources/iteminfo.h"
+#include "resources/spriteset.h"
extern Spriteset *itemset;
diff --git a/src/gui/equipmentwindow.cpp b/src/gui/equipmentwindow.cpp
index fd979beb..bef39dff 100644
--- a/src/gui/equipmentwindow.cpp
+++ b/src/gui/equipmentwindow.cpp
@@ -28,10 +28,9 @@
#include "../item.h"
#include "../log.h"
-#include "../graphic/spriteset.h"
-
#include "../resources/iteminfo.h"
#include "../resources/resourcemanager.h"
+#include "../resources/spriteset.h"
#include "../utils/tostring.h"
@@ -42,14 +41,14 @@ EquipmentWindow::EquipmentWindow(Equipment *equipment):
setDefaultSize(5, 230, 200, 120);
loadWindowState();
- mItemset = ResourceManager::getInstance()->createSpriteset(
+ mItemset = ResourceManager::getInstance()->getSpriteset(
"graphics/sprites/items.png", 32, 32);
if (!mItemset) logger->error("Unable to load items.png");
}
EquipmentWindow::~EquipmentWindow()
{
- delete mItemset;
+ mItemset->decRef();
}
void EquipmentWindow::draw(gcn::Graphics *graphics)
diff --git a/src/gui/itemcontainer.cpp b/src/gui/itemcontainer.cpp
index 9b8dc09b..edcf9764 100644
--- a/src/gui/itemcontainer.cpp
+++ b/src/gui/itemcontainer.cpp
@@ -30,11 +30,10 @@
#include "../item.h"
#include "../log.h"
-#include "../graphic/spriteset.h"
-
#include "../resources/image.h"
#include "../resources/iteminfo.h"
#include "../resources/resourcemanager.h"
+#include "../resources/spriteset.h"
#include "../utils/tostring.h"
@@ -42,7 +41,7 @@ ItemContainer::ItemContainer(Inventory *inventory):
mInventory(inventory)
{
ResourceManager *resman = ResourceManager::getInstance();
- mItemset = resman->createSpriteset("graphics/sprites/items.png", 32, 32);
+ mItemset = resman->getSpriteset("graphics/sprites/items.png", 32, 32);
if (!mItemset) logger->error("Unable to load items.png");
mSelImg = resman->getImage("graphics/gui/selection.png");
@@ -56,7 +55,7 @@ ItemContainer::ItemContainer(Inventory *inventory):
ItemContainer::~ItemContainer()
{
- delete mItemset;
+ mItemset->decRef();
mSelImg->decRef();
}
diff --git a/src/gui/playerbox.cpp b/src/gui/playerbox.cpp
index d5c70ffe..f0ed9b71 100644
--- a/src/gui/playerbox.cpp
+++ b/src/gui/playerbox.cpp
@@ -27,10 +27,10 @@
#include "../graphics.h"
#include "../graphic/imagerect.h"
-#include "../graphic/spriteset.h"
#include "../resources/image.h"
#include "../resources/resourcemanager.h"
+#include "../resources/spriteset.h"
#include "../utils/dtor.h"
diff --git a/src/log.cpp b/src/log.cpp
index d40927c5..3d101d29 100644
--- a/src/log.cpp
+++ b/src/log.cpp
@@ -53,7 +53,8 @@ void Logger::setLogFile(const std::string &logFilename)
void Logger::log(const char *log_text, ...)
{
- if (!mLogFile.is_open()) {
+ if (!mLogFile.is_open())
+ {
return;
}
diff --git a/src/main.cpp b/src/main.cpp
index 5ecb4f35..28debf47 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -56,8 +56,6 @@
#endif
#include "sound.h"
-#include "graphic/spriteset.h"
-
#include "gui/char_server.h"
#include "gui/char_select.h"
#include "gui/connection.h"
@@ -76,6 +74,7 @@
#include "resources/image.h"
#include "resources/resourcemanager.h"
+#include "resources/spriteset.h"
#include "utils/dtor.h"
#include "utils/tostring.h"
@@ -244,17 +243,17 @@ void init_engine()
// Initialize for drawing
graphics->_beginDraw();
- playerset[0] = resman->createSpriteset(
+ playerset[0] = resman->getSpriteset(
"graphics/sprites/player_male_base.png", 64, 64);
if (!playerset[0]) logger->error("Couldn't load male player spriteset!");
- playerset[1] = resman->createSpriteset(
+ playerset[1] = resman->getSpriteset(
"graphics/sprites/player_female_base.png", 64, 64);
if (!playerset[1]) logger->error("Couldn't load female player spriteset!");
for (int i=0; i < NR_HAIR_STYLES; i++)
{
- Spriteset *tmp = ResourceManager::getInstance()->createSpriteset(
+ Spriteset *tmp = ResourceManager::getInstance()->getSpriteset(
"graphics/sprites/hairstyle" + toString(i + 1) + ".png",
40, 40);
if (!tmp) {
@@ -288,10 +287,16 @@ void exit_engine()
config.write();
delete gui;
delete graphics;
- for_each(hairset.begin(), hairset.end(), make_dtor(hairset));
+
+ std::vector<Spriteset *>::iterator iter;
+ for (iter = hairset.begin(); iter != hairset.end(); ++iter)
+ {
+ (*iter)->decRef();
+ }
hairset.clear();
- delete playerset[0];
- delete playerset[1];
+
+ playerset[0]->decRef();
+ playerset[1]->decRef();
// Shutdown libxml
xmlCleanupParser();
diff --git a/src/resources/mapreader.cpp b/src/resources/mapreader.cpp
index 48f23aea..af79480a 100644
--- a/src/resources/mapreader.cpp
+++ b/src/resources/mapreader.cpp
@@ -28,14 +28,13 @@
#include "resourcemanager.h"
#include "image.h"
+#include "spriteset.h"
#include "../base64.h"
#include "../log.h"
#include "../map.h"
#include "../tileset.h"
-#include "../graphic/spriteset.h"
-
const unsigned int DEFAULT_TILE_WIDTH = 32;
const unsigned int DEFAULT_TILE_HEIGHT = 32;
diff --git a/src/resources/resourcemanager.cpp b/src/resources/resourcemanager.cpp
index a6dc692b..26899d77 100644
--- a/src/resources/resourcemanager.cpp
+++ b/src/resources/resourcemanager.cpp
@@ -30,11 +30,10 @@
#include "image.h"
#include "music.h"
#include "soundeffect.h"
+#include "spriteset.h"
#include "../log.h"
-#include "../graphic/spriteset.h"
-
ResourceManager *ResourceManager::instance = NULL;
@@ -44,25 +43,39 @@ ResourceManager::ResourceManager()
ResourceManager::~ResourceManager()
{
- // Create our resource iterator.
+ // Release any remaining spritesets first because they depend on images
ResourceIterator iter = mResources.begin();
+ while (iter != mResources.end())
+ {
+ if (dynamic_cast<Spriteset*>(iter->second) != NULL)
+ {
+ cleanUp(iter->second);
+ ResourceIterator toErase = iter;
+ ++iter;
+ mResources.erase(toErase);
+ }
+ else
+ {
+ ++iter;
+ }
+ }
- // Iterate through and release references until objects are deleted.
+ // Release remaining resources, logging the number of dangling references.
while (!mResources.empty())
{
- Resource *res = mResources.begin()->second;
- std::string id = res->getIdPath();
- int references = 0;
-
- references += res->mRefCount;
- release(res->mIdPath);
- delete res;
-
- logger->log("ResourceManager::~ResourceManager() cleaned up %d "
- "references to %s", references, id.c_str());
+ cleanUp(mResources.begin()->second);
+ mResources.erase(mResources.begin());
}
}
+void
+ResourceManager::cleanUp(Resource *res)
+{
+ logger->log("ResourceManager::~ResourceManager() cleaning up %d "
+ "references to %s", res->mRefCount, res->mIdPath.c_str());
+ delete res;
+}
+
bool
ResourceManager::setWriteDir(const std::string &path)
{
@@ -151,42 +164,55 @@ ResourceManager::get(const E_RESOURCE_TYPE &type, const std::string &idPath)
mResources[idPath] = resource;
}
- // Return NULL if the object could not be created.
+ // Returns NULL if the object could not be created.
return resource;
}
Image*
ResourceManager::getImage(const std::string &idPath)
{
- return (Image*)get(IMAGE, idPath);
+ return dynamic_cast<Image*>(get(IMAGE, idPath));
}
Music*
ResourceManager::getMusic(const std::string &idPath)
{
- return (Music*)get(MUSIC, idPath);
+ return dynamic_cast<Music*>(get(MUSIC, idPath));
}
SoundEffect*
ResourceManager::getSoundEffect(const std::string &idPath)
{
- return (SoundEffect*)get(SOUND_EFFECT, idPath);
+ return dynamic_cast<SoundEffect*>(get(SOUND_EFFECT, idPath));
}
-Spriteset* ResourceManager::createSpriteset(const std::string &imagePath,
- int w, int h)
+Spriteset*
+ResourceManager::getSpriteset(const std::string &imagePath, int w, int h)
{
- Image *img;
+ std::stringstream ss;
+ ss << imagePath << "[" << w << "x" << h << "]";
+ const std::string idPath = ss.str();
+
+ ResourceIterator resIter = mResources.find(idPath);
+
+ if (resIter != mResources.end()) {
+ resIter->second->incRef();
+ return dynamic_cast<Spriteset*>(resIter->second);
+ }
+
+ Image *img = getImage(imagePath);
- if (!(img = getImage(imagePath))) {
+ if (!img) {
return NULL;
}
- Spriteset *result = new Spriteset(img, w, h);
+ Spriteset *spriteset = new Spriteset(idPath, img, w, h);
+ spriteset->incRef();
+ mResources[idPath] = spriteset;
img->decRef();
- return result;
+ return spriteset;
}
void
diff --git a/src/resources/resourcemanager.h b/src/resources/resourcemanager.h
index 8d60ae8c..f254a8b4 100644
--- a/src/resources/resourcemanager.h
+++ b/src/resources/resourcemanager.h
@@ -136,7 +136,7 @@ class ResourceManager
* Creates a spriteset based on the image referenced by the given
* path and the supplied sprite sizes
*/
- Spriteset* createSpriteset(const std::string &imagePath, int w, int h);
+ Spriteset* getSpriteset(const std::string &imagePath, int w, int h);
/**
* Releases a resource, removing it from the set of loaded resources.
@@ -177,6 +177,12 @@ class ResourceManager
deleteInstance();
private:
+ /**
+ * Deletes the resource after logging a cleanup message.
+ */
+ static void
+ cleanUp(Resource *resource);
+
static ResourceManager *instance;
typedef std::map<std::string, Resource*> Resources;
typedef Resources::iterator ResourceIterator;
diff --git a/src/graphic/spriteset.cpp b/src/resources/spriteset.cpp
index 3b190f31..9b09f1e5 100644
--- a/src/graphic/spriteset.cpp
+++ b/src/resources/spriteset.cpp
@@ -25,11 +25,14 @@
#include "../log.h"
-#include "../resources/image.h"
+#include "image.h"
#include "../utils/dtor.h"
-Spriteset::Spriteset(Image *img, int width, int height)
+Spriteset::Spriteset(const std::string& idPath,
+ Image *img,
+ int width, int height):
+ Resource(idPath)
{
for (int y = 0; y + height <= img->getHeight(); y += height)
{
@@ -47,7 +50,7 @@ Spriteset::~Spriteset()
for_each(mSpriteset.begin(), mSpriteset.end(), make_dtor(mSpriteset));
}
-Image *
+Image*
Spriteset::get(size_type i)
{
if (i > mSpriteset.size())
diff --git a/src/graphic/spriteset.h b/src/resources/spriteset.h
index 94ccb742..c51e6a75 100644
--- a/src/graphic/spriteset.h
+++ b/src/resources/spriteset.h
@@ -26,18 +26,21 @@
#include <vector>
+#include "resource.h"
+
class Image;
/**
* Stores a complete set of sprites.
*/
-class Spriteset {
+class Spriteset : public Resource
+{
public:
/*
* Cuts the passed image in a grid of sub images.
*/
- Spriteset(Image *img, int w, int h);
+ Spriteset(const std::string& idPath, Image *img, int w, int h);
/**
* Destructor.
@@ -49,14 +52,14 @@ class Spriteset {
int getHeight() { return mHeight; };
typedef std::vector<Image*>::size_type size_type;
- Image * get(size_type i);
+ Image* get(size_type i);
size_type size() { return mSpriteset.size(); }
private:
// Vector storing the whole spriteset.
std::vector<Image*> mSpriteset;
- //height and width of the images in the spriteset
+ // Height and width of the images in the spriteset
int mHeight;
int mWidth;
};
diff --git a/src/tileset.h b/src/tileset.h
index 5fa4ade1..27bc28c3 100644
--- a/src/tileset.h
+++ b/src/tileset.h
@@ -24,7 +24,7 @@
#ifndef _TMW_TILESET_H_
#define _TMW_TILESET_H_
-#include "graphic/spriteset.h"
+#include "resources/spriteset.h"
/**
* A tileset, which is basically just a spriteset but it stores a firstgid.
@@ -36,7 +36,7 @@ class Tileset : public Spriteset
* Constructor.
*/
Tileset(Image *img, int w, int h, int firstGid):
- Spriteset(img, w, h),
+ Spriteset("", img, w, h),
mFirstGid(firstGid)
{
}