summaryrefslogtreecommitdiff
path: root/src/resources/spritedef.cpp
diff options
context:
space:
mode:
authorBjørn Lindeijer <bjorn@lindeijer.nl>2006-11-19 21:24:36 +0000
committerBjørn Lindeijer <bjorn@lindeijer.nl>2006-11-19 21:24:36 +0000
commit7ac7d0e030464f744546b4e6183a7242f640d5d3 (patch)
treef19831b29511d46e8aba45ace6017c8e6afe815b /src/resources/spritedef.cpp
parentb7cfcffd7a156e19dfa9882d67426f4fa6edef57 (diff)
downloadmana-client-7ac7d0e030464f744546b4e6183a7242f640d5d3.tar.gz
mana-client-7ac7d0e030464f744546b4e6183a7242f640d5d3.tar.bz2
mana-client-7ac7d0e030464f744546b4e6183a7242f640d5d3.tar.xz
mana-client-7ac7d0e030464f744546b4e6183a7242f640d5d3.zip
Separated sprite definition from playback.
Diffstat (limited to 'src/resources/spritedef.cpp')
-rw-r--r--src/resources/spritedef.cpp329
1 files changed, 329 insertions, 0 deletions
diff --git a/src/resources/spritedef.cpp b/src/resources/spritedef.cpp
new file mode 100644
index 00000000..21eae6e0
--- /dev/null
+++ b/src/resources/spritedef.cpp
@@ -0,0 +1,329 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World 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
+ * any later version.
+ *
+ * The Mana World 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 The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id$
+ */
+
+#include "spritedef.h"
+
+#include "../animation.h"
+#include "../action.h"
+#include "../graphics.h"
+#include "../log.h"
+
+#include "resourcemanager.h"
+#include "spriteset.h"
+#include "image.h"
+
+#include "../utils/xml.h"
+
+SpriteDef::SpriteDef(const std::string &idPath,
+ const std::string &file, int variant):
+ Resource(idPath),
+ mAction(NULL),
+ mDirection(DIRECTION_DOWN),
+ mLastTime(0)
+{
+ load(file, variant);
+}
+
+Action*
+SpriteDef::getAction(SpriteAction action) const
+{
+ Actions::const_iterator i = mActions.find(action);
+
+ if (i == mActions.end())
+ {
+ logger->log("Warning: no action \"%u\" defined!", action);
+ return NULL;
+ }
+
+ return i->second;
+}
+
+void
+SpriteDef::load(const std::string &animationFile, int variant)
+{
+ int size;
+ ResourceManager *resman = ResourceManager::getInstance();
+ char *data = (char*) resman->loadFile(animationFile.c_str(), size);
+
+ if (!data) {
+ logger->error("Animation: Could not find " + animationFile + "!");
+ }
+
+ xmlDocPtr doc = xmlParseMemory(data, size);
+ free(data);
+
+ if (!doc) {
+ logger->error(
+ "Animation: Error while parsing animation definition file!");
+ }
+
+ xmlNodePtr node = xmlDocGetRootElement(doc);
+ if (!node || !xmlStrEqual(node->name, BAD_CAST "sprite")) {
+ logger->error(
+ "Animation: this is not a valid animation definition file!");
+ }
+
+ // Get the variant
+ int variant_num = XML::getProperty(node, "variants", 0);
+ int variant_offset = XML::getProperty(node, "variant_offset", 0);
+
+ if (variant_num > 0 && variant < variant_num ) {
+ variant_offset *= variant;
+ } else {
+ variant_offset = 0;
+ }
+
+ for (node = node->xmlChildrenNode; node != NULL; node = node->next)
+ {
+ if (xmlStrEqual(node->name, BAD_CAST "imageset"))
+ {
+ int width = XML::getProperty(node, "width", 0);
+ int height = XML::getProperty(node, "height", 0);
+ std::string name = XML::getProperty(node, "name", "");
+ std::string imageSrc = XML::getProperty(node, "src", "");
+
+ Spriteset *spriteset =
+ resman->getSpriteset(imageSrc, width, height);
+
+ if (!spriteset) {
+ logger->error("Couldn't load spriteset!");
+ }
+
+ mSpritesets[name] = spriteset;
+ }
+ // get action
+ else if (xmlStrEqual(node->name, BAD_CAST "action"))
+ {
+ std::string actionName = XML::getProperty(node, "name", "");
+ std::string imagesetName = XML::getProperty(node, "imageset", "");
+
+ SpritesetIterator si = mSpritesets.find(imagesetName);
+ if (si == mSpritesets.end()) {
+ logger->log("Warning: imageset \"%s\" not defined in %s",
+ imagesetName.c_str(),
+ animationFile.c_str());
+
+ // skip loading animations
+ continue;
+ }
+ Spriteset *imageset = si->second;
+
+ SpriteAction actionType = makeSpriteAction(actionName);
+ if (actionType == ACTION_INVALID)
+ {
+ logger->log("Warning: Unknown action \"%s\" defined in %s",
+ actionName.c_str(),
+ animationFile.c_str());
+ continue;
+ }
+ Action *action = new Action();
+ mActions[actionType] = action;
+
+ // When first action set it as default direction
+ if (mActions.empty())
+ {
+ mActions[ACTION_DEFAULT] = action;
+ }
+
+
+ // get animations
+ for (xmlNodePtr animationNode = node->xmlChildrenNode;
+ animationNode != NULL;
+ animationNode = animationNode->next)
+ {
+ // We're only interested in animations
+ if (!xmlStrEqual(animationNode->name, BAD_CAST "animation"))
+ continue;
+
+ std::string directionName =
+ XML::getProperty(animationNode, "direction", "");
+ SpriteDirection directionType =
+ makeSpriteDirection(directionName);
+
+ if (directionType == DIRECTION_INVALID)
+ {
+ logger->log("Warning: Unknown direction \"%s\" defined "
+ "for action %s in %s",
+ directionName.c_str(),
+ actionName.c_str(),
+ animationFile.c_str());
+ continue;
+ }
+
+ Animation *animation = new Animation();
+ action->setAnimation(directionType, animation);
+
+ // Get animation phases
+ for (xmlNodePtr phaseNode = animationNode->xmlChildrenNode;
+ phaseNode != NULL;
+ phaseNode = phaseNode->next)
+ {
+ int delay = XML::getProperty(phaseNode, "delay", 0);
+
+ if (xmlStrEqual(phaseNode->name, BAD_CAST "frame"))
+ {
+ int index = XML::getProperty(phaseNode, "index", -1);
+ int offsetX = XML::getProperty(phaseNode, "offsetX", 0);
+ int offsetY = XML::getProperty(phaseNode, "offsetY", 0);
+
+ offsetY -= imageset->getHeight() - 32;
+ offsetX -= imageset->getWidth() / 2 - 16;
+ Image *img = imageset->get(index + variant_offset);
+ animation->addPhase(img, delay, offsetX, offsetY);
+ }
+ else if (xmlStrEqual(phaseNode->name, BAD_CAST "sequence"))
+ {
+ int start = XML::getProperty(phaseNode, "start", 0);
+ int end = XML::getProperty(phaseNode, "end", 0);
+ int offsetY = -imageset->getHeight() + 32;
+ int offsetX = -imageset->getWidth() / 2 + 16;
+ while (end >= start)
+ {
+ Image *img = imageset->get(start + variant_offset);
+ animation->addPhase(img, delay, offsetX, offsetY);
+ start++;
+ }
+ }
+ else if (xmlStrEqual(phaseNode->name, BAD_CAST "end"))
+ {
+ animation->addTerminator();
+ }
+ } // for phaseNode
+ } // for animationNode
+ } // if "<imageset>" else if "<action>"
+ } // for node
+
+ // Complete missing actions
+ substituteAction(ACTION_STAND, ACTION_DEFAULT);
+ substituteAction(ACTION_WALK, ACTION_STAND);
+ substituteAction(ACTION_WALK, ACTION_RUN);
+ substituteAction(ACTION_ATTACK, ACTION_STAND);
+ substituteAction(ACTION_ATTACK_SWING, ACTION_ATTACK);
+ substituteAction(ACTION_ATTACK_STAB, ACTION_ATTACK_SWING);
+ substituteAction(ACTION_ATTACK_BOW, ACTION_ATTACK_STAB);
+ substituteAction(ACTION_ATTACK_THROW, ACTION_ATTACK_SWING);
+ substituteAction(ACTION_CAST_MAGIC, ACTION_ATTACK_SWING);
+ substituteAction(ACTION_USE_ITEM, ACTION_CAST_MAGIC);
+ substituteAction(ACTION_SIT, ACTION_STAND);
+ substituteAction(ACTION_SLEEP, ACTION_SIT);
+ substituteAction(ACTION_HURT, ACTION_STAND);
+ substituteAction(ACTION_DEAD, ACTION_HURT);
+
+ xmlFreeDoc(doc);
+}
+
+void
+SpriteDef::substituteAction(SpriteAction complete, SpriteAction with)
+{
+ if (mActions.find(complete) == mActions.end())
+ {
+ Actions::iterator i = mActions.find(with);
+ if (i != mActions.end()) {
+ mActions[complete] = i->second;
+ }
+ }
+}
+
+SpriteDef::~SpriteDef()
+{
+ for (SpritesetIterator i = mSpritesets.begin(); i != mSpritesets.end(); ++i)
+ {
+ i->second->decRef();
+ }
+}
+
+SpriteAction
+SpriteDef::makeSpriteAction(const std::string& action)
+{
+ if (action == "" || action == "default") {
+ return ACTION_DEFAULT;
+ }
+ if (action == "stand") {
+ return ACTION_STAND;
+ }
+ else if (action == "walk") {
+ return ACTION_WALK;
+ }
+ else if (action == "run") {
+ return ACTION_RUN;
+ }
+ else if (action == "attack") {
+ return ACTION_ATTACK;
+ }
+ else if (action == "attack_swing") {
+ return ACTION_ATTACK_SWING;
+ }
+ else if (action == "attack_stab") {
+ return ACTION_ATTACK_STAB;
+ }
+ else if (action == "attack_bow") {
+ return ACTION_ATTACK_BOW;
+ }
+ else if (action == "attack_throw") {
+ return ACTION_ATTACK_THROW;
+ }
+ else if (action == "cast_magic") {
+ return ACTION_CAST_MAGIC;
+ }
+ else if (action == "use_item") {
+ return ACTION_USE_ITEM;
+ }
+ else if (action == "sit") {
+ return ACTION_SIT;
+ }
+ else if (action == "sleep") {
+ return ACTION_SLEEP;
+ }
+ else if (action == "hurt") {
+ return ACTION_HURT;
+ }
+ else if (action == "dead") {
+ return ACTION_DEAD;
+ }
+ else {
+ return ACTION_INVALID;
+ }
+}
+
+SpriteDirection
+SpriteDef::makeSpriteDirection(const std::string& direction)
+{
+ if (direction == "" || direction == "default") {
+ return DIRECTION_DEFAULT;
+ }
+ else if (direction == "up") {
+ return DIRECTION_UP;
+ }
+ else if (direction == "left") {
+ return DIRECTION_LEFT;
+ }
+ else if (direction == "right") {
+ return DIRECTION_RIGHT;
+ }
+ else if (direction == "down") {
+ return DIRECTION_DOWN;
+ }
+ else {
+ return DIRECTION_INVALID;
+ };
+}