[+] Added drawlevel sorting for particles
This commit is contained in:
parent
b9fb1bfd1b
commit
a63a4fff61
8 changed files with 118 additions and 41 deletions
|
@ -77,8 +77,8 @@ public:
|
|||
class CParticle
|
||||
{
|
||||
public:
|
||||
CParticle(CPosition position) :
|
||||
pos(position), destroyed(false)
|
||||
CParticle(CPosition position, int drawlevel = 0) :
|
||||
pos(position), destroyed(false), drawLevel(drawlevel)
|
||||
{}
|
||||
virtual ~CParticle() {}
|
||||
|
||||
|
@ -91,16 +91,20 @@ public:
|
|||
|
||||
virtual CParticle *clone() = 0;
|
||||
|
||||
int getDrawLevel() const { return drawLevel; }
|
||||
void setDrawLevel(int value) { drawLevel = value; }
|
||||
|
||||
protected:
|
||||
CPosition pos;
|
||||
bool destroyed;
|
||||
int drawLevel;
|
||||
};
|
||||
|
||||
|
||||
class StaticParticle : public CParticle
|
||||
{
|
||||
public:
|
||||
StaticParticle(CPosition position, GraphicAnimation *flame);
|
||||
StaticParticle(CPosition position, GraphicAnimation *flame, int drawlevel = 0);
|
||||
virtual ~StaticParticle();
|
||||
|
||||
virtual bool isVisible(const CViewport &vp) const;
|
||||
|
@ -120,13 +124,17 @@ public:
|
|||
CChunkParticle(CPosition position, GraphicAnimation *smokeAnimation, GraphicAnimation *debrisAnimation,
|
||||
GraphicAnimation *destroyAnimation,
|
||||
int minVelocity = 0, int maxVelocity = 400,
|
||||
int minTrajectoryAngle = 77, int maxTTL = 0);
|
||||
int minTrajectoryAngle = 77, int maxTTL = 0, int drawlevel = 0);
|
||||
virtual ~CChunkParticle();
|
||||
|
||||
virtual bool isVisible(const CViewport &vp) const;
|
||||
virtual void draw();
|
||||
virtual void update(int ticks);
|
||||
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:
|
||||
CPosition initialPos;
|
||||
|
@ -140,6 +148,8 @@ protected:
|
|||
int maxVelocity;
|
||||
int minTrajectoryAngle;
|
||||
float height;
|
||||
int smokeDrawLevel;
|
||||
int destroyDrawLevel;
|
||||
GraphicAnimation *debrisAnimation;
|
||||
GraphicAnimation *smokeAnimation;
|
||||
GraphicAnimation *destroyAnimation;
|
||||
|
@ -155,7 +165,7 @@ protected:
|
|||
class CSmokeParticle : public CParticle
|
||||
{
|
||||
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 bool isVisible(const CViewport &vp) const;
|
||||
|
@ -174,7 +184,7 @@ protected:
|
|||
class CRadialParticle : public CParticle
|
||||
{
|
||||
public:
|
||||
CRadialParticle(CPosition position, GraphicAnimation *animation, int maxSpeed);
|
||||
CRadialParticle(CPosition position, GraphicAnimation *animation, int maxSpeed, int drawlevel = 0);
|
||||
virtual ~CRadialParticle();
|
||||
|
||||
virtual bool isVisible(const CViewport &vp) const;
|
||||
|
@ -199,7 +209,9 @@ public:
|
|||
static void init();
|
||||
static void exit();
|
||||
|
||||
void draw(const CViewport &vp);
|
||||
void prepareToDraw(const CViewport &vp, std::vector<CParticle *> &table);
|
||||
void endDraw();
|
||||
|
||||
void update();
|
||||
|
||||
void add(CParticle *particle);
|
||||
|
|
|
@ -332,25 +332,68 @@ void CViewport::Draw() const
|
|||
|
||||
CurrentViewport = this;
|
||||
{
|
||||
// Now we need to sort units, missiles, particles by draw level and draw them
|
||||
std::vector<CUnit *> unittable;
|
||||
std::vector<Missile *> missiletable;
|
||||
std::vector<CParticle *> particletable;
|
||||
|
||||
// We find and sort units after draw level.
|
||||
FindAndSortUnits(*this, unittable);
|
||||
const size_t nunits = unittable.size();
|
||||
FindAndSortMissiles(*this, missiletable);
|
||||
const size_t nmissiles = missiletable.size();
|
||||
ParticleManager.prepareToDraw(*this, particletable);
|
||||
const size_t nparticles = particletable.size();
|
||||
|
||||
size_t i = 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)
|
||||
|| (j < nmissiles && k < nparticles)) {
|
||||
if (i == nunits) {
|
||||
if (missiletable[j]->Type->DrawLevel < particletable[k]->getDrawLevel()) {
|
||||
missiletable[j]->DrawMissile(*this);
|
||||
++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) {
|
||||
unittable[i]->Draw(*this);
|
||||
|
@ -358,9 +401,11 @@ void CViewport::Draw() const
|
|||
for (; j < nmissiles; ++j) {
|
||||
missiletable[j]->DrawMissile(*this);
|
||||
}
|
||||
for (; k < nparticles; ++k) {
|
||||
particletable[k]->draw();
|
||||
}
|
||||
ParticleManager.endDraw();
|
||||
}
|
||||
|
||||
ParticleManager.draw(*this);
|
||||
|
||||
this->DrawMapFogOfWar();
|
||||
|
||||
|
|
|
@ -46,8 +46,8 @@ static inline float deg2rad(int degrees)
|
|||
|
||||
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),
|
||||
int minVelocity, int maxVelocity, int minTrajectoryAngle, int maxTTL, int drawlevel) :
|
||||
CParticle(position, drawlevel), initialPos(position), maxTTL(maxTTL), nextSmokeTicks(0),
|
||||
age(0), height(0.f)
|
||||
{
|
||||
float radians = deg2rad(MyRand() % 360);
|
||||
|
@ -112,7 +112,7 @@ void CChunkParticle::update(int ticks)
|
|||
if (destroyAnimation) {
|
||||
CPosition p(pos.x, calculateScreenPos(pos.y, height));
|
||||
GraphicAnimation *destroyanimation = destroyAnimation->clone();
|
||||
StaticParticle *destroy = new StaticParticle(p, destroyanimation);
|
||||
StaticParticle *destroy = new StaticParticle(p, destroyanimation, destroyDrawLevel);
|
||||
ParticleManager.add(destroy);
|
||||
}
|
||||
|
||||
|
@ -126,7 +126,7 @@ void CChunkParticle::update(int ticks)
|
|||
if (age > nextSmokeTicks) {
|
||||
CPosition p(pos.x, calculateScreenPos(pos.y, height));
|
||||
GraphicAnimation *smokeanimation = smokeAnimation->clone();
|
||||
CSmokeParticle *smoke = new CSmokeParticle(p, smokeanimation);
|
||||
CSmokeParticle *smoke = new CSmokeParticle(p, smokeanimation, 0, -22.0f, smokeDrawLevel);
|
||||
ParticleManager.add(smoke);
|
||||
|
||||
nextSmokeTicks += MyRand() % randSmokeTicks + minSmokeTicks;
|
||||
|
@ -151,7 +151,10 @@ void CChunkParticle::update(int ticks)
|
|||
|
||||
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;
|
||||
}
|
||||
|
||||
//@}
|
||||
|
|
|
@ -34,6 +34,8 @@
|
|||
#include "ui.h"
|
||||
#include "video.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
CParticleManager ParticleManager;
|
||||
|
||||
|
@ -70,17 +72,27 @@ void CParticleManager::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;
|
||||
|
||||
std::vector<CParticle *>::iterator i;
|
||||
for (i = particles.begin(); i != particles.end(); ++i) {
|
||||
if ((*i)->isVisible(vp)) {
|
||||
(*i)->draw();
|
||||
for (std::vector<CParticle *>::iterator it = particles.begin(); it != particles.end(); ++it) {
|
||||
CParticle &particle = **it;
|
||||
if (particle.isVisible(vp)) {
|
||||
table.push_back(&particle);
|
||||
}
|
||||
}
|
||||
|
||||
std::sort(table.begin(), table.end(), DrawLevelCompare);
|
||||
}
|
||||
|
||||
void CParticleManager::endDraw()
|
||||
{
|
||||
this->vp = NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,8 +34,8 @@
|
|||
#include "stratagus.h"
|
||||
#include "particle.h"
|
||||
|
||||
CRadialParticle::CRadialParticle(CPosition position, GraphicAnimation *animation, int maxSpeed) :
|
||||
CParticle(position)
|
||||
CRadialParticle::CRadialParticle(CPosition position, GraphicAnimation *animation, int maxSpeed, int drawlevel) :
|
||||
CParticle(position, drawlevel)
|
||||
{
|
||||
Assert(animation);
|
||||
this->animation = animation->clone();
|
||||
|
@ -76,7 +76,7 @@ void CRadialParticle::update(int ticks)
|
|||
|
||||
CParticle *CRadialParticle::clone()
|
||||
{
|
||||
CParticle *p = new CRadialParticle(pos, animation, maxSpeed);
|
||||
CParticle *p = new CRadialParticle(pos, animation, maxSpeed, drawLevel);
|
||||
return p;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,8 +36,8 @@
|
|||
|
||||
|
||||
CSmokeParticle::CSmokeParticle(CPosition position, GraphicAnimation *smoke,
|
||||
float speedx, float speedy) :
|
||||
CParticle(position)
|
||||
float speedx, float speedy, int drawlevel) :
|
||||
CParticle(position, drawlevel)
|
||||
{
|
||||
Assert(smoke);
|
||||
this->puff = smoke->clone();
|
||||
|
@ -77,7 +77,7 @@ void CSmokeParticle::update(int ticks)
|
|||
|
||||
CParticle *CSmokeParticle::clone()
|
||||
{
|
||||
return new CSmokeParticle(pos, puff, speedVector.x, speedVector.y);
|
||||
return new CSmokeParticle(pos, puff, speedVector.x, speedVector.y, drawLevel);
|
||||
}
|
||||
|
||||
//@}
|
||||
|
|
|
@ -33,8 +33,8 @@
|
|||
#include "particle.h"
|
||||
|
||||
|
||||
StaticParticle::StaticParticle(CPosition position, GraphicAnimation *animation) :
|
||||
CParticle(position)
|
||||
StaticParticle::StaticParticle(CPosition position, GraphicAnimation *animation, int drawlevel) :
|
||||
CParticle(position, drawlevel)
|
||||
{
|
||||
Assert(animation);
|
||||
this->animation = animation->clone();
|
||||
|
@ -66,7 +66,7 @@ void StaticParticle::update(int ticks)
|
|||
|
||||
CParticle *StaticParticle::clone()
|
||||
{
|
||||
CParticle *p = new StaticParticle(pos, animation);
|
||||
CParticle *p = new StaticParticle(pos, animation, drawLevel);
|
||||
return p;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,30 +16,35 @@ class GraphicAnimation
|
|||
class CParticle
|
||||
{
|
||||
virtual CParticle* clone();
|
||||
void setDrawLevel(int value);
|
||||
};
|
||||
|
||||
class StaticParticle : public CParticle
|
||||
{
|
||||
public:
|
||||
StaticParticle(CPosition position, GraphicAnimation *animation);
|
||||
StaticParticle(CPosition position, GraphicAnimation *animation, int drawlevel = 0);
|
||||
};
|
||||
|
||||
class CChunkParticle : public CParticle
|
||||
{
|
||||
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
|
||||
{
|
||||
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
|
||||
{
|
||||
public:
|
||||
CRadialParticle(CPosition position, GraphicAnimation *smokeAnimation, int maxSpeed);
|
||||
CRadialParticle(CPosition position, GraphicAnimation *smokeAnimation, int maxSpeed, int drawlevel = 0);
|
||||
};
|
||||
|
||||
class CParticleManager
|
||||
|
|
Loading…
Reference in a new issue