我們在試用andengine編寫遊戲應用的時候,如果想在遊戲中增加豐富多彩絢麗的元素,可是嘗試下試用粒子發射器,
andengine examples中提供了三個例子來示範兩種動態火焰的形成,效果很逼真,粒子發射器能夠形成火焰,其原理可以理解成跟示波器形成圖形有點相似,粒子發射器發射的是自訂的效果元素,示波器發射的是電子,都是通過大量的元素進行重新整理,繪製等操作形成的圖形,所不同的是,粒子發射器發射的粒子有範圍的限制,而且需要自己手動的將到期的粒子殺死來形成動態效果,而示波器是電子不斷打在螢幕上形成的印記。
下面我嘗試從源碼來解釋火焰效果的形成。
一,圓盤型粒子發射器,先看:
a. b.
c. d.
onLoadResources()方法:
@Overridepublic void onLoadResources() {this.mTexture = new Texture(32, 32, TextureOptions.BILINEAR_PREMULTIPLYALPHA);this.mParticleTextureRegion = TextureRegionFactory.createFromAsset(this.mTexture, this, "gfx/particle_point.png", 0, 0);this.mEngine.getTextureManager().loadTexture(this.mTexture);}
這個方法不用多說了,前面的博文都有介紹,注意:particle_point.png便是粒子的樣式圖片,為一個光點。
onLoadScene()方法:
@Overridepublic Scene onLoadScene() {this.mEngine.registerUpdateHandler(new FPSLogger());final Scene scene = new Scene(1);//CircleOutlineParticleEmitter為圓形的例子發射器,其構造方法中的參數:第一第二個為圓心的位置,第三個為半徑final CircleOutlineParticleEmitter particleEmitter = new CircleOutlineParticleEmitter(CAMERA_WIDTH * 0.5f, CAMERA_HEIGHT * 0.5f + 20, 80);//ParticleSystem為粒子系統,螢幕上的所有粒子都歸這個類統一管理final ParticleSystem particleSystem = new ParticleSystem(particleEmitter, 60, 60, 360, this.mParticleTextureRegion);//備忘1scene.setOnSceneTouchListener(new IOnSceneTouchListener() {@Overridepublic boolean onSceneTouchEvent(Scene pScene, TouchEvent pSceneTouchEvent) {particleEmitter.setCenter(pSceneTouchEvent.getX(), pSceneTouchEvent.getY());return true;}});//初始化粒子的狀態//ColorInitializer中的參數為RGB顏色,(1,0,0)就代表紅色//AlphaInitializer中的參數為透明值//setBlendFunction這個是顏色的混合方式,這裡有詳細的介紹:http://www.cnblogs.com/yujunyong/archive/2011/04/13/2015467.html//VelocityInitializer中的參數:第一個為x軸最小的速度,第二個為x軸最大的速度,第三個為y軸最小的速度,第四個為y軸最大的速度//RotationInitializer中的參數:第一個是最小的角度,第二個是最大的角度particleSystem.addParticleInitializer(new ColorInitializer(1, 0, 0));particleSystem.addParticleInitializer(new AlphaInitializer(0));particleSystem.setBlendFunction(GL10.GL_SRC_ALPHA, GL10.GL_ONE);particleSystem.addParticleInitializer(new VelocityInitializer(-2, 2, -20, -10));particleSystem.addParticleInitializer(new RotationInitializer(0.0f, 360.0f));//修改粒子的狀態//ScaleModifier中的參數:第一個為from狀態,第二個為to狀態,第三個為開始的時間,第四個為結束的時間;//ScaleModifier(1.0f, 2.0f, 0, 5)代表是在0-5秒,粒子放大一倍;//-------------------------------------------------------------------------------------------------//ColorModifier中的參數:第一第三第五代表開始的顏色RBG值,第二第四第六代表最終的顏色RGB值,第七第八個參數為時間範圍//ColorModifier(1, 1, 0, 0.5f, 0, 0, 0, 3)代表0-3秒,顏色(1,0,0)變為(1,0.5f,0);//-------------------------------------------------------------------------------------------------//AlphaModifier中的參數:第一個代表from的透明值,第二個代表to的透明值,第三第四個為時間的範圍//AlphaModifier(0, 1, 0, 1)代表在0-1秒,粒子由不透明變成透明狀態//-------------------------------------------------------------------------------------------------//ExpireModifier中的參數:第一個參數為粒子的最小存活時間,第二個參數為粒子最長的存活時間;//ExpireModifier(6, 6)代表粒子可以存活6秒particleSystem.addParticleModifier(new ScaleModifier(1.0f, 2.0f, 0, 5));particleSystem.addParticleModifier(new ColorModifier(1, 1, 0, 0.5f, 0, 0, 0, 3));particleSystem.addParticleModifier(new ColorModifier(1, 1, 0.5f, 1, 0, 1, 4, 6));particleSystem.addParticleModifier(new AlphaModifier(0, 1, 0, 1));particleSystem.addParticleModifier(new AlphaModifier(1, 0, 5, 6));particleSystem.addParticleModifier(new ExpireModifier(6, 6));//備忘2scene.getTopLayer().addEntity(particleSystem);return scene;}
備忘1:ParticleSystem粒子系統類中的構造參數,第一個為定義的粒子發射器,第二個是一秒中能同時發射到螢幕上的粒子最小的數量,第三個是一秒中能同時發射到螢幕上的粒子最大的數量,第四個參數為螢幕上允許可以存活的最大的粒子數,第五個為粒子紋理。
備忘2:這裡是形成效果動態最關鍵的代碼,將到期的粒子殺死,粒子系統則會發布新的粒子來湊足自己所規定的最大的粒子數,此處規定6秒鐘為到期的時間,於是當到了第6秒的時候,第一個發射出來的粒子便被殺死了。
可以看到ParticleSystem類中更新的源碼:
final int particlesToSpawnThisFrame = Math.min(this.mMaxParticles - this.mParticlesAlive, (int)FloatMath.floor(this.mParticlesDueToSpawn));this.mParticlesDueToSpawn -= particlesToSpawnThisFrame;for(int i = 0; i < particlesToSpawnThisFrame; i++){this.spawnParticle();}
mMaxParticles便是我們上面規定的最大的粒子數360,而mParticlesAlive則為螢幕上還存活的粒子的數量,這條代碼就是得到粒子系統根據螢幕上的粒子存活的數量以及必須要達到多少數量來確定還需要發射多少數量,於是知道了自己還需要發射多少數量,便用了一個for迴圈來進行發射。
其中的更新的方法:
@Overrideprotected void onManagedUpdate(final float pSecondsElapsed) {if(this.mParticlesSpawnEnabled) {this.spawnParticles(pSecondsElapsed);}final Particle[] particles = this.mParticles;final ArrayList<IParticleModifier> particleModifiers = this.mParticleModifiers;final int particleModifierCountMinusOne = this.mParticleModifierCount - 1;for(int i = this.mParticlesAlive - 1; i >= 0; i--) {final Particle particle = particles[i];/* Apply all particleModifiers */for(int j = particleModifierCountMinusOne; j >= 0; j--) {particleModifiers.get(j).onUpdateParticle(particle);}particle.onUpdate(pSecondsElapsed);if(particle.mDead){this.mParticlesAlive--;final int particlesAlive = this.mParticlesAlive;particles[i] = particles[particlesAlive];particles[particlesAlive] = particle;}}}
可以看到,最後if判斷,如果粒子已經被殺死,那麼螢幕上存活的粒子數將會減少一個,並且重新賦值。我們殺死的語句便是在備忘2處。上面寫了當我們第6秒的時候,第一個發射出來的粒子便被殺死,那麼螢幕上存活的數量便減少了一個,由於數量減少了一個,那麼粒子系統發現數量沒有達到自己所規定的最大的數量,於是便會又發射出粒子來滿足自己最大的數量。這樣殺掉,然後又產生,又殺掉,又產生,因此看起來便有了動態感覺。
二,點粒子發射器,其原理跟上面是一樣的,先看:
1. 2.
3. 4.
看到效果是不是很炫呢,我們看看代碼,跟上面的差不多:
onLoadResources()方法:
@Overridepublic void onLoadResources() {this.mTexture = new Texture(32, 32, TextureOptions.BILINEAR_PREMULTIPLYALPHA);this.mParticleTextureRegion = TextureRegionFactory.createFromAsset(this.mTexture, this, "gfx/particle_fire.png", 0, 0);this.mEngine.getTextureManager().loadTexture(this.mTexture);}
onLoadScene()方法:
public Scene onLoadScene() {this.mEngine.registerUpdateHandler(new FPSLogger());final Scene scene = new Scene(1);scene.setBackground(new ColorBackground(0.0f, 0.0f, 0.0f));/* Left to right Particle System. */{final ParticleSystem particleSystem = new ParticleSystem(new PointParticleEmitter(0, CAMERA_HEIGHT), 6, 10, 200, this.mParticleTextureRegion);particleSystem.setBlendFunction(GL10.GL_SRC_ALPHA, GL10.GL_ONE);particleSystem.addParticleInitializer(new VelocityInitializer(15, 22, -60, -90));particleSystem.addParticleInitializer(new AccelerationInitializer(5, 15));particleSystem.addParticleInitializer(new RotationInitializer(0.0f, 360.0f));particleSystem.addParticleInitializer(new ColorInitializer(1.0f, 0.0f, 0.0f));particleSystem.addParticleModifier(new ScaleModifier(0.5f, 2.0f, 0, 5));particleSystem.addParticleModifier(new ExpireModifier(11.5f));particleSystem.addParticleModifier(new AlphaModifier(1.0f, 0.0f, 2.5f, 3.5f));particleSystem.addParticleModifier(new AlphaModifier(0.0f, 1.0f, 3.5f, 4.5f));particleSystem.addParticleModifier(new ColorModifier(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 11.5f));particleSystem.addParticleModifier(new AlphaModifier(1.0f, 0.0f, 4.5f, 11.5f));scene.getTopLayer().addEntity(particleSystem);}/* Right to left Particle System. */{final ParticleSystem particleSystem = new ParticleSystem(new PointParticleEmitter(CAMERA_WIDTH - 32, CAMERA_HEIGHT), 8, 12, 200, this.mParticleTextureRegion);particleSystem.setBlendFunction(GL10.GL_SRC_ALPHA, GL10.GL_ONE);particleSystem.addParticleInitializer(new VelocityInitializer(-15, -22, -60, -90));particleSystem.addParticleInitializer(new AccelerationInitializer(-5, 15));particleSystem.addParticleInitializer(new RotationInitializer(0.0f, 360.0f));particleSystem.addParticleInitializer(new ColorInitializer(0.0f, 0.0f, 1.0f));particleSystem.addParticleModifier(new ScaleModifier(0.5f, 2.0f, 0, 5));particleSystem.addParticleModifier(new ExpireModifier(11.5f));particleSystem.addParticleModifier(new AlphaModifier(1.0f, 0.0f, 2.5f, 3.5f));particleSystem.addParticleModifier(new AlphaModifier(0.0f, 1.0f, 3.5f, 4.5f));particleSystem.addParticleModifier(new ColorModifier(0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 11.5f));particleSystem.addParticleModifier(new AlphaModifier(1.0f, 0.0f, 4.5f, 11.5f));scene.getTopLayer().addEntity(particleSystem);}return scene;}
可以發現,除了發射器的類換了,加上發射器的數量變了意外,其他的幾乎一模一樣,其中的初始化和狀態修改如果稍有差別,也可以按照上面類似的理解來理解這裡。好了,今天就到這。