例子系统常见的应用有:描述群体(一个子弹群)、描述自然现象(下雨、下雪、火焰、水、雾)。此文关注的是后者。
实现粒子系统的成本
实现通用粒子系统的前提:
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;
/*
* [...][x] :x-coordinates, [...][y] :y-coordinates, [...][vx] :x-velocity,
* [...][vy] :y-velocity, [...][xacc] :x-acceleration,
* [...][yacc]:y-acceleration, [...][life] :life cycle, [...][decay] :decay
*/
/**
*
*/
public waterfall(int max) {
this.max = max;
particle = new int[max][8];
pal = new palette();
initpal();
}
private void initpal() {//初始化调色板
for (int i = 0; i < pal.data.length; i++) {//black-->blue-->white
pal.setcolor(i, i >= 128 ? (i - 128) * 2 : 0, i, i * 2 >= 255 ? 255
: i * 2);
}
// for(int i=0;i<64;i++)
// pal.setcolor(i,i,i/3,0);
// for(int i=64;i<192;i++)
// pal.setcolor(i,63,21+(i-64)/3,0);
// for(int i=192;i<256;i++)
// pal.setcolor(i,63,63,(i-192)*4);
}
public void init(int x, int y, int high) {//初始化
for (int i = 0; i < max; i++) {
particle[i][life] = 0;//kill all particle first
}
refreshstate(x, y);
last = (y + high) << 10;
}
public void refreshstate(int x, int y) {//更新
int xx = x << 10;
int yy = y << 10;
for (int i = 0; i < max; i++) {
if (particle[i][life] <= 0) {
particle[i][x] = xx;
particle[i][y] = yy;
particle[i][vx] = coreutilities.rand(500, 500);
particle[i][vy] = coreutilities.rand(500, 1500);
particle[i][xacc] = 0;
particle[i][yacc] = 50;
particle[i][life] = 1000;
particle[i][decay] = coreutilities.rand(0, 125);
}
}
}
public void move() {//移动
for (int i = 0; i < max; i++) {
if (particle[i][life] > 0) {
particle[i][x] += particle[i][vx];
particle[i][y] += particle[i][vy];
// particle[i][vx]+=particle[i][xacc];//not need this time
particle[i][vy] += particle[i][yacc];
particle[i][life] -= particle[i][decay];
}
if (particle[i][y] > last) {
// system.out.println("before: "+particle[i][vy]);
// particle[i][vy] = -particle[i][vy];
// particle[i][decay]+=50;
particle[i][life] -= 500;//模拟能量衰减
// particle[i][vy] += 3500;//manual speed-down
particle[i][vy] = coreutilities.rand(-1000,400);//模拟能量衰减
// system.out.println("after "+particle[i][vy]);
// particle[i][vx] ;
// particle[i][life] = 0;
// system.out.println("particle[i][life]: "+particle[i][life]);
}
}
}
public void paint(byte[] buffer, int scanlength) {//绘画
int i = 0;
int col = 0, row = 0;
int lastrow = buffer.length / scanlength - 1;
int lastcol = scanlength - 1;
try {
for (i = 0; i < max; i++) {
col = particle[i][x] >> 10;
row = particle[i][y] >> 10;
if(row > lastrowrow<0col<0col>lastcol)
continue;
buffer[scanlength * (row > lastrow ? lastrow : row)
+ (col > lastcol ? lastcol : col)] = 127;
}
} catch (exception e) {
system.out.println(e);
system.out.println("particle[i][x] : " + particle[i][x]);
system.out.println("particle[i][y] : " + particle[i][y]);
system.out
.println("particle[i][x]>>10 : " + (particle[i][x] >>10));
system.out
.println("particle[i][y]>>10 : " + (particle[i][y] >>10));
system.out.println("scanlength * (row > lastrow ? lastrow : row)+ (col > lastcol ? lastcol : col) :"
+ (scanlength * (row > lastrow ? lastrow : row)
+ (col > lastcol ? lastcol : col)));
}
}
public void blur(byte[] inbuffer, byte[] outbuffer, int scanlength) {//模糊算法
int k = scanlength;
int backheight = inbuffer.length / scanlength;
for (int i = 1; i < backheight - 1; i++) {
for (int j = 0; j < scanlength; j++) {
outbuffer[k] = (byte) ((inbuffer[k - 1] + inbuffer[k + 1]
+ inbuffer[k - scanlength] + inbuffer[k + scanlength]) >> 2);
// if (outbuffer[k] > -126)
// outbuffer[k] -= 2;
// else
// outbuffer[k] = -128;
k++;
}
}
// for (k = 0; k < scanlength; k++) {
// outbuffer[k] = inbuffer[k];
// }
// for (k = (backheight - 1) * scanlength; k < inbuffer.length; k++) {
// outbuffer[k] = inbuffer[k];
// }
}
public string tostring() {//调试信息
stringbuffer sb = new stringbuffer();
for (int i = 0; i < max; i++) {
sb.append(particle[i][x] + " " + particle[i][y] + " "
+ particle[i][vx] + " " + particle[i][vy] + " "
+ particle[i][xacc] + " " + particle[i][yacc] + " "
+ particle[i][life] + " " + particle[i][decay] + "\n");
}
return sb.tostring();
}
}
[1] [2] 下一页
Java Asp PHP .Net XML C/C++ CGI VB Jsp J2ee J2se J2me EJB Servlet Tomcat Resin Struts Weblogic Eclipse ANT GUI JMS Web servise IDEA Webphere Hibernate Spring Jboss Applet Swing Socket Javamail Perl Ajax P2P 安全 模式 框架 测试 开源 游戏
Windows XP Windows 2000 Windows 2003 Windows Me Windows 9.x Linux UNIX 注册表 操作系统 服务器 应用服务器