From e454585b8ea9f0106cf8ade62a653d4d6145f0ff Mon Sep 17 00:00:00 2001 From: Paul Merrill Date: Sun, 17 Jul 2011 01:17:31 -0700 Subject: [PATCH] factored generic Animation class out of Area::TileType --- src/Makefile | 2 +- src/animation.cpp | 50 ++++++++++++++++++++++++++++++++++++++++++++++ src/animation.h | 53 ++++++++++++++++++++++++++++++++++++++++++++++++ src/area.cpp | 60 +++++++++++++++++++------------------------------------ src/area.h | 11 ++-------- src/entity.h | 4 ++-- 6 files changed, 129 insertions(+), 51 deletions(-) create mode 100644 src/animation.cpp create mode 100644 src/animation.h diff --git a/src/Makefile b/src/Makefile index 2fb7722..56c29c1 100644 --- a/src/Makefile +++ b/src/Makefile @@ -24,7 +24,7 @@ TESTWORLD = babysfirst.world all: tsunagari $(TESTWORLD) -tsunagari: area.o cmd.o common.o entity.o log.o main.o player.o resourcer.o window.o world.o +tsunagari: animation.o area.o cmd.o common.o entity.o log.o main.o player.o resourcer.o window.o world.o $(CXX) -o tsunagari *.o $(LDFLAGS) %.world: %/* diff --git a/src/animation.cpp b/src/animation.cpp new file mode 100644 index 0000000..abcdbaa --- /dev/null +++ b/src/animation.cpp @@ -0,0 +1,50 @@ +#include "animation.h" + +Animation::Animation() + : img(NULL), + animated(false), + frameLen(0), + animLen(0), + frameShowing(0) +{ +} + +void Animation::addFrame(ImageRef frame) +{ + frames.push_back(frame); + animLen = frameLen * (int)frames.size(); + if (frames.size() == 1) + img = frame.get(); + if (frames.size() > 1) + animated = true; +} + +void Animation::setFrameLen(int milliseconds) +{ + frameLen = milliseconds; + animLen = frameLen * (int)frames.size(); +} + +bool Animation::needsUpdate(int milliseconds) const +{ + if (animated) { + int frame = (milliseconds % animLen) / frameLen; + if (frame != frameShowing) + return true; + } + return false; +} + +void Animation::updateFrame(int milliseconds) +{ + if (animated) { + frameShowing = (milliseconds % animLen) / frameLen; + img = frames[frameShowing].get(); + } +} + +Gosu::Image* Animation::image() const +{ + return img; +} + diff --git a/src/animation.h b/src/animation.h new file mode 100644 index 0000000..60c3dbd --- /dev/null +++ b/src/animation.h @@ -0,0 +1,53 @@ +/****************************** +** Tsunagari Tile Engine ** +** animation.h ** +** Copyright 2011 OmegaSDG ** +******************************/ + +#ifndef ANIMATED_H +#define ANIMATED_H + +#include + +#include + +#include "resourcer.h" + +namespace Gosu { + class Image; +} + +class Animation +{ +public: + Animation(); + + void addFrame(ImageRef frame); + void setFrameLen(int milliseconds); + + bool needsUpdate(int milliseconds) const; + void updateFrame(int milliseconds); + Gosu::Image* image() const; + +private: + //! List of images in animation. + std::vector frames; + + //! Current graphic displaying on screen. + Gosu::Image* img; + + //! Are we animated? Same as frames.size() > 1 + bool animated; + + //! Length of each frame in animation. + int frameLen; + + //! Total length of one complete cycle through animation. + int animLen; + + //! Index of frame currently displaying on screen. + int frameShowing; +}; + +#endif + diff --git a/src/area.cpp b/src/area.cpp index 88da621..07942e0 100644 --- a/src/area.cpp +++ b/src/area.cpp @@ -98,16 +98,9 @@ void Area::drawTiles() { // Calculate frame to show for each type of tile int millis = (int)Gosu::milliseconds(); - BOOST_FOREACH(TileSet& set, tilesets) { - BOOST_FOREACH(TileType& type, set.tileTypes) { - if (type.animated) { - int frame = (millis % type.animLen) / - type.frameLen; - type.frameShowing = frame; - type.graphic = type.graphics[frame].get(); - } - } - } + BOOST_FOREACH(TileSet& set, tilesets) + BOOST_FOREACH(TileType& type, set.tileTypes) + type.anim.updateFrame(millis); // Render for (unsigned z = 0; z != map.size(); z++) { @@ -117,7 +110,7 @@ void Area::drawTiles() for (unsigned x = 0; x != row.size(); x++) { const Tile& tile = row[x]; const TileType* type = tile.type; - const Gosu::Image* img = type->graphic; + const Gosu::Image* img = type->anim.image(); img->draw(x*img->width(), y*img->height(), 0); } } @@ -136,18 +129,11 @@ bool Area::needsRedraw() const // Do any onscreen tile types need to update their animations? int millis = (int)Gosu::milliseconds(); - BOOST_FOREACH(const TileSet& set, tilesets) { - BOOST_FOREACH(const TileType& type, set.tileTypes) { - if (type.animated) { - int frame = (millis % type.animLen) / - type.frameLen; - if (frame != type.frameShowing && + BOOST_FOREACH(const TileSet& set, tilesets) + BOOST_FOREACH(const TileType& type, set.tileTypes) + if (type.anim.needsUpdate(millis) && tileTypeOnScreen(type)) - return true; - } - } - } - + return true; return false; } @@ -371,16 +357,12 @@ bool Area::processTileSet(xmlNode* node) Area::TileType Area::defaultTileType(TileSet& set) { TileType type; - type.animated = false; - type.frameLen = 1000; - type.flags = 0x0; - type.graphics.push_back(set.tiles.front()); - type.graphic = type.graphics[0].get(); + type.anim.addFrame(set.tiles.front()); set.tiles.pop_front(); return type; } -bool Area::processTileType(xmlNode* node, TileSet& ts) +bool Area::processTileType(xmlNode* node, TileSet& set) { /* @@ -401,11 +383,11 @@ bool Area::processTileType(xmlNode* node, TileSet& ts) */ // Initialize a default TileType, we'll build on that. - TileType tt = defaultTileType(ts); + TileType type = defaultTileType(set); xmlChar* idstr = xmlGetProp(node, BAD_CAST("id")); unsigned id = (unsigned)atoi((const char*)idstr); // atoi - long expectedId = ts.tileTypes.size(); + long expectedId = set.tileTypes.size(); if (id != expectedId) { Log::err(descriptor, std::string("expected TileType id ") + itostr(expectedId) + ", but got " + @@ -419,7 +401,7 @@ bool Area::processTileType(xmlNode* node, TileSet& ts) xmlChar* name = xmlGetProp(child, BAD_CAST("name")); xmlChar* value = xmlGetProp(child, BAD_CAST("value")); if (!xmlStrncmp(name, BAD_CAST("flags"), 6)) { - tt.flags = splitTileFlags((const char*)value); + type.flags = splitTileFlags((const char*)value); } else if (!xmlStrncmp(name, BAD_CAST("onEnter"), 8)) { // TODO events @@ -428,7 +410,8 @@ bool Area::processTileType(xmlNode* node, TileSet& ts) // TODO events } else if (!xmlStrncmp(name, BAD_CAST("animated"), 9)) { - tt.animated = parseBool((const char*)value); + // XXX still needed? + // type.animated = parseBool((const char*)value); } else if (!xmlStrncmp(name, BAD_CAST("size"), 5)) { int size = atoi((const char*)value); // atoi @@ -436,23 +419,22 @@ bool Area::processTileType(xmlNode* node, TileSet& ts) // Add size-1 more frames to our animation. // We already have one from defaultTileType. for (int i = 1; i < size; i++) { - if (ts.tiles.empty()) { + if (set.tiles.empty()) { Log::err(descriptor, "ran out of tiles" "/frames for animated tile"); return false; } - tt.graphics.push_back(ts.tiles.front()); - ts.tiles.pop_front(); + type.anim.addFrame(set.tiles.front()); + set.tiles.pop_front(); } - tt.animLen = tt.frameLen * (int)tt.graphics.size(); } else if (!xmlStrncmp(name, BAD_CAST("speed"), 6)) { - tt.frameLen = (int)(1000.0/atof((const char*)value)); - tt.animLen = tt.frameLen * (int)tt.graphics.size(); + int len = (int)(1000.0/atof((const char*)value)); + type.anim.setFrameLen(len); } } - ts.tileTypes.push_back(tt); + set.tileTypes.push_back(type); return true; } diff --git a/src/area.h b/src/area.h index a00bcba..64103e1 100644 --- a/src/area.h +++ b/src/area.h @@ -16,6 +16,7 @@ #include // for Gosu::Transform #include +#include "animation.h" #include "common.h" #include "player.h" #include "resourcer.h" @@ -103,17 +104,9 @@ public: */ struct Tile; struct TileType { - std::vector graphics; + Animation anim; // Graphics for tiles of this type. std::vector events; std::vector allOfType; - Gosu::Image* graphic; // Current graphic to use for all tiles of - // this type - bool animated; // Is the tile animated? - int frameLen; // Length of each frame in animation - int animLen; // Total length of one complete cycle through - // animation - int frameShowing; // Index of frame currently displaying on - // screen unsigned flags; // bitflags for each option in TileFlags enum // TODO: boost::scoped_ptr door }; diff --git a/src/entity.h b/src/entity.h index 143fc7a..c6cddfe 100644 --- a/src/entity.h +++ b/src/entity.h @@ -4,8 +4,8 @@ ** Copyright 2011 OmegaSDG ** ******************************/ -#ifndef SPRITE_H -#define SPRITE_H +#ifndef ENTITY_H +#define ENTITY_H #include -- 2.11.4.GIT