爆炸不过是一堆散布在屏幕上的,源自单个点的粒子(无论是像素,小形状还是图像)。 为了方便起见,并非总是如此,而是为了简洁起见,我们将假定所有粒子都源自单个点。
想想烟花。 一颗微小的小火箭弹起来并爆炸成数百颗闪闪发光的小星星,它们在坠落时逐渐消失。 发生的情况是,火箭中心的巨大力将身体撕裂(从而产生粒子),并在爆炸点附近将它们随机散布。
为简单起见,我们将创建一些粒子,将它们放置在一个位置(原点)并赋予它们随机的力。 力是矢量。 这意味着它具有大小和方向。 大小将决定其速度,其方向将告诉粒子走哪条路。
粒子
类文件:
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个点表示: x和y 。
它还具有速度和方向。 您记得速度是一个向量,因此它在2D中具有2个分量。 在3D模式下,它也将具有z分量,但我们暂时停留在2D模式下。 为了简单起见,我们为此添加两个属性。 vx和vy
粒子的年龄在开始时是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);
}
检查粒子的创建,它应该是直接的。
您会注意到在位置x , y处创建了粒子。
状态设置为活着 。
我们想要随机化矩形的大小,因为爆炸会产生不同大小和形状的粒子,但是我们只会随机化大小和颜色。
我编写了一些辅助方法,这些方法为我提供了随机数,为此请检查完整的源代码。
接下来设置寿命 。 每个粒子将具有相同的寿命。
当然, 年龄是0 ,因为粒子刚出生。
接下来是有趣的一点。 这是非常业余的。 为了设置速度,我对速度矢量的2个分量( vx和vy )使用了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 。
update和render方法很简单。 遍历爆炸,如果爆炸不为null并且仍然存在,则分别调用其update和draw方法。
在最后的代码中,我为屏幕添加了边框作为墙,并为粒子添加了基本的碰撞检测功能,以使粒子从墙反弹。 正在传输墙作为参考,更新方法将检查是否与墙发生碰撞。 将其用作练习并消除碰撞,然后尝试将图像附加到粒子而不是矩形。 要创建爆炸,只需单击屏幕。
它看起来应该像这样:
探索代码并玩得开心。
在此处下载( android.particles.tgz )。
参考:来自JCG合作伙伴Tamas Jano的Android进行的《粒子爆炸》,来自“ Against The Grain ”博客。
- Android游戏开发教程简介
- Android游戏开发–游戏创意
- Android游戏开发–创建项目
- Android游戏开发–基本游戏架构
- Android游戏开发–基本游戏循环
- Android游戏开发–使用Android显示图像
- Android游戏开发–在屏幕上移动图像
- Android游戏开发–游戏循环
- Android游戏开发–测量FPS
- Android游戏开发–雪碧动画
- Android游戏开发–设计游戏实体–策略模式
- Android游戏开发–使用位图字体
- Android游戏开发–从Canvas切换到OpenGL ES
- Android游戏开发–使用OpenGL ES显示图形元素(原语)
- Android游戏开发– OpenGL纹理映射
- Android游戏开发–设计游戏实体–状态模式
- Android游戏文章系列
翻译自: https://www.javacodegeeks.com/2011/08/android-game-development-particle.html