JGE 游戏引擎粒子系统分析

JGE 游戏引擎粒子系统分析
作者: 刘鹏
日期: 2009-05-07
JGE 游戏引擎提供了粒子系统,基于粒子系统可以实现火、爆炸、烟、云、雾等效果。本文对该粒子系统的实现做了深入剖析。




简介

粒子系统主要用来解决由大量按一定规则运动(变化)的微小物质组成的大物质 在计算机上的生成与显示的问题。经常使用粒子系统模拟的现象有火、爆炸、烟、 水流、火花、落叶、云、雾、雪、尘、流星尾迹或者象发光轨迹这样的抽象视觉 效果等等。

粒子系统的实现:

  • 每个粒子是一个带纹理的三角形/多边形,粒子系统由多个粒子组成;
  • 粒子按一定规则运动;
  • 每个粒子有自己的属性,如位置、速度、质量、尺寸、年龄、运动轨迹斜率、颜色等;
  • 粒子系统更新循环划分为两个不同的阶段:参数更新/模拟阶段以及渲染阶段。
  • 参数更新/模拟阶段根据粒子系统信息更新每个粒子的速度、位置、尺寸、颜 色等信息;
  • 渲染阶段根据粒子属性重新绘制粒子;
  • 每个粒子都有自己的生命,年龄超过最大年龄的粒子会被销毁,系统会生成 新的粒子。

JGE 游戏引擎提供了一个粒子系统,基于该引擎的很多游戏的爆炸效果就是使用 粒子系统实现的。该粒子系统从 HGE 游戏引擎移植而来,下面将对其做深入的剖析。

粒子属性

每个粒子包括如下属性:

  • vecLocation:粒子的位置;
  • vecVelocity:粒子速度,记录粒子下一个位置相对于当前位置的偏移(包括 x 和 y 方向);
  • fGravity:粒子质量,决定粒子受重力影响(自由落体)的程度,值越大,粒子自由落体越远;
  • fRadialAccel:决定粒子往四周的发散程度,值越大发射出去的越远;
  • fTangentialAccel:决定粒子的运动轨迹的斜率,斜率越大运动轨迹弯曲程度越大,斜率越小,轨迹越趋向于直线。
  • fSpin:
  • fSpinDelta:
  • fSize:粒子的大小;
  • fSizeDelta:粒子大小的变化;
  • colColor:粒子的颜色;
  • colColorDelta:颜色的变化;
  • fAge:粒子的年龄,当粒子超过死亡年龄后死亡,被系统销毁;
  • fTerminalAge:粒子死亡年龄;

粒子的速度受到 fDeltaTime, fRadialAccel, fTangentialAccel, fGravity 等 参数的影响,求粒子下一 frame 的速度如下所示:

  vecAccel = par->vecLocation-vecLocation;
  vecAccel.Normalize();
  vecAccel2 = vecAccel;
  vecAccel *= par->fRadialAccel;

  // vecAccel2.Rotate(M_PI_2);
  // the following is faster
  ang = vecAccel2.x;
  vecAccel2.x = -vecAccel2.y;
  vecAccel2.y = ang;

  vecAccel2 *= par->fTangentialAccel;
  par->vecVelocity += (vecAccel+vecAccel2)*fDeltaTime;
  par->vecVelocity.y += par->fGravity*fDeltaTime;

粒子的位置与速度有关,求粒子下一 frame 处的位置如下所示:

  par->vecLocation += par->vecVelocity;

粒子参数 fSpin, fSize, colColor 受 fDeltaTime 影响,求粒子下一 frame 处的 spin, size 和 color 如下所示:

  par->fSpin += par->fSpinDelta*fDeltaTime;
  par->fSize += par->fSizeDelta*fDeltaTime;
  par->colColor += par->colColorDelta*fDeltaTime;

粒子系统属性

粒子系统具有如下属性:

  • hgeParticle particles[MAX_PARTICLES]:粒子数组,保存所有粒子;
  • hgeParticleSystemInfo info:粒子系统信息,此数据从 psi 文件读取得到;
  • fAge: 粒子系统年龄;
  • fEmissionResidue:
  • vecPrevLocation:上一 frame 中粒子系统的中心点位置;
  • vecLocation:当前 frame 中粒子系统的中心位置;
  • fTx, fTy:
  • nParticlesAlive:活着的粒子个数;
  • rectBoundingBox:粒子系统外包矩形。
  • mTimer:
粒子系统数据文件 psi

粒子系统数据文件以 psi 作为后缀,该文件记录了粒子系统的所有信息。

粒子系统信息通常使用粒子系统编辑工具生成。利用粒子系统编辑工具可以以所 见即所得的方式对粒子系统参数进行编辑,并可以实时地看到效果。这里介绍的 psi 文件就是使用 HGE 游戏引擎的粒子系统工具 particleed 生成的。

粒子系统具体信息包括:

  • nEmission:每秒产生的粒子数;
  • fLifetime
  • fParticleLifeMin:粒子最短生命周期;
  • fParticleLifeMax:粒子最长生命周期;
  • fDirection:
  • fSpread;粒子发散程度;
  • bRelative;
  • fSpeedMin:最小速度;
  • fSpeedMax:最大速度;
  • fGravityMin:最小重量;
  • fGravityMax:最大重量;
  • fRadialAccelMin:最小发射速度;
  • fRadialAccelMax:最大发射速度;
  • fTangentialAccelMin:粒子运动轨迹最小斜率;
  • fTangentialAccelMax:粒子运动轨迹最大斜率;
  • fSizeStart:粒子初始尺寸;
  • fSizeEnd:粒子最后尺寸;
  • fSizeVar:尺寸变化;
  • fSpinStart
  • fSpinEnd;
  • fSpinVar;
  • colColorStart: 粒子初始颜色;
  • colColorEnd:粒子最后颜色;
  • fColorVar:粒子颜色变化;
  • fAlphaVar:粒子 Alpha 值变化。

粒子系统信息数据结构如下所示:

struct hgeParticleSystemInfo
{
 JQuad* sprite; // texture + blend mode
 int nEmission; // particles per sec
 float fLifetime;

 float fParticleLifeMin;
 float fParticleLifeMax;

 float fDirection;
 float fSpread;
 bool bRelative;

 float fSpeedMin;
 float fSpeedMax;

 float fGravityMin;
 float fGravityMax;

 float fRadialAccelMin;
 float fRadialAccelMax;

 float fTangentialAccelMin;
 float fTangentialAccelMax;

 float fSizeStart;
 float fSizeEnd;
 float fSizeVar;

 float fSpinStart;
 float fSpinEnd;
 float fSpinVar;

 hgeColor colColorStart; // + alpha
 hgeColor colColorEnd;
 float fColorVar;
 float fAlphaVar;
};

粒子系统类图

粒子系统主要由两个结构和两个类组成:

结构 hgeParticle 封装了粒子的所有属性,如位置、速度、尺寸、颜色等。

结构 hgeParticleSystemInfo 封装了粒子系统的所有信息。

类 hgeParticleSystem 封装了粒子系统的所有属性和操作。所有粒子保存在数 组 particles[MAX_PARTICLES] 中。Fire() 方法启动粒子系统;MoveTo() 方法移 动粒子系统的中心点;Update() 方法更新粒子的各个属性值;Render() 方法将 各个粒子绘制出来。

类 hgeParticleManager 提供了一个管理器,实现了对多个粒子系统的管理和操作。


粒子系统使用样例

下面是基于上述粒子系统模块实现一个粒子系统的具体例子,该例子来自 JGE 引擎的教程 11 (hgeparticles),它在屏幕中央放了一个粒子系统。

class GameApp:  public JApp
{

public:
    virtual void Create();
    virtual void Update();
    virtual void Render();
    void LoadNewParticleSys();
    ... ...

private:
    hgeParticleSystem*  mParticleSys;
    JQuad *mParticles[16];
    JTexture *mTexture;
    ... ...


};


void GameApp::LoadNewParticleSys()
{
    if (mParticleSys)
    {
        delete mParticleSys;
        mParticleSys = NULL;
    }

    char s[80];
    sprintf(s, "particle%d.psi", (mCurrParticleSys+1));
    mParticleSys = new hgeParticleSystem(s, mParticles[mCurrParticle]);
    mParticleSys->MoveTo(SCREEN_WIDTH_F/2, SCREEN_HEIGHT_F/2);
    mParticleSys->Fire();
}


void GameApp::Create()
{

    mTexture = JRenderer::GetInstance()->LoadTexture("particles.png", TEX_TYPE_USE_VRAM);

    // load all the particle images
    int n = 0;
    for (int i=0;i<4;i++)
    {
        for (int j=0;j<4;j++)
        {
            mParticles[n] = new JQuad(mTexture, j*32, i*32, 32, 32);
            mParticles[n]->SetHotSpot(16,16);
            n++;
        }
    }

    LoadNewParticleSys();

    ... ...

}


void GameApp::Update()
{
    ... ...

    float dt = engine->GetDelta();      // Get time elapsed since last update.

    ... ...

    mParticleSys->Update(dt);

}

void GameApp::Render()
{
    // get JRenderer instance
    JRenderer* renderer = JRenderer::GetInstance();

    // clear screen to black
    renderer->ClearScreen(ARGB(0,0,0,0));

    ... ...

    mParticleSys->Render();

    ... ...
}

void GameApp::Destroy()
{

    for (int i=0;i<16;i++)
        SAFE_DELETE(mParticles[i]);

    SAFE_DELETE(mParticleSys);
    SAFE_DELETE(mTexture);

    ... ...

}


Reference

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值