实现的思路:缓存池+(Image或者CHActor) + Actions
例:实现星星右中心点向圆形周围扩散,且星星不断的旋转,缩小,到达圆上时消失。
这个需求里面对于单个星星包含的Action有:
moveTo 移动
roatateBy 旋转
scaleTo 缩小
我们使用Actions.parallel(...)来同时执行上面三个Action。当然我们再执行上面所有Action还需要加上最后的RunnableAction.用来处理粒子结束后的其他工作(释放星星对象到缓存池)。
单个星星的运动过程了解后,剩下的就简单了,我们约定使用30个星星来实现这个效果,在360度的范围随机30次,得到各个星星的运动目标位置,随机整个运动时长。OK。加入舞台,就可以了。
同样,如果我需要一个烟花效果呢?
确定一个矩形范围
在矩形范围随机位置,播放上面的星星效果,这就是个烟花释放的效果。
理解了这种思路,其他的粒子的效果都不在话下了,自由扩展吧!!!
下面为本人封装两种粒子效果:
package com.oahcfly.chgame.core.helper;
import java.util.Random;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.scenes.scene2d.Action;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.actions.Actions;
import com.badlogic.gdx.utils.Align;
import com.badlogic.gdx.utils.Pool;
import com.badlogic.gdx.utils.Pool.Poolable;
import com.badlogic.gdx.utils.Pools;
import com.oahcfly.chgame.core.Chao;
import com.oahcfly.chgame.core.actions.CHScheduleAction;
import com.oahcfly.chgame.core.mvc.CHActor;
/**
*
* <pre>
*
* 可自由扩展的粒子播放器
* <设置粒子图片路径即可>
* date: 2015年3月26日
* </pre>
*
* @author caohao
*/
public class CHAutoParticle implements Poolable {
private Random random = new Random();
private Pool<CHActor> starPool = null;
// 半径
private int cradius = 100;
public void setRadius(int radius) {
cradius = radius;
}
private String imgString;
// 设置图片路径assets目录下
public void setImagePath(final String imgPath) {
this.imgString = imgPath;
starPool = (Pool<CHActor>) Pools.get(CHActor.class);
}
private CHActor getActor() {
CHActor chActor = starPool.obtain();
Texture texture = Chao.game.getTexture(imgString);
chActor.setBgTexture(texture);
chActor.setSize(50, 50);
chActor.setOrigin(com.badlogic.gdx.utils.Align.center);
float r = (float) ((Math.random() * 0.4f) + 0.7f);
float g = (float) ((Math.random() * 0.4f) + 0.7f);
float b = (float) ((Math.random() * 0.4f) + 0.7f);
chActor.setColor(r, g, b, 1);
return chActor;
}
/**
*
* @param imgPath
* 图片路径
*/
public CHAutoParticle(final String imgPath) {
setImagePath(imgPath);
}
public CHAutoParticle() {
}
/**
*
* <pre>
* <由中心向周围扩散并且旋转缩小>
* 播放粒子效果
* date: 2015年3月26日
* </pre>
*
* @author caohao
* @param stage
* @param centerX
* 中心点位置X
* @param centerY
* 中心点位置Y
*/
public void playCircleParticle(Stage stage, float centerX, float centerY) {
// 半径范围
float initRadius = cradius;
// 星星数量
float starNum = 30;
float initStarDuration = 0.3f;
for (int i = 0; i < starNum; i++) {
// 随机角度
int degree = random.nextInt(360) + 1;
// 随机运行时间
float starDuration = (float) (initStarDuration + random.nextInt(5) / 10f);
// 随机半径
float radius = initRadius + random.nextInt(10);
final CHActor starImg = getActor();
starImg.setPosition(centerX, centerY, Align.center);
starImg.setScale(1);
// 目标点
float targetX = centerX + (float) (radius * Math.cos(Math.toRadians(degree)));
float targetY = centerY + (float) (radius * Math.sin(Math.toRadians(degree)));
final boolean islast = i == starNum - 1;
// 运动同时进行旋转,缩小
Action parallelAction = Actions.parallel(Actions.moveTo(targetX, targetY, starDuration),
Actions.rotateBy(360, starDuration), Actions.scaleTo(0.1f, 0.1f, starDuration));
starImg.addAction(Actions.sequence(parallelAction, Actions.run(new Runnable() {
@Override
public void run() {
// 释放加移除
starPool.free(starImg);
starImg.remove();
if (islast) {
Pool<CHAutoParticle> pool = Pools.get(CHAutoParticle.class);
pool.free(CHAutoParticle.this);
}
}
})));
stage.addActor(starImg);
}
}
/**
*
* <pre>
* <烟花效果>
*
* date: 2015年3月26日
* </pre>
*
* @author caohao
* @param stage
* @param rangeRectangle
* 烟花范围
*/
public void playFireWorks(final Stage stage, final Rectangle rangeRectangle, final int playCount,
final Runnable callbackRunnable) {
Action runnableAction = Actions.run(new Runnable() {
int count;
@Override
public void run() {
count++;
if (count > playCount) {
for (Action action : stage.getRoot().getActions()) {
if (action instanceof CHScheduleAction) {
((CHScheduleAction) action).finish();
}
}
return;
}
for (int i = 0; i < 10; i++) {
int x = (int) (random.nextInt((int) rangeRectangle.width) + rangeRectangle.x);
int y = (int) (random.nextInt((int) rangeRectangle.height) + rangeRectangle.y);
playCircleParticle(stage, x, y);
}
}
});
Runnable runnable = new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
if (callbackRunnable != null) {
callbackRunnable.run();
}
Pool<CHAutoParticle> pool = Pools.get(CHAutoParticle.class);
pool.free(CHAutoParticle.this);
}
};
CHScheduleAction scheduleAction = new CHScheduleAction(0.5f, playCount, runnableAction);
scheduleAction.setCallbackRunnable(runnable);
stage.addAction(scheduleAction);
}
@Override
public void reset() {
// TODO Auto-generated method stub
cradius = 100;
if (starPool != null) {
starPool.clear();
}
}
public static CHAutoParticle obtain(String imgPath) {
Pool<CHAutoParticle> pool = Pools.get(CHAutoParticle.class);
CHAutoParticle chAutoParticle = pool.obtain();
chAutoParticle.setImagePath(imgPath);
return chAutoParticle;
}
}
基于libGdx二次封装的CHGame框架 :
https://git.oschina.net/oahcfly/CHGame