diff options
-rw-r--r-- | src/actorsprite.cpp | 6 | ||||
-rw-r--r-- | src/animatedsprite.cpp | 34 | ||||
-rw-r--r-- | src/animatedsprite.h | 10 | ||||
-rw-r--r-- | src/being.cpp | 12 | ||||
-rw-r--r-- | src/compoundsprite.cpp | 221 | ||||
-rw-r--r-- | src/compoundsprite.h | 50 | ||||
-rw-r--r-- | src/graphics.cpp | 10 | ||||
-rw-r--r-- | src/graphics.h | 12 | ||||
-rw-r--r-- | src/imagesprite.h | 14 | ||||
-rw-r--r-- | src/sprite.h | 20 |
10 files changed, 320 insertions, 69 deletions
diff --git a/src/actorsprite.cpp b/src/actorsprite.cpp index da81873f..92894b04 100644 --- a/src/actorsprite.cpp +++ b/src/actorsprite.cpp @@ -304,14 +304,14 @@ void ActorSprite::setupSpriteDisplay(const SpriteDisplay &display, { std::string file = "graphics/sprites/" + (*it)->sprite; int variant = (*it)->variant; - push_back(AnimatedSprite::load(file, variant)); + addSprite(AnimatedSprite::load(file, variant)); } // Ensure that something is shown, if desired if (size() == 0 && forceDisplay) { if (display.image.empty()) - push_back(AnimatedSprite::load("graphics/sprites/error.xml")); + addSprite(AnimatedSprite::load("graphics/sprites/error.xml")); else { ResourceManager *resman = ResourceManager::getInstance(); @@ -321,7 +321,7 @@ void ActorSprite::setupSpriteDisplay(const SpriteDisplay &display, if (!img) img = Theme::getImageFromTheme("unknown-item.png"); - push_back(new ImageSprite(img)); + addSprite(new ImageSprite(img)); } } diff --git a/src/animatedsprite.cpp b/src/animatedsprite.cpp index bc595f79..3e4104a9 100644 --- a/src/animatedsprite.cpp +++ b/src/animatedsprite.cpp @@ -70,18 +70,22 @@ AnimatedSprite::~AnimatedSprite() mSprite->decRef(); } -void AnimatedSprite::reset() +bool AnimatedSprite::reset() { + bool ret = mFrameIndex !=0 || mFrameTime != 0 || mLastTime != 0; + mFrameIndex = 0; mFrameTime = 0; mLastTime = 0; + + return ret; } -void AnimatedSprite::play(SpriteAction spriteAction) +bool AnimatedSprite::play(SpriteAction spriteAction) { Action *action = mSprite->getAction(spriteAction); if (!action) - return; + return false; mAction = action; Animation *animation = mAction->getAnimation(mDirection); @@ -92,10 +96,14 @@ void AnimatedSprite::play(SpriteAction spriteAction) mFrame = mAnimation->getFrame(0); reset(); + + return true; } + + return false; } -void AnimatedSprite::update(int time) +bool AnimatedSprite::update(int time) { // Avoid freaking out at first frame or when tick_time overflows if (time < mLastTime || mLastTime == 0) @@ -103,16 +111,22 @@ void AnimatedSprite::update(int time) // If not enough time has passed yet, do nothing if (time <= mLastTime || !mAnimation) - return; + return false; unsigned int dt = time - mLastTime; mLastTime = time; + Animation *animation = mAnimation; + Frame *frame = mFrame; + if (!updateCurrentAnimation(dt)) { // Animation finished, reset to default play(ACTION_STAND); } + + // Make sure something actually changed + return animation != mAnimation || frame != mFrame; } bool AnimatedSprite::updateCurrentAnimation(unsigned int time) @@ -159,14 +173,14 @@ bool AnimatedSprite::draw(Graphics *graphics, int posX, int posY) const posY + mFrame->offsetY); } -void AnimatedSprite::setDirection(SpriteDirection direction) +bool AnimatedSprite::setDirection(SpriteDirection direction) { if (mDirection != direction) { mDirection = direction; if (!mAction) - return; + return false; Animation *animation = mAction->getAnimation(mDirection); @@ -176,7 +190,11 @@ void AnimatedSprite::setDirection(SpriteDirection direction) mFrame = mAnimation->getFrame(0); reset(); } + + return true; } + + return false; } int AnimatedSprite::getWidth() const @@ -195,7 +213,7 @@ int AnimatedSprite::getHeight() const return 0; } -Image* AnimatedSprite::getImage() const +const Image* AnimatedSprite::getImage() const { return mFrame ? mFrame->image : 0; } diff --git a/src/animatedsprite.h b/src/animatedsprite.h index 833a07a3..aae116be 100644 --- a/src/animatedsprite.h +++ b/src/animatedsprite.h @@ -54,11 +54,11 @@ class AnimatedSprite : public Sprite virtual ~AnimatedSprite(); - void reset(); + bool reset(); - void play(SpriteAction action); + bool play(SpriteAction action); - void update(int time); + bool update(int time); bool draw(Graphics* graphics, int posX, int posY) const; @@ -66,9 +66,9 @@ class AnimatedSprite : public Sprite int getHeight() const; - Image* getImage() const; + const Image* getImage() const; - void setDirection(SpriteDirection direction); + bool setDirection(SpriteDirection direction); int getNumberOfLayers() { return 1; } diff --git a/src/being.cpp b/src/being.cpp index a2180c84..24f2e2e1 100644 --- a/src/being.cpp +++ b/src/being.cpp @@ -1063,7 +1063,7 @@ void Being::setSprite(unsigned int slot, int id, const std::string &color, assert(slot < Net::getCharHandler()->maxSprite()); if (slot >= size()) - resize(slot + 1, NULL); + ensureSize(slot + 1); if (slot >= mSpriteIDs.size()) mSpriteIDs.resize(slot + 1, 0); @@ -1074,8 +1074,7 @@ void Being::setSprite(unsigned int slot, int id, const std::string &color, // id = 0 means unequip if (id == 0) { - delete at(slot); - at(slot) = NULL; + removeSprite(slot); if (isWeapon) mEquippedWeapon = NULL; @@ -1097,10 +1096,7 @@ void Being::setSprite(unsigned int slot, int id, const std::string &color, if (equipmentSprite) equipmentSprite->setDirection(getSpriteDirection()); - if (at(slot)) - delete at(slot); - - at(slot) = equipmentSprite; + CompoundSprite::setSprite(slot, equipmentSprite); if (isWeapon) mEquippedWeapon = &ItemDB::get(id); @@ -1124,7 +1120,7 @@ void Being::setSpriteColor(unsigned int slot, const std::string &color) int Being::getNumberOfLayers() const { - return size(); + return CompoundSprite::getNumberOfLayers(); } void Being::load() diff --git a/src/compoundsprite.cpp b/src/compoundsprite.cpp index a9a521ef..53fdd7c2 100644 --- a/src/compoundsprite.cpp +++ b/src/compoundsprite.cpp @@ -20,9 +20,24 @@ #include "compoundsprite.h" +#include "game.h" +#include "graphics.h" +#include "openglgraphics.h" +#include "map.h" + +#include "resources/image.h" + #include "utils/dtor.h" -CompoundSprite::CompoundSprite() +#include <SDL.h> + +#define BUFFER_WIDTH 100 +#define BUFFER_HEIGHT 100 + +CompoundSprite::CompoundSprite(): + mImage(NULL), + mAlphaImage(NULL), + mNeedsRedraw(false) { mAlpha = 1.0f; } @@ -36,44 +51,73 @@ CompoundSprite::~CompoundSprite() clear(); } -void CompoundSprite::reset() +bool CompoundSprite::reset() { + bool ret = false; + SpriteIterator it, it_end; for (it = begin(), it_end = end(); it != it_end; it++) if (*it) - (*it)->reset(); + ret |= (*it)->reset(); + + mNeedsRedraw |= ret; + return ret; } -void CompoundSprite::play(SpriteAction action) +bool CompoundSprite::play(SpriteAction action) { + bool ret = false; + SpriteIterator it, it_end; for (it = begin(), it_end = end(); it != it_end; it++) if (*it) - (*it)->play(action); + ret |= (*it)->play(action); + + mNeedsRedraw |= ret; + return ret; } -void CompoundSprite::update(int time) +bool CompoundSprite::update(int time) { + bool ret = false; + SpriteIterator it, it_end; for (it = begin(), it_end = end(); it != it_end; it++) if (*it) - (*it)->update(time); + ret |= (*it)->update(time); + + mNeedsRedraw |= ret; + return ret; } bool CompoundSprite::draw(Graphics* graphics, int posX, int posY) const { - SpriteConstIterator it, it_end; - for (it = begin(), it_end = end(); it != it_end; it++) + if (mNeedsRedraw) + redraw(); + + if (mAlpha == 1.0f && mImage) + return graphics->drawImage(mImage, posX + mOffsetX, posY + mOffsetY); + else if (mAlpha && mAlphaImage) { - if (*it) + if (mAlphaImage->getAlpha() != mAlpha) + mAlphaImage->setAlpha(mAlpha); + + return graphics->drawImage(mAlphaImage, + posX + mOffsetX, posY + mOffsetY); + } + else + { + SpriteConstIterator it, it_end; + for (it = begin(), it_end = end(); it != it_end; it++) { - if ((*it)->getAlpha() != mAlpha) - (*it)->setAlpha(mAlpha); - (*it)->draw(graphics, posX, posY); + if (*it) + { + (*it)->draw(graphics, posX, posY); + } } } - return true; + return false; } int CompoundSprite::getWidth() const @@ -106,16 +150,155 @@ int CompoundSprite::getHeight() const return 0; } -Image* CompoundSprite::getImage() const +const Image* CompoundSprite::getImage() const { - // TODO http://bugs.manasource.org/view.php?id=24 - return NULL; + return mImage; } -void CompoundSprite::setDirection(SpriteDirection direction) +bool CompoundSprite::setDirection(SpriteDirection direction) { + bool ret = false; + SpriteIterator it, it_end; for (it = begin(), it_end = end(); it != it_end; it++) if (*it) - (*it)->setDirection(direction); + ret |= (*it)->setDirection(direction); + + mNeedsRedraw |= ret; + return ret; +} + +int CompoundSprite::getNumberOfLayers() const +{ + if (mImage || mAlphaImage) + { + return 1; + } + else + { + return size(); + } +} + +void CompoundSprite::addSprite(Sprite* sprite) +{ + push_back(sprite); + mNeedsRedraw = true; +} + +void CompoundSprite::setSprite(int layer, Sprite* sprite) +{ + // Skip if it won't change anything + if (at(layer) == sprite) + return; + + if (at(layer)) + delete at(layer); + at(layer) = sprite; + mNeedsRedraw = true; +} + +void CompoundSprite::removeSprite(int layer) +{ + // Skip if it won't change anything + if (at(layer) == NULL) + return; + + delete at(layer); + at(layer) = NULL; + mNeedsRedraw = true; +} + +void CompoundSprite::clear() +{ + // Skip if it won't change anything + if (empty()) + return; + + std::vector<Sprite*>::clear(); + mNeedsRedraw = true; +} + +void CompoundSprite::ensureSize(size_t layerCount) +{ + // Skip if it won't change anything + if (size() >= layerCount) + return; + + resize(layerCount, NULL); + mNeedsRedraw = true; +} + +void CompoundSprite::redraw() const +{ + // TODO OpenGL support + if (Image::getLoadAsOpenGL()) + { + mNeedsRedraw = false; + return; + } + +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + int rmask = 0xff000000; + int gmask = 0x00ff0000; + int bmask = 0x0000ff00; + int amask = 0x000000ff; +#else + int rmask = 0x000000ff; + int gmask = 0x0000ff00; + int bmask = 0x00ff0000; + int amask = 0xff000000; +#endif + + SDL_Surface *surface = SDL_CreateRGBSurface(SDL_HWSURFACE, + BUFFER_WIDTH, BUFFER_HEIGHT, + 32, rmask, gmask, bmask, amask); + + if (!surface) + return; + + Graphics *graphics = new Graphics(); + graphics->setBlitMode(Graphics::BLIT_GFX); + graphics->setTarget(surface); + graphics->_beginDraw(); + + int tileX = 32 / 2; + int tileY = 32; + + Game *game = Game::instance(); + if (game) + { + Map *map = game->getCurrentMap(); + tileX = map->getTileWidth() / 2; + tileY = map->getTileWidth(); + } + + int posX = BUFFER_WIDTH / 2 - tileX; + int posY = BUFFER_HEIGHT - tileY; + + mOffsetX = tileX - BUFFER_WIDTH / 2; + mOffsetY = tileY - BUFFER_HEIGHT; + + SpriteConstIterator it, it_end; + for (it = begin(), it_end = end(); it != it_end; it++) + { + if (*it) + { + (*it)->draw(graphics, posX, posY); + } + } + + delete graphics; + + SDL_Surface *surfaceA = SDL_CreateRGBSurface(SDL_HWSURFACE, + BUFFER_WIDTH, BUFFER_HEIGHT, + 32, rmask, gmask, bmask, amask); + + SDL_SetAlpha(surface, 0, SDL_ALPHA_OPAQUE); + SDL_BlitSurface(surface, NULL, surfaceA, NULL); + + mImage = Image::load(surface); + mAlphaImage = Image::load(surfaceA); + + mNeedsRedraw = false; } diff --git a/src/compoundsprite.h b/src/compoundsprite.h index b3925216..c714c34b 100644 --- a/src/compoundsprite.h +++ b/src/compoundsprite.h @@ -25,18 +25,20 @@ #include <vector> -class CompoundSprite : public Sprite, public std::vector<Sprite*> +class Image; + +class CompoundSprite : public Sprite, private std::vector<Sprite*> { public: CompoundSprite(); ~CompoundSprite(); - virtual void reset(); + virtual bool reset(); - virtual void play(SpriteAction action); + virtual bool play(SpriteAction action); - virtual void update(int time); + virtual bool update(int time); virtual bool draw(Graphics* graphics, int posX, int posY) const; @@ -50,18 +52,40 @@ public: */ virtual int getHeight() const; - virtual Image* getImage() const; + virtual const Image* getImage() const; - virtual void setDirection(SpriteDirection direction); + virtual bool setDirection(SpriteDirection direction); - virtual Sprite *getSprite(int index) const - { return at(index); } + int getNumberOfLayers() const; - int getNumberOfLayers() - { return size(); } -}; + size_t size() const + { return std::vector<Sprite*>::size(); } + + void addSprite(Sprite* sprite); + + void setSprite(int layer, Sprite* sprite); + + Sprite *getSprite(int layer) const + { return at(layer); } + + void removeSprite(int layer); + + void clear(); -typedef CompoundSprite::iterator SpriteIterator; -typedef CompoundSprite::const_iterator SpriteConstIterator; + void ensureSize(size_t layerCount); + +private: + typedef CompoundSprite::iterator SpriteIterator; + typedef CompoundSprite::const_iterator SpriteConstIterator; + + void redraw() const; + + mutable Image *mImage; + mutable Image *mAlphaImage; + + mutable int mOffsetX, mOffsetY; + + mutable bool mNeedsRedraw; +}; #endif // COMPOUNDSPRITE_H diff --git a/src/graphics.cpp b/src/graphics.cpp index 9815e1ad..24f92544 100644 --- a/src/graphics.cpp +++ b/src/graphics.cpp @@ -27,12 +27,15 @@ #include "resources/image.h" #include "resources/imageloader.h" +#include <SDL_gfxBlitFunc.h> + Graphics::Graphics(): mWidth(0), mHeight(0), mBpp(0), mFullscreen(false), - mHWAccel(false) + mHWAccel(false), + mBlitMode(BLIT_NORMAL) { } @@ -183,7 +186,10 @@ bool Graphics::drawImage(Image *image, int srcX, int srcY, int dstX, int dstY, srcRect.w = width; srcRect.h = height; - return !(SDL_BlitSurface(image->mSDLSurface, &srcRect, mTarget, &dstRect) < 0); + if (mBlitMode == BLIT_NORMAL) + return !(SDL_BlitSurface(image->mSDLSurface, &srcRect, mTarget, &dstRect) < 0); + else + return !(SDL_gfxBlitRGBA(image->mSDLSurface, &srcRect, mTarget, &dstRect) < 0); } void Graphics::drawImage(gcn::Image const *image, int srcX, int srcY, diff --git a/src/graphics.h b/src/graphics.h index 211fb901..344c31c3 100644 --- a/src/graphics.h +++ b/src/graphics.h @@ -73,6 +73,11 @@ struct ImageRect class Graphics : public gcn::SDLGraphics { public: + enum BlitMode { + BLIT_NORMAL = 0, + BLIT_GFX + }; + /** * Constructor. */ @@ -182,6 +187,12 @@ class Graphics : public gcn::SDLGraphics drawImageRect(area.x, area.y, area.width, area.height, imgRect); } + void setBlitMode(BlitMode mode) + { mBlitMode = mode; } + + BlitMode getBlitMode() + { return mBlitMode; } + /** * Updates the screen. This is done by either copying the buffer to the * screen or swapping pages. @@ -211,6 +222,7 @@ class Graphics : public gcn::SDLGraphics int mBpp; bool mFullscreen; bool mHWAccel; + BlitMode mBlitMode; }; extern Graphics *graphics; diff --git a/src/imagesprite.h b/src/imagesprite.h index 83fcfa12..20f9fbef 100644 --- a/src/imagesprite.h +++ b/src/imagesprite.h @@ -34,11 +34,14 @@ public: ~ImageSprite(); - virtual void reset() {} + virtual bool reset() + { return false; } - virtual void play(SpriteAction action) {} + virtual bool play(SpriteAction action) + { return false; } - virtual void update(int time) {} + virtual bool update(int time) + { return false; } virtual bool draw(Graphics* graphics, int posX, int posY) const; @@ -48,10 +51,11 @@ public: virtual int getHeight() const { return mImage->getHeight(); } - virtual Image* getImage() const + virtual const Image* getImage() const { return mImage; } - virtual void setDirection(SpriteDirection direction) {} + virtual bool setDirection(SpriteDirection direction) + { return false; } int getNumberOfLayers() { return 1; } diff --git a/src/sprite.h b/src/sprite.h index d8345ab8..2bcd754a 100644 --- a/src/sprite.h +++ b/src/sprite.h @@ -33,19 +33,25 @@ class Sprite /** * Resets the sprite. + * + * @returns true if the sprite changed, false otherwise */ - virtual void reset() = 0; + virtual bool reset() = 0; /** - * Plays an action using the current direction + * Plays an action using the current direction. + * + * @returns true if the sprite changed, false otherwise */ - virtual void play(SpriteAction action) = 0; + virtual bool play(SpriteAction action) = 0; /** * Inform the animation of the passed time so that it can output the * correct animation frame. + * + * @returns true if the sprite changed, false otherwise */ - virtual void update(int time) = 0; + virtual bool update(int time) = 0; /** * Draw the current animation frame at the coordinates given in screen @@ -66,12 +72,14 @@ class Sprite /** * Returns a reference to the current image being drawn. */ - virtual Image* getImage() const = 0; + virtual const Image* getImage() const = 0; /** * Sets the direction. + * + * @returns true if the sprite changed, false otherwise */ - virtual void setDirection(SpriteDirection direction) = 0; + virtual bool setDirection(SpriteDirection direction) = 0; /** * Sets the alpha value of the animated sprite |