7-Particle Explosion with 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坐标位置,在系统中用x和y表示

也有一个速度和方向,速度是一个向量,所以它有两个元素在2D环境下。在3D时候还会有一个z的元素,现在我们还在2D的时候,为了简单,还是先有两个属性吧

粒子年纪开始时候是0,每一次功能更新都会增加

lifetime是粒子挂了之前最大的年纪

其他的是颜色和画笔,都是为了画图用的

回想以前的记录,游戏更新只不过是调用每个实体的更新函数,并显示他们。粒子的更新方法相当简单

首先我们来创建粒子

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);
}

检查一下粒子的创建过程,是很直观的。

粒子是在位置x,y创建的

状态设置为活着的

我们需要把矩形的大小随机化,因为爆炸创建粒子以不同的大小和形状,我们只是把大小和颜色随机了。

我写了一些帮助方法来产生随机数,请参考完整的代码

下一步是设置生命时间,每个粒子都会有相同的生命时间

出生的时候粒子的年纪是0

Next is the interesting bit. It’s very amateurish. To set the speed I have used 2 random numbers for the 2 components of the speed vector (vx andvy). The smoothing is needed because if both components are near the maximum value then the resulting magnitude will be over the max speed. You could use simple trigonometric functions with a random degree instead of this.

下一步是有意思的,非常的业余,为了设置速度,我用了两个随机数来表述速度向量的两个元素 vx和vy。

最后是设置颜色,同样是随机的

There you have it.

粒子的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,那就意味着粒子完全透明了,也就意味着生命的终结

If you wonder about the magic with colours, it is quite simple once you get the bitwise operators. Don’t worry, I’m rubbish as well, just make sure you know where to look. Here is a good explanation of colour components and how to use bitwise operators to manipulate them: http://lab.polygonal.de/2007/05/10/bitwise-gems-fast-integer-math. It’s faster than using the objects but you can safely use the android methods too.

如果你想知道关于颜色的奥秘,如果你了解了位值运算 那么就太简单了,别担心,我也不懂,这里有个关于颜色的非常好的解释,怎么样运用位运算来控制他们,http://lab.polygonal.de/2007/05/10/bitwise-gems-fast-integer-math.直接操作对象要快的多,当然你也可以安全的运用android的方法

 

关于颜色的边注

在android里面颜色是整型的,如果你了解rgb和argb,那就太好了,rgb是24位的,而argb是32位的,有一个alpha值,代表透明或者不透明

Opacity values: 0 = transparent, 255 = completely opaque.

不透明度,0 是透明的,255是完全透明的

为了表示16进制,可以加一个前缀0x,用16进制表示颜色是很简单的,比如0x00FF00代表绿色,模式是0xRRGGBB(红,绿,蓝)。加上alpha值就是0xAARRGGBB

因为是16进制,值是在00和FF之间的,0就是0,FF是10进制的255

下面是如何提取颜色中的各种值

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

画的方法也很简单

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


这一步就是在画板上创建很多的粒子,观察一下现象

The Explosion

爆炸就是数百计的例子从原点爆炸

Explosion

In the image above you see the first 4 updates of a simple explosion. All the particles have the same speed but they spread out in different directions. Each circle is one update.

The main properties of an explosion are:

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
}

It contains an array of particles. The size is the number of particles. An explosion is alive if it has at least one particle alive.

The update is extremely simple. It iterates through all the particles and calls theupdate() method on each particle. The draw() ditto.

In our application we will create explosions on the screen where we touch it.
The constructor is very simple:

	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;
	}

The array of particles is being filled at the touch down position.

In our application we will allow up to 10 explosions. So in the MainGamePanel we declare an array of explosions.

	private Explosion[] explosions;

In the surfaceCreated method we instantiate the array and fill it withnull.

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

The onTouchEvent is where we create explosions.

	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;
	}

What we do is iterate through the explosions and when we find the first null (this means we never used it for an instance) or the first dead explosion we create a new one at the touch position.

The update and render methods are straight forward. Iterate through the explosions and if they are not null and are alive then call their update and draw methods respectively.

In the final code I added a border for the screen as the wall and added a basic collision detection for the particles so they bounce off the walls. The wall is being transmitted as a reference and the update method checks for collision with it. Use it as an exercise and remove the collision and try attaching an image to the particle instead of being a rectangle. To create explosions just click on the screen.

It should look like this:

Explosion Screenshot

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值