粒子系统在图形学上的应用十分广泛。最常见的,是通过控制大量的、具有相似行为的点元素,来描绘自然现象。例如下雨、下雪、火焰、水、雾等等。在家用控制台或PC上的2D、3D游戏中,粒子特效代替了更为传统的精灵绘图,并取得了更灵活多变的视觉效果。但在手机设备上,因为机能和API的诸多限制,对于这一技术的应用并不常见。本文试图尝试一下如何在这些设备上实现简单的例子系统。这仅仅是一次试验,并不能保证一定能用于你的实际开发。
粒子系统简介
粒子系统,即粒子群系统。在自然界中,微粒以各种各样的方式聚集在一起形成,拥有了自身的属性和运动规律,构成了复杂的世界。对这种微粒的研究过于宽泛,我们仅仅关注微粒系统在图形学上应用的一小部分应用。一个常见的微粒系统由两部分组成:微粒群和微粒治理器。微粒包括了一系列的属性:速度、颜色、贴图等和一系列的行为。微粒治理器则负责创建微粒群,调用微粒群的行为、以及将微粒群表现出来(显示)。
例子系统常见的应用有:描述群体(一个子弹群)、描述自然现象(下雨、下雪、火焰、水、雾)。此文关注的是后者。
实现粒子系统的成本
实现通用粒子系统的前提:
1,要有足够的内存空间保存粒子系统本身
2,可以对屏幕上的点进行控制
对于第1条,我的建议是,不要为每一个粒子系统建立类对象,仅仅保存一个多维数组用作描述状态信息。行为可以抽象到粒子治理器去处理。尽管这样,当粒子数目很多时其消耗也是非常惊人的。
对于第2条,MIDP2.0提供了对屏幕上的点进行访问的能力。这一能力是通过Graphics的
void drawRGB(int[] rgbData, int offset, int scanlength, int x, int y, int width, int height, boolean PRocessAlpha)
Renders a series of device-independent RGB+transparency values in a specified region.
方法实现的。此方法不是直接取得对缓冲区的操作能力,而是通过对一个rgbData进行各种操作,然后将它绘画出来,从而实现点的控制。换句话说,对屏幕的点的控制,转换为了对数组的控制。不开放对缓冲区的直接操作,优点是:不去限制硬件厂商的实现;缺点是:一旦要对整个屏幕进行像素操作,就不得不开辟一个足够大的数组,则对普通的手机来说显得负担承重。以sek700为例,176*221=38896像素,每个像素一个int(占2Byte),则总共需要77792B约76KB的连续空间。正如后面看到的,大量的例子算法需要使用到Blur技术用于提高画面效果。此技术需要上次的屏幕的点信息,因此需要两个76KB的连续空间。这还不算粒子群本身需要的空间。假如仅仅作为屏幕特效,就吃掉两个76KB的连续空间似乎有些得不偿失。另外,标准没有对数组进行操作的绘图指令,因此如何对数组进行简单的画圆、输出字符等操作都很棘手。所以可以预见,因为标准API的限制,我们仅能有限的利用粒子系统。
试验一:模拟瀑布
基本思路:将粒子群的出生地定于一点,随机产生一个小范围的水平速度。让粒子按照自然规律自由落体。在接触地的时候发生碰撞,产生很小的向上动力(能量衰减)。
以下是代码,其中blur是一种简单的模糊算法,它可以上画面更见好看,这里使用的是算法是取一个点为其四周四个点的平均值。这个例子使用了调色板技术实现了瀑布由白向蓝再向黑的过渡(查表法)。通过这个例子,你可了解到例子系统的基本实现、简单的物理模型模拟和调色板的使用技巧。在模拟器上运行很慢,但在Nokia3310上有13fps。
public class Waterfall {
public static final int X = 0;
public static final int Y = 1;
public static final int VX = 2;
public static final int VY = 3;
public static final int XACC = 4;
public static final int YACC = 5;
public static final int LIFE = 6;
public static final int DECAY = 7;
int[][] particle;
private int max;
private int last;
public Palette pal;