summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/actorsprite.cpp6
-rw-r--r--src/animatedsprite.cpp34
-rw-r--r--src/animatedsprite.h10
-rw-r--r--src/being.cpp12
-rw-r--r--src/compoundsprite.cpp221
-rw-r--r--src/compoundsprite.h50
-rw-r--r--src/graphics.cpp10
-rw-r--r--src/graphics.h12
-rw-r--r--src/imagesprite.h14
-rw-r--r--src/sprite.h20
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