summaryrefslogtreecommitdiff
path: root/src/resources
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
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')
-rw-r--r--src/resources/resourcemanager.cpp47
-rw-r--r--src/resources/resourcemanager.h17
-rw-r--r--src/resources/spritedef.cpp329
-rw-r--r--src/resources/spritedef.h130
-rw-r--r--src/resources/spriteset.h6
5 files changed, 519 insertions, 10 deletions
diff --git a/src/resources/resourcemanager.cpp b/src/resources/resourcemanager.cpp
index e729ecfc..f9a57e87 100644
--- a/src/resources/resourcemanager.cpp
+++ b/src/resources/resourcemanager.cpp
@@ -32,6 +32,7 @@
#include "music.h"
#include "soundeffect.h"
#include "spriteset.h"
+#include "spritedef.h"
#include "../log.h"
@@ -44,11 +45,28 @@ ResourceManager::ResourceManager()
ResourceManager::~ResourceManager()
{
- // Release any remaining spritesets first because they depend on images
+ // Release any remaining spritedefs first because they depend on spritesets
ResourceIterator iter = mResources.begin();
while (iter != mResources.end())
{
- if (dynamic_cast<Spriteset*>(iter->second) != NULL)
+ if (dynamic_cast<SpriteDef*>(iter->second) != 0)
+ {
+ cleanUp(iter->second);
+ ResourceIterator toErase = iter;
+ ++iter;
+ mResources.erase(toErase);
+ }
+ else
+ {
+ ++iter;
+ }
+ }
+
+ // Release any remaining spritesets first because they depend on images
+ iter = mResources.begin();
+ while (iter != mResources.end())
+ {
+ if (dynamic_cast<Spriteset*>(iter->second) != 0)
{
cleanUp(iter->second);
ResourceIterator toErase = iter;
@@ -80,7 +98,7 @@ ResourceManager::cleanUp(Resource *res)
bool
ResourceManager::setWriteDir(const std::string &path)
{
- return (bool)PHYSFS_setWriteDir(path.c_str());
+ return (bool) PHYSFS_setWriteDir(path.c_str());
}
void
@@ -93,7 +111,7 @@ ResourceManager::addToSearchPath(const std::string &path, bool append)
bool
ResourceManager::mkdir(const std::string &path)
{
- return (bool)PHYSFS_mkdir(path.c_str());
+ return (bool) PHYSFS_mkdir(path.c_str());
}
bool
@@ -212,6 +230,27 @@ ResourceManager::getSpriteset(const std::string &imagePath, int w, int h)
return spriteset;
}
+SpriteDef*
+ResourceManager::getSprite(const std::string &path, int variant)
+{
+ std::stringstream ss;
+ ss << path << "[" << variant << "]";
+ const std::string idPath = ss.str();
+
+ ResourceIterator resIter = mResources.find(idPath);
+
+ if (resIter != mResources.end()) {
+ resIter->second->incRef();
+ return dynamic_cast<SpriteDef*>(resIter->second);
+ }
+
+ SpriteDef *sprite = new SpriteDef(idPath, path, variant);
+ sprite->incRef();
+ mResources[idPath] = sprite;
+
+ return sprite;
+}
+
void
ResourceManager::release(const std::string &idPath)
{
diff --git a/src/resources/resourcemanager.h b/src/resources/resourcemanager.h
index 0086b167..4367cd5e 100644
--- a/src/resources/resourcemanager.h
+++ b/src/resources/resourcemanager.h
@@ -34,6 +34,7 @@ class Image;
class Music;
class SoundEffect;
class Spriteset;
+class SpriteDef;
/**
* A class for loading and managing resources.
@@ -113,21 +114,21 @@ class ResourceManager
get(const E_RESOURCE_TYPE &type, const std::string &idPath);
/**
- * Convenience wrapper around ResourceManager::create for loading
+ * Convenience wrapper around ResourceManager::get for loading
* images.
*/
Image*
getImage(const std::string &idPath);
/**
- * Convenience wrapper around ResourceManager::create for loading
+ * Convenience wrapper around ResourceManager::get for loading
* songs.
*/
Music*
getMusic(const std::string &idPath);
/**
- * Convenience wrapper around ResourceManager::create for loading
+ * Convenience wrapper around ResourceManager::get for loading
* samples.
*/
SoundEffect*
@@ -137,7 +138,15 @@ class ResourceManager
* Creates a spriteset based on the image referenced by the given
* path and the supplied sprite sizes
*/
- Spriteset* getSpriteset(const std::string &imagePath, int w, int h);
+ Spriteset*
+ getSpriteset(const std::string &imagePath, int w, int h);
+
+ /**
+ * Creates a sprite definition based on a given path and the supplied
+ * variant.
+ */
+ SpriteDef*
+ getSprite(const std::string &path, int variant);
/**
* Releases a resource, removing it from the set of loaded resources.
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;
+ };
+}
diff --git a/src/resources/spritedef.h b/src/resources/spritedef.h
new file mode 100644
index 00000000..51c47a24
--- /dev/null
+++ b/src/resources/spritedef.h
@@ -0,0 +1,130 @@
+/*
+ * 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$
+ */
+
+#ifndef _TMW_SPRITEDEF_H
+#define _TMW_SPRITEDEF_H
+
+#include "resource.h"
+
+#include <map>
+#include <string>
+
+class Action;
+class Graphics;
+class Spriteset;
+struct AnimationPhase;
+class Animation;
+
+enum SpriteAction
+{
+ ACTION_DEFAULT = 0,
+ ACTION_STAND,
+ ACTION_WALK,
+ ACTION_RUN,
+ ACTION_ATTACK,
+ ACTION_ATTACK_SWING,
+ ACTION_ATTACK_STAB,
+ ACTION_ATTACK_BOW,
+ ACTION_ATTACK_THROW,
+ ACTION_CAST_MAGIC,
+ ACTION_USE_ITEM,
+ ACTION_SIT,
+ ACTION_SLEEP,
+ ACTION_HURT,
+ ACTION_DEAD,
+ ACTION_INVALID
+};
+
+enum SpriteDirection
+{
+ DIRECTION_DEFAULT = 0,
+ DIRECTION_DOWN,
+ DIRECTION_UP,
+ DIRECTION_LEFT,
+ DIRECTION_RIGHT,
+ DIRECTION_INVALID
+};
+
+/**
+ * Defines a class to load an animation.
+ */
+class SpriteDef : public Resource
+{
+ public:
+ /**
+ * Constructor.
+ */
+ SpriteDef(const std::string &idPath,
+ const std::string &file, int variant);
+
+ /**
+ * Destructor.
+ */
+ ~SpriteDef();
+
+ /**
+ * Returns the specified action.
+ */
+ Action*
+ getAction(SpriteAction action) const;
+
+ private:
+ /**
+ * Loads a sprite definition file.
+ */
+ void
+ load(const std::string &file, int variant);
+
+ /**
+ * When there are no animations defined for the action "complete", its
+ * animations become a copy of those of the action "with".
+ */
+ void
+ substituteAction(SpriteAction complete, SpriteAction with);
+
+ /**
+ * Converts a string into a SpriteAction enum.
+ */
+ static SpriteAction
+ makeSpriteAction(const std::string &action);
+
+ /**
+ * Converts a string into a SpriteDirection enum.
+ */
+ static SpriteDirection
+ makeSpriteDirection(const std::string &direction);
+
+
+ typedef std::map<std::string, Spriteset*> Spritesets;
+ typedef Spritesets::iterator SpritesetIterator;
+
+ typedef std::map<SpriteAction, Action*> Actions;
+
+ Spritesets mSpritesets;
+ Actions mActions;
+ Action *mAction;
+ SpriteDirection mDirection;
+ int mLastTime;
+};
+
+#endif
diff --git a/src/resources/spriteset.h b/src/resources/spriteset.h
index c51e6a75..7f6b42df 100644
--- a/src/resources/spriteset.h
+++ b/src/resources/spriteset.h
@@ -32,7 +32,9 @@ class Image;
/**
- * Stores a complete set of sprites.
+ * Stores a set of subimages originating from a single image.
+ *
+ * TODO: Should probably be renamed to ImageSet or TileSet.
*/
class Spriteset : public Resource
{
@@ -40,7 +42,7 @@ class Spriteset : public Resource
/*
* Cuts the passed image in a grid of sub images.
*/
- Spriteset(const std::string& idPath, Image *img, int w, int h);
+ Spriteset(const std::string &idPath, Image *img, int w, int h);
/**
* Destructor.