[+] Added drawlevel sorting for particles

This commit is contained in:
cybermind 2013-05-09 11:07:50 +06:00
parent b9fb1bfd1b
commit a63a4fff61
8 changed files with 118 additions and 41 deletions

View file

@ -77,8 +77,8 @@ public:
class CParticle class CParticle
{ {
public: public:
CParticle(CPosition position) : CParticle(CPosition position, int drawlevel = 0) :
pos(position), destroyed(false) pos(position), destroyed(false), drawLevel(drawlevel)
{} {}
virtual ~CParticle() {} virtual ~CParticle() {}
@ -91,16 +91,20 @@ public:
virtual CParticle *clone() = 0; virtual CParticle *clone() = 0;
int getDrawLevel() const { return drawLevel; }
void setDrawLevel(int value) { drawLevel = value; }
protected: protected:
CPosition pos; CPosition pos;
bool destroyed; bool destroyed;
int drawLevel;
}; };
class StaticParticle : public CParticle class StaticParticle : public CParticle
{ {
public: public:
StaticParticle(CPosition position, GraphicAnimation *flame); StaticParticle(CPosition position, GraphicAnimation *flame, int drawlevel = 0);
virtual ~StaticParticle(); virtual ~StaticParticle();
virtual bool isVisible(const CViewport &vp) const; virtual bool isVisible(const CViewport &vp) const;
@ -120,13 +124,17 @@ public:
CChunkParticle(CPosition position, GraphicAnimation *smokeAnimation, GraphicAnimation *debrisAnimation, CChunkParticle(CPosition position, GraphicAnimation *smokeAnimation, GraphicAnimation *debrisAnimation,
GraphicAnimation *destroyAnimation, GraphicAnimation *destroyAnimation,
int minVelocity = 0, int maxVelocity = 400, int minVelocity = 0, int maxVelocity = 400,
int minTrajectoryAngle = 77, int maxTTL = 0); int minTrajectoryAngle = 77, int maxTTL = 0, int drawlevel = 0);
virtual ~CChunkParticle(); virtual ~CChunkParticle();
virtual bool isVisible(const CViewport &vp) const; virtual bool isVisible(const CViewport &vp) const;
virtual void draw(); virtual void draw();
virtual void update(int ticks); virtual void update(int ticks);
virtual CParticle *clone(); virtual CParticle *clone();
int getSmokeDrawLevel() const { return smokeDrawLevel; }
int getDestroyDrawLevel() const { return destroyDrawLevel; }
void setSmokeDrawLevel(int value) { smokeDrawLevel = value; }
void setDestroyDrawLevel(int value) { destroyDrawLevel = value; }
protected: protected:
CPosition initialPos; CPosition initialPos;
@ -140,6 +148,8 @@ protected:
int maxVelocity; int maxVelocity;
int minTrajectoryAngle; int minTrajectoryAngle;
float height; float height;
int smokeDrawLevel;
int destroyDrawLevel;
GraphicAnimation *debrisAnimation; GraphicAnimation *debrisAnimation;
GraphicAnimation *smokeAnimation; GraphicAnimation *smokeAnimation;
GraphicAnimation *destroyAnimation; GraphicAnimation *destroyAnimation;
@ -155,7 +165,7 @@ protected:
class CSmokeParticle : public CParticle class CSmokeParticle : public CParticle
{ {
public: public:
CSmokeParticle(CPosition position, GraphicAnimation *animation, float speedx = 0, float speedy = -22.0f); CSmokeParticle(CPosition position, GraphicAnimation *animation, float speedx = 0, float speedy = -22.0f, int drawlevel = 0);
virtual ~CSmokeParticle(); virtual ~CSmokeParticle();
virtual bool isVisible(const CViewport &vp) const; virtual bool isVisible(const CViewport &vp) const;
@ -174,7 +184,7 @@ protected:
class CRadialParticle : public CParticle class CRadialParticle : public CParticle
{ {
public: public:
CRadialParticle(CPosition position, GraphicAnimation *animation, int maxSpeed); CRadialParticle(CPosition position, GraphicAnimation *animation, int maxSpeed, int drawlevel = 0);
virtual ~CRadialParticle(); virtual ~CRadialParticle();
virtual bool isVisible(const CViewport &vp) const; virtual bool isVisible(const CViewport &vp) const;
@ -199,7 +209,9 @@ public:
static void init(); static void init();
static void exit(); static void exit();
void draw(const CViewport &vp); void prepareToDraw(const CViewport &vp, std::vector<CParticle *> &table);
void endDraw();
void update(); void update();
void add(CParticle *particle); void add(CParticle *particle);

View file

@ -332,25 +332,68 @@ void CViewport::Draw() const
CurrentViewport = this; CurrentViewport = this;
{ {
// Now we need to sort units, missiles, particles by draw level and draw them
std::vector<CUnit *> unittable; std::vector<CUnit *> unittable;
std::vector<Missile *> missiletable; std::vector<Missile *> missiletable;
std::vector<CParticle *> particletable;
// We find and sort units after draw level.
FindAndSortUnits(*this, unittable); FindAndSortUnits(*this, unittable);
const size_t nunits = unittable.size(); const size_t nunits = unittable.size();
FindAndSortMissiles(*this, missiletable); FindAndSortMissiles(*this, missiletable);
const size_t nmissiles = missiletable.size(); const size_t nmissiles = missiletable.size();
ParticleManager.prepareToDraw(*this, particletable);
const size_t nparticles = particletable.size();
size_t i = 0; size_t i = 0;
size_t j = 0; size_t j = 0;
size_t k = 0;
while (i < nunits && j < nmissiles) {
if (unittable[i]->Type->DrawLevel <= missiletable[j]->Type->DrawLevel) { while ((i < nunits && j < nmissiles) || (i < nunits && k < nparticles)
unittable[i]->Draw(*this); || (j < nmissiles && k < nparticles)) {
++i; if (i == nunits) {
} else { if (missiletable[j]->Type->DrawLevel < particletable[k]->getDrawLevel()) {
missiletable[j]->DrawMissile(*this); missiletable[j]->DrawMissile(*this);
++j; ++j;
} } else {
particletable[k]->draw();
++k;
}
} else if (j == nmissiles) {
if (unittable[i]->Type->DrawLevel < particletable[k]->getDrawLevel()) {
unittable[i]->Draw(*this);
++i;
} else {
particletable[k]->draw();
++k;
}
} else if (k == nparticles) {
if (unittable[i]->Type->DrawLevel < missiletable[j]->Type->DrawLevel) {
unittable[i]->Draw(*this);
++i;
} else {
missiletable[j]->DrawMissile(*this);
++j;
}
} else {
if (unittable[i]->Type->DrawLevel <= missiletable[j]->Type->DrawLevel) {
if (unittable[i]->Type->DrawLevel < particletable[k]->getDrawLevel()) {
unittable[i]->Draw(*this);
++i;
} else {
particletable[k]->draw();
++k;
}
} else {
if (missiletable[j]->Type->DrawLevel < particletable[k]->getDrawLevel()) {
missiletable[j]->DrawMissile(*this);
++j;
} else {
particletable[k]->draw();
++k;
}
}
}
} }
for (; i < nunits; ++i) { for (; i < nunits; ++i) {
unittable[i]->Draw(*this); unittable[i]->Draw(*this);
@ -358,10 +401,12 @@ void CViewport::Draw() const
for (; j < nmissiles; ++j) { for (; j < nmissiles; ++j) {
missiletable[j]->DrawMissile(*this); missiletable[j]->DrawMissile(*this);
} }
for (; k < nparticles; ++k) {
particletable[k]->draw();
}
ParticleManager.endDraw();
} }
ParticleManager.draw(*this);
this->DrawMapFogOfWar(); this->DrawMapFogOfWar();
// //

View file

@ -46,8 +46,8 @@ static inline float deg2rad(int degrees)
CChunkParticle::CChunkParticle(CPosition position, GraphicAnimation *smokeAnimation, GraphicAnimation *debrisAnimation, CChunkParticle::CChunkParticle(CPosition position, GraphicAnimation *smokeAnimation, GraphicAnimation *debrisAnimation,
GraphicAnimation *destroyAnimation, GraphicAnimation *destroyAnimation,
int minVelocity, int maxVelocity, int minTrajectoryAngle, int maxTTL) : int minVelocity, int maxVelocity, int minTrajectoryAngle, int maxTTL, int drawlevel) :
CParticle(position), initialPos(position), maxTTL(maxTTL), nextSmokeTicks(0), CParticle(position, drawlevel), initialPos(position), maxTTL(maxTTL), nextSmokeTicks(0),
age(0), height(0.f) age(0), height(0.f)
{ {
float radians = deg2rad(MyRand() % 360); float radians = deg2rad(MyRand() % 360);
@ -112,7 +112,7 @@ void CChunkParticle::update(int ticks)
if (destroyAnimation) { if (destroyAnimation) {
CPosition p(pos.x, calculateScreenPos(pos.y, height)); CPosition p(pos.x, calculateScreenPos(pos.y, height));
GraphicAnimation *destroyanimation = destroyAnimation->clone(); GraphicAnimation *destroyanimation = destroyAnimation->clone();
StaticParticle *destroy = new StaticParticle(p, destroyanimation); StaticParticle *destroy = new StaticParticle(p, destroyanimation, destroyDrawLevel);
ParticleManager.add(destroy); ParticleManager.add(destroy);
} }
@ -126,7 +126,7 @@ void CChunkParticle::update(int ticks)
if (age > nextSmokeTicks) { if (age > nextSmokeTicks) {
CPosition p(pos.x, calculateScreenPos(pos.y, height)); CPosition p(pos.x, calculateScreenPos(pos.y, height));
GraphicAnimation *smokeanimation = smokeAnimation->clone(); GraphicAnimation *smokeanimation = smokeAnimation->clone();
CSmokeParticle *smoke = new CSmokeParticle(p, smokeanimation); CSmokeParticle *smoke = new CSmokeParticle(p, smokeanimation, 0, -22.0f, smokeDrawLevel);
ParticleManager.add(smoke); ParticleManager.add(smoke);
nextSmokeTicks += MyRand() % randSmokeTicks + minSmokeTicks; nextSmokeTicks += MyRand() % randSmokeTicks + minSmokeTicks;
@ -151,7 +151,10 @@ void CChunkParticle::update(int ticks)
CParticle *CChunkParticle::clone() CParticle *CChunkParticle::clone()
{ {
return new CChunkParticle(pos, smokeAnimation, debrisAnimation, destroyAnimation, minVelocity, maxVelocity, minTrajectoryAngle, maxTTL); CChunkParticle *particle = new CChunkParticle(pos, smokeAnimation, debrisAnimation, destroyAnimation, minVelocity, maxVelocity, minTrajectoryAngle, maxTTL, drawLevel);
particle->smokeDrawLevel = smokeDrawLevel;
particle->destroyDrawLevel = destroyDrawLevel;
return particle;
} }
//@} //@}

View file

@ -34,6 +34,8 @@
#include "ui.h" #include "ui.h"
#include "video.h" #include "video.h"
#include <algorithm>
CParticleManager ParticleManager; CParticleManager ParticleManager;
@ -70,17 +72,27 @@ void CParticleManager::clear()
new_particles.clear(); new_particles.clear();
} }
void CParticleManager::draw(const CViewport &vp) static inline bool DrawLevelCompare(const CParticle *lhs, const CParticle *rhs)
{
return lhs->getDrawLevel() < rhs->getDrawLevel();
}
void CParticleManager::prepareToDraw(const CViewport &vp, std::vector<CParticle *> &table)
{ {
this->vp = &vp; this->vp = &vp;
std::vector<CParticle *>::iterator i; for (std::vector<CParticle *>::iterator it = particles.begin(); it != particles.end(); ++it) {
for (i = particles.begin(); i != particles.end(); ++i) { CParticle &particle = **it;
if ((*i)->isVisible(vp)) { if (particle.isVisible(vp)) {
(*i)->draw(); table.push_back(&particle);
} }
} }
std::sort(table.begin(), table.end(), DrawLevelCompare);
}
void CParticleManager::endDraw()
{
this->vp = NULL; this->vp = NULL;
} }

View file

@ -34,8 +34,8 @@
#include "stratagus.h" #include "stratagus.h"
#include "particle.h" #include "particle.h"
CRadialParticle::CRadialParticle(CPosition position, GraphicAnimation *animation, int maxSpeed) : CRadialParticle::CRadialParticle(CPosition position, GraphicAnimation *animation, int maxSpeed, int drawlevel) :
CParticle(position) CParticle(position, drawlevel)
{ {
Assert(animation); Assert(animation);
this->animation = animation->clone(); this->animation = animation->clone();
@ -76,7 +76,7 @@ void CRadialParticle::update(int ticks)
CParticle *CRadialParticle::clone() CParticle *CRadialParticle::clone()
{ {
CParticle *p = new CRadialParticle(pos, animation, maxSpeed); CParticle *p = new CRadialParticle(pos, animation, maxSpeed, drawLevel);
return p; return p;
} }

View file

@ -36,8 +36,8 @@
CSmokeParticle::CSmokeParticle(CPosition position, GraphicAnimation *smoke, CSmokeParticle::CSmokeParticle(CPosition position, GraphicAnimation *smoke,
float speedx, float speedy) : float speedx, float speedy, int drawlevel) :
CParticle(position) CParticle(position, drawlevel)
{ {
Assert(smoke); Assert(smoke);
this->puff = smoke->clone(); this->puff = smoke->clone();
@ -77,7 +77,7 @@ void CSmokeParticle::update(int ticks)
CParticle *CSmokeParticle::clone() CParticle *CSmokeParticle::clone()
{ {
return new CSmokeParticle(pos, puff, speedVector.x, speedVector.y); return new CSmokeParticle(pos, puff, speedVector.x, speedVector.y, drawLevel);
} }
//@} //@}

View file

@ -33,8 +33,8 @@
#include "particle.h" #include "particle.h"
StaticParticle::StaticParticle(CPosition position, GraphicAnimation *animation) : StaticParticle::StaticParticle(CPosition position, GraphicAnimation *animation, int drawlevel) :
CParticle(position) CParticle(position, drawlevel)
{ {
Assert(animation); Assert(animation);
this->animation = animation->clone(); this->animation = animation->clone();
@ -66,7 +66,7 @@ void StaticParticle::update(int ticks)
CParticle *StaticParticle::clone() CParticle *StaticParticle::clone()
{ {
CParticle *p = new StaticParticle(pos, animation); CParticle *p = new StaticParticle(pos, animation, drawLevel);
return p; return p;
} }

View file

@ -16,30 +16,35 @@ class GraphicAnimation
class CParticle class CParticle
{ {
virtual CParticle* clone(); virtual CParticle* clone();
void setDrawLevel(int value);
}; };
class StaticParticle : public CParticle class StaticParticle : public CParticle
{ {
public: public:
StaticParticle(CPosition position, GraphicAnimation *animation); StaticParticle(CPosition position, GraphicAnimation *animation, int drawlevel = 0);
}; };
class CChunkParticle : public CParticle class CChunkParticle : public CParticle
{ {
public: public:
CChunkParticle(CPosition position, GraphicAnimation *smokeAnimation, GraphicAnimation *debrisAnimation, GraphicAnimation *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, int drawlevel = 0);
int getSmokeDrawLevel() const;
int getDestroyDrawLevel() const;
void setSmokeDrawLevel(int value);
void setDestroyDrawLevel(int value);
}; };
class CSmokeParticle : public CParticle class CSmokeParticle : public CParticle
{ {
public: public:
CSmokeParticle(CPosition position, GraphicAnimation *animation, float speedx = 0, float speedy = -22.0); CSmokeParticle(CPosition position, GraphicAnimation *animation, float speedx = 0, float speedy = -22.0, int drawlevel = 0);
}; };
class CRadialParticle : public CParticle class CRadialParticle : public CParticle
{ {
public: public:
CRadialParticle(CPosition position, GraphicAnimation *smokeAnimation, int maxSpeed); CRadialParticle(CPosition position, GraphicAnimation *smokeAnimation, int maxSpeed, int drawlevel = 0);
}; };
class CParticleManager class CParticleManager