diff options
author | Bjørn Lindeijer <bjorn@lindeijer.nl> | 2006-08-13 11:36:36 +0000 |
---|---|---|
committer | Bjørn Lindeijer <bjorn@lindeijer.nl> | 2006-08-13 11:36:36 +0000 |
commit | afc770043be553998555e9ac1cffca68dc482d48 (patch) | |
tree | 60e99ade9464b0a1de2ec246724a7bfe0957eec4 | |
parent | cfcc1bc3a756185bd39dd858ebbe69b5916ac11b (diff) | |
download | mana-afc770043be553998555e9ac1cffca68dc482d48.tar.gz mana-afc770043be553998555e9ac1cffca68dc482d48.tar.bz2 mana-afc770043be553998555e9ac1cffca68dc482d48.tar.xz mana-afc770043be553998555e9ac1cffca68dc482d48.zip |
Merged cleanups and content changes from the trunk. Also fixed compiling with
OpenGL enabled.
-rw-r--r-- | ChangeLog | 161 | ||||
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/animatedsprite.cpp | 382 | ||||
-rw-r--r-- | src/animatedsprite.h | 178 | ||||
-rw-r--r-- | src/animation.cpp | 387 | ||||
-rw-r--r-- | src/animation.h | 135 | ||||
-rw-r--r-- | src/being.cpp | 169 | ||||
-rw-r--r-- | src/being.h | 11 | ||||
-rw-r--r-- | src/configuration.cpp | 56 | ||||
-rw-r--r-- | src/engine.cpp | 15 | ||||
-rw-r--r-- | src/game.cpp | 30 | ||||
-rw-r--r-- | src/gui/browserbox.h | 1 | ||||
-rw-r--r-- | src/gui/chat.cpp | 81 | ||||
-rw-r--r-- | src/gui/chat.h | 9 | ||||
-rw-r--r-- | src/gui/gui.cpp | 7 | ||||
-rw-r--r-- | src/gui/setup_video.cpp | 1 | ||||
-rw-r--r-- | src/gui/updatewindow.cpp | 2 | ||||
-rw-r--r-- | src/main.cpp | 29 | ||||
-rw-r--r-- | src/monster.cpp | 4 | ||||
-rw-r--r-- | src/npc.cpp | 2 | ||||
-rw-r--r-- | src/openglgraphics.cpp | 2 | ||||
-rw-r--r-- | src/player.cpp | 47 | ||||
-rw-r--r-- | src/resources/image.h | 2 | ||||
-rw-r--r-- | src/resources/itemmanager.cpp | 4 | ||||
-rw-r--r-- | src/resources/mapreader.cpp | 214 | ||||
-rw-r--r-- | src/resources/openglsdlimageloader.cpp | 6 |
26 files changed, 1086 insertions, 851 deletions
@@ -1,11 +1,82 @@ +2006-08-13 Bjørn Lindeijer <bjorn@lindeijer.nl> + + * src/openglgraphics.cpp, src/gui/browserbox.h, src/gui/gui.cpp, + src/gui/chat.cpp, src/resources/image.h: Added include main.h in order + to have USE_OPENGL defined correctly, since it is no longer passed as + a compiler parameter. + +2006-08-12 Philipp Sehmisch <tmw@crushnet.org> + + * data/maps/new_9-1.tmx.gz, data/maps/new_14-1.tmx.gz, + data/maps/new_15-1.tmx.gz, data/maps/new_16-1.tmx.gz: Fixed some + inaccessible areas. + +2006-08-07 Philipp Sehmisch <tmw@crushnet.org> + * data/maps/new_9-1.tmx.gz, data/maps/new_14-1.tmx.gz, + data/maps/new_15-1.tmx.gz, data/maps/new_16-1.tmx.gz, + data/graphics/images/minimap_new_9-1.png, + data/graphics/images/minimap_new_14-1.png, + data/graphics/images/minimap_new_15-1.png, + data/graphics/images/minimap_new_16-1.png: Added minimaps for woodland + maps. + +2006-08-07 Philipp Sehmisch <tmw@crushnet.org> + + * data/maps/new_1-1.tmx.gz, data/maps/new_14-1.tmx.gz, + data/maps/new_15-1.tmx.gz, data/maps/new_16-1.tmx.gz: Added a new + woodland map and a connection map between desert and woodland. + * data/graphics/woodland_ground.png: Added some new rocks. + +2006-08-07 Björn Steinbrink <B.Steinbrink@gmx.de> + + * src/game.cpp, src/gui/chat.h, src/gui/chat.cpp, src/main.cpp: A + bunch of cleanups. + 2006-08-06 Bjørn Lindeijer <bjorn@lindeijer.nl> * INSTALL: Updated required Guichan to version 0.5.0. +2006-08-05 Björn Steinbrink <B.Steinbrink@gmx.de> + + * src/configuration.cpp, src/game.cpp, src/engine.cpp, src/player.cpp, + src/being.cpp, src/resources/mapreader.cpp, + src/resources/itemmanager.cpp: Some cleanups, mostly lowering + indentation. + * src/being.cpp: Small code cleanup. + 2006-08-04 Guillaume Melquiond <guillaume.melquiond@gmail.com> * src/gui/char_select.cpp: Fixed character gender in selection dialog. +2006-08-04 Björn Steinbrink <B.Steinbrink@gmx.de> + + * src/animatedsprite.cpp: Fix enum being treated as string. + * src/animation.cpp: Small code cleanups. Removed unused headers. + * src/animatedsprite.cpp: Small code cleanup/lower indentation. + +2006-08-04 Bjørn Lindeijer <bjorn@lindeijer.nl> + + * src/animatedsprite.cpp: Fixed presence of NULL actions. This is + doener's version of the fix, because it was more efficient in the more + common case. + +2006-08-04 Frode Lindeijer <f.lindeijer@gmail.com> + + * data/graphics/tiles/desert_x3.png: Replaced the old cactus with + a nice new high-res one. + +2006-08-03 Bjørn Lindeijer <bjorn@lindeijer.nl> + + * src/player.cpp, src/being.cpp, src/being.h: Removed three + setDirection(mDirection) calls by instead specifically setting the + current direction on the newly added animated sprite. The same might + be done for the action later. + * src/animatedsprite.h, src/animatedsprite.cpp: Since this class isn't + subclassed and has no virtual functions, make protected members + private. Also added a start of a reset function which could be a + solution to unsynchronized animated sprites. + * src/net/network.cpp: Fixed two delete/delete[] errors. + 2006-08-02 Guillaume Melquiond <guillaume.melquiond@gmail.com> * configure.ac, src/Makefile.am: Put object files in subdirectories. @@ -37,10 +108,26 @@ * src/gui/gui.cpp, The Mana World.dev, tmw.cbp: Fixed compilation issues in windows. +2006-08-01 Philipp Sehmisch <tmw@crushnet.org> + + * src/animation.h, src/animation.cpp, src/animatedsprite.h, + src/animatedsprite.cpp, src/being.cpp: Animations and directions + are now passed and stored as enums and no longer as strings. + 2006-07-31 Bjørn Lindeijer <bjorn@lindeijer.nl> * src/net/network.cpp: Corrected an off by one error in packet size. +2006-07-30 Björn Steinbrink <B.Steinbrink@gmx.de> + + * src/animatedsprite.h, src/animatedsprite.cpp: Unified the play + methods. + +2006-07-30 Philipp Sehmisch <tmw@crushnet.org> + + * data/maps/new_5-1.tmx.gz: Fixed two minor mapping errors (no new + walkmap required). + 2006-07-30 Bjørn Lindeijer <bjorn@lindeijer.nl> * src/openglgraphics.cpp, src/game.cpp, src/main.cpp, @@ -74,6 +161,21 @@ Updated TMW to be compatible with Guichan 0.5.0 (merged from guichan-0.5.0 branch). +2006-07-29 Björn Steinbrink <B.Steinbrink@gmx.de> + + * src/animatedsprite.h, src/animatedsprite.cpp, src/animation.cpp: A + bunch of cleanups. + * src/animation.h, src/animatedsprite.cpp: Moved included from header + to source file. + +2006-07-28 Björn Steinbrink <B.Steinbrink@gmx.de> + + * src/npc.cpp, src/player.cpp, src/animatedsprite.h, src/animation.h, + src/being.cpp, src/main.cpp, src/monster.cpp, src/animatedsprite.cpp, + src/animation.cpp, src/Makefile.am, src/being.h: Moved AnimatedSprite + into its own files, removed useless includes. + * src/engine.cpp: Removed an unused var. + 2006-07-27 Eugenio Favalli <elvenprogrammer@gmail.com> * src/gui/main.cpp: Modified client version to be an int. @@ -81,20 +183,32 @@ 2006-07-26 Eugenio Favalli <elvenprogrammer@gmail.com> * src/gui/char_server.cpp, src/gui/char_sever.h, src/main.cpp, - src/net/loginhandler.cpp, src/net/loginhandler.h, tmw,cbp: Removed char - server selection dialog, and added character visualization in character - selection dialog. - -2006-07-25 Bjørn Lindeijer <bjorn@lindeijer.nl> - - * src/gui/updatewindow.cpp: Fixed updating on Windows. - * src/net/beinghandler.cpp, src/net/network.cpp, configure.ac: Fixed - Linux compiling issues. - * src/configuration.cpp: Reduced amount of logging. - * src/log.cpp, src/log.h: Added support for writing log to standard - output. - * src/main.cpp: Reorganized initialization somewhat. - * src/resources/resourcemanager.cpp: Take into account singular form. + src/net/loginhandler.cpp, src/net/loginhandler.h, tmw,cbp: Removed + char server selection dialog, and added character visualization in + character selection dialog. + * data/graphics/sprites/Makefile.am, data/graphics/tiles/Makefile.am, + data/maps/Makefile.am, data/maps/new_13-1.tmx.gz: Added map with inside + of snow village buildings and fixed makefiles. + * src/being.cpp, src/being.h, src/player.cpp: Fixed direction and + action issues when changing appeareance, frames are still out of sync. + * data/maps/Makefile.am, data/maps/new_14-1.tmx.gz, + data/maps/new_9-1.tmx.gz: Added new woodland map by Crush and fixed + connection with the old one. + +2006-07-26 Bjørn Lindeijer <bjorn@lindeijer.nl> + + * data/maps/new_4-1.tmx.gz: Fixes to the collision layer. + +2006-07-26 Frode Lindeijer <f.lindeijer@gmail.com> + + * data/graphics/tiles/snowset.png, data/graphics/tiles/snow_x2.png, + data/graphics/tiles/snow_x3.png: Moved the lamppost, the rock and the + bench to seperate tall tilebitmaps. + * data/maps/new_11-1.tmx.gz: Improved the snow village map, main + changes are that the player can now walk better behind houses, + lampposts, rocks and benches. + * data/graphics/sprites/item003.png, data/graphics/sprites/item003.xml: + Added the leather shirt 2006-07-25 Eugenio Favalli <elvenprogrammer@gmail.com> @@ -113,6 +227,17 @@ tmw.cbp: Switched client to use enet and modified login sequence to work with the new protocol from tmwserv. +2006-07-25 Bjørn Lindeijer <bjorn@lindeijer.nl> + + * src/gui/updatewindow.cpp: Fixed updating on Windows. + * src/net/beinghandler.cpp, src/net/network.cpp, configure.ac: Fixed + Linux compiling issues. + * src/configuration.cpp: Reduced amount of logging. + * src/log.cpp, src/log.h: Added support for writing log to standard + output. + * src/main.cpp: Reorganized initialization somewhat. + * src/resources/resourcemanager.cpp: Take into account singular form. + 2006-07-24 Bjørn Lindeijer <bjorn@lindeijer.nl> * src/main.cpp: Fixed the loading of updates and made skipping the @@ -126,10 +251,10 @@ 2006-07-24 Frode Lindeijer <f.lindeijer@gmail.com> * data/graphics/sprites/npcs.png: Added the organdealer to - the NPCs + the NPCs. * data/graphics/sprites/player_male_base.png, data/graphics/sprites/player_female_base.png: Fixed some - transparency issues + transparency issues. 2006-07-24 Eugenio Favalli <elvenprogrammer@gmail.com> @@ -144,7 +269,7 @@ * data/help/about.txt, data/help/changes.txt, data/help/commands.txt, data/help/header.txt, data/help/index.txt, data/help/skills.txt, data/help/support.txt, data/help/team.txt: Forced to use UNIX end of - line character. + line character. * src/net/equipmenthandler.cpp: Equipments now use real slot positions. 2006-07-24 Bjørn Lindeijer <bjorn@lindeijer.nl> @@ -230,7 +355,7 @@ 2006-07-17 Frode Lindeijer <f.lindeijer@gmail.com> - * Added shorts to items.png + * data/graphics/sprites/items.png: Added shorts' icon to items.png 2006-07-12 Bjørn Lindeijer <bjorn@lindeijer.nl> diff --git a/src/Makefile.am b/src/Makefile.am index 13ec7308..42671f64 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -183,6 +183,8 @@ tmw_SOURCES = graphic/imagerect.h \ resources/buddylist.cpp \ utils/dtor.h \ utils/tostring.h \ + animatedsprite.cpp \ + animatedsprite.h \ animation.cpp \ animation.h \ base64.cpp \ diff --git a/src/animatedsprite.cpp b/src/animatedsprite.cpp new file mode 100644 index 00000000..d1201042 --- /dev/null +++ b/src/animatedsprite.cpp @@ -0,0 +1,382 @@ +/* + * 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: animation.cpp 2430 2006-07-24 00:13:24Z b_lindeijer $ + */ + +#include "animatedsprite.h" + +#include "animation.h" +#include "graphics.h" +#include "log.h" + +#include "resources/resourcemanager.h" +#include "resources/spriteset.h" + +AnimatedSprite::AnimatedSprite(const std::string& animationFile, int variant): + mAction(NULL), + mDirection(DIRECTION_DOWN), + mLastTime(0), + mSpeed(1.0f) +{ + 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 = getProperty(node, "variants", 0); + int variant_offset = 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 = 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!"); + } + + mSpritesets[name] = spriteset; + } + // get action + else if (xmlStrEqual(node->name, BAD_CAST "action")) + { + std::string name = getProperty(node, "name", ""); + std::string imageset = getProperty(node, "imageset", ""); + + if (name.empty()) + { + logger->log("Warning: unnamed action in %s", + animationFile.c_str()); + } + if (mSpritesets.find(imageset) == mSpritesets.end()) { + logger->log("Warning: imageset \"%s\" not defined in %s", + imageset.c_str(), + animationFile.c_str()); + + // skip loading animations + continue; + } + + Action *action = new Action(); + + action->setSpriteset(mSpritesets[imageset]); + mActions[makeSpriteAction(name)] = 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 dir = getProperty(animationNode, "direction", ""); + Animation *animation = new Animation(); + action->setAnimation(makeSpriteDirection(dir), animation); + + // Get animation phases + for (xmlNodePtr phaseNode = animationNode->xmlChildrenNode; + phaseNode != NULL; + phaseNode = phaseNode->next) + { + int delay = getProperty(phaseNode, "delay", 0); + + if (xmlStrEqual(phaseNode->name, BAD_CAST "frame")) + { + int index = getProperty(phaseNode, "index", -1); + int offsetX = getProperty(phaseNode, "offsetX", 0); + int offsetY = getProperty(phaseNode, "offsetY", 0); + + offsetY -= mSpritesets[imageset]->getHeight() - 32; + offsetX -= mSpritesets[imageset]->getWidth() / 2 - 16; + animation->addPhase(index + variant_offset, delay, + offsetX, offsetY); + } + else if (xmlStrEqual(phaseNode->name, BAD_CAST "sequence")) + { + int start = getProperty(phaseNode, "start", 0); + int end = getProperty(phaseNode, "end", 0); + int offsetY = -mSpritesets[imageset]->getHeight() + 32; + int offsetX = -mSpritesets[imageset]->getWidth() / 2 + 16; + while (end >= start) + { + animation->addPhase(start + variant_offset, + delay, offsetX, offsetY); + start++; + } + } + } // for phaseNode + } // for animationNode + } // if "<imageset>" else if "<action>" + } // for node + + // Complete missing actions + 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); + + // Play the stand animation by default + play(ACTION_STAND); + + xmlFreeDoc(doc); +} + +int +AnimatedSprite::getProperty(xmlNodePtr node, const char* name, int def) +{ + int &ret = def; + + xmlChar *prop = xmlGetProp(node, BAD_CAST name); + if (prop) { + ret = atoi((char*)prop); + xmlFree(prop); + } + + return ret; +} + +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; + } + + return def; +} + +void +AnimatedSprite::substituteAction(SpriteAction complete, + SpriteAction with) +{ + if (mActions.find(complete) == mActions.end()) + { + ActionIterator i = mActions.find(with); + if (i != mActions.end()) { + mActions[complete] = i->second; + } + } +} + +AnimatedSprite::~AnimatedSprite() +{ + for (SpritesetIterator i = mSpritesets.begin(); i != mSpritesets.end(); ++i) + { + i->second->decRef(); + } + mSpritesets.clear(); +} + +void +AnimatedSprite::reset() +{ + // Reset all defined actions (because of aliases, some will be resetted + // multiple times) + for (ActionIterator i = mActions.begin(); i != mActions.end(); ++i) + { + //TODO: If resetting everything is really a nice way of fixing the + // synchronization issues, finish implementing this. + //i->second->reset(); + } +} + +void +AnimatedSprite::play(SpriteAction action, int time) +{ + ActionIterator i = mActions.find(action); + + if (i == mActions.end()) + { + logger->log("Warning: no action \"%u\" defined!", action); + mAction = NULL; + return; + } + + if (mAction != i->second) + { + mAction = i->second; + mLastTime = 0; + } + + if (!mAction || !time) + mSpeed = 1.0f; + else { + int animationLength = mAction->getAnimation(mDirection)->getLength(); + mSpeed = (float) animationLength / time; + } +} + +void +AnimatedSprite::update(int time) +{ + // 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 (time > mLastTime && mAction) + { + Animation *animation = mAction->getAnimation(mDirection); + animation->update((unsigned int)((time - mLastTime) * mSpeed)); + mLastTime = time; + } +} + +bool +AnimatedSprite::draw(Graphics* graphics, Sint32 posX, Sint32 posY) const +{ + if (!mAction) + return false; + + Animation *animation = mAction->getAnimation(mDirection); + int phase = animation->getCurrentPhase(); + if (phase < 0) + return false; + + Spriteset *spriteset = mAction->getSpriteset(); + Image *image = spriteset->get(phase); + Sint32 offsetX = animation->getOffsetX(); + Sint32 offsetY = animation->getOffsetY(); + return graphics->drawImage(image, posX + offsetX, posY + offsetY); +} + +int +AnimatedSprite::getWidth() const +{ + return mAction ? mAction->getSpriteset()->getWidth() : 0; +} + +int +AnimatedSprite::getHeight() const +{ + return mAction ? mAction->getSpriteset()->getHeight() : 0; +} + +SpriteAction +AnimatedSprite::makeSpriteAction(const std::string& action) +{ + 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_DEFAULT; + } +} + +SpriteDirection +AnimatedSprite::makeSpriteDirection(const std::string& direction) +{ + if (direction == "up") { + return DIRECTION_UP; + } + else if (direction == "left") { + return DIRECTION_LEFT; + } + else if (direction == "right") { + return DIRECTION_RIGHT; + } + else { + return DIRECTION_DOWN; + } +} diff --git a/src/animatedsprite.h b/src/animatedsprite.h new file mode 100644 index 00000000..89394d6c --- /dev/null +++ b/src/animatedsprite.h @@ -0,0 +1,178 @@ +/* + * 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: animation.h 2430 2006-07-24 00:13:24Z b_lindeijer $ + */ + +#ifndef _TMW_ANIMATEDSPRITE_H +#define _TMW_ANIMATEDSPRITE_H + +#include <map> +#include <string> +#include <SDL_types.h> + +#include <libxml/tree.h> + +class Action; +class Graphics; +class Spriteset; + +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 +}; + +enum SpriteDirection +{ + DIRECTION_DOWN = 0, + DIRECTION_UP, + DIRECTION_LEFT, + DIRECTION_RIGHT +}; + +/** + * Defines a class to load an animation. + */ +class AnimatedSprite +{ + public: + /** + * Constructor. + */ + AnimatedSprite(const std::string& animationFile, int variant); + + /** + * Destructor. + */ + ~AnimatedSprite(); + + /** + * Resets the animated sprite. This is used to synchronize several + * animated sprites. + */ + void + reset(); + + /** + * Plays an action using the current direction that will have a + * duration of the specified time, 0 means default. + */ + void + play(SpriteAction action, int time = 0); + + /** + * Inform the animation of the passed time so that it can output the + * correct animation phase. + */ + void update(int time); + + /** + * Draw the current animation phase at the coordinates given in screen + * pixels. + */ + bool + draw(Graphics* graphics, Sint32 posX, Sint32 posY) const; + + /** + * gets the width in pixels of the current animation phase. + */ + int + getWidth() const; + + /** + * gets the height in pixels of the current animation phase. + */ + int + getHeight() const; + + /** + * Sets the direction. + */ + void + setDirection(SpriteDirection direction) + { + mDirection = direction; + } + + private: + /** + * 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); + + /** + * 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); + + /** + * 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; + typedef Actions::iterator ActionIterator; + + Spritesets mSpritesets; + Actions mActions; + Action *mAction; + SpriteDirection mDirection; + int mLastTime; + float mSpeed; +}; + +#endif diff --git a/src/animation.cpp b/src/animation.cpp index 313fd25c..1213d0d6 100644 --- a/src/animation.cpp +++ b/src/animation.cpp @@ -23,13 +23,9 @@ #include "animation.h" -#include <cassert> +#include <algorithm> -#include "log.h" - -#include "resources/image.h" -#include "resources/resourcemanager.h" -#include "resources/spriteset.h" +#include "utils/dtor.h" Animation::Animation(): mTime(0) @@ -41,17 +37,20 @@ void Animation::update(unsigned int time) { mTime += time; - if (!mAnimationPhases.empty()) + if (mAnimationPhases.empty()) + return; + + unsigned int delay = iCurrentPhase->delay; + if (!delay) + return; + + while (mTime > delay) { - unsigned int delay = iCurrentPhase->delay; - while (mTime > delay && delay > 0) + mTime -= delay; + iCurrentPhase++; + if (iCurrentPhase == mAnimationPhases.end()) { - mTime -= delay; - iCurrentPhase++; - if (iCurrentPhase == mAnimationPhases.end()) - { - iCurrentPhase = mAnimationPhases.begin(); - } + iCurrentPhase = mAnimationPhases.begin(); } } } @@ -59,25 +58,15 @@ Animation::update(unsigned int time) int Animation::getCurrentPhase() const { - if (mAnimationPhases.empty()) - { - return -1; - } - else - { - return iCurrentPhase->image; - } + return mAnimationPhases.empty() ? -1 : iCurrentPhase->image; } void Animation::addPhase(int image, unsigned int delay, int offsetX, int offsetY) { //add new phase to animation list - AnimationPhase newPhase; - newPhase.image = image; - newPhase.delay = delay; - newPhase.offsetX = offsetX; - newPhase.offsetY = offsetY; + AnimationPhase newPhase = { image, delay, offsetX, offsetY }; + mAnimationPhases.push_back(newPhase); //reset animation circle iCurrentPhase = mAnimationPhases.begin(); @@ -86,14 +75,14 @@ Animation::addPhase(int image, unsigned int delay, int offsetX, int offsetY) int Animation::getLength() { + if (mAnimationPhases.empty()) + return 0; + std::list<AnimationPhase>::iterator i; int length = 0; - if (!mAnimationPhases.empty()) + for (i = mAnimationPhases.begin(); i != mAnimationPhases.end(); i++) { - for (i = mAnimationPhases.begin(); i != mAnimationPhases.end(); i++) - { - length += (*i).delay; - } + length += i->delay; } return length; } @@ -105,352 +94,32 @@ Action::Action(): Action::~Action() { - for (AnimationIterator i = mAnimations.begin(); i != mAnimations.end(); i++) - { - delete i->second; - } + std::for_each(mAnimations.begin(), mAnimations.end(), make_dtor(mAnimations)); mAnimations.clear(); } Animation* -Action::getAnimation(const std::string& direction) const +Action::getAnimation(int direction) const { - Animation *animation = NULL; Animations::const_iterator i = mAnimations.find(direction); // When the direction isn't defined, try the default if (i == mAnimations.end()) { - i = mAnimations.find("default"); + i = mAnimations.find(0); } - if (i != mAnimations.end()) - { - animation = i->second; - } - - return animation; + return (i == mAnimations.end()) ? NULL : i->second; } void -Action::setAnimation(const std::string& direction, Animation *animation) +Action::setAnimation(int direction, Animation *animation) { // Set first direction as default direction if (mAnimations.empty()) { - mAnimations["default"] = animation; + mAnimations[0] = animation; } mAnimations[direction] = animation; } - - -AnimatedSprite::AnimatedSprite(const std::string& animationFile, int variant): - mAction(NULL), - mDirection("down"), - mLastTime(0), - mSpeed(1.0f) -{ - 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!"); - return; - } - - xmlNodePtr node = xmlDocGetRootElement(doc); - if (!node || !xmlStrEqual(node->name, BAD_CAST "sprite")) - { - logger->error("Animation: this is not a valid animation definition file!"); - return; - } - - // 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 ) - { - 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 = 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!"); - } - else - { - mSpritesets[name] = spriteset; - } - } - // get action - else if (xmlStrEqual(node->name, BAD_CAST "action")) - { - 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(); - - 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 = - getProperty(animationNode, "direction", ""); - - Animation *animation = new Animation(); - - // Get animation phases - for (xmlNodePtr phaseNode = animationNode->xmlChildrenNode; - phaseNode != NULL; - phaseNode = phaseNode->next) - { - int delay = getProperty(phaseNode, "delay", 0); - - if (xmlStrEqual(phaseNode->name, BAD_CAST "frame")) - { - 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); - } - else if (xmlStrEqual(phaseNode->name, BAD_CAST "sequence")) - { - 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); - start++; - } - } - } // for phaseNode - action->setAnimation(direction, animation); - } // if "<animation>" - } // for animationNode - } // if "<imageset>" else if "<action>" - } // for node - - // Complete missing actions - substituteAction("walk", "stand"); - substituteAction("walk", "run"); - substituteAction("attack", "stand"); - substituteAction("attack_swing", "attack"); - substituteAction("attack_stab", "attack_swing"); - substituteAction("attack_bow", "attack_stab"); - substituteAction("attack_throw", "attack_swing"); - substituteAction("cast_magic", "attack_swing"); - substituteAction("use_item", "cast_magic"); - substituteAction("sit", "stand"); - substituteAction("sleeping", "sit"); - 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(const std::string& complete, - const std::string& with) -{ - if (mActions.find(complete) == mActions.end()) - { - mActions[complete] = mActions[with]; - } -} - -AnimatedSprite::~AnimatedSprite() -{ - for (SpritesetIterator i = mSpritesets.begin(); i != mSpritesets.end(); ++i) - { - i->second->decRef(); - } - mSpritesets.clear(); -} - -void -AnimatedSprite::play(const std::string& 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 = iAction->second; - mLastTime = 0; - } - - mSpeed = 1.0f; -} - -void -AnimatedSprite::play(const std::string& action, int time) -{ - play(action); - - if (mAction != NULL) - { - Animation *animation = mAction->getAnimation(mDirection); - int animationLength = animation->getLength(); - mSpeed = (float) animationLength / time; - } -} - -void -AnimatedSprite::update(int time) -{ - // 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 (time > mLastTime) - { - 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) const -{ - if (mAction != NULL) - { - 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; -} - -int -AnimatedSprite::getWidth() const -{ - if (mAction != NULL) - { - Spriteset *spriteset = mAction->getSpriteset(); - return spriteset->getWidth(); - } - - return 0; -} - -int -AnimatedSprite::getHeight() const -{ - if (mAction != NULL) - { - Spriteset *spriteset = mAction->getSpriteset(); - return spriteset->getHeight(); - } - - return 0; -} diff --git a/src/animation.h b/src/animation.h index c5adb873..c5b277b7 100644 --- a/src/animation.h +++ b/src/animation.h @@ -26,12 +26,9 @@ #include <list> #include <map> -#include <string> #include <libxml/tree.h> -#include "graphics.h" - class Image; class Spriteset; @@ -58,16 +55,32 @@ class Animation */ Animation(); - void addPhase(int image, unsigned int delay, int offsetX, int offsetY); + void + addPhase(int image, unsigned int delay, int offsetX, int offsetY); + + void + update(unsigned int time); - void update(unsigned int time); + int + getCurrentPhase() const; - int getCurrentPhase() const; + /** + * Returns the x offset of the current frame. + */ + int + getOffsetX() const { return (*iCurrentPhase).offsetX; }; - int getOffsetX() const { return (*iCurrentPhase).offsetX; }; - int getOffsetY() const { return (*iCurrentPhase).offsetY; }; + /** + * Returns the y offset of the current frame. + */ + int + getOffsetY() const { return (*iCurrentPhase).offsetY; }; - int getLength(); + /** + * Returns the length of this animation. + */ + int + getLength(); protected: std::list<AnimationPhase> mAnimationPhases; @@ -104,114 +117,16 @@ class Action getSpriteset() const { return mSpriteset; } void - setAnimation(const std::string& direction, Animation *animation); + setAnimation(int direction, Animation *animation); Animation* - getAnimation(const std::string& direction) const; + getAnimation(int direction) const; protected: Spriteset *mSpriteset; - typedef std::map<std::string, Animation*> Animations; + typedef std::map<int, Animation*> Animations; typedef Animations::iterator AnimationIterator; Animations mAnimations; }; -/** - * Defines a class to load an animation. - */ -class AnimatedSprite -{ - public: - /** - * Constructor. - */ - AnimatedSprite(const std::string& animationFile, int variant); - - /** - * Destructor. - */ - ~AnimatedSprite(); - - /** - * Sets a new action using the current direction. - */ - void - play(const std::string& action); - - /** - * Plays an action in a specified time. - */ - void - play(const std::string& action, int time); - - /** - * Inform the animation of the passed time so that it can output the - * correct animation phase. - */ - void update(int time); - - /** - * Draw the current animation phase at the coordinates given in screen - * pixels. - */ - bool - draw(Graphics* graphics, Sint32 posX, Sint32 posY) const; - - /** - * gets the width in pixels of the current animation phase. - */ - int - getWidth() const; - - /** - * gets the height in pixels of the current animation phase. - */ - int - getHeight() const; - - /** - * Sets the 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(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; - 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 8a55f2e2..1ca8929a 100644 --- a/src/being.cpp +++ b/src/being.cpp @@ -22,6 +22,9 @@ */ #include "being.h" +#include <algorithm> + +#include "animatedsprite.h" #include "equipment.h" #include "game.h" #include "graphics.h" @@ -32,6 +35,7 @@ #include "gui/gui.h" +#include "utils/dtor.h" #include "utils/tostring.h" extern Spriteset *emotionset; @@ -65,14 +69,7 @@ Being::Being(Uint32 id, Uint16 job, Map *map): Being::~Being() { - for (int i = 0; i < VECTOREND_SPRITE; i++) - { - if (mSprites[i] != NULL) - { - delete mSprites[i]; - } - } - + std::for_each(mSprites.begin(), mSprites.end(), make_dtor(mSprites)); clearPath(); setMap(NULL); } @@ -164,66 +161,65 @@ Being::setMap(Map *map) } void -Being::setAction(Action action) +Being::setAction(Uint8 action) { - if (action != mAction) + SpriteAction currentAction = ACTION_STAND; + switch (action) { - std::string currentAction = "stand"; - switch (action) - { - case WALK: - currentAction = "walk"; - break; - case SIT: - currentAction = "sit"; - break; - case ATTACK: - if (getType() == MONSTER) - { - currentAction = "dead"; - }else{ - switch (getWeapon()) - { - case 2: - currentAction = "attack_bow"; - break; - case 1: - currentAction = "attack_stab"; - break; - case 0: - currentAction = "attack"; - break; - } - }; - break; - case MONSTER_ATTACK: - currentAction = "attack"; - break; - case DEAD: - currentAction = "dead"; - break; - default: - currentAction = "stand"; - break; - } - - for (int i = 0; i < VECTOREND_SPRITE; i++) - { - if (mSprites[i] != NULL) + case WALK: + currentAction = ACTION_WALK; + break; + case SIT: + currentAction = ACTION_SIT; + break; + case ATTACK: + if (getType() == MONSTER) { - if (currentAction == "attack" || - currentAction == "attack_stab" || - currentAction == "attack_bow") - { - mSprites[i]->play(currentAction, mAttackSpeed); - } - else + currentAction = ACTION_DEAD; + } + else { + switch (getWeapon()) { - mSprites[i]->play(currentAction); + case 2: + currentAction = ACTION_ATTACK_BOW; + break; + case 1: + currentAction = ACTION_ATTACK_STAB; + break; + case 0: + currentAction = ACTION_ATTACK; + break; } - } + }; + break; + case MONSTER_ATTACK: + currentAction = ACTION_ATTACK; + break; + case DEAD: + currentAction = ACTION_DEAD; + break; + default: + currentAction = ACTION_STAND; + break; + } + + for (int i = 0; i < VECTOREND_SPRITE; i++) + { + if (!mSprites[i]) + continue; + + if (currentAction == ACTION_ATTACK || + currentAction == ACTION_ATTACK_STAB || + currentAction == ACTION_ATTACK_BOW) + { + mSprites[i]->play(currentAction, mAttackSpeed); + } + else + { + mSprites[i]->play(currentAction); } } + mAction = action; } @@ -231,29 +227,37 @@ void Being::setDirection(Uint8 direction) { mDirection = direction; - std::string dir; + SpriteDirection dir = getSpriteDirection(); - if (direction & UP) + for (int i = 0; i < VECTOREND_SPRITE; i++) { - dir = "up"; + if (mSprites[i] != NULL) + mSprites[i]->setDirection(dir); } - else if (direction & RIGHT) +} + +SpriteDirection +Being::getSpriteDirection() const +{ + SpriteDirection dir; + + if (mDirection & UP) { - dir = "right"; + dir = DIRECTION_UP; } - else if (direction & DOWN) + else if (mDirection & RIGHT) { - dir = "down"; + dir = DIRECTION_RIGHT; } - else + else if (mDirection & DOWN) { - dir = "left"; + dir = DIRECTION_DOWN; } - - for (int i = 0; i < VECTOREND_SPRITE; i++) - { - if (mSprites[i] != NULL) mSprites[i]->setDirection(dir); + else { + dir = DIRECTION_LEFT; } + + return dir; } void @@ -329,10 +333,6 @@ Being::draw(Graphics *graphics, int offsetX, int offsetY) int px = mPx + offsetX; int py = mPy + offsetY; - //what are these two lines good for? please add a comment. - unsigned char dir = 0; - while (!(mDirection & (1 << dir))) dir++; - for (int i = 0; i < VECTOREND_SPRITE; i++) { if (mSprites[i] != NULL) @@ -345,14 +345,13 @@ Being::draw(Graphics *graphics, int offsetX, int offsetY) void Being::drawEmotion(Graphics *graphics, Sint32 offsetX, Sint32 offsetY) { - int px = mPx + offsetX; - int py = mPy + offsetY; + if (!mEmotion) + return; - if (mEmotion) - { - graphics->drawImage(emotionset->get(mEmotion - 1), - px + 3, py - 60); - } + int px = mPx + offsetX + 3; + int py = mPy + offsetY - 60; + + graphics->drawImage(emotionset->get(mEmotion - 1), px, py); } void diff --git a/src/being.h b/src/being.h index 478bc018..0735efe9 100644 --- a/src/being.h +++ b/src/being.h @@ -29,13 +29,14 @@ #include <SDL_types.h> #include <vector> -#include "animation.h" #include "sprite.h" #include "map.h" +#include "animatedsprite.h" #define NR_HAIR_STYLES 7 #define NR_HAIR_COLORS 10 +class AnimatedSprite; class Equipment; class Item; class Map; @@ -290,7 +291,7 @@ class Being : public Sprite /** * Sets the current action. */ - void setAction(Action action); + void setAction(Uint8 action); /** * Sets the current direction. @@ -347,6 +348,12 @@ class Being : public Sprite */ int getOffset(char pos, char neg) const; + /** + * Returns the sprite direction of this being. + */ + SpriteDirection + getSpriteDirection() const; + Uint32 mId; /**< Unique sprite id */ Uint16 mWeapon; /**< Weapon picture id */ Uint16 mWalkSpeed; /**< Walking speed */ diff --git a/src/configuration.cpp b/src/configuration.cpp index 9c3ff008..8bb0b8ca 100644 --- a/src/configuration.cpp +++ b/src/configuration.cpp @@ -57,18 +57,18 @@ void Configuration::init(const std::string &filename) for (node = node->xmlChildrenNode; node != NULL; node = node->next) { - if (xmlStrEqual(node->name, BAD_CAST "option")) - { - xmlChar *name = xmlGetProp(node, BAD_CAST "name"); - xmlChar *value = xmlGetProp(node, BAD_CAST "value"); + if (!xmlStrEqual(node->name, BAD_CAST "option")) + continue; - if (name && value) { - mOptions[(const char*)name] = (const char*)value; - } + xmlChar *name = xmlGetProp(node, BAD_CAST "name"); + xmlChar *value = xmlGetProp(node, BAD_CAST "value"); - if (name) xmlFree(name); - if (value) xmlFree(value); + if (name && value) { + mOptions[(const char*)name] = (const char*)value; } + + if (name) xmlFree(name); + if (value) xmlFree(value); } xmlFreeDoc(doc); @@ -89,31 +89,29 @@ void Configuration::write() xmlTextWriterPtr writer = xmlNewTextWriterFilename(mConfigPath.c_str(), 0); - if (writer) - { - logger->log("Configuration::write() writing configuration..."); + if (!writer) { + logger->log("Configuration::write() error while creating writer"); + return; + } - xmlTextWriterSetIndent(writer, 1); - xmlTextWriterStartDocument(writer, NULL, NULL, NULL); - xmlTextWriterStartElement(writer, BAD_CAST "configuration"); + logger->log("Configuration::write() writing configuration..."); - for (OptionIterator i = mOptions.begin(); i != mOptions.end(); i++) - { - xmlTextWriterStartElement(writer, BAD_CAST "option"); - xmlTextWriterWriteAttribute(writer, - BAD_CAST "name", BAD_CAST i->first.c_str()); - xmlTextWriterWriteAttribute(writer, - BAD_CAST "value", BAD_CAST i->second.c_str()); - xmlTextWriterEndElement(writer); - } + xmlTextWriterSetIndent(writer, 1); + xmlTextWriterStartDocument(writer, NULL, NULL, NULL); + xmlTextWriterStartElement(writer, BAD_CAST "configuration"); - xmlTextWriterEndDocument(writer); - xmlFreeTextWriter(writer); - } - else + for (OptionIterator i = mOptions.begin(); i != mOptions.end(); i++) { - logger->log("Configuration::write() error while creating writer"); + xmlTextWriterStartElement(writer, BAD_CAST "option"); + xmlTextWriterWriteAttribute(writer, + BAD_CAST "name", BAD_CAST i->first.c_str()); + xmlTextWriterWriteAttribute(writer, + BAD_CAST "value", BAD_CAST i->second.c_str()); + xmlTextWriterEndElement(writer); } + + xmlTextWriterEndDocument(writer); + xmlFreeTextWriter(writer); } void Configuration::setValue(const std::string &key, std::string value) diff --git a/src/engine.cpp b/src/engine.cpp index c6a4e55c..84574b26 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -25,7 +25,6 @@ #include <list> -#include "animation.h" #include "being.h" #include "beingmanager.h" #include "flooritemmanager.h" @@ -34,7 +33,6 @@ #include "main.h" #include "localplayer.h" #include "log.h" -#include "main.h" #include "map.h" #include "sound.h" @@ -63,8 +61,6 @@ Spriteset *itemset; Spriteset *emotionset; Spriteset *npcset; std::vector<Spriteset *> weaponset; -AnimatedSprite *animatedSprite; - Engine::Engine(Network *network): mShowDebugPath(false), @@ -104,16 +100,11 @@ Engine::~Engine() emotionset->decRef(); itemset->decRef(); - std::vector<Spriteset *>::iterator iter; - for (iter = weaponset.begin(); iter != weaponset.end(); ++iter) - { - (*iter)->decRef(); - } + std::for_each(weaponset.begin(), weaponset.end(), + std::mem_fun(&Spriteset::decRef)); weaponset.clear(); delete itemDb; - - delete animatedSprite; } void Engine::changeMap(const std::string &mapPath) @@ -219,12 +210,12 @@ void Engine::draw(Graphics *graphics) player_node->mX, player_node->mY, mouseTileX, mouseTileY); + graphics->setColor(gcn::Color(255, 0, 0)); for (PathIterator i = debugPath.begin(); i != debugPath.end(); i++) { int squareX = i->x * 32 - map_x + 12; int squareY = i->y * 32 - map_y + 12; - graphics->setColor(gcn::Color(255, 0, 0)); graphics->fillRectangle(gcn::Rectangle(squareX, squareY, 8, 8)); graphics->drawText( toString(mCurrentMap->getMetaTile(i->x, i->y)->Gcost), diff --git a/src/game.cpp b/src/game.cpp index fab88aa9..eada1128 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -167,8 +167,7 @@ int get_elapsed_time(int start_time) void createGuiWindows(Network *network) { // Create dialogs - chatWindow = new ChatWindow( - config.getValue("homeDir", "") + std::string("/chatlog.txt"), network); + chatWindow = new ChatWindow(network); menuWindow = new MenuWindow(); statusWindow = new StatusWindow(player_node); miniStatusWindow = new MiniStatusWindow(); @@ -359,29 +358,16 @@ void Game::logic() gameTime = tick_time; fpsLimit = (int)config.getValue("fpslimit", 50); - if (fpsLimit) - { - delta = 1000 / fpsLimit; - } - else - { - delta = 0; - } + delta = fpsLimit ? 1000 / fpsLimit : 0; // Update the screen when application is active, delay otherwise - if (SDL_GetAppState() & SDL_APPACTIVE) + if (SDL_GetAppState() & SDL_APPACTIVE && + (abs(tick_time * 10 - drawTime) >= delta)) { - if (abs(tick_time * 10 - drawTime) >= delta) - { - frame++; - engine->draw(graphics); - graphics->updateScreen(); - drawTime += delta; - } - else - { - SDL_Delay(10); - } + frame++; + engine->draw(graphics); + graphics->updateScreen(); + drawTime += delta; } else { diff --git a/src/gui/browserbox.h b/src/gui/browserbox.h index 95b181ad..a2c9dd9b 100644 --- a/src/gui/browserbox.h +++ b/src/gui/browserbox.h @@ -31,6 +31,7 @@ #include <guichan/mouselistener.hpp> #include "../guichanfwd.h" +#include "../main.h" class LinkHandler; diff --git a/src/gui/chat.cpp b/src/gui/chat.cpp index 133e5e3a..592439fc 100644 --- a/src/gui/chat.cpp +++ b/src/gui/chat.cpp @@ -35,18 +35,16 @@ #include "../game.h" #include "../localplayer.h" -#include "../log.h" #include "../net/messageout.h" #include "../net/protocol.h" -ChatWindow::ChatWindow(const std::string &logfile, Network *network): +ChatWindow::ChatWindow(Network *network): Window(""), mNetwork(network), mTmpVisible(false) { setWindowName("Chat"); - mChatlogFile.open(logfile.c_str(), std::ios::out | std::ios::app); mItems = 0; mItemsKeep = 20; @@ -76,12 +74,6 @@ ChatWindow::ChatWindow(const std::string &logfile, Network *network): mCurHist = mHistory.end(); } -ChatWindow::~ChatWindow() -{ - mChatlogFile.flush(); - mChatlogFile.close(); -} - void ChatWindow::logic() { @@ -251,44 +243,12 @@ ChatWindow::isFocused() void ChatWindow::chatSend(const std::string &nick, std::string msg) { - // Prepare command - if (msg.substr(0, 1) == "/") - { - /* Some messages are managed client side, while others - * require server handling by proper packet. Probably - * those if elses should be replaced by protocol calls */ - if (msg.substr(0, IS_ANNOUNCE_LENGTH) == IS_ANNOUNCE) - { - msg.erase(0, IS_ANNOUNCE_LENGTH); - MessageOut outMsg; - outMsg.writeShort(0x0099); - outMsg.writeShort(msg.length() + 4); - outMsg.writeString(msg, msg.length()); - } - else if (msg.substr(0, IS_HELP_LENGTH) == IS_HELP) - { - chatLog("-- Help --", BY_SERVER); - chatLog("/help : Display this help.", BY_SERVER); - chatLog("/announce : Global announcement (GM only)", BY_SERVER); - chatLog("/where : Display map name", BY_SERVER); - chatLog("/who : Display number of online users", BY_SERVER); - } - else if (msg.substr(0, IS_WHERE_LENGTH) == IS_WHERE) - { - chatLog(map_path, BY_SERVER); - } - else if (msg.substr(0, IS_WHO_LENGTH) == IS_WHO) - { - MessageOut outMsg; - outMsg.writeShort(0x00c1); - } - else - { - chatLog("Unknown command", BY_SERVER); - } - } + /* Some messages are managed client side, while others + * require server handling by proper packet. Probably + * those if elses should be replaced by protocol calls */ + // Prepare ordinary message - else { + if (msg.substr(0, 1) != "/") { msg = nick + " : " + msg; MessageOut outMsg; @@ -296,6 +256,35 @@ ChatWindow::chatSend(const std::string &nick, std::string msg) outMsg.writeShort(msg.length() + 4); outMsg.writeString(msg, msg.length()); } + else if (msg.substr(0, IS_ANNOUNCE_LENGTH) == IS_ANNOUNCE) + { + msg.erase(0, IS_ANNOUNCE_LENGTH); + MessageOut outMsg; + outMsg.writeShort(0x0099); + outMsg.writeShort(msg.length() + 4); + outMsg.writeString(msg, msg.length()); + } + else if (msg.substr(0, IS_HELP_LENGTH) == IS_HELP) + { + chatLog("-- Help --", BY_SERVER); + chatLog("/help : Display this help.", BY_SERVER); + chatLog("/announce : Global announcement (GM only)", BY_SERVER); + chatLog("/where : Display map name", BY_SERVER); + chatLog("/who : Display number of online users", BY_SERVER); + } + else if (msg.substr(0, IS_WHERE_LENGTH) == IS_WHERE) + { + chatLog(map_path, BY_SERVER); + } + else if (msg.substr(0, IS_WHO_LENGTH) == IS_WHO) + { + MessageOut outMsg; + outMsg.writeShort(0x00c1); + } + else + { + chatLog("Unknown command", BY_SERVER); + } } std::string diff --git a/src/gui/chat.h b/src/gui/chat.h index addfb6b5..20841873 100644 --- a/src/gui/chat.h +++ b/src/gui/chat.h @@ -24,7 +24,6 @@ #ifndef _TMW_CHAT_H #define _TMW_CHAT_H -#include <fstream> #include <list> #include <string> @@ -117,12 +116,7 @@ class ChatWindow : public Window, public gcn::ActionListener, /** * Constructor. */ - ChatWindow(const std::string &logfile, Network *network); - - /** - * Destructor. - */ - ~ChatWindow(); + ChatWindow(Network *network); /** * Logic (updates components' size) @@ -195,7 +189,6 @@ class ChatWindow : public Window, public gcn::ActionListener, private: Network *mNetwork; - std::ofstream mChatlogFile; bool mTmpVisible; /** One item in the chat log */ diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 88998f7a..026f24bd 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -32,10 +32,6 @@ // constant as well as guichan does #include <guichan/sdl/sdlinput.hpp> -#ifdef USE_OPENGL -#include "../resources/openglsdlimageloader.h" -#endif - #include "focushandler.h" #include "popupmenu.h" #include "window.h" @@ -57,6 +53,9 @@ #include "../resources/image.h" #include "../resources/resourcemanager.h" #include "../resources/sdlimageloader.h" +#ifdef USE_OPENGL +#include "../resources/openglsdlimageloader.h" +#endif // Guichan stuff Gui *gui; diff --git a/src/gui/setup_video.cpp b/src/gui/setup_video.cpp index 9eb94520..7ac226d3 100644 --- a/src/gui/setup_video.cpp +++ b/src/gui/setup_video.cpp @@ -42,6 +42,7 @@ #include "../configuration.h" #include "../graphics.h" #include "../log.h" +#include "../main.h" #include "../utils/tostring.h" diff --git a/src/gui/updatewindow.cpp b/src/gui/updatewindow.cpp index 9188b6de..8c69d3ef 100644 --- a/src/gui/updatewindow.cpp +++ b/src/gui/updatewindow.cpp @@ -300,7 +300,7 @@ int UpdaterWindow::downloadThread(void *ptr) // Any existing file with this name is deleted first, otherwise the // rename will fail on Windows. ::remove(newName.c_str()); - rename(outFilename.c_str(), newName.c_str()); + ::rename(outFilename.c_str(), newName.c_str()); } } diff --git a/src/main.cpp b/src/main.cpp index ce68b7bb..a4ef29ee 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -43,7 +43,6 @@ #define NOGDI #endif -#include "animation.h" #include "configuration.h" #include "game.h" #include "graphics.h" @@ -216,15 +215,6 @@ void init_engine() resman->addToSearchPath("data", true); resman->addToSearchPath(TMW_DATADIR "data", true); - int width, height, bpp; - bool fullscreen, hwaccel; - - width = (int)config.getValue("screenwidth", 800); - height = (int)config.getValue("screenheight", 600); - bpp = 0; - fullscreen = ((int)config.getValue("screen", 0) == 1); - hwaccel = ((int)config.getValue("hwaccel", 0) == 1); - #ifdef USE_OPENGL bool useOpenGL = (config.getValue("opengl", 0) == 1); @@ -232,16 +222,18 @@ void init_engine() Image::setLoadAsOpenGL(useOpenGL); // Create the graphics context - if (useOpenGL) { - graphics = new OpenGLGraphics(); - } else { - graphics = new Graphics(); - } + graphics = useOpenGL ? new OpenGLGraphics() : new Graphics(); #else // Create the graphics context graphics = new Graphics(); #endif + int width = (int)config.getValue("screenwidth", 800); + int height = (int)config.getValue("screenheight", 600); + int bpp = 0; + bool fullscreen = ((int)config.getValue("screen", 0) == 1); + bool hwaccel = ((int)config.getValue("hwaccel", 0) == 1); + // Try to set the desired video mode if (!graphics->setVideoMode(width, height, bpp, fullscreen, hwaccel)) { @@ -299,11 +291,8 @@ void exit_engine() delete gui; delete graphics; - std::vector<Spriteset *>::iterator iter; - for (iter = hairset.begin(); iter != hairset.end(); ++iter) - { - (*iter)->decRef(); - } + std::for_each(hairset.begin(), hairset.end(), + std::mem_fun(&Spriteset::decRef)); hairset.clear(); playerset[0]->decRef(); diff --git a/src/monster.cpp b/src/monster.cpp index 43823e50..8a7e2f32 100644 --- a/src/monster.cpp +++ b/src/monster.cpp @@ -23,10 +23,8 @@ #include "monster.h" +#include "animatedsprite.h" #include "game.h" -#include "log.h" - -#include "resources/resourcemanager.h" #include "utils/tostring.h" diff --git a/src/npc.cpp b/src/npc.cpp index 54205ad3..a82490ae 100644 --- a/src/npc.cpp +++ b/src/npc.cpp @@ -23,6 +23,8 @@ #include "npc.h" +#include "animatedsprite.h" + #include "net/messageout.h" #include "net/protocol.h" diff --git a/src/openglgraphics.cpp b/src/openglgraphics.cpp index 2a6c931d..05bbb6b3 100644 --- a/src/openglgraphics.cpp +++ b/src/openglgraphics.cpp @@ -21,6 +21,8 @@ * $Id$ */ +#include "main.h" + #ifdef USE_OPENGL #include "openglgraphics.h" diff --git a/src/player.cpp b/src/player.cpp index 05825f6e..3fe608c7 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -23,8 +23,7 @@ #include "player.h" -#include "animation.h" -#include "equipment.h" +#include "animatedsprite.h" #include "game.h" #include "graphics.h" @@ -91,11 +90,13 @@ Player::setSex(Uint8 sex) delete mSprites[BASE_SPRITE]; if (sex == 0) { - mSprites[BASE_SPRITE] = new AnimatedSprite("graphics/sprites/player_male_base.xml", 0); + mSprites[BASE_SPRITE] = new AnimatedSprite( + "graphics/sprites/player_male_base.xml", 0); } else { - mSprites[BASE_SPRITE] = new AnimatedSprite("graphics/sprites/player_female_base.xml", 0); + mSprites[BASE_SPRITE] = new AnimatedSprite( + "graphics/sprites/player_female_base.xml", 0); } } Being::setSex(sex); @@ -107,8 +108,16 @@ Player::setHairColor(Uint16 color) if (color != mHairColor && mHairStyle > 0) { delete mSprites[HAIR_SPRITE]; - mSprites[HAIR_SPRITE] = new AnimatedSprite("graphics/sprites/hairstyle"+toString(mHairStyle)+".xml", color - 1); + AnimatedSprite *newHairSprite = new AnimatedSprite( + "graphics/sprites/hairstyle" + toString(mHairStyle) + ".xml", + color - 1); + newHairSprite->setDirection(getSpriteDirection()); + + mSprites[HAIR_SPRITE] = newHairSprite; + + setAction(mAction); } + Being::setHairColor(color); } @@ -118,8 +127,16 @@ Player::setHairStyle(Uint16 style) if (style != mHairStyle && mHairColor > 0) { delete mSprites[HAIR_SPRITE]; - mSprites[HAIR_SPRITE] = new AnimatedSprite("graphics/sprites/hairstyle"+toString(style)+".xml", mHairColor - 1); + AnimatedSprite *newHairSprite = new AnimatedSprite( + "graphics/sprites/hairstyle" + toString(style) + ".xml", + mHairColor - 1); + newHairSprite->setDirection(getSpriteDirection()); + + mSprites[HAIR_SPRITE] = newHairSprite; + + setAction(mAction); } + Being::setHairStyle(style); } @@ -139,18 +156,24 @@ Player::setVisibleEquipment(Uint8 slot, Uint8 id) position = TOPCLOTHES_SPRITE; break; } + + delete mSprites[position]; + mSprites[position] = NULL; + // id = 0 means unequip - if (mSprites[position]) { - delete mSprites[position]; - mSprites[position] = 0; - } if (id) { char stringId[4]; sprintf(stringId, "%03i", id); - printf("Id: %i %i %s\n", id, slot, stringId); - mSprites[position] = new AnimatedSprite( + + AnimatedSprite *equipmentSprite = new AnimatedSprite( "graphics/sprites/item" + toString(stringId) + ".xml", 0); + equipmentSprite->setDirection(getSpriteDirection()); + + mSprites[position] = equipmentSprite; + + setAction(mAction); } + Being::setVisibleEquipment(slot, id); } diff --git a/src/resources/image.h b/src/resources/image.h index 1f67fcae..78751394 100644 --- a/src/resources/image.h +++ b/src/resources/image.h @@ -24,6 +24,8 @@ #ifndef _TMW_IMAGE_H #define _TMW_IMAGE_H +#include "../main.h" + #include <SDL.h> #ifdef USE_OPENGL #include <SDL_opengl.h> diff --git a/src/resources/itemmanager.cpp b/src/resources/itemmanager.cpp index 56ac6354..63c0b036 100644 --- a/src/resources/itemmanager.cpp +++ b/src/resources/itemmanager.cpp @@ -30,6 +30,8 @@ #include "../log.h" +#include "../utils/dtor.h" + #define READ_PROP(node, prop, name, target, cast) \ prop = xmlGetProp(node, BAD_CAST name); \ if (prop) { \ @@ -56,14 +58,12 @@ ItemManager::ItemManager() if (!doc) { logger->error("Item Manager: Error while parsing item database (items.xml)!"); - return; } xmlNodePtr node = xmlDocGetRootElement(doc); if (!node || !xmlStrEqual(node->name, BAD_CAST "items")) { logger->error("Item Manager: items.xml is not a valid database file!"); - return; } for (node = node->xmlChildrenNode; node != NULL; node = node->next) diff --git a/src/resources/mapreader.cpp b/src/resources/mapreader.cpp index af79480a..382b0797 100644 --- a/src/resources/mapreader.cpp +++ b/src/resources/mapreader.cpp @@ -28,7 +28,6 @@ #include "resourcemanager.h" #include "image.h" -#include "spriteset.h" #include "../base64.h" #include "../log.h" @@ -220,34 +219,26 @@ MapReader::readMap(xmlNodePtr node, const std::string &path) void MapReader::readProperties(xmlNodePtr node, Properties* props) { - node = node->xmlChildrenNode; + for (node = node->xmlChildrenNode; node; node = node->next) { + if (!xmlStrEqual(node->name, BAD_CAST "property")) + continue; - while (node != NULL) - { - if (xmlStrEqual(node->name, BAD_CAST "property")) - { - // Example: <property name="name" value="value"/> - - xmlChar *name = xmlGetProp(node, BAD_CAST "name"); - xmlChar *value = xmlGetProp(node, BAD_CAST "value"); + // Example: <property name="name" value="value"/> + xmlChar *name = xmlGetProp(node, BAD_CAST "name"); + xmlChar *value = xmlGetProp(node, BAD_CAST "value"); - if (name && value) - { - props->setProperty((const char*) name, (const char*) value); - } - - if (name) xmlFree(name); - if (value) xmlFree(value); + if (name && value) { + props->setProperty((const char*)name, (const char*)value); } - node = node->next; + if (name) xmlFree(name); + if (value) xmlFree(value); } } void MapReader::readLayer(xmlNodePtr node, Map *map, int layer) { - node = node->xmlChildrenNode; int h = map->getHeight(); int w = map->getWidth(); int x = 0; @@ -255,89 +246,86 @@ MapReader::readLayer(xmlNodePtr node, Map *map, int layer) // Load the tile data. Layers are assumed to be map size, with (0,0) as // origin. - while (node != NULL) - { - if (xmlStrEqual(node->name, BAD_CAST "data")) + for (node = node->xmlChildrenNode; node; node = node->next) { + if (!xmlStrEqual(node->name, BAD_CAST "data")) + continue; + + xmlChar *encoding = xmlGetProp(node, BAD_CAST "encoding"); + xmlChar *compression = xmlGetProp(node, BAD_CAST "compression"); + + if (encoding && xmlStrEqual(encoding, BAD_CAST "base64")) { - xmlChar *encoding = xmlGetProp(node, BAD_CAST "encoding"); - xmlChar *compression = xmlGetProp(node, BAD_CAST "compression"); + xmlFree(encoding); - if (encoding && xmlStrEqual(encoding, BAD_CAST "base64")) - { - xmlFree(encoding); + if (compression) { + logger->log("Warning: no layer compression supported!"); + xmlFree(compression); + return; + } - if (compression) { - logger->log("Warning: no layer compression supported!"); - xmlFree(compression); - return; - } + // Read base64 encoded map file + xmlNodePtr dataChild = node->xmlChildrenNode; + if (!dataChild) + continue; - // Read base64 encoded map file - xmlNodePtr dataChild = node->xmlChildrenNode; - if (!dataChild) continue; - - int len = strlen((const char*)dataChild->content) + 1; - unsigned char *charData = new unsigned char[len + 1]; - const char *charStart = (const char*)dataChild->content; - unsigned char *charIndex = charData; - - while (*charStart) { - if (*charStart != ' ' && *charStart != '\t' && - *charStart != '\n') - { - *charIndex = *charStart; - charIndex++; - } - charStart++; + int len = strlen((const char*)dataChild->content) + 1; + unsigned char *charData = new unsigned char[len + 1]; + const char *charStart = (const char*)dataChild->content; + unsigned char *charIndex = charData; + + while (*charStart) { + if (*charStart != ' ' && *charStart != '\t' && + *charStart != '\n') + { + *charIndex = *charStart; + charIndex++; } - *charIndex = '\0'; + charStart++; + } + *charIndex = '\0'; - int binLen; - unsigned char *binData = - php_base64_decode(charData, strlen((char*)charData), - &binLen); + int binLen; + unsigned char *binData = + php_base64_decode(charData, strlen((char*)charData), + &binLen); - delete[] charData; + delete[] charData; - if (binData) { - for (int i = 0; i < binLen - 3; i += 4) { - int gid = binData[i] | - binData[i + 1] << 8 | - binData[i + 2] << 16 | - binData[i + 3] << 24; + if (binData) { + for (int i = 0; i < binLen - 3; i += 4) { + int gid = binData[i] | + binData[i + 1] << 8 | + binData[i + 2] << 16 | + binData[i + 3] << 24; - map->setTileWithGid(x, y, layer, gid); + map->setTileWithGid(x, y, layer, gid); - x++; - if (x == w) {x = 0; y++;} - } - free(binData); + x++; + if (x == w) {x = 0; y++;} } + free(binData); } - else { - // Read plain XML map file - xmlNodePtr n2 = node->xmlChildrenNode; - - while (n2 != NULL) - { - if (xmlStrEqual(n2->name, BAD_CAST "tile") && y < h) - { - int gid = getProperty(n2, "gid", -1); - map->setTileWithGid(x, y, layer, gid); - - x++; - if (x == w) {x = 0; y++;} - } - - n2 = n2->next; + } + else { + // Read plain XML map file + for (xmlNodePtr n2 = node->xmlChildrenNode; n2; n2 = n2->next) { + if (!xmlStrEqual(n2->name, BAD_CAST "tile")) + continue; + + int gid = getProperty(n2, "gid", -1); + map->setTileWithGid(x, y, layer, gid); + + x++; + if (x == w) { + x = 0; y++; + if (y >= h) + break; } } - - // There can be only one data element - break; } - node = node->next; + // There can be only one data element + break; } } @@ -356,38 +344,33 @@ MapReader::readTileset(xmlNodePtr node, int tw = getProperty(node, "tilewidth", map->getTileWidth()); int th = getProperty(node, "tileheight", map->getTileHeight()); - node = node->xmlChildrenNode; + for (node = node->xmlChildrenNode; node; node = node->next) { + if (!xmlStrEqual(node->name, BAD_CAST "image")) + continue; - while (node != NULL) - { - if (xmlStrEqual(node->name, BAD_CAST "image")) - { - xmlChar* source = xmlGetProp(node, BAD_CAST "source"); + xmlChar* source = xmlGetProp(node, BAD_CAST "source"); - if (source) - { - std::string sourceStr = std::string((const char*)source); - sourceStr.erase(0, 3); // Remove "../" + if (source) + { + std::string sourceStr = std::string((const char*)source); + sourceStr.erase(0, 3); // Remove "../" - ResourceManager *resman = ResourceManager::getInstance(); - Image* tilebmp = resman->getImage(sourceStr); + ResourceManager *resman = ResourceManager::getInstance(); + Image* tilebmp = resman->getImage(sourceStr); - if (tilebmp) - { - Tileset *set = new Tileset(tilebmp, tw, th, firstGid); - tilebmp->decRef(); - xmlFree(source); - return set; - } - else { - logger->log("Warning: Failed to load tileset (%s)", source); - } + if (tilebmp) + { + Tileset *set = new Tileset(tilebmp, tw, th, firstGid); + tilebmp->decRef(); + xmlFree(source); + return set; + } + else { + logger->log("Warning: Failed to load tileset (%s)", source); } - - break; } - node = node->next; + break; } return NULL; @@ -396,13 +379,12 @@ MapReader::readTileset(xmlNodePtr node, int MapReader::getProperty(xmlNodePtr node, const char* name, int def) { + int &ret = def; + xmlChar *prop = xmlGetProp(node, BAD_CAST name); if (prop) { - int val = atoi((char*)prop); + ret = atoi((char*)prop); xmlFree(prop); - return val; - } - else { - return def; } + return ret; } diff --git a/src/resources/openglsdlimageloader.cpp b/src/resources/openglsdlimageloader.cpp index c7ddec74..b3e1601e 100644 --- a/src/resources/openglsdlimageloader.cpp +++ b/src/resources/openglsdlimageloader.cpp @@ -21,14 +21,16 @@ * $Id: sdlimageloader.cpp 2121 2006-01-31 02:55:26Z der_doener $ */ -#ifdef USE_OPENGL - #include "openglsdlimageloader.h" #include <string> #include "resourcemanager.h" +#include "../main.h" + +#ifdef USE_OPENGL + SDL_Surface* OpenGLSDLImageLoader::loadSDLSurface(const std::string& filename) { ResourceManager *resman = ResourceManager::getInstance(); |