diff --git a/src/include/particle.h b/src/include/particle.h index 3c5e37282..9338377fa 100644 --- a/src/include/particle.h +++ b/src/include/particle.h @@ -43,17 +43,7 @@ struct CPosition { float y; }; -class Animation -{ -public: - virtual ~Animation() {} - virtual void draw(int x, int y) = 0; - virtual void update(int ticks) = 0; - virtual bool isFinished() = 0; - virtual Animation *clone() = 0; -}; - -class GraphicAnimation : public Animation +class GraphicAnimation { CGraphic *g; int ticksPerFrame; @@ -61,24 +51,24 @@ class GraphicAnimation : public Animation int currTicks; public: GraphicAnimation(CGraphic *g, int ticksPerFrame); - virtual ~GraphicAnimation() {} + ~GraphicAnimation() {} /** ** Draw the current frame of the animation. ** @param x x screen coordinate where to draw the animation. ** @param y y screen coordinate where to draw the animation. */ - virtual void draw(int x, int y); + void draw(int x, int y); /** ** Update the animation. ** @param ticks the number of ticks elapsed since the last call. */ - virtual void update(int ticks); + void update(int ticks); - virtual bool isFinished(); - - virtual Animation *clone(); + bool isFinished(); + bool isVisible(const CViewport &vp, const CPosition &pos); + GraphicAnimation *clone(); }; @@ -92,8 +82,9 @@ public: {} virtual ~CParticle() {} - virtual void draw() {} - virtual void update(int) {} + virtual bool isVisible(const CViewport &vp) const = 0; + virtual void draw() = 0; + virtual void update(int) = 0; inline void destroy() { destroyed = true; } inline bool isDestroyed() { return destroyed; } @@ -109,15 +100,16 @@ protected: class StaticParticle : public CParticle { public: - StaticParticle(CPosition position, Animation *flame); + StaticParticle(CPosition position, GraphicAnimation *flame); virtual ~StaticParticle(); + virtual bool isVisible(const CViewport &vp) const; virtual void draw(); virtual void update(int ticks); virtual CParticle *clone(); protected: - Animation *animation; + GraphicAnimation *animation; }; @@ -125,12 +117,13 @@ protected: class CChunkParticle : public CParticle { public: - CChunkParticle(CPosition position, Animation *smokeAnimation, Animation *debrisAnimation, - Animation *destroyAnimation, + CChunkParticle(CPosition position, GraphicAnimation *smokeAnimation, GraphicAnimation *debrisAnimation, + GraphicAnimation *destroyAnimation, int minVelocity = 0, int maxVelocity = 400, int minTrajectoryAngle = 77, int maxTTL = 0); virtual ~CChunkParticle(); + virtual bool isVisible(const CViewport &vp) const; virtual void draw(); virtual void update(int ticks); virtual CParticle *clone(); @@ -147,9 +140,9 @@ protected: int maxVelocity; int minTrajectoryAngle; float height; - Animation *debrisAnimation; - Animation *smokeAnimation; - Animation *destroyAnimation; + GraphicAnimation *debrisAnimation; + GraphicAnimation *smokeAnimation; + GraphicAnimation *destroyAnimation; struct { float x; @@ -162,15 +155,16 @@ protected: class CSmokeParticle : public CParticle { public: - CSmokeParticle(CPosition position, Animation *animation, float speedx = 0, float speedy = -22.0f); + CSmokeParticle(CPosition position, GraphicAnimation *animation, float speedx = 0, float speedy = -22.0f); virtual ~CSmokeParticle(); + virtual bool isVisible(const CViewport &vp) const; virtual void draw(); virtual void update(int ticks); virtual CParticle *clone(); protected: - Animation *puff; + GraphicAnimation *puff; struct { float x; float y; @@ -180,15 +174,16 @@ protected: class CRadialParticle : public CParticle { public: - CRadialParticle(CPosition position, Animation *animation, int maxSpeed); + CRadialParticle(CPosition position, GraphicAnimation *animation, int maxSpeed); virtual ~CRadialParticle(); + virtual bool isVisible(const CViewport &vp) const; virtual void draw(); virtual void update(int ticks); virtual CParticle *clone(); protected: - Animation *animation; + GraphicAnimation *animation; float direction; int speed; int maxSpeed; diff --git a/src/particle/chunkparticle.cpp b/src/particle/chunkparticle.cpp index 8e99bbb66..e858974a5 100644 --- a/src/particle/chunkparticle.cpp +++ b/src/particle/chunkparticle.cpp @@ -44,8 +44,8 @@ static inline float deg2rad(int degrees) } -CChunkParticle::CChunkParticle(CPosition position, Animation *smokeAnimation, Animation *debrisAnimation, - Animation *destroyAnimation, +CChunkParticle::CChunkParticle(CPosition position, GraphicAnimation *smokeAnimation, GraphicAnimation *debrisAnimation, + GraphicAnimation *destroyAnimation, int minVelocity, int maxVelocity, int minTrajectoryAngle, int maxTTL) : CParticle(position), initialPos(position), maxTTL(maxTTL), nextSmokeTicks(0), age(0), height(0.f) @@ -81,6 +81,12 @@ static float calculateScreenPos(float posy, float height) return posy - height * 0.2f; } + +bool CChunkParticle::isVisible(const CViewport &vp) const +{ + return debrisAnimation && debrisAnimation->isVisible(vp, pos); +} + void CChunkParticle::draw() { CPosition screenPos = ParticleManager.getScreenPos(pos); @@ -105,7 +111,7 @@ void CChunkParticle::update(int ticks) if (age >= lifetime) { if (destroyAnimation) { CPosition p(pos.x, calculateScreenPos(pos.y, height)); - Animation *destroyanimation = destroyAnimation->clone(); + GraphicAnimation *destroyanimation = destroyAnimation->clone(); StaticParticle *destroy = new StaticParticle(p, destroyanimation); ParticleManager.add(destroy); } @@ -119,7 +125,7 @@ void CChunkParticle::update(int ticks) if (age > nextSmokeTicks) { CPosition p(pos.x, calculateScreenPos(pos.y, height)); - Animation *smokeanimation = smokeAnimation->clone(); + GraphicAnimation *smokeanimation = smokeAnimation->clone(); CSmokeParticle *smoke = new CSmokeParticle(p, smokeanimation); ParticleManager.add(smoke); @@ -128,7 +134,7 @@ void CChunkParticle::update(int ticks) debrisAnimation->update(ticks); if (debrisAnimation->isFinished()) { - Animation *debrisanimation = debrisAnimation->clone(); + GraphicAnimation *debrisanimation = debrisAnimation->clone(); delete debrisAnimation; debrisAnimation = debrisanimation; } diff --git a/src/particle/graphicanimation.cpp b/src/particle/graphicanimation.cpp index a4537a172..7e83fc857 100644 --- a/src/particle/graphicanimation.cpp +++ b/src/particle/graphicanimation.cpp @@ -30,7 +30,12 @@ //@{ #include "stratagus.h" + #include "particle.h" + +#include "map.h" +#include "player.h" +#include "ui.h" #include "video.h" GraphicAnimation::GraphicAnimation(CGraphic *g, int ticksPerFrame) : @@ -61,7 +66,37 @@ bool GraphicAnimation::isFinished() return currentFrame >= g->NumFrames; } -Animation *GraphicAnimation::clone() +bool GraphicAnimation::isVisible(const CViewport &vp, const CPosition &pos) +{ + // invisible graphics always invisible + if (!g) { + return false; + } + + PixelSize graphicSize(g->Width, g->Height); + PixelDiff margin(PixelTileSize.x - 1, PixelTileSize.y - 1); + PixelPos position(pos.x, pos.y); + Vec2i minPos = Map.MapPixelPosToTilePos(position); + Vec2i maxPos = Map.MapPixelPosToTilePos(position + graphicSize + margin); + Map.Clamp(minPos); + Map.Clamp(maxPos); + + if (!vp.AnyMapAreaVisibleInViewport(minPos, maxPos)) { + return false; + } + + Vec2i p; + for (p.x = minPos.x; p.x <= maxPos.x; ++p.x) { + for (p.y = minPos.y; p.y <= maxPos.y; ++p.y) { + if (ReplayRevealMap || Map.Field(p)->playerInfo.IsTeamVisible(*ThisPlayer)) { + return true; + } + } + } + return false; +} + +GraphicAnimation *GraphicAnimation::clone() { return new GraphicAnimation(g, ticksPerFrame); } diff --git a/src/particle/particlemanager.cpp b/src/particle/particlemanager.cpp index 8fe974676..8025f3394 100644 --- a/src/particle/particlemanager.cpp +++ b/src/particle/particlemanager.cpp @@ -31,8 +31,8 @@ #include "stratagus.h" #include "particle.h" -#include "video.h" #include "ui.h" +#include "video.h" CParticleManager ParticleManager; @@ -76,7 +76,9 @@ void CParticleManager::draw(const CViewport &vp) std::vector<CParticle *>::iterator i; for (i = particles.begin(); i != particles.end(); ++i) { - (*i)->draw(); + if ((*i)->isVisible(vp)) { + (*i)->draw(); + } } this->vp = NULL; @@ -117,4 +119,4 @@ CPosition CParticleManager::getScreenPos(const CPosition &pos) const return CPosition(screenPixelPos.x, screenPixelPos.y); } -//@} +//@} \ No newline at end of file diff --git a/src/particle/radialparticle.cpp b/src/particle/radialparticle.cpp index c5b7d94c1..e27008312 100644 --- a/src/particle/radialparticle.cpp +++ b/src/particle/radialparticle.cpp @@ -34,7 +34,7 @@ #include "stratagus.h" #include "particle.h" -CRadialParticle::CRadialParticle(CPosition position, Animation *animation, int maxSpeed) : +CRadialParticle::CRadialParticle(CPosition position, GraphicAnimation *animation, int maxSpeed) : CParticle(position) { Assert(animation); @@ -52,6 +52,11 @@ CRadialParticle::~CRadialParticle() delete animation; } +bool CRadialParticle::isVisible(const CViewport &vp) const +{ + return animation && animation->isVisible(vp, pos); +} + void CRadialParticle::draw() { CPosition screenPos = ParticleManager.getScreenPos(pos); diff --git a/src/particle/smokeparticle.cpp b/src/particle/smokeparticle.cpp index ff6720e78..e0cbdac18 100644 --- a/src/particle/smokeparticle.cpp +++ b/src/particle/smokeparticle.cpp @@ -35,7 +35,7 @@ -CSmokeParticle::CSmokeParticle(CPosition position, Animation *smoke, +CSmokeParticle::CSmokeParticle(CPosition position, GraphicAnimation *smoke, float speedx, float speedy) : CParticle(position) { @@ -51,6 +51,11 @@ CSmokeParticle::~CSmokeParticle() delete puff; } +bool CSmokeParticle::isVisible(const CViewport &vp) const +{ + return puff && puff->isVisible(vp, pos); +} + void CSmokeParticle::draw() { CPosition screenPos = ParticleManager.getScreenPos(pos); diff --git a/src/particle/staticparticle.cpp b/src/particle/staticparticle.cpp index a32ffec2b..e0cfa6f54 100644 --- a/src/particle/staticparticle.cpp +++ b/src/particle/staticparticle.cpp @@ -33,7 +33,7 @@ #include "particle.h" -StaticParticle::StaticParticle(CPosition position, Animation *animation) : +StaticParticle::StaticParticle(CPosition position, GraphicAnimation *animation) : CParticle(position) { Assert(animation); @@ -45,6 +45,11 @@ StaticParticle::~StaticParticle() delete animation; } +bool StaticParticle::isVisible(const CViewport &vp) const +{ + return animation && animation->isVisible(vp, pos); +} + void StaticParticle::draw() { CPosition screenPos = ParticleManager.getScreenPos(pos); diff --git a/src/tolua/particle.pkg b/src/tolua/particle.pkg index b9eafc507..3d157495d 100644 --- a/src/tolua/particle.pkg +++ b/src/tolua/particle.pkg @@ -7,10 +7,10 @@ struct CPosition float y; }; -class GraphicAnimation : public Animation +class GraphicAnimation { GraphicAnimation(CGraphic *g, int ticksPerFrame); - virtual Animation * clone(); + virtual GraphicAnimation * clone(); }; class CParticle @@ -21,25 +21,25 @@ class CParticle class StaticParticle : public CParticle { public: - StaticParticle(CPosition position, Animation *animation); + StaticParticle(CPosition position, GraphicAnimation *animation); }; class CChunkParticle : public CParticle { public: - CChunkParticle(CPosition position, Animation *smokeAnimation, Animation *debrisAnimation, Animation *destroyAnimation, int minVelocity = 0, int maxVelocity = 400, int minTrajectoryAngle = 77, int maxTTL = 0); + CChunkParticle(CPosition position, GraphicAnimation *smokeAnimation, GraphicAnimation *debrisAnimation, GraphicAnimation *destroyAnimation, int minVelocity = 0, int maxVelocity = 400, int minTrajectoryAngle = 77, int maxTTL = 0); }; class CSmokeParticle : public CParticle { public: - CSmokeParticle(CPosition position, Animation *animation, float speedx = 0, float speedy = -22.0); + CSmokeParticle(CPosition position, GraphicAnimation *animation, float speedx = 0, float speedy = -22.0); }; class CRadialParticle : public CParticle { public: - CRadialParticle(CPosition position, Animation *smokeAnimation, int maxSpeed); + CRadialParticle(CPosition position, GraphicAnimation *smokeAnimation, int maxSpeed); }; class CParticleManager