Libgdx学习笔记:自己封装各种粒子特效
博客专区 > flyoahc 的博客 > 博客详情
Libgdx学习笔记:自己封装各种粒子特效
flyoahc 发表于3年前
Libgdx学习笔记:自己封装各种粒子特效
  • 发表于 3年前
  • 阅读 592
  • 收藏 5
  • 点赞 0
  • 评论 0

【腾讯云】买域名送云解析+SSL证书+建站!>>>   

摘要: 不使用官方粒子播放器,我们自己来封装一些常见,简单的粒子效果,本文更多的是提供一种思路,剩下的则由读者自由发散了。

实现的思路:缓存池+(Image或者CHActor) + Actions

例:实现星星右中心点向圆形周围扩散,且星星不断的旋转,缩小,到达圆上时消失。

这个需求里面对于单个星星包含的Action有:

moveTo 移动

roatateBy 旋转

scaleTo 缩小

我们使用Actions.parallel(...)来同时执行上面三个Action。当然我们再执行上面所有Action还需要加上最后的RunnableAction.用来处理粒子结束后的其他工作(释放星星对象到缓存池)。

单个星星的运动过程了解后,剩下的就简单了,我们约定使用30个星星来实现这个效果,在360度的范围随机30次,得到各个星星的运动目标位置,随机整个运动时长。OK。加入舞台,就可以了。


同样,如果我需要一个烟花效果呢?

  1. 确定一个矩形范围

  2. 在矩形范围随机位置,播放上面的星星效果,这就是个烟花释放的效果。


理解了这种思路,其他的粒子的效果都不在话下了,自由扩展吧!!!


下面为本人封装两种粒子效果:


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



  • 打赏
  • 点赞
  • 收藏
  • 分享
共有 人打赏支持
粉丝 12
博文 37
码字总数 15728
×
flyoahc
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: