summaryrefslogtreecommitdiff
path: root/src/animation.cpp
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 /src/animation.cpp
parent1b7ff9ad4160fd0ff79d2da658eca8d8c8abf815 (diff)
downloadmana-client-4789ebb11407eb9402c385f3cc6fa242d91214c2.tar.gz
mana-client-4789ebb11407eb9402c385f3cc6fa242d91214c2.tar.bz2
mana-client-4789ebb11407eb9402c385f3cc6fa242d91214c2.tar.xz
mana-client-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.
Diffstat (limited to 'src/animation.cpp')
-rw-r--r--src/animation.cpp320
1 files changed, 179 insertions, 141 deletions
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;
}