原文地址链接
这个例子演示了在不使用高级粒子引擎的情况下,如何创建烟雾效果。主要是使用一些透明纹理精灵(sprite)来实现的。并让这些精灵向上移动,顺时针或逆时针旋转。这样用的好处为了使精灵始终正对这照相机。虽然这个例子是在Mascot Capsule v3实现的,不过同样的技术可以用于JSR-184中。
下载源代码 ![](http://www.j2medev.com/Article/UploadFiles/200512/20051212171848184.gif) 程序截图,用烟雾纹理来生成的烟雾效果
下面是smoke类的代码: import com.mascotcapsule.micro3d.v3.*; import java.util.*;
public class Smoke extends V3Object{
private FigureLayout layout; private Effect3D effect; private AffineTrans trans;
// The point sprite command used when rendering the smoke. private final int COMMAND = Graphics3D.PRIMITVE_POINT_SPRITES | Graphics3D.PDATA_POINT_SPRITE_PARAMS_PER_CMD | Graphics3D.PATTR_BLEND_ADD | Graphics3D.PATTR_COLORKEY;
// The number of sprites used. private final int NUM_POINT_SPRITES = 10; private SmokeItem []smokeItem = new SmokeItem[NUM_POINT_SPRITES];
// randomize the sprite rotation. private Random r;
// the smoke texture. private Texture texture = null; private long ticks = 0; // frame counter.
public Smoke(int w, int h){ try{ texture = new Texture("/res/smoke.bmp", true); }catch(Exception e){ e.printStackTrace(); }
layout = new FigureLayout(); effect = new Effect3D(); trans = new AffineTrans(); trans.setIdentity();
effect.setShadingType(Effect3D.NORMAL_SHADING); effect.setSemiTransparentEnabled(true);
layout.setAffineTrans( trans ); layout.setPerspective(1, 4096, 512); layout.setCenter(w/2, h/2);
trans.mul(lookAt); // the lookAt is from the super class.
// Create the smoke sprites. smokeItem[0] = new SmokeItem(null); for(int i=1; i smokeItem[i] = new SmokeItem(smokeItem[i-1]); } smokeItem[NUM_POINT_SPRITES-1].start(); }
public void update(){ trans.setIdentity(); trans.mul(lookAt); }
public void draw(Graphics3D g3d){
ticks++; for(int i=0; i smokeItem[i].render(g3d); }
}
private class SmokeItem{ // each item has a reference to the next item so it can // be started after a certain time or in this case when the item // reaches a certain point. private SmokeItem next = null;
private int [] POINT = { 0, 0, 0 }; // Position of the sprite private int [] TEXTURE = {10, 10, 512, 0, 0, 128, 128, Graphics3D.POINT_SPRITE_PERSPECTIVE}; private int ROT; // The rotation of the point sprite, // this is randomized // w0, h0, a0, x00, y00, x01, y01, f0, // w1, h1, a1, x10, y10, x11, y11, f1, ...
private int []NORMAL = new int[] {4096}; private int []COLOR = new int[] {0x00};
private boolean started = false; private Random r = new Random(); private int mod; public SmokeItem(SmokeItem next){ this.next = next; reset(); }
public void start(){ started = true; }
/* * Reset the size and position of the sprite */ private void reset(){ TEXTURE[0] = 10; TEXTURE[1] = 10; POINT[1] = 0;
ROT = -16 + r.nextInt(32); }
/* * The sprite is scaled and moved before rendered to the screen. */ protected void render(Graphics3D g3d){ if(started && FPS.fps > 0){ mod = FPS.fps/5; mod = mod <1?1:mod; if(ticks%mod==0){ if(TEXTURE[0] < 80){ // make the size of the sprite bigger. TEXTURE[0]++; TEXTURE[1]++; } } mod = FPS.fps/10; mod = mod <1?1:mod; if(ticks%mod==0){ POINT[1] ++; // add 1 to the y position. if(POINT[1] == 180){ reset(); // start over. } if(POINT[1] > 18 && next != null){ next.start(); // start moving the next sprite } }
TEXTURE[2] += ROT; } // render the sprite. g3d.renderPrimitives(texture, 0, 0, layout, effect, COMMAND, 1, POINT,
NORMAL
, TEXTURE, COLOR); } } }
|