遊戲粒子系統?什麼是粒子系統?第一次聽說這個東西,我再想這個東西是不是像化學原子分子那樣的系統引擎。經過多年疑惑以及unity3d粒子系統使用,我才恍然明白原來這東西纔是粒子系統。初中時候,化學老師告訴我們大千世界千物萬物都是由分子原子組成,同樣許多自然現象也是由很多微小的顆粒組成,它們都有很多相似的行爲。如,煙花炮火,瀑布,噴泉,雪花飄飄,山崩地裂。遊戲中的粒子系統是用來模擬這種自然現象,給人一種震感的動畫效果。(原創:醉翁 )
顧名思義,粒子系統,他是多個部分組成的複雜系統。以unity3d遊戲爲例, 由粒子發射器,粒子渲染器,粒子動畫器,粒子尾帶器等組成,其中運用了美學,物理學動力等。我們先學粒子名專有名詞:Particle粒子,ParticlesSystem粒子系統,emitter發射器。其原理就是再整個粒子系統生命週期中emitter發射器不斷髮射粒子,由粒子系統再生命週期每一幀不斷使用物理力學地改變粒子的顏色、大小、角度達到一種變換無窮魅力效果。本文將以網頁遊戲粒子系統簡單講解粒子系統,我這裏先看看煙花粒子效果,由於我的筆記本性能不好,運行效果並截圖沒有那麼亮麗:
看看開源粒子系統源碼:下載其開源源碼這裏http://github.com/flashhawk/Simple-Physics-Particle
粒子系統源碼:請重點看看紅色部分源碼
public class ParticlesSystem extends EventDispatcher
{
private var _particlePool : ParticlePool;
private var _particles : Array = [];
private var l : int;
private var _renderBefore:Function;
private var _renderAfter:Function;
public static var STAGE:Stage;
public function ParticlesSystem(renderAfter:Function=null,renderBefore:Function=null)
{
_particlePool = new ParticlePool();
this._renderBefore=renderBefore;
this._renderAfter=renderAfter;
}
{
_particlePool = new ParticlePool();
this._renderBefore=renderBefore;
this._renderAfter=renderAfter;
}
public function createParticle(particleType : Class) : Particle
{
var p : Particle = _particlePool.get(particleType);
p.addEventListener(ParticleEvent.DEAD, removeDeadParticle, false, -1);
_particles.push(p);
return p;
}
//在這裏就是粒子系統核心,在粒子系統生命週期不斷調用粒子的update函數
來改變粒子
{
var p : Particle = _particlePool.get(particleType);
p.addEventListener(ParticleEvent.DEAD, removeDeadParticle, false, -1);
_particles.push(p);
return p;
}
//在這裏就是粒子系統核心,在粒子系統生命週期不斷調用粒子的update函數
來改變粒子
private function singleRender(event : Event) : void
{
if(_renderBefore!=null)_renderBefore();
l = _particles.length;
//_particles[l]是粒子發射器發射出來的粒子
while (l-- > 0) _particles[l].update();
if(_renderAfter!=null)_renderAfter();
}
{
if(_renderBefore!=null)_renderBefore();
l = _particles.length;
//_particles[l]是粒子發射器發射出來的粒子
while (l-- > 0) _particles[l].update();
if(_renderAfter!=null)_renderAfter();
}
//開始啓動粒子系統:
public function startRendering() : void
{
STAGE.addEventListener(Event.ENTER_FRAME, singleRender);
}
............................
}
我們在看看粒子代碼:
public class Particle extends EventDispatcher
{
public var position : Vector2D = new Vector2D();
public var point : Point = new Point();
//粒子開始速度,也就是說粒子往哪裏運動
public var velocity : Vector2D = new Vector2D();
//加速度
public var acceleration : Vector2D = new Vector2D();
//粒子摩擦力,物理老師告訴我們摩擦力用來剎車用的
public var friction : Vector2D = new Vector2D(0.1, 0.1) ;
//粒子生命,每一陣減一
private var _life : Number;
private var _forces : Object = {};
//力綜合:可能由重力Gravity、吸引力Attraction、旋轉角力,排斥力Repulsion,布朗運動力SimpleBrownian
private var _sumForce : Vector2D = new Vector2D();
碰撞矩形邊界,除了這個範圍粒子生命週期就結束
public var boundary : Rectangle = null;
碰到邊界時候的反彈強度係數,默認是2
public var bounceIntensity : Number = 2;
...........................
public function startRendering() : void
{
STAGE.addEventListener(Event.ENTER_FRAME, singleRender);
}
............................
}
我們在看看粒子代碼:
public class Particle extends EventDispatcher
{
public var position : Vector2D = new Vector2D();
public var point : Point = new Point();
//粒子開始速度,也就是說粒子往哪裏運動
public var velocity : Vector2D = new Vector2D();
//加速度
public var acceleration : Vector2D = new Vector2D();
//粒子摩擦力,物理老師告訴我們摩擦力用來剎車用的
public var friction : Vector2D = new Vector2D(0.1, 0.1) ;
//粒子生命,每一陣減一
private var _life : Number;
private var _forces : Object = {};
//力綜合:可能由重力Gravity、吸引力Attraction、旋轉角力,排斥力Repulsion,布朗運動力SimpleBrownian
private var _sumForce : Vector2D = new Vector2D();
碰撞矩形邊界,除了這個範圍粒子生命週期就結束
public var boundary : Rectangle = null;
碰到邊界時候的反彈強度係數,默認是2
public var bounceIntensity : Number = 2;
...........................
}
如何實現煙花爆炸:
ParticlesSystem.STAGE=stage;
//設置粒子系統每幀回調函數,也就是這裏不斷改變粒子形狀顏色位置等
ps=new ParticlesSystem(loop);
initCanvas();
private function loop() : void
{
canvasBmd.clear();
//找出所有粒子
l = ps.particles.length;
如何實現煙花爆炸:
ParticlesSystem.STAGE=stage;
//設置粒子系統每幀回調函數,也就是這裏不斷改變粒子形狀顏色位置等
ps=new ParticlesSystem(loop);
initCanvas();
private function loop() : void
{
canvasBmd.clear();
//找出所有粒子
l = ps.particles.length;
while (l-- > 0)
{
var p:Particle=ps.particles[l];
if (ps.particles[l].extra.isFire)
{
//改變粒子位置大小以及顏色
canvasBmd.fillRect(new Rectangle(p.position.x, p.position.y, 4, 4), p.extra.color);
}
else
{
canvasBmd.fillRect(new Rectangle(p.position.x, p.position.y, 3, 3), ps.particles[l].extra.color);
}
}
//重畫粒子模版
{
var p:Particle=ps.particles[l];
if (ps.particles[l].extra.isFire)
{
//改變粒子位置大小以及顏色
canvasBmd.fillRect(new Rectangle(p.position.x, p.position.y, 4, 4), p.extra.color);
}
else
{
canvasBmd.fillRect(new Rectangle(p.position.x, p.position.y, 3, 3), ps.particles[l].extra.color);
}
}
//重畫粒子模版
blurBmd.draw(canvas, null, null, BlendMode.ADD);
//加上模糊特效
blurBmd.filter = blurFilter;
blurBmd.colorOffset(-5, -5, -5, 0);
postBmd.draw(blurBmp, matrix);
}
、//鼠標點擊發射粒子
private function fire(e : MouseEvent) : void
{
var fireParticle : Particle = ps.createParticle(Particle);
//粒子活動範圍,超過這個範圍混滅粒子
fireParticle.init(canvasBmd.width / 2, canvasBmd.height, 2.6);
fireParticle.extra = {color:Math.random() * 0xffffff, isFire:true};
//這是開始粒子速度
fireParticle.velocity.reset(0, -(6.5 + Math.random() * 4));
//粒子旋轉角度,也就是說我往左邊或右邊運動角度
fireParticle.velocity.rotate(15 - Math.random() * 30);
fireParticle.friction.reset(0, 0);
//加上重力,牛頓定律
fireParticle.addForce("g", gravity);
//煙花飛到空中開始毀滅自己,爆炸
fireParticle.addEventListener(ParticleEvent.DEAD, boom);
}
//這裏開始爆炸
//加上模糊特效
blurBmd.filter = blurFilter;
blurBmd.colorOffset(-5, -5, -5, 0);
postBmd.draw(blurBmp, matrix);
}
、//鼠標點擊發射粒子
private function fire(e : MouseEvent) : void
{
var fireParticle : Particle = ps.createParticle(Particle);
//粒子活動範圍,超過這個範圍混滅粒子
fireParticle.init(canvasBmd.width / 2, canvasBmd.height, 2.6);
fireParticle.extra = {color:Math.random() * 0xffffff, isFire:true};
//這是開始粒子速度
fireParticle.velocity.reset(0, -(6.5 + Math.random() * 4));
//粒子旋轉角度,也就是說我往左邊或右邊運動角度
fireParticle.velocity.rotate(15 - Math.random() * 30);
fireParticle.friction.reset(0, 0);
//加上重力,牛頓定律
fireParticle.addForce("g", gravity);
//煙花飛到空中開始毀滅自己,爆炸
fireParticle.addEventListener(ParticleEvent.DEAD, boom);
}
//這裏開始爆炸
private function boom(e : Event) : void
{
Particle(e.target).removeEventListener(ParticleEvent.DEAD, boom);
//這裏是爆炸粒子數目
var fireNum : int = int(Math.random() * 100 + 200);
while (fireNum-- > 0)
{
// 想擁有你的特效嗎請改變他 這裏初始化爆炸粒子信息:速度,角速度,重力,摩擦力。改變這裏你看到不一樣的效果
var fireParticle : Particle = ps.createParticle(Particle);
fireParticle.init(e.target.position.x, e.target.position.y, 1.5);
fireParticle.extra = {color:e.target.extra.color, isFire:false,size:0.5};
fireParticle.velocity.reset(0, 2+Math.random()*2);
fireParticle.velocity.rotate(Math.random() * 360);
fireParticle.friction.reset(0.1, 0.1);
fireParticle.addForce("g", gravity);
}
}
這裏是隨便改變參數效果:
再看看其他粒子特效:火龍FireDragon
動動手,運用您的智慧,創造您的魅力來!
{
Particle(e.target).removeEventListener(ParticleEvent.DEAD, boom);
//這裏是爆炸粒子數目
var fireNum : int = int(Math.random() * 100 + 200);
while (fireNum-- > 0)
{
// 想擁有你的特效嗎請改變他 這裏初始化爆炸粒子信息:速度,角速度,重力,摩擦力。改變這裏你看到不一樣的效果
var fireParticle : Particle = ps.createParticle(Particle);
fireParticle.init(e.target.position.x, e.target.position.y, 1.5);
fireParticle.extra = {color:e.target.extra.color, isFire:false,size:0.5};
fireParticle.velocity.reset(0, 2+Math.random()*2);
fireParticle.velocity.rotate(Math.random() * 360);
fireParticle.friction.reset(0.1, 0.1);
fireParticle.addForce("g", gravity);
}
}
這裏是隨便改變參數效果:
再看看其他粒子特效:火龍FireDragon
動動手,運用您的智慧,創造您的魅力來!