diff options
Diffstat (limited to 'src/compoundsprite.cpp')
-rw-r--r-- | src/compoundsprite.cpp | 221 |
1 files changed, 202 insertions, 19 deletions
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; } |