// This is the file for the mvxParticleEngine
#include "mvx.h"
// psuedo 3D particles
mvxIsoParticleEngine::mvxIsoParticleEngine(mvxImage* p_image, D3DXVECTOR2 p_origin)
{
mvxParticleImage = p_image;
mvxOrigin = p_origin;
mvxParticle = NULL;
mvxFree = NULL;
mvxParticleCount = 0;
}
mvxIsoParticleEngine::~mvxIsoParticleEngine()
{
}
void mvxIsoParticleEngine::mvxDestroy()
{
mvxParticleImage = NULL;
while (mvxParticle)
{
mvxISO_PARTICLE* current = mvxParticle;
mvxParticle = current->mvxNext;
delete current;
}
while (mvxFree)
{
mvxISO_PARTICLE* current = mvxFree;
mvxFree = current->mvxNext;
delete current;
}
}
void mvxIsoParticleEngine::mvxStart(D3DXVECTOR3 p_location, D3DXVECTOR3 p_velocity, D3DCOLOR p_color, D3DCOLOR p_fade, unsigned long p_life)
{
// create a new particle
mvxISO_PARTICLE *pPart, **ppPart;
ppPart = &mvxParticle;
// create new projectile
if( mvxParticleCount < 1024 )
{
if( mvxFree )
{
pPart = mvxFree;
mvxFree = pPart->mvxNext;
}
else
{
if( NULL == ( pPart = new mvxISO_PARTICLE ) )
return;
}
pPart->mvxNext = mvxParticle;
mvxParticle = pPart;
mvxParticleCount++;
pPart->mvxColor = p_color;
pPart->mvxLocation = p_location;
pPart->mvxVelocity = p_velocity;
pPart->mvxLife = p_life;
pPart->mvxColor = p_color;
pPart->mvxFade = p_fade;
}
}
void mvxIsoParticleEngine::mvxUpdate(unsigned long p_timedelta)
{
// move all particles do collision
mvxISO_PARTICLE *pPart, **ppPart;
ppPart = &mvxParticle;
while( *ppPart )
{
pPart = *ppPart;
pPart->mvxLocation += pPart->mvxVelocity;
// gravity
if (pPart->mvxVelocity.y != 0)
{
pPart->mvxVelocity.y += -.001f;
}
if (pPart->mvxLocation.y < 1)
{
pPart->mvxVelocity.y *= -0.75f;
}
if (pPart->mvxLocation.x > 10 || pPart->mvxLocation.x < 0)
{
pPart->mvxVelocity.x *= -1;
}
if (pPart->mvxLocation.z > 10 || pPart->mvxLocation.z < 0)
{
pPart->mvxVelocity.z *= -1;
}
pPart->mvxColor -= pPart->mvxFade;
pPart->mvxLife--;
if (pPart->mvxLife <= 0)
{
*ppPart = pPart->mvxNext;
pPart->mvxNext = mvxFree;
mvxFree = pPart;
mvxParticleCount--;
continue;
}
ppPart = &pPart->mvxNext;
}
}
void mvxIsoParticleEngine::mvxRenderParticles(mvxViewport* p_view)
{
// convert x,y,z to x,y screen space
// draw
mvxISO_PARTICLE *pPart, **ppPart;
ppPart = &mvxParticle;
D3DXVECTOR2 screen;
while( *ppPart )
{
pPart = *ppPart;
// numbers are hardcoded, will be changed
screen.x = mvxOrigin.x + (pPart->mvxLocation.x * 64 - pPart->mvxLocation.z * 64)-2;
screen.y = mvxOrigin.y + (pPart->mvxLocation.x * -32 + pPart->mvxLocation.z * -32 + pPart->mvxLocation.y * - 224)-2;
mvxParticleImage->mvxRenderThis(NULL, NULL, NULL, NULL, &(screen - p_view->mvxLocation), pPart->mvxColor);
ppPart = &pPart->mvxNext;
}
}
void mvxIsoParticleEngine::mvxEmitter(D3DXVECTOR3 p_location, D3DXVECTOR3 p_initvector, D3DXVECTOR3 p_offset, D3DCOLOR p_color, unsigned long p_maxlife, unsigned long p_count)
{
while (p_count--)
{
D3DXVECTOR3 vect = p_initvector;
D3DXVECTOR3 offset = p_offset;
offset.x *= (((float)(rand()%100)) / 100.0f) - .5f;
offset.y *= (((float)(rand()%100)) / 100.0f) - .5f;
offset.z *= (((float)(rand()%100)) / 100.0f) - .5f;
vect = p_initvector + offset;
unsigned long life = p_maxlife;
mvxStart(p_location, vect, p_color, D3DCOLOR_ARGB(1, 0, 0, 0), life);
}
}
// Now for 2D particles
mvxParticleEngine2D::mvxParticleEngine2D()
{
mvxParticleImage = NULL;
mvxParticles = NULL;
mvxParticlesFree = NULL;
mvxParticleCount = 0;
}
mvxParticleEngine2D::~mvxParticleEngine2D()
{
mvxDestroy();
}
void mvxParticleEngine2D::mvxDestroy()
{
mvxParticleImage = NULL;
while (mvxParticles)
{
mvxPARTICLE2D* current = mvxParticles;
mvxParticles = current->mvxNext;
delete current;
}
while (mvxParticlesFree)
{
mvxPARTICLE2D* current = mvxParticlesFree;
mvxParticlesFree = current->mvxNext;
delete current;
}
}
void mvxParticleEngine2D::mvxStart(D3DXVECTOR2 p_point, D3DXCOLOR p_col, D3DXVECTOR2 p_velocity, float p_ang, bool p_fde, bool p_rot, D3DXCOLOR p_fdeamt, float p_rotamt)
{
// create a new particle
mvxPARTICLE2D *pPart, **ppPart;
ppPart = &mvxParticles;
// create new projectile
if( mvxParticleCount < PARTICLE_MAX )
{
if( mvxParticlesFree )
{
pPart = mvxParticlesFree;
mvxParticlesFree = pPart->mvxNext;
}
else
{
if( NULL == ( pPart = new mvxPARTICLE2D ) )
return;
}
pPart->mvxNext = mvxParticles;
mvxParticles = pPart;
mvxParticleCount++;
pPart->mvxAngle = p_ang;
pPart->mvxLocation = p_point;
pPart->mvxColor = p_col;
pPart->mvxVelocity = p_velocity;
pPart->mvxRotate = p_rot;
pPart->mvxFade = p_fde;
pPart->mvxFadeAmount = p_fdeamt;
pPart->mvxRotateAmount = p_rotamt;
}
}
void mvxParticleEngine2D::mvxExplode(D3DXVECTOR2 p_point, D3DCOLOR p_col, float p_force, int p_count, bool p_fde, bool p_rot, D3DXCOLOR p_fdeamt, float p_rotamt)
{
// create an explosion from this loc
while (p_count > 0 && mvxParticleCount < PARTICLE_MAX)
{
float currangle;
currangle = (float)(rand() % 360);
currangle = ((currangle * D3DX_PI) / 180);
float force2 = (float)((rand() % 100) / 100);
float xv, yv;
xv = (float)cos(currangle)*force2;
yv = (float)sin(currangle)*force2;
mvxStart(p_point, p_col, D3DXVECTOR2(xv, yv), -currangle, p_fde, p_rot, p_fdeamt, p_rotamt);
p_count--;
}
}
void mvxParticleEngine2D::mvxUpdate(unsigned long p_timedelta)
{
// translate all mvxParticles
mvxPARTICLE2D *pPart, **ppPart;
ppPart = &mvxParticles;
while( *ppPart )
{
pPart = *ppPart;
pPart->mvxLocation += pPart->mvxVelocity;
if (pPart->mvxRotate)
{
pPart->mvxAngle += pPart->mvxRotateAmount;
}
if (pPart->mvxColor > mvxARGB(0,0,0,0))
{
if (rand() % 9 == 0)
pPart->mvxColor -= pPart->mvxFadeAmount;
}
else
{
// Kill mvxPARTICLE2D
*ppPart = pPart->mvxNext;
pPart->mvxNext = mvxParticlesFree;
mvxParticlesFree = pPart;
mvxParticleCount--;
continue;
}
// boundry detection
if (pPart->mvxLocation.x < 0 || pPart->mvxLocation.x > 1024 ||
pPart->mvxLocation.y < 0 || pPart->mvxLocation.y > 768)
{
// Kill mvxPARTICLE2D
*ppPart = pPart->mvxNext;
pPart->mvxNext = mvxParticlesFree;
mvxParticlesFree = pPart;
mvxParticleCount--;
}
else
{
ppPart = &pPart->mvxNext;
}
}
}
void mvxParticleEngine2D::mvxRender(mvxViewport* p_view)
{
mvxPARTICLE2D *pPart, **ppPart;
ppPart = &mvxParticles;
while( *ppPart )
{
pPart = *ppPart;
mvxParticleImage->mvxRenderThis(NULL, &mvxParticleImage->mvxScaling, &mvxParticleImage->mvxRotationCenter, pPart->mvxAngle, &(pPart->mvxLocation - p_view->mvxLocation), pPart->mvxColor);
ppPart = &pPart->mvxNext;
}
}