粒子群算法_Android游戏开发–粒子爆炸

粒子群算法

粒子群算法

有没有想过爆炸是如何产生的? 让我们绕个弯路,尝试实现基本的粒子爆炸。

爆炸不过是一堆散布在屏幕上的,源自单个点的粒子(无论是像素,小形状还是图像)。 并非总是如此,而是为了简单起见,我们将假定所有粒子都源自单个点。

想想烟花。 一个微小的小火箭弹起来,爆炸成数百个闪闪发光的小星星,它们在坠落时逐渐消失。 发生的情况是,火箭中心的巨大力将尸体撕裂(从而产生粒子)并将其随机散布在爆炸点附近。

为简单起见,我们将创建一些粒子,将它们放置在一个位置(原点)并赋予它们随机的力。 力是矢量。 这意味着它具有大小和方向。 大小将决定其速度,其方向将告诉粒子走哪条路。

粒子

类文件:

public class Particle {

	public static final int STATE_ALIVE = 0;	// particle is alive
	public static final int STATE_DEAD = 1;		// particle is dead

	public static final int DEFAULT_LIFETIME 	= 200;	// play with this
	public static final int MAX_DIMENSION		= 5;	// the maximum width or height
	public static final int MAX_SPEED			= 10;	// maximum speed (per update)

	private int state;			// particle is alive or dead
	private float width;		// width of the particle
	private float height;		// height of the particle
	private float x, y;			// horizontal and vertical position
	private double xv, yv;		// vertical and horizontal velocity
	private int age;			// current age of the particle
	private int lifetime;		// particle dies when it reaches this value
	private int color;			// the color of the particle
	private Paint paint;		// internal use to avoid instantiation
}

粒子不过是一个带有一些属性的小矩形(可以是图像,圆形或任何其他形状,但是在我们的情况下,我们使用的是矩形)。

它具有状态。 这表明粒子是存活的还是死亡的。 一个质点是活着的时候,它的颜色不是黑色的(它具有不褪色)和它的年龄还没有达到其寿命。 稍后再详细介绍。

它有一个位置。 它在2D坐标系中的位置由2个点表示: xy

它还具有速度和方向。 您记得速度是一个向量,所以它在2D中有2个分量。 在3D中,它也将具有z分量,但我们暂时停留在2D中。 为了简单起见,我们为此添加两个属性。 vxvy

粒子的年龄在开始时是0,并且在每次更新时都会增加。

寿命是粒子死亡之前可以达到的最大年龄。

其余的是颜色油漆。 这些仅用于绘图。

如果您回想起先前的条目,则游戏更新无非就是调用游戏中每个实体的更新方法并显示它们。 粒子的更新方法非常简单。

但是首先我们需要创建粒子:

public Particle(int x, int y) {
	this.x = x;
	this.y = y;
	this.state = Particle.STATE_ALIVE;
	this.widht = rndInt(1, MAX_DIMENSION);
	this.height = this.widht;
	this.lifetime = DEFAULT_LIFETIME;
	this.age = 0;
	this.xv = (rndDbl(0, MAX_SPEED * 2) - MAX_SPEED);
	this.yv = (rndDbl(0, MAX_SPEED * 2) - MAX_SPEED);
	// smoothing out the diagonal speed
	if (xv * xv + yv * yv > MAX_SPEED * MAX_SPEED) {
		xv *= 0.7;
		yv *= 0.7;
	}
	this.color = Color.argb(255, rndInt(0, 255), rndInt(0, 255), rndInt(0, 255));
	this.paint = new Paint(this.color);
}

检查粒子的创建,应该简单明了。

您会注意到,在位置xy处创建了粒子。

状态设置为活着。我们希望随机化矩形的大小,因为爆炸会产生不同大小和形状的粒子,但我们只会随机化大小和颜色。我编写了一些辅助方法,这些方法为我提供了随机数,为此请检查完整的源代码。

接下来设置寿命。 每个粒子将具有相同的寿命。

当然,年龄0 ,因为粒子刚出生。

接下来是有趣的一点。 这是非常业余的。 为了设置速度,我对速度矢量的2个分量( vxvy )使用了2个随机数。 之所以需要平滑,是因为如果两个分量都接近最大值,那么最终的幅度将超过最大速度。 您可以使用具有随机度的简单三角函数代替此函数。

可以设置的是再次随机化的颜色

你有它。

粒子的update()方法。

public void update() {
	if (this.state != STATE_DEAD) {
		this.x += this.xv;
		this.y += this.yv;

		// extract alpha
		int a = this.color >>> 24;
		a -= 2; // fade by 2
		if (a <= 0) { // if reached transparency kill the particle
			this.state = STATE_DEAD;
		} else {
			this.color = (this.color & 0x00ffffff) + (a << 24);		// set the new alpha
			this.paint.setAlpha(a);
			this.age++; // increase the age of the particle
		}
		if (this.age >= this.lifetime) {	// reached the end if its life
			this.state = STATE_DEAD;
		}
	}
}

很简单每次更新时,位置都会根据速度进行设置,并且粒子颜色的alpha分量会减少。 换句话说,粒子正在褪色。

如果寿命超过寿命或不透明度为0(这意味着它是完全透明的),则该粒子将被声明为死亡。

如果您想知道彩色魔术,那么一旦获得按位运算符,它就非常简单。 别担心,我也是垃圾,只要确保您知道要看的地方即可。 这是颜色成分以及如何使用按位运算符对其进行操作的很好的解释: http : //lab.polygonal.de/2007/05/10/bitwise-gems-fast-integer-math/ 。 它比使用对象要快,但是您也可以安全地使用android方法。

就像关于颜色的附注您可以在Android中将颜色指定为int。 如果您熟悉rgb和argb,那就太好了。rgb是24位彩色,而argb是32位。 它还具有透明度/不透明度的alpha分量。

不透明度值:0 =透明,255 =完全不透明。

要以十六进制表示一个int,只需在其前面加上0x即可。 十六进制的颜色很简单:例如0x00FF00为绿色。 模式为: 0xRRGGBB (红色,绿色,蓝色)。 现在要添加Alpha,请将其添加到开头。 0xAARRGGBB 。因为它是十六进制的,所以值在00到FF之间。 0为0,FF为255(十进制)。当使用诸如color(a,r,g,b)之类的分量创建颜色时(例如: new Color(125,255,0,0)创建半透明红色),您可以简单地用表示为整数的整数来创建它像这样十六进制: new Color(0x80FF0000);

这就是提取argb颜色的成分的方式。

int color = 0xff336699;
int alpha = color >>> 24;
int red   = color >>> 16 & 0xFF;
int green = color >>>  8 & 0xFF;
int blue  = color & 0xFF;

draw()方法再次很简单。

public void draw(Canvas canvas) {
	paint.setColor(this.color);
	canvas.drawRect(this.x, this.y, this.x + this.widht, this.y + this.height, paint);
}

在此阶段,尝试在游戏面板中创建一些粒子,然后看看会发生什么。

爆炸

爆炸不过是数百个来自某个地方(即起源)的粒子。

在上图中,您看到一个简单爆炸的前4个更新。 所有粒子都具有相同的速度,但是它们以不同的方向散布。 每个圆圈是一个更新。

爆炸的主要特性是:

public class Explosion {

	public static final int STATE_ALIVE 	= 0;	// at least 1 particle is alive
	public static final int STATE_DEAD 		= 1;	// all particles are dead

	private Particle[] particles;			// particles in the explosion
	private int x, y;						// the explosion's origin
	private int size;						// number of particles
	private int state;						// whether it's still active or not
}

它包含粒子阵列。 大小是颗粒数。 如果爆炸中至少有一个活着的粒子,那么它就是活着的。

更新非常简单。 它遍历所有粒子,并在每个粒子上调用update()方法。 draw()同上。

在我们的应用程序中,我们将在触摸它的屏幕上创建爆炸。构造函数非常简单:

public Explosion(int particleNr, int x, int y) {
	Log.d(TAG, "Explosion created at " + x + "," + y);
	this.state = STATE_ALIVE;
	this.particles = new Particle[particleNr];
 	for (int i = 0; i < this.particles.length; i++) {
		Particle p = new Particle(x, y);
		this.particles[i] = p;
	}
 	this.size = particleNr;
}

颗粒阵列在触地位置处被填充。

在我们的应用中,我们最多允许爆炸10次。 因此,在MainGamePanel中,我们声明了一系列爆炸。

private Explosion[] explosions;

surfaceCreated方法中,我们实例化该数组并将其填充为null

explosions = new Explosion[10];
for (int i = 0; i < explosions.length; i++) {
	explosions[i] = null;
}

onTouchEvent是我们创建爆炸的地方。

public boolean onTouchEvent(MotionEvent event) {
	if (event.getAction() == MotionEvent.ACTION_DOWN) {
		// check if explosion is null or if it is still active
		int currentExplosion = 0;
		Explosion explosion = explosions[currentExplosion];
		while (explosion != null && explosion.isAlive() && currentExplosion < explosions.length) {
			currentExplosion++;
			explosion = explosions[currentExplosion];
		}
		if (explosion == null || explosion.isDead()) {
			explosion = new Explosion(EXPLOSION_SIZE, (int)event.getX(), (int)event.getY());
			explosions[currentExplosion] = explosion;
		}
	}
	return true;
}

我们要做的是遍历爆炸,当我们发现第一个null (这意味着我们从未在实例中使用过)或第一次死爆炸时,我们会在触摸位置创建一个新的null

updaterender方法很简单。 遍历爆炸,如果爆炸不为null并且仍然存在,则分别调用其update和draw方法。

在最后的代码中,我为屏幕添加了边框作为墙,并为粒子添加了基本的碰撞检测,以使粒子从墙反弹。 正在传输墙作为参考,更新方法将检查是否与墙发生碰撞。 将其用作练习并消除碰撞,然后尝试将图像附加到粒子而不是矩形。 要创建爆炸,只需单击屏幕。

它看起来应该像这样:

探索代码并玩得开心。

在此处下载( android.particles.tgz )。

参考资料:来自JCG合作伙伴Tamas Jano的“ Android上的粒子爆炸”,来自“ Against The Grain ”博客。

不要忘记查看我们的新Android游戏ArkDroid (以下屏幕截图) 。 您的反馈将大有帮助!
相关文章:

翻译自: https://www.javacodegeeks.com/2011/08/android-game-development-particle.html

粒子群算法

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值