summaryrefslogtreecommitdiff
path: root/src/compoundsprite.cpp
diff options
context:
space:
mode:
authorJared Adams <jaxad0127@gmail.com>2010-05-20 01:35:17 -0600
committerJared Adams <jaxad0127@gmail.com>2010-05-20 12:25:37 -0600
commit487a86fe7dc9904f445d91667095f641f72f7c81 (patch)
tree57191d175f7b2fe771f6b2da225bc2d9cb5ff1d9 /src/compoundsprite.cpp
parent36832f3a5378f739da7040f0711b7101dbc2af02 (diff)
downloadMana-487a86fe7dc9904f445d91667095f641f72f7c81.tar.gz
Mana-487a86fe7dc9904f445d91667095f641f72f7c81.tar.bz2
Mana-487a86fe7dc9904f445d91667095f641f72f7c81.tar.xz
Mana-487a86fe7dc9904f445d91667095f641f72f7c81.zip
Buffer layered sprites under SDL
This improves framerate and allows transparent overlay for complex sprites. Two copies of the buffer are kept, one at full opacity, one with variable opactiy, to reduce calls to setAlpha. Reviewed-by: Bertram
Diffstat (limited to 'src/compoundsprite.cpp')
-rw-r--r--src/compoundsprite.cpp221
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;
}