diff options
author | Bjørn Lindeijer <bjorn@lindeijer.nl> | 2006-07-24 00:13:24 +0000 |
---|---|---|
committer | Bjørn Lindeijer <bjorn@lindeijer.nl> | 2006-07-24 00:13:24 +0000 |
commit | 4789ebb11407eb9402c385f3cc6fa242d91214c2 (patch) | |
tree | 6bf5bed52073ae19ef4b5b08e7fe92af603f04d8 /src/animation.cpp | |
parent | 1b7ff9ad4160fd0ff79d2da658eca8d8c8abf815 (diff) | |
download | mana-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.
Diffstat (limited to 'src/animation.cpp')
-rw-r--r-- | src/animation.cpp | 320 |
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; } |