天天看點

JSR184,我學完自己做的程式

這是很早以前看184規範時寫的小程式,純脆是練手的,因為當時沒做過真機測試,是以效能上肯定不行,代碼也不是很規範,沒寫注釋.整個項目都是跑通的,我在朋友索愛的walkman上測試了下.

現在做app了,遊戲方面,很久沒看了,一句話很讓人省悟,雖然不太願意相信:基于j2me+web的遊戲,是做不出PC平台遊戲的那種輝煌的.(game規模,game界面,響應速度,費用,限制太多太多了,還需要硬體的進一步發展,這個産業才能真正壯大起來)

汗死,CRC校驗錯誤,所有資源檔案都不能用.PNG M3G MAX都失效了,隻有源檔案了,等我回家了再把東西補傳上來吧,大家将就下先湊合下看看源碼吧。

下圖是遊戲截圖:

JSR184,我學完自己做的程式

About.java

//Text "About" code skeleton

import javax.microedition.lcdui.*;

public class About extends Form implements CommandListener

{

//Command for going back to the main menu

private Command back = new Command("Back", Command.BACK, 1);

private AirFighterMIDlet parent = null;

private MainMenu menu = null;

public About(String title,AirFighterMIDlet parent, MainMenu menu)

 {

 super(title);

 this.parent = parent;

 this.menu = menu;

 this.addCommand(back);

 this.append("/n/n/n/n    ==== Version 1.0.0 ====/n    Legion 2007年作版權所有(C)");

 this.setCommandListener(this);

 }

public void commandAction(Command p0, Displayable p1)

 {

 if (p0 == back)

  {

  parent.setDisplayable(menu);

  }

 }

}

Aim.java

import java.util.Random;

import javax.microedition.m3g.Group;

import javax.microedition.m3g.Loader;

import javax.microedition.m3g.RayIntersection;

public class Aim

{

 private float[] pos = {0.0f, 0.0f, 0.0f};

 //是否死亡

 private boolean life=true;

 private int itemID=0;

 private Random rand;

 private Group goomba;

 RayIntersection ri;

 public Aim(int itemID,Group group,Random ran)

     {

   //System.out.println("Create Aim:");

   goomba=MeshFactory.createGoomba("/res/goomba.m3g");

   //  /res/machine.m3g

   //  /res/goomba.m3g

   group.addChild(goomba);

   goomba.setUserID(itemID);

   setID(itemID);

   ri = new RayIntersection();

   rand=ran;

   setLife(false);

     }

 public void init(int i,Group group)

 {

  pos[0] = 15.0f-rand.nextFloat()*30.0f;

  pos[2] = 15.0f-rand.nextFloat()*30.0f;

  group.pick(-1, pos[0],10.0f, pos[2], 0.0f, -1.0f, 0.0f, ri);

   pos[1] = 10.0f-ri.getDistance();

        setLife(true);

  //System.out.println("Aim "+i+" pos:"+pos[0]+","+pos[1]+","+pos[2]);

        //System.out.println();

        goomba.translate(pos[0],pos[1],pos[2]);

 }

 public void setPos(float[] tpos)

 {

     System.arraycopy(tpos, 0, pos, 0, pos.length);

 }

 float[] getPos()

 {

     return pos;

 }

     void setLife(boolean life)

     {

         this.life = life;

     }

     boolean getLife()

     {

         return life;

     }

     void setID(int id)

     {

      itemID = id;

     }

     int getID()

     {

         return itemID;

     }

}

AimSystem.java

import java.util.Random;

import javax.microedition.m3g.Group;

import javax.microedition.m3g.Transform;

public class AimSystem

{

 Aim[] aim=null;

    int hitnum=0;//記錄擊中數

    Transform tran;

    Random ran;

 public AimSystem(int aimNum,Group group,BulletSystem bs)

 {

  aim=new Aim[aimNum];

  ran=new Random();

  tran=new Transform();

  tran.setIdentity();

  tran.postTranslate(0.0f, 2.0f, 0.0f);

  for(int i=0;i<aim.length;i++)

  {

   aim[i]=new Aim(300+i,group,ran);

   //System.out.println("Goomba[i] ID:"+aim[i].getID());

   aim[i].init(i,group);

   //System.out.print("Bullet "+(i+1)+"init:");

   tran.postRotate(45.0f-ran.nextFloat()*90.0f, 1.0f, 0.0f, 0.0f);

   tran.postRotate(45.0f-ran.nextFloat()*90.0f, 0.0f, 1.0f, 0.0f); 

   bs.start(i+1, aim[i].getPos(), tran);

  } 

 }

 public void kpbulletsurvive(BulletSystem bs)

 {

  for(int i=1;i<bs.getBulletnum();i++)

  {

  if(!bs.getBulletState(i))

   {

   tran.postRotate(ran.nextFloat()*180.0f, 1.0f, 0.0f, 0.0f);

   tran.postRotate(90.0f-ran.nextFloat()*180.0f, 0.0f, 1.0f, 0.0f); 

   bs.start(i, aim[i-1].getPos(), tran);

   }

  }

 }

 public void update(Group group)

 {

  for(int i=0;i<aim.length;i++)

  {

   if(!aim[i].getLife())

   {

    aim[i].init(i,group);

   }

   else

   {

    //aim[i].updata(group);

   }

  }

 }

 public float[] hit(int itemID)

 {

 float pos[]=null;

  for(int i=0;i<aim.length;i++)

  {

   if(aim[i].getID()==itemID)

   {

   hitnum++;

   pos=aim[i].getPos();

   aim[i].setLife(false);

   }

  }

  return pos;

 }

 int gethitNum()

 {

  return hitnum;

 }

}

AirFighterCanvas.java

import javax.microedition.lcdui.Command;

import javax.microedition.lcdui.Graphics;

import javax.microedition.lcdui.Image;

import javax.microedition.lcdui.game.GameCanvas;

import javax.microedition.m3g.Background;

import javax.microedition.m3g.Camera;

import javax.microedition.m3g.Graphics3D;

import javax.microedition.m3g.Group;

import javax.microedition.m3g.Image2D;

import javax.microedition.m3g.Light;

import javax.microedition.m3g.Transform;

import javax.microedition.m3g.World;

public class AirFighterCanvas extends GameCanvas implements Runnable

{

private AirFighterMIDlet parent = null;

private MainMenu menu = null;

private StarHScroller scroller; // scroll stars on the screen.

private int width;

private int height;

private boolean gamePaused;

//private boolean pxCollides=true;

//private boolean trance = false;

//private long delay;

private World world;

private Group heightmap;

private Graphics g;

private Graphics3D g3;

private AimSystem as;

private Camera cameraog;

private Camera camera;

private FountainEffect fe;

private ParticleSystem ps;

private BulletSystem bs;

private Transform transform;

private Light[] light;

private Background background;

private Image2D image2d;

private Image crossImage;

private float camerapos[] = new float[] {0.0f, 2.0f, 2.0f };

private float[] gettrans;

private float radian = 3.0f;// 旋轉角度

private float cameramove=0.5f;

private float[] bompos;

private boolean key[] = new boolean[9];

private int keystate;

private static final int FIRE = 0;

private static final int UP = 1;

private static final int DOWN = 2;

private static final int LEFT = 3;

private static final int RIGHT = 4;

private static final int GAME_A=5;

private static final int GAME_B=6;

private static final int GAME_C=7;

private static final int GAME_D=8;

static final int TERRAIN_ID = 14;

static final int CAMERA_ID = 15;

static final int SLEEP=30;

static final int AimNum=5;

private int round=0;

private int firnum=0;

private int score=0;

 public AirFighterCanvas(AirFighterMIDlet parent, MainMenu menu)

 {

  // TODO Auto-generated constructor stub

  super(true);

  this.parent = parent;

  this.menu = menu;

  setFullScreenMode(true);

  this.width = getWidth();

  this.height = getHeight();

        scroller = new StarHScroller(width, height);

  init();

 }

 public void init()

 { 

  world=new World();

  light = new Light[2];

  //System.out.println("World ID:"+world.getUserID()); 

        background = new Background();

        image2d=new Image2D(Image2D.RGB, scroller.getImage());

        background.setImage(image2d);

        world.setBackground(background);

        try

        {

        crossImage = Image.createImage("/res/cross.png");

        }

        catch(Exception e)

        {

        }

  light[0] = new Light();

  light[0].setMode(Light.OMNI); // Light Mode

  light[0].setColor(0xFFFFFF); // The color of the light

  light[0].setTranslation(15.0f, 15.0f, -15.0f);

  light[0].setUserID(2);

  light[1] = new Light();

  light[1].setMode(Light.OMNI); // Light Mode

  light[1].setColor(0xFFFFFF); // The color of the light

  light[1].setTranslation(-15.0f, 15.0f, 15.0f);

  light[1].setUserID(3);

  for (int i = 0; i < light.length; i++)

  {

   world.addChild(light[i]);

   //System.out.println("Light ID:"+light[i].getUserID());   

  }

  transform = new Transform();

  transform.setIdentity();

  this.g = this.getGraphics();

  g3 = Graphics3D.getInstance();

  gettrans=new float[16];

  heightmap=MeshFactory.createHeightMap("/res/heightmap.m3g");

  heightmap.setUserID(1);

  world.addChild(heightmap);

  //System.out.println("HeightMap ID:"+heightmap.getUserID());

  loadcamera();

  //loadcameraog();

  bs=new BulletSystem(AimNum+1,world);

  as = new AimSystem(AimNum, world,bs);

  fe = new FountainEffect(-90);

  ps = new ParticleSystem(fe, 10);

 }

 private void loadcamera()

 {

  camera = new Camera();

  float aspect = (float) width / (float) height;

  camera.setPerspective(60.0f, aspect, 0.1f, 100.0f);

  camera.setTranslation(camerapos[0], camerapos[1], camerapos[2]);

  world.addChild(camera);

  world.setActiveCamera(camera);  

 }

 private void loadcameraog()

 {

  try

  {   

   // Find a specific Camera node in the World.

   camera = (Camera) world.find(CAMERA_ID);

   world.setActiveCamera(camera);

   camera.getTransform(transform);

   transform.get(gettrans);

   camerapos[0]=gettrans[3];

   camerapos[1]=gettrans[7];

   camerapos[2]=gettrans[11];

   //System.out.println("/ncameraog init:");

   //System.out.println("Camera posog:"+camerapos[0]+" "+camerapos[1]+" "+camerapos[2]);

   //System.out.println("Camera tran:"+gettrans[3]+" "+gettrans[7]+" "+gettrans[11]);

  }

  catch (Exception e)

  {

   e.printStackTrace();

  }  

 }

 private void cameramove()

 {

  //transform.postTranslate(0.0f, 0.0f,cameramove);

  if (key[LEFT])

  {

   transform.postRotate(radian, 0.0f, 1.0f, 0.0f);

   // System.out.println(".......left...............");

  }

  else if (key[RIGHT])

  {

   transform.postRotate(-radian, 0.0f,1.0f, 0.0f);

   // System.out.println(".......right...............");

  }

  if (key[UP])

  {

   //camera.postRotate(radian, 1.0f, 0.0f, 0.0f);

   transform.postRotate(radian, 1.0f, 0.0f, 0.0f);

   // System.out.println(".......up...............");

  }

  else if (key[DOWN])

  {

   //camera.postRotate(-radian, 1.0f, 0.0f, 0.0f);

   transform.postRotate(-radian, 1.0f, 0.0f, 0.0f);

  }

  if(key[GAME_A])

  {

   transform.postTranslate(0.0f,cameramove, 0.0f);

   //System.out.println("key[GAME_A] processing.");

  }

  if(key[GAME_B])

  {

   transform.postTranslate(0.0f,-cameramove,0.0f);

  }

  if(key[GAME_C])

  {

   transform.postTranslate(0.0f, 0.0f,-cameramove);

  }

  if(key[GAME_D])

  {

   transform.postTranslate(0.0f, 0.0f,cameramove);

  }

  if (key[FIRE])

  {

   if(!bs.getBulletState(0))

   {

    transform.get(gettrans);

    //System.out.println("/nFire Pressed:");

    //System.out.println("Camera posog:"+camerapos[0]+" "+camerapos[1]+" "+camerapos[2]);

    //System.out.println("Camera tran:"+gettrans[3]+" "+gettrans[7]+" "+gettrans[11]);

    bs.start(0,camerapos,transform);

    firnum++;//射擊數

   }

  }

 //transform.get(gettrans);

 //System.out.println("Camera pos:"+(camerapos[0]+gettrans[3])+" "+(camerapos[1]+gettrans[7])+" "+(camerapos[2]+gettrans[11]));

 camera.setTransform(transform); 

 }

 public void start()

 {

 gamePaused=false;

 Thread t=new Thread(this);

 t.start();

 }

 public void run()

 {

  while (!parent.isFinished())

  {

   if (!parent.isPaused())

   {

    draw3D(g);

    //drawMenu(g);

    flushGraphics();

    try

    {

     Thread.sleep(SLEEP);//original 10

    }

    catch (InterruptedException e)

    {

     //TODO Auto-generated catch block

     e.printStackTrace();

    }

   }

  }

 }

 public void draw3D(Graphics g)

 {

  try {

   keyprocess();

   cameramove();

   as.update(world);

   int id= bs.update(world);

   as.kpbulletsurvive(bs);

   if(id!=0)

   {

    //bompos=as.hit(id);

    bompos=bs.hit(id);

    if(bompos!=null)

    {

     ps.init(bompos);

     //System.out.println("trance");

    }

   }

   // 綁定目标

   g3.bindTarget(g); // Binds the given Graphics or mutable Image2D

   //if(((++round)%10)==0)

   // background.setImage(new Image2D(Image2D.RGB, scroller.getImage()));

   //image2d.set(0, 0, width, height, scroller.getByteArray(scroller.getImage()));

   // 渲染世界 // as the rendering target of this Graphics3D

   g3.render(world); // Render the world

   ps.emit(g3);

  }

  catch (Exception e)

  {

   System.out.println(".......render exception...............");

   e.printStackTrace();

  }

  finally

  {

   g3.releaseTarget();   // 釋放目标

  }

  menupaint(g);

 }

 void menupaint(Graphics g)

 {

  //g.setColor(0, 255, 0);

  //g.drawRect(width / 2 - 1, height / 2 - 1, 2, 2);

  if(firnum<10)

  {

   score=0;

  }else

  {

   score=(int)((as.gethitNum()+bs.gethitNum())/(firnum/10.0f)*10);

  }

  g.setColor(255, 255, 255);

  g.drawString("Shoot:" + firnum, 0, 0, Graphics.TOP | Graphics.LEFT);

  g.drawString("Hit:" + (as.gethitNum()+bs.gethitNum()), 0, 20, Graphics.TOP | Graphics.LEFT);

  g.drawString("Score:"+score, width - 50, 0, Graphics.TOP| Graphics.LEFT);

  transform.get(gettrans);

  //System.out.println("/nFire Pressed:");

  //System.out.println("Camera posog:"+camerapos[0]+" "+camerapos[1]+" "+camerapos[2]);

  //System.out.println("Camera tran:"+gettrans[3]+" "+gettrans[7]+" "+gettrans[11]);

  g.drawString("Pos[x]:"+(camerapos[0]+gettrans[3]), 0, height-60, 0);

  g.drawString("Pos[y]:"+(camerapos[1]+gettrans[7]), 0, height-40, 0);

  g.drawString("Pos[z]:"+(camerapos[2]+gettrans[11]), 0, height-20, 0);

  g.drawString("Enemy:" + AimNum, width - 50, height - 20, Graphics.TOP | Graphics.LEFT);

     g.drawImage(crossImage,getWidth()/2, getHeight()/2, Graphics.VCENTER | Graphics.HCENTER);

 }

 private void keyprocess()

 {

  keystate = getKeyStates();

  if ((keystate & GameCanvas.FIRE_PRESSED) != 0)

   key[FIRE] = true;

  else

   key[FIRE] = false;

  if ((keystate & GameCanvas.UP_PRESSED) != 0)

   key[UP] = true;

  else

   key[UP] = false;

  if ((keystate & GameCanvas.DOWN_PRESSED) != 0)

   key[DOWN] = true;

  else

   key[DOWN] = false;

  if ((keystate & GameCanvas.LEFT_PRESSED) != 0)

   key[LEFT] = true;

  else

   key[LEFT] = false;

  if ((keystate & GameCanvas.RIGHT_PRESSED) != 0)

   key[RIGHT] = true;

  else

   key[RIGHT] = false;

  if ((keystate & GameCanvas.GAME_A_PRESSED)!= 0) //GameCanvas.KEY_NUM5

   {

   key[GAME_A]=true;

   //System.out.println("key[GAME_A] pressed.");

   }

  else

   key[GAME_A]=false;

  if ((keystate & GameCanvas.GAME_B_PRESSED)!= 0) //GameCanvas.KEY_NUM5

   {

   key[GAME_B]=true;

   //System.out.println("key[GAME_A] pressed.");

   }

  else

   key[GAME_B]=false;

  if ((keystate & GameCanvas.GAME_C_PRESSED)!= 0) //GameCanvas.KEY_NUM5

   {

   key[GAME_C]=true;

   //System.out.println("key[GAME_A] pressed.");

   }

  else

   key[GAME_C]=false;

  if ((keystate & GameCanvas.GAME_D_PRESSED)!= 0) //GameCanvas.KEY_NUM5

   {

   key[GAME_D]=true;

   //System.out.println("key[GAME_A] pressed.");

   }

  else

   key[GAME_D]=false;

 }

 public void stop()

 {

 gamePaused=true; 

 }

 public boolean isPaused()

 {

 return gamePaused;

 }

 public void gameContinue()

 {

 gamePaused = false;

 }

}

AirFighterMIDlet.java

import javax.microedition.lcdui.Command;

import javax.microedition.lcdui.Display;

import javax.microedition.lcdui.Displayable;

import javax.microedition.midlet.MIDlet;

import javax.microedition.midlet.MIDletStateChangeException;

public class AirFighterMIDlet extends MIDlet

{

private Display display = null;

private SplashCanvas splash;

boolean started = false;

boolean finished = false;

boolean paused=false;

Thread drawThread;

AirFighterCanvas canvas;

 public AirFighterMIDlet()

 {

 // TODO Auto-generated constructor stub

 splash = new SplashCanvas(this); 

 this.display = Display.getDisplay(this);

 }

 protected void startApp()

 {

 // TODO Auto-generated method stub

 if (display == null)

  {

  display = Display.getDisplay(this);

  }

 //splash screen to the display

 setDisplayable(splash);

 }

 protected void destroyApp(boolean arg0) throws MIDletStateChangeException

 {

 // TODO Auto-generated method stub

  setFinished();

 }

 protected void pauseApp()

 {

 // TODO Auto-generated method stub

  paused=true;

 }

 public void setDisplayable(Displayable dl)

 {

 display.setCurrent(dl);

 }

 public synchronized boolean isFinished()

 {

  return finished;

 }

 public synchronized void setFinished()

 {

  finished = true;

 }

 public synchronized boolean isPaused()

 {

  return paused;

 }

}

BaseRMS.java

import javax.microedition.rms.*;

import java.util.*;

import java.io.*;

abstract public class BaseRMS {

  private String rmsName;

  private RecordStore recordStore;

  BaseRMS(String rmsName) {

    this.rmsName = rmsName;

  }

public void open() throws Exception

  {

    try

    {

      recordStore = RecordStore.openRecordStore(this.rmsName,true);

      if (recordStore.getNumRecords() > 0)

      {

        loadData();

      }

      else

      {

        createDefaultData();

      }

    }

    catch (Exception e)

    {

      throw new Exception(this.rmsName+"::open::"+e);

    }

  }

  public void close()

  {

    if (recordStore != null)

    {

      try

      {

        recordStore.closeRecordStore();

      }

      catch(Exception e)

      {

      System.out.println(this.rmsName+"::close::"+e);

      }

    }

  }

  public RecordStore getRecordStore()

  {

    return this.recordStore;

  }

  public String getRMSName()

  {

    return this.rmsName;

  }

  abstract void loadData() throws Exception;

  abstract void createDefaultData() throws Exception;

  abstract void updateData() throws Exception;

}

Bullet.java

import java.util.Random;

import javax.microedition.m3g.Group;

import javax.microedition.m3g.Loader;

import javax.microedition.m3g.Mesh;

import javax.microedition.m3g.RayIntersection;

import javax.microedition.m3g.Transform;

public class Bullet

{

 private Mesh mesh;

 private float scaleobj = 0.2f;

 private float scalebullet = 0.1f;

 RayIntersection ri;

 private Random rand;

    private boolean life=true;

 private Transform transform;

    private int itemID=0;   

 private float[] pos = { 0.0f, 0.0f, 0.0f };

 private float[] posinit = { 0.0f, 0.0f, 0.0f };

 private float[] poshide={0.0f,-3.0f,0.0f};

 private float[] gettrans;

 private float vog = 2.0f;

 private float vobject=0.05f;

 private float v = 0.0f; 

 private float dis=0.2f;

 public Bullet(int ID,Group group,Random ran)

 {

  mesh = MeshFactory.createSquare("/res/Legion.png");

  group.addChild(mesh);

  mesh.translate(poshide[0], poshide[1], poshide[2]);

  mesh.setUserID(ID);

  setID(ID);

  gettrans=new float[16];

  transform=new Transform();

  transform.setIdentity();

  ri = new RayIntersection();

  rand=ran;

  setLife(false);

 }

 public void init(float[] posog,Transform tran,boolean flag)

 {

        System.arraycopy(posog, 0,posinit, 0, posog.length);

  transform.set(tran);

  transform.get(gettrans);

  pos[0]=posinit[0]+gettrans[3];

  pos[1]=posinit[1]+gettrans[7];

  pos[2]=posinit[2]+gettrans[11];

  if(flag)

   {

   //true for Camera

   v=vog;

   mesh.setScale(scalebullet, scalebullet, scalebullet);

   }

  else

   {

   v=vobject+rand.nextFloat()*0.05f;

   mesh.setScale(scaleobj, scaleobj, scaleobj);

   }

  //System.out.println("/nBullet init:");

  //System.out.println("Camera posog:"+posog[0]+" "+posog[1]+" "+posog[2]);

  //System.out.println("Bullet posog:"+pos[0]+" "+pos[1]+" "+pos[2]);

  //System.out.println("Camera tran:"+gettrans[3]+" "+gettrans[7]+" "+gettrans[11]);

  setLife(true);

  mesh.setTranslation(pos[0], pos[1],pos[2]);

 }

 public int update(Group group)

 {

  int id=0;

  mesh.postRotate(15.0f, 0.0f, 0.0f, 1.0f);

  if (group.pick(-1, pos[0], pos[1], pos[2],  1.0f, 0.0f,  0.0f, ri)&& (ri.getDistance() < dis))

  {

   id = ri.getIntersected().getUserID();

   //System.out.println("Bullet Intersected:"+id);

   //System.out.println("Bullet Intersected Class:"+ri.getIntersected().getClass());

   //System.out.println("Bullet Intersected Parent:"+ri.getIntersected().getParent());

   setLife(false);

         System.arraycopy(poshide, 0,pos, 0, poshide.length);

  }

  else if(group.pick(-1, pos[0], pos[1], pos[2], -1.0f, 0.0f,  0.0f, ri)&& (ri.getDistance() < dis))

  {

   id = ri.getIntersected().getUserID();

   //System.out.println("Bullet Intersected:"+id);

   //System.out.println("Bullet Intersected Class:"+ri.getIntersected().getClass());

   //System.out.println("Bullet Intersected Parent:"+ri.getIntersected().getParent());

   setLife(false);

         System.arraycopy(poshide, 0,pos, 0, poshide.length);

  }

  else if(group.pick(-1, pos[0], pos[1], pos[2],  0.0f, 1.0f,  0.0f, ri)&& (ri.getDistance() < dis))

  {

   id = ri.getIntersected().getUserID();

   //System.out.println("Bullet Intersected:"+id);

   //System.out.println("Bullet Intersected Class:"+ri.getIntersected().getClass());

   //System.out.println("Bullet Intersected Parent:"+ri.getIntersected().getParent());

   setLife(false);

         System.arraycopy(poshide, 0,pos, 0, poshide.length);

  }

  else if (group.pick(-1, pos[0], pos[1], pos[2],  0.0f,-1.0f,  0.0f, ri)&& (ri.getDistance() < dis))

  {

   id = ri.getIntersected().getUserID();

   //System.out.println("Bullet Intersected:"+id);

   //System.out.println("Bullet Intersected Class:"+ri.getIntersected().getClass());

   //System.out.println("Bullet Intersected Parent:"+ri.getIntersected().getParent());

   setLife(false);

         System.arraycopy(poshide, 0,pos, 0, poshide.length);

  }

  else if(group.pick(-1, pos[0], pos[1], pos[2],  0.0f, 0.0f,  1.0f, ri)&& (ri.getDistance() < dis))

  {

   id = ri.getIntersected().getUserID();

   //System.out.println("Bullet Intersected:"+id);

   //System.out.println("Bullet Intersected Class:"+ri.getIntersected().getClass());

   //System.out.println("Bullet Intersected Parent:"+ri.getIntersected().getParent());

   setLife(false);

         System.arraycopy(poshide, 0,pos, 0, poshide.length);

  }

  else if(group.pick(-1, pos[0], pos[1], pos[2],  0.0f, 0.0f,   -1.0f, ri)&& (ri.getDistance() < dis))

  {

   id = ri.getIntersected().getUserID();

   //System.out.println("Bullet Intersected:"+id);

   //System.out.println("Bullet Intersected Class:"+ri.getIntersected().getClass());

   //System.out.println("Bullet Intersected Parent:"+ri.getIntersected().getParent());

   setLife(false);

         System.arraycopy(poshide, 0,pos, 0, poshide.length);

  } 

  else if(pos[0]<=-15.0f||pos[0]>=15.0f||pos[2]<=-15.0f||pos[2]>=15.0f||pos[1]<=-0.0f||pos[1]>=10.0f)

  {

   setLife(false);

         System.arraycopy(poshide, 0,pos, 0, poshide.length);

  }

  else

  { 

   transform.postTranslate(0.0f, 0.0f, -v);

   transform.get(gettrans);

   pos[0]=posinit[0]+gettrans[3];

   pos[1]=posinit[1]+gettrans[7];

   pos[2]=posinit[2]+gettrans[11];

  }

  mesh.setTranslation(pos[0], pos[1], pos[2]);

  //System.out.println("Bullet pos:"+pos[0]+","+pos[1]+","+pos[2]);

  return id;

 }

    void setLife(boolean life)

    {

        this.life = life;

    }

    boolean getLife()

    {

        return life;

    }

    void setID(int id)

    {

     itemID = id;

    }

    int getID()

    {

        return itemID;

    }

 float[] getPos()

 {

     return pos;

 }

}

BulletSystem.java

import java.util.Random;

import javax.microedition.m3g.Group;

import javax.microedition.m3g.Transform;

public class BulletSystem

{

 Bullet[] bullet=null;

 int hitnum=0;

 int bulletnum=0;

 private Random rand;

 public BulletSystem(int bulletNum,Group group)

 {

  bullet=new Bullet[bulletNum];

  bulletnum=bulletNum;

  rand=new Random();

  for(int i=0;i<bullet.length;i++)

  {

   bullet[i]=new Bullet(100+i,group,rand);

   //System.out.println("Bullet"+i+"ID:"+bullet[i].getID());

  } 

 }

 public int getBulletnum()

 {

  return bulletnum;

 }

 public boolean getBulletState(int i)

 {

  return bullet[i].getLife();

 }

 public void start(int i,float[] posog,Transform tran)

 {

  bullet[i].init(posog, tran,i==0?true:false);

 }

 public int update(Group group)

 {

  int id=0;

  int temp=0;

  for(int i=0;i<bullet.length;i++)

   {

   if(bullet[i].getLife())

    {

    temp=bullet[i].update(group);

    if(temp!=0)

     id=temp;

    }

   }

  return id;

 }

 public float[] hit(int itemID)

 {

 float pos[]=null;

  for(int i=1;i<bullet.length;i++)

  {

   if(bullet[i].getID()==itemID)

   {

   hitnum++;

   pos=bullet[i].getPos();

   bullet[i].setLife(false);

   }

  }

  return pos;

 }

 int gethitNum()

 {

  return hitnum;

 }

}

 FountainEffect.java

import java.util.Random;

import javax.microedition.m3g.Graphics3D;

import javax.microedition.m3g.Mesh;

import javax.microedition.m3g.Transform;

public class FountainEffect

{

    // The angle of particle emission

    private int angle = 90;

    // The sine and cosine of the current angle

    private float[] trig = {1.0f, 0.0f};

    // The emitting origin

    private float[] initpos = {0.0f, 7.0f, -7.0f};

    private float[] initvel = {0.0f, 0.0f, 0.0f};

    // The randomizer

    Random rand = null;

    // The mesh

    Mesh mesh = null;

    // The transformation matrix

    Transform trans = new Transform();

    // The scale

    //縮放刻度

    float scale = 1.0f;

    public FountainEffect(int angle)

    {

        // Init the bitmap

     scale=0.15f;

     mesh = MeshFactory.createAlphaPlane("/res/particle.png",0xffffff);

        // Set the angle

        setAngle(angle);

        // Get randomizer

        rand = new Random();

    }

    public void update(Particle p)

    {

        float[] ppos = p.getPos();

        float[] vel = p.getVel();

        ppos[0] += vel[0];

        ppos[1] += vel[1];

        ppos[2] += vel[2];

        p.setPos(ppos);

        p.setLife(p.getLife() - p.getDegradation());

        if(p.getLife() < -0.001f)

        {

        // init(p,new float[]{0.0f,3.0f,-5.0f});

         p.setPos(initpos);

            p.setVel(initvel);

        }

    }

    public void render(Particle p, Graphics3D g3d)

    {

        if(p.getLife()>0.01f)

        {

     // Calculate the alpha

        int alpha = (int)(255 * p.getLife());

        // Create the color

        int color = p.getColor() | (alpha << 24);//alpha左移3位元組

        // Set alpha

        MeshOperator.setMeshAlpha(mesh, color);

        // Transform

        trans.setIdentity();

        //使圖檔始終面對錄影機

        float[] pos = p.getPos();

        trans.postTranslate(pos[0], pos[1], pos[2]);

        trans.postRotate(rand.nextFloat()*90, 1.0f, 0.0f, 0.0f);

        trans.postRotate(rand.nextFloat()*90, 0.0f, 0.0f, 1.0f);

        trans.postScale(scale, scale, scale);

       // System.out.print("mesh pos="+pos[0]+","+pos[1]+","+pos[2]);

      //  System.out.println("   life="+p.getLife()+"  col="+alpha);

        // Render

       g3d.render(mesh, trans);

        }

        else

        {

        }

    }

    public void init(Particle p, float[] pos)

    {

//      Set the particle's life

        p.setLife(1.0f);

     p.setPos(pos);

        // Create the particle's velocties

        float[] vel = new float[3];

        //數度從0.1~0.2

        float xyvel = rand.nextFloat() * 0.05f+0.05f;

        // We want the particle to die slowly

        p.setDegradation(xyvel / 3f);

        // Set velocities according to trigonometry with a small deviation

        // ...=1.0f*cos/sin +

        vel[0] = xyvel * trig[1] + rand.nextFloat() * 0.125f-0.0625f;

        vel[1] = xyvel * trig[0] + rand.nextFloat() * 0.025f-0.025f;

        // No movement in depth

        vel[2] = 0.0f;

        // Set the velocity

        p.setVel(vel);

        // Set the random color

        int r = (int)(120 * rand.nextFloat()) + 135;

        int g = (int)(120 * rand.nextFloat()) + 135;

        int b = (int)(120 * rand.nextFloat()) + 135;

        int col = (r << 16) | (g << 8) | b;

        p.setColor(col);

    }

    public void setAngle(int angle)

    {

        this.angle = angle;

        trig[0] = (float)Math.sin(Math.toRadians(angle));

        trig[1] = (float)Math.cos(Math.toRadians(angle));

    }

    public int getAngle() {

        return angle;

    }

}

HighScore.java

import javax.microedition.lcdui.Command;

import javax.microedition.lcdui.CommandListener;

import javax.microedition.lcdui.Displayable;

import javax.microedition.lcdui.Graphics;

import javax.microedition.lcdui.List;

public class HighScore extends List implements CommandListener

{

private AirFighterMIDlet parent = null;

private MainMenu menu = null;

private Command back=new Command("back",Command.BACK,2);

private HighScoreRMS db;

public HighScore(AirFighterMIDlet parent, MainMenu menu)

{

 super("HighScore",List.IMPLICIT);

 this.parent = parent;

 this.menu = menu;

 db=new HighScoreRMS("HighScore");

 db.loadHighScore();

 String[] temp=new String[9];

 temp=db.getHighScore();

 this.append("Level     Seconds     Score",null);

 this.addCommand(back);

 this.setCommandListener(this);

 for(int i=0;i<3;i++)

 {

  //temp=db.gethighscore(i);

  if(i%3==0)

   this.append(" ",null);

  this.append(temp[i*3]+"         "+temp[i*3+1]+"         "+temp[i*3+2],null);

 }

}

protected void paint(Graphics g)

 {

 //Paint the high scores here

 }

public void commandAction(Command p0, Displayable p1)

{

if (p0 == back)

 {

 parent.setDisplayable(menu);

 }

}

HighScoreRMS.java

import javax.microedition.rms.*;

import java.util.*;

import java.io.*;

public class HighScoreRMS extends BaseRMS

{

  private int sound = 0; //0:on;1:off;

  private int shake = 0;  //0:on;1:off;

  private String[] HighScorelist=null;

  public HighScoreRMS(String rmsName)

  {

    super(rmsName);

    HighScorelist=new String[9];

  }

public void loadHighScore()

  {

    try

    {

      // Will call either loadData() or createDefaultData()

      this.open();

      // Add any other neccessary processing, in this case there is none

      // Close

      if (this.getRecordStore() != null)

        this.close();

    }

    catch (Exception e)

    {

      System.out.println("Error loading HighScoreRMS" + e);

    }

  }

  public String[] getHighScore()

  {

    return this.HighScorelist;

  }

  public void updateHighScore(String[] str)

  {

    try

    {

      // load current scores

      this.open();

      // update data

      this.HighScorelist = str;

      // Update High Scores

      updateData();

      // close

      if (this.getRecordStore() != null)

        this.close();

    }

    catch (Exception e)

    {

      System.out.println(this.getRMSName() + "::updateHighScore::" + e);

    }

  }

  protected void loadData() throws Exception

  {

    try

    {

        byte[] record = this.getRecordStore().getRecord(1);

        DataInputStream istream = new DataInputStream(new ByteArrayInputStream(record,0,record.length));

        for(int i=0;i<9;i++)

        {

        HighScorelist[i]=istream.readUTF();

        }

    }

    catch (Exception e)

    {

      throw new Exception (this.getRMSName() + "::loadData::" + e);

    }

  }

  protected void createDefaultData() throws Exception

  {

    try

    {

      ByteArrayOutputStream bstream = new ByteArrayOutputStream(30);

      DataOutputStream ostream = new DataOutputStream(bstream);

      ostream.writeUTF("1");

      ostream.writeUTF("60");

      ostream.writeUTF("300");

      ostream.writeUTF("2");

      ostream.writeUTF("60");

      ostream.writeUTF("200");

      ostream.writeUTF("3");

      ostream.writeUTF("60");

      ostream.writeUTF("100");     

      ostream.flush();

      ostream.close();

      byte[] record = bstream.toByteArray();

      this.getRecordStore().addRecord(record, 0, record.length);

    }

    catch (Exception e)

    {

      throw new Exception(this.getRMSName() + "::createDefaultData::" + e);

    }

  }

protected void updateData() throws Exception

  {

    try

    {

      ByteArrayOutputStream bstream = new ByteArrayOutputStream(30);

      DataOutputStream ostream = new DataOutputStream(bstream);

      for(int i=0;i<9;i++)

       {

          ostream.writeUTF(HighScorelist[i]);

       }

      ostream.flush();

      ostream.close();

      byte[] record = bstream.toByteArray();

      this.getRecordStore().setRecord(1, record, 0, record.length);

    }

    catch(Exception e)

    {

      throw new Exception(this.getRMSName() + "::updateData::" + e);

    }

  }

}

Instructions.java

//Text instructions. Text can be written in constructor or in own method.

//Developer should remember that also instruction texts should be

//internationalized

import javax.microedition.lcdui.*;

public class Instructions extends Form implements CommandListener

{

//Command for going next instruction if needed

private Command more = new Command(Resources.getString(Resources.ID_GAME_MORE),Command.OK, 1);

//Command for going back to the main menu

private Command back = new Command("Back", Command.BACK, 2);

private AirFighterMIDlet parent = null;

private MainMenu menu = null;

public Instructions(String title,AirFighterMIDlet parent, MainMenu menu)

 {

 super(title);

 this.parent = parent;

 this.menu = menu;

 this.addCommand(back);

 this.addCommand(more);

 this.setCommandListener(this);

 this.append("Up:向上旋轉瞄準器;/n" +

   "Down:向下旋轉瞄準器;/n"+

   "Left:向左旋轉瞄準器;/n"+

   "Right:向右旋轉瞄準器;/n"+

   "1(Game_A):向前移動瞄準器;/n"+

   "3(Game_B):向後移動瞄準器;/n"+

   "5(Game_C):向瞄準器;/n"+

   "7(Game_D):向瞄準器./n");

 }

public void commandAction(Command p0, Displayable p1)

 {

 if (p0 == more)

  {

  //go to the next if needed e.g animation

  //parent.setDisplayable(new InstructionAnimation(parent));

  }

 else if (p0 == back)

  {

  parent.setDisplayable(menu);

  }

 }

}

Language.java

import javax.microedition.lcdui.Command;

import javax.microedition.lcdui.CommandListener;

import javax.microedition.lcdui.Displayable;

import javax.microedition.lcdui.Image;

import javax.microedition.lcdui.List;

public class Language extends List implements CommandListener

{

private AirFighterMIDlet parent = null;

private OptionList opt= null;

private LanguageRMS db;

private Command back = new Command("Back", Command.BACK, 2);

private String lang;

public Language(AirFighterMIDlet parent,OptionList optf)

 {

 // TODO Auto-generated constructor stub

 super(Resources.getString(Resources.ID_GAME_LANGUAGE),List.IMPLICIT);

 this.opt = optf;

 this.parent=parent;

 lang=new String();

 db=new LanguageRMS("Language");

 db.loadLanguage();

 lang=db.getlanguage();

 this.addCommand(back);

 this.setCommandListener(this); 

 this.append(Resources.supportedLocales[0],null);

 this.append(Resources.supportedLocales[1],null);

 this.append(Resources.supportedLocales[2],null); 

 this.append(Resources.supportedLocales[3],null); 

 }

public Language(String arg0, int arg1, String[] arg2, Image[] arg3)

 {

 super(arg0, arg1, arg2, arg3);

 // TODO Auto-generated constructor stub

 }

public void commandAction(Command p0, Displayable p1)

{

if (p0==back)

 {

 //System.out.println("Back pressed:");

 //System.out.println(lang);

 db.updateLanguage(lang);

 //System.out.println("After update:"+db.getlanguage());

 parent.setDisplayable(opt);

 }

else

 {

 List lis = (List) p1;

 int idx = lis.getSelectedIndex();

 switch (idx)

  {

  case 0:

   //TODO

   lang=Resources.supportedLocales[0];

   break;

  case 1:

   //TODO

   lang=Resources.supportedLocales[1];

   break;

  case 2:

   //TODO

   lang=Resources.supportedLocales[2];  

   break;

  case 3:

   lang=Resources.supportedLocales[3];

   break;

   //More if needed

  default:

   break;

  }

 //System.out.println("lang:"+lang);

 }

}

}

LanguageRMS.java

import java.io.ByteArrayInputStream;

import java.io.ByteArrayOutputStream;

import java.io.DataInputStream;

import java.io.DataOutputStream;

public class LanguageRMS extends BaseRMS

{

private String lang;

public LanguageRMS(String rmsName)

 {

 // TODO Auto-generated constructor stub

 super(rmsName);

 lang=new String();

 }

public void loadLanguage()

   {

     try

     {

       // Will call either loadData() or createDefaultData()

       this.open();

       // Add any other neccessary processing, in this case there is none

       // Close

       if (this.getRecordStore() != null)

         this.close();

     }

     catch (Exception e)

     {

       System.out.println("Error loading Settings" + e);

     }

   } 

public String getlanguage()

 {

    return this.lang;

  }

public void updateLanguage(String lan)

{

  try

  {

    // load current scores

    this.open();

    // update data

    this.lang =lan;

    // Update High Scores

    updateData();

    // close

    if (this.getRecordStore() != null)

      this.close();

  }

  catch (Exception e)

  {

    System.out.println(this.getRMSName() + "::updateSettings::" + e);

  }

}

protected void createDefaultData() throws Exception

 {

 // TODO Auto-generated method stub

    try

    {

      ByteArrayOutputStream bstream = new ByteArrayOutputStream(20);

      DataOutputStream ostream = new DataOutputStream(bstream);

      ostream.writeUTF("en");

      ostream.flush();

      ostream.close();

      byte[] record = bstream.toByteArray();

      this.getRecordStore().addRecord(record, 0, record.length);

    }

    catch (Exception e)

    {

      throw new Exception(this.getRMSName() + "::createDefaultData::" + e);

    }

 }

void loadData() throws Exception

 {

 // TODO Auto-generated method stub

    try

    {

        byte[] record = this.getRecordStore().getRecord(1);

        DataInputStream istream = new DataInputStream(new ByteArrayInputStream(record,0,record.length));

        lang= istream.readUTF();

    }

    catch (Exception e)

    {

      throw new Exception (this.getRMSName() + "::loadData::" + e);

    }

 }

void updateData() throws Exception

 {

 // TODO Auto-generated method stub

    try

    {

      ByteArrayOutputStream bstream = new ByteArrayOutputStream(20);

      DataOutputStream ostream = new DataOutputStream(bstream);

      ostream.writeUTF(lang);

      ostream.flush();

      ostream.close();

      byte[] record = bstream.toByteArray();

      this.getRecordStore().setRecord(1, record, 0, record.length);

    }

    catch(Exception e)

    {

      throw new Exception(this.getRMSName() + "::updateData::" + e);

    } 

 }

}

MainMenu.java

import javax.microedition.lcdui.*;

public class MainMenu extends List implements CommandListener

{

private AirFighterMIDlet parent=null;

private AirFighterCanvas game=null;

private LanguageRMS dbl;

private String lang;

private final Command exitCommand = new Command("Exit", Command.EXIT, 1);

public MainMenu(String p0, int p1, String[] p2, Image[] p3,AirFighterMIDlet parent)

 {

 super(p0, p1, p2, p3);

 init(parent);

 }

public MainMenu(String p0, int p1, AirFighterMIDlet parent)

 {

 super(p0, p1);

 init(parent);

 }

public void Refreshlang()

 {

 dbl=new LanguageRMS("Language");

 dbl.loadLanguage();

 lang=dbl.getlanguage();  

 this.deleteAll();

 this.append(Resources.getString(lang,Resources.ID_GAME_NEW), null);

 this.append(Resources.getString(lang,Resources.ID_GAME_OPTIONS),null);

 this.append(Resources.getString(lang,Resources.ID_GAME_HIGHSCORES), null);

 this.append(Resources.getString(lang,Resources.ID_GAME_INSTRUCTIONS), null);

 this.append(Resources.getString(lang,Resources.ID_GAME_ABOUT),null);

 this.append(Resources.getString(lang,Resources.ID_GAME_EXIT),null);

 }

public void init(AirFighterMIDlet parent)

 {

 this.parent = parent;

 dbl=new LanguageRMS("Language");

 dbl.loadLanguage();

 lang=dbl.getlanguage(); 

 this.setCommandListener(this);

 //if game paused then "Continue" should be available in

 //selection list

 //These must be with or without icons

 if (game != null && game.isPaused())

 {

 if(!(this.getString(0).equals(new String(Resources.getString(lang,Resources.ID_GAME_CONTINUE)))))

  {

  this.insert(0,Resources.getString(lang,Resources.ID_GAME_CONTINUE),null);

  }

 this.setSelectedIndex(0,true);

 }

 else

 {

 //These must be with or without icons

 this.append(Resources.getString(lang,Resources.ID_GAME_NEW), null);

 this.append(Resources.getString(lang,Resources.ID_GAME_OPTIONS),null);

 this.append(Resources.getString(lang,Resources.ID_GAME_HIGHSCORES), null);

 this.append(Resources.getString(lang,Resources.ID_GAME_INSTRUCTIONS), null);

 this.append(Resources.getString(lang,Resources.ID_GAME_ABOUT),null);

 this.append(Resources.getString(lang,Resources.ID_GAME_EXIT),null);

 }

 }

public void commandAction(Command p0, Displayable p1)

 {

 if(p0 == exitCommand)

 {

 System.out.println("ExitCommand Pressed.");

 parent.setFinished();

   parent.setDisplayable(this);

 }

 else

 {

 List lis = (List)p1;

 String selected =lis.getString(lis.getSelectedIndex());

 System.out.println(selected);

 if (selected.equals(Resources.getString(lang,Resources.ID_GAME_NEW)))

  {

  game = new AirFighterCanvas(parent, this);

  game.addCommand(exitCommand);

  game.setCommandListener(this);

  parent.setDisplayable(game);

  game.start();

  }

 else if (selected.equals(Resources.getString(lang,Resources.ID_GAME_OPTIONS)))

  {

  parent.setDisplayable(new OptionList(Resources.getString(lang,Resources.ID_GAME_OPTIONS),List.IMPLICIT,parent, this));

  }

 else if (selected.equals(Resources.getString(lang,Resources.ID_GAME_HIGHSCORES)))

  {

  parent.setDisplayable(new HighScore(parent,this));

  }

 else if (selected.equals(Resources.getString(lang,Resources.ID_GAME_INSTRUCTIONS)))

  {

  parent.setDisplayable(new Instructions(Resources.getString(lang,Resources.ID_GAME_INSTRUCTIONS),parent,this));

  }

 else if (selected.equals(Resources.getString(lang,Resources.ID_GAME_ABOUT)))

  {

  parent.setDisplayable(new About(Resources.getString(lang,Resources.ID_GAME_ABOUT),parent,this));

  }

 else if (selected.equals(Resources.getString(lang,Resources.ID_GAME_EXIT)))

  {

  parent.notifyDestroyed();

  }

 else if (selected.equals(Resources.getString(lang,Resources.ID_GAME_CONTINUE)))

  {

  if (game != null)

   {

   game.gameContinue();

   parent.setDisplayable(game);

   }

  else

   {}

  }

 }

 }

}

MeshFactory.java

import javax.microedition.lcdui.Image;

import javax.microedition.m3g.Appearance;

import javax.microedition.m3g.Background;

import javax.microedition.m3g.Group;

import javax.microedition.m3g.Image2D;

import javax.microedition.m3g.Loader;

import javax.microedition.m3g.Material;

import javax.microedition.m3g.Mesh;

import javax.microedition.m3g.PolygonMode;

import javax.microedition.m3g.Texture2D;

import javax.microedition.m3g.TriangleStripArray;

import javax.microedition.m3g.VertexArray;

import javax.microedition.m3g.VertexBuffer;

public class MeshFactory {

 private static VertexArray vertexarray; // 頂點數組

 private static VertexBuffer vertexbuff; // 緩沖器

 private static VertexArray texturearray; // 紋理數組

 private static VertexArray normalarray;

 private static Material material;

 private static TriangleStripArray TSArray; // 三角形帶

 private static Appearance appearnce; // 外觀

 private static Texture2D t2d;

 // 底頂點

 private static final byte[] s_plane_v = new byte[]

        { -1, 0, 1,   1, 0, 1,

   1, 0, -1,    -1, 0, -1 };

 private static final int[] s_plane_index = { 0, 1, 3, 2 };

 private static final int[] plane_indices = new int[] { 4 };

 private static final byte[] s_plane_normal = new byte[] {

    0, 1, 0,   0, 1, 0,

      0, 1, 0,   0, 1, 0 };

 // 紋理坐标

 private static final byte[] s_plane_texture = new byte[]{

    0, 1,   1, 1,   1,0,   0, 0 };

//  8 頂點

 private static final byte[] s_vertices =

 {

 // 0 1 2 3

   -1, -1, 1,  1, -1, 1,  -1, 1, 1,  1, 1, 1,

   // 4,6,5,7,

   -1, -1, -1, -1, 1, -1,  1, -1, -1,  1, 1, -1,

   // 2 3 6 7

   -1, 1, 1,  1, 1, 1,  -1, 1, -1,  1, 1, -1,

   // 0,4,1,5,

   -1, -1, 1,  -1,-1, -1,  1,-1, 1,  1,-1, -1,

   // 1 5 3 7

   1, -1, 1,  1, -1, -1,  1, 1, 1,  1, 1, -1,

   // 0,2,4,6

   -1,-1, 1,  -1, 1, 1, -1,-1,-1,  -1, 1, -1,

 };

 // 定義各個面,外觀全部逆時針

 private static final int[] s_indices = { 0, 1, 2, 3,

 4, 5, 6, 7,

 8, 9, 10, 11,

 12, 13, 14, 15,

 16, 17, 18, 19,

 20, 21, 22, 23

 };

 // 面頂點長度

 private static final int[] indices_Length = new int[] { 4, 4, 4, 4, 4, 4 };

 // 紋理坐标

 private static final byte[] s_texture = new byte[] { 0, 1, 1, 1, 0, 0, 1,

   0,

   1, 1, 1, 0, 0, 1, 0, 0,

   0, 0, 0, 1, 1, 0, 1, 1,

   0, 0, 0, 1, 1, 0, 1, 1,

   0, 1, 1, 1, 0, 0, 1, 0,

   1, 1, 1, 0, 0, 1, 0, 0

 };

 // 正方體法線向量

 private static final byte[] s_normal = new byte[] {

 // 0 1 2 3

   0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1,

   // 4,6,5,7,

   0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1,

   // 2 3 6 7

   0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0,

   // 0,4,1,5,

   0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0,

   // 1 5 3 7

   1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0,

   // 0,2,4,6

   -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0,

 };

 public static Group createHeightMap(String path)

 {

 Group group=null;

  try

  {

   group=(Group)Loader.load(path)[0];

   group.postRotate(-90.0f, 1.0f, 0.0f, 0.0f);

  }

  catch (Exception e)

  {

   e.printStackTrace();

  }

 return group;

 }

 public static Group createGoomba(String path)

 {

 Group goomba=null;

  try

  {

   //System.out.println("Loading Aim Model:"+path);

   goomba=(Group)Loader.load(path)[0];

   goomba.postRotate(-90.0f, 1.0f, 0.0f, 0.0f);

  }

  catch (Exception e)

  {

   System.out.println("Model Loadiing ERROR");

   e.printStackTrace();

  }

 return goomba;

 }

 public static Mesh createPlane(String path)

 {

        Mesh mesh=null;

//      頂點矩陣

  vertexarray = new VertexArray(s_plane_v.length / 3, 3, 1);

  vertexarray.set(0, s_plane_v.length / 3, s_plane_v);

  normalarray = new VertexArray(s_plane_normal.length / 3, 3, 1);

  normalarray.set(0, s_plane_normal.length / 3, s_plane_normal);

  // 面三角形條帶

  TSArray = new TriangleStripArray(s_plane_index, plane_indices);// 索引,索引長度

  texturearray = new VertexArray(s_plane_texture.length / 2, 2, 1);

  texturearray.set(0, s_plane_texture.length / 2, s_plane_texture);

  vertexbuff = new VertexBuffer();

  vertexbuff.setPositions(vertexarray, 1.0f, null);

  vertexbuff.setTexCoords(0, texturearray, 1.0f, null);

  vertexbuff.setNormals(normalarray);

  //vertexbuff.setDefaultColor(0xffffffff);

  // 設定多邊形模式設定

  PolygonMode polygonMode = new PolygonMode();

  // 起用透視修正,這樣在多個三角形組成的平面中,紋理就不會彎曲

  polygonMode.setPerspectiveCorrectionEnable(true);

  // 建立紋理

  t2d = createTexture(path);

  // 材料

  material = new Material();

  material.setVertexColorTrackingEnable(true);

  // 生成外貌

  appearnce = new Appearance();

  appearnce.setPolygonMode(polygonMode);

  appearnce.setMaterial(material);

  appearnce.setTexture(0, t2d);

  // 生成網眼

  mesh = new Mesh(vertexbuff, TSArray, appearnce);

  return mesh;

 }

 public static Mesh createSquare(String path)

 {

  Mesh mesh = null;

  // Create vertex data.

  // 頂點矩陣

  vertexarray = new VertexArray(s_vertices.length / 3, 3, 1);

  vertexarray.set(0, s_vertices.length / 3, s_vertices);

  normalarray = new VertexArray(s_normal.length / 3, 3, 1);

  normalarray.set(0, s_normal.length / 3, s_normal);

  // 面三角形條帶

  TSArray = new TriangleStripArray(s_indices, indices_Length);// 索引,索引長度

  texturearray = new VertexArray(s_texture.length / 2, 2, 1);

  texturearray.set(0, s_texture.length / 2, s_texture);

  vertexbuff = new VertexBuffer();

  vertexbuff.setPositions(vertexarray, 1.0f, null);

  vertexbuff.setTexCoords(0, texturearray, 1.0f, null);

  vertexbuff.setNormals(normalarray);

  // 設定多邊形模式設定

  PolygonMode polygonMode = new PolygonMode();

  polygonMode.setCulling(PolygonMode.CULL_BACK);

  polygonMode.setPerspectiveCorrectionEnable(true);

  // 建立紋理

  t2d = createTexture(path);

  // 材料

  material = new Material();

  material.setVertexColorTrackingEnable(true);

  // 生成外貌

  appearnce = new Appearance();

  appearnce.setPolygonMode(polygonMode);

  appearnce.setMaterial(material);

  appearnce.setTexture(0, t2d);

  // appearnce.setFog(fog);

  // 生成網眼

  mesh = new Mesh(vertexbuff, TSArray, appearnce);

  return mesh;

 }

 public static Mesh createAlphaPlane(String path,int alpha)

 {

  Mesh mesh=createPlane(path);

  MeshOperator.convertToBlended(mesh, alpha, Texture2D.FUNC_BLEND);

  return mesh;

 }

 private static Texture2D createTexture(String path)

 {

  Texture2D texture = null;

  try {

   // 載入圖檔

   Image texImg = Image.createImage(path); // Load the image

   // 建立紋理

            //create the texture from the image

   //注意Image2D.RGB /Image2D.RGBA的差別

   texture = new Texture2D(new Image2D(Image2D.RGBA, texImg));

           //  設定混合方式

   texture.setBlending(Texture2D.FUNC_REPLACE);

            //repeat the texture.

   texture.setWrapping(Texture2D.WRAP_CLAMP,Texture2D.WRAP_CLAMP);

   // 設定過濾方式

   texture.setFiltering(Texture2D.FILTER_BASE_LEVEL, Texture2D.FILTER_NEAREST);

  } catch (Exception e) {

   System.out.println("Failed to create texture");

  }

    return texture;

 }

 private static Background createBackground(String path)

 {

  Background background=null;

  return background;

 }

}

MeshOperator.java

import javax.microedition.m3g.CompositingMode;

import javax.microedition.m3g.Mesh;

public class MeshOperator

{

 public static void setMeshAlpha(Mesh m, int alpha)

    {

        m.getVertexBuffer().setDefaultColor(alpha);

    }

    public static void convertToBlended(Mesh m, int alpha, int textureBlending)

    {

        // Set the alpha

        setMeshAlpha(m, alpha);

        // Fix the compositing mode

        CompositingMode cm = new CompositingMode();

        cm.setBlending(CompositingMode.ALPHA);

        m.getAppearance(0).setCompositingMode(cm);

        m.getAppearance(0).getTexture(0).setBlending(textureBlending);

    }

}

OptionList.java

import javax.microedition.lcdui.Command;

import javax.microedition.lcdui.CommandListener;

import javax.microedition.lcdui.Displayable;

import javax.microedition.lcdui.Image;

import javax.microedition.lcdui.List;

public class OptionList extends List implements CommandListener

{

private AirFighterMIDlet parent = null;

private MainMenu menu = null;

private Settings db;

private LanguageRMS dbl;

private String lang;

//private KeyDefinitions def = null;

private Command back = new Command("Back", Command.BACK, 2);

private String[] change;

private int[] sets;

public OptionList(String p0, int p1, String[] p2, Image[] p3,AirFighterMIDlet parent, MainMenu menu)

 {

 super(p0, p1, p2, p3);

 this.menu = menu;

 init(parent);

 }

public OptionList(String p0, int p1, AirFighterMIDlet parent,MainMenu menu)

 {

 super(p0, p1);

 this.menu = menu;

 init(parent);

 }

private void init(AirFighterMIDlet parent)

 {

 //System.out.println("Parent:"+this.parent.toString());

 this.parent = parent;

 dbl=new LanguageRMS("Language");

 dbl.loadLanguage();

 lang=dbl.getlanguage(); 

 //System.out.println("Menu:"+menu.toString());

 //System.out.println("Parent:"+this.parent.toString());

 this.addCommand(back);

 this.setCommandListener(this);

 db=new Settings("Settings");

 db.loadSettings();

 change=new String[2];

 sets=new int[2];

 change[0]=change[1]="OFF";

 sets[0]=db.getsound();

 sets[1]=db.getshake();

 //System.out.println(db.getRMSName());

 //System.out.println("before:"+db.getsound()+" "+db.getshake());

 if(sets[0]==0)

  change[0]="ON";

 if(sets[1]==0)

  change[1]="ON";

 //These are just a examples for the game specific options

 this.append(Resources.getString(lang,Resources.ID_GAME_SOUNDS)+":/t"+change[0],null);

 this.append(Resources.getString(lang,Resources.ID_GAME_VIBRA)+":/t"+change[1],null);

 this.append(Resources.getString(lang,Resources.ID_GAME_LANGUAGE)+":/t",null);

 }

private void setstring(String s0,String s1)

 {

 this.set(0, s0, null);

 this.set(1, s1, null);

 }

public void commandAction(Command p0, Displayable p1)

 {

 if (p0 == back)

  {

  db.updateSettings(sets[0],sets[1]);

  //System.out.println("After:"+db.getsound()+" "+db.getshake());

  parent.setDisplayable(menu);

  menu.Refreshlang();

  }

 else

  {

  List lis = (List) p1;

  int idx = lis.getSelectedIndex();

  switch (idx)

   {

   case 0:

    //TODO

    if(change[0]=="ON")

     {

     sets[0]=1;

     change[0]="OFF";

     }

    else

     {

     sets[0]=0;

     change[0]="ON";

     }

    break;

   case 1:

    //TODO

    if(change[1]=="ON")

     {

     change[1]="OFF";

     sets[1]=1;

     }

    else

     {

     change[1]="ON";

     sets[1]=0;

     }

    break;

   case 2:

    //TODO

    parent.setDisplayable(new Language(parent,this));

    break;

   case 3:

    //parent.setDisplayable(def);

    break;

    //More if needed

   default:

    break;

   }

  setstring(Resources.getString(lang,Resources.ID_GAME_SOUNDS)+":/t"+change[0],Resources.getString(lang,Resources.ID_GAME_VIBRA)+":/t"+change[1]);

  }

 }

}

Particle.java

public class Particle

{

    // The life of the particle. Goes from 1.0f to 0.0f

   // 粒子的壽命. 從 1.0f 到 0.0f

    private float life = 0.001f;

    // The degradation of the particle

    //衰變

    private float degradation = 0.01f;

    // The velocities of the particle

    //速率

    private float[] vel = {0.0f, 0.0f, 0.0f};

    // The position of the particle

    //位置

    private float[] pos = {1.0f, 1.0f, 3.0f};

    // The color of the particle (RGB format 0xRRGGBB)

    //  粒子的顔色 (RGB 形式 0xRRGGBB)

    private int color = 0xffffff;

    public Particle()

    {

    }

    public Particle(float[] velocity, float[] position, int color)

    {

        if((velocity!=null)&&(velocity.length==3))

         setVel(velocity);

        if((position!=null)&&(velocity.length==3))

         setPos(position);

        if(color>=0)

         this.setColor(color);

    }

    void setLife(float life) {

        this.life = life;

    }

    float getLife() {

        return life;

    }

    void setVel(float[] tvel) {

        System.arraycopy(tvel, 0, vel, 0, vel.length);

    }

    float[] getVel() {

        return vel;

    }

    void setPos(float[] tpos) {

        System.arraycopy(tpos, 0, pos, 0, pos.length);

    }

    float[] getPos() {

        return pos;

    }

    void setColor(int color) {

        this.color = color;

    }

    int getColor() {

        return color;

    }

    public void setDegradation(float degradation) {

        this.degradation = degradation;

    }

    public float getDegradation() {

        return degradation;

    }

}

ParticleSystem.java

import javax.microedition.m3g.Graphics3D;

public class ParticleSystem

{

 //效果,接口

    private FountainEffect ft = null;

    // The particles

    //粒子

    Particle[] parts = null;

    public ParticleSystem(FountainEffect effect, int numParticles)

    {

        // Copy the effect

        this.ft = effect; 

        // Init the particles

        parts = new Particle[numParticles];

        for(int i = 0; i < parts.length; i++)

        {

         parts[i] = new Particle();

        }

    }

    public void init(float pos[])

    {

     for(int i = 0; i < parts.length; i++)

        {

            ft.init(parts[i],pos);

        }

    // System.out.println("parts init");

    }

    public void emit(Graphics3D g3d)

    {

        for(int i = 0; i < parts.length; i++)

        {

         ft.update(parts[i]);

         ft.render(parts[i], g3d);          

        }

    }

}

Resources.java

public class Resources

{

// Identifiers for text strings.

public static final int ID_GAME_NEW = 0;

public static final int ID_GAME_OPTIONS = 1;

public static final int ID_GAME_HIGHSCORES = 2;

public static final int ID_GAME_INSTRUCTIONS = 3;

public static final int ID_GAME_ABOUT = 4;

public static final int ID_GAME_CONTINUE = 5;

public static final int ID_GAME_BACK = 6;

public static final int ID_GAME_MORE = 7;

public static final int ID_GAME_EXIT = 8;

public static final int ID_GAME_LEVEL = 9;

public static final int ID_GAME_SOUNDS = 10;

public static final int ID_GAME_VIBRA = 11;

public static final int ID_GAME_NAME = 12;

public static final int ID_GAME_LANGUAGE = 13;

// List of supported locales.

// The strings are Nokia-specific values

// of the "microedition.locale" system property.

public static final String[] supportedLocales ={"en", "fi-FI", "fr", "de"};

//NOTE: default language must be the first one

//for getString to work!

// Strings for each locale, indexed according to the

// contents of supportedLocales

private static final String[][] strings = {

{ "New game",   "Settings",  "High scores",   "Instructions", "About", "Continue", "Back",   "More",  "Exit game","Level",   "Sounds", "Shakes",    "Game name", "Language"},

{ "Uusi peli",   "Asetukset",  "Huipputulokset",  "Peliohjeet", "Tietoja", "Jatka",  "Poistu", "Jatka", "Poistu", "Vaikeusaste",  "Peli??net","V?rin?tehosteet", "Pelin nimi", "Language"},

{ "Nouveau jeu",  "Paramètres",  "Scores",    "Instructions", "A propos", "Continuer","Retour", "Suite",  "Sortir", "Niveau",   "Sons",  "Vibrations",   "Jeu nom",  "Language"},

{ "Neues Spiel",  "Einstellungen","Rekord",    "Anleitung", "über",  "Weiter",  "Zurück", "Weiter", "Beenden", "Ebene",   "Ton",   "Vibrationen",   "Spiel name", "Language"}};

public static String getString(String lang,int key)

{

String locale = lang;

if (locale == null)

 {

 locale = new String(""); // use empty instead of null

 }

// find the index of the locale id

int localeIndex = -1;

for (int i = 0; i < supportedLocales.length; i++)

 {

 if (locale.equals(supportedLocales[i]))

  {

  localeIndex = i;

  break;

  }

 }

// not found

if (localeIndex == -1)

 {

 // defaults to first language, in this example English

 return strings[0][key];

 }

return strings[localeIndex][key];

}

public static String getString(int key)

 {

 String locale = System.getProperty("microedition.locale");

 if (locale == null)

  {

  locale = new String(""); // use empty instead of null

  }

 // find the index of the locale id

 int localeIndex = -1;

 for (int i = 0; i < supportedLocales.length; i++)

  {

  if (locale.equals(supportedLocales[i]))

   {

   localeIndex = i;

   break;

   }

  }

 // not found

 if (localeIndex == -1)

  {

  // defaults to first language, in this example English

  return strings[0][key];

  }

 return strings[localeIndex][key];

 }

}

Seconds.java

public class Seconds extends Thread

{

private int second=0;

private boolean running;

private AirFighterCanvas t;

public Seconds(AirFighterCanvas t)

 {

 this.t=t;

 }

public void start()

 {

 running=true;

 super.start();

 }

public void halt()

 {

 running=false;

 }

public void run()

 {

 while(running)

  {

  second++;

  //t.repaint();

  try

   {

   Thread.sleep(1000);

   }

  catch(InterruptedException ie)

   {

   }

  }

 }

public int getSecond()

 {

 return second;

 }

}

SplashCanvas.java

import java.util.Timer;

import java.util.TimerTask;

import javax.microedition.lcdui.Canvas;

import javax.microedition.lcdui.Graphics;

import javax.microedition.lcdui.Image;

import javax.microedition.lcdui.List;

public class SplashCanvas extends Canvas

{

private AirFighterMIDlet  parent = null;

private MainMenu menu = null;

private Timer timer = null;

private Image img;

public SplashCanvas(AirFighterMIDlet parent)

 {

 this.parent = parent;

 menu = new MainMenu(Resources.getString(Resources.ID_GAME_NAME),List.IMPLICIT, parent);

 startTimer();

 try

 {

 img=Image.createImage("/res/LogoImage.png");

 }

 catch(Exception e)

 {

 System.out.println("Splash Image create Error:"); 

 System.out.println(e.toString());  

 }

 }

protected void paint(Graphics g)

 {//Do the splash screen here

 //gi.setColor(0x1211FF);

 //gi.fillRect(0,0 ,getWidth(),getHeight());

 g.drawImage(img, (this.getWidth()-img.getWidth())/2,(this.getHeight()-img.getHeight())/2,16|4);//16TOP|4LEFT|1HCENTER

 //g.setColor(0,0,0);

 }

protected void keyPressed(int keyCode)

 {

 timer.cancel();

 timer = null;

 //All key events received set the main menu to the screen

 parent.setDisplayable(menu);

 }

//Timer for the splash screen. Main menu is set to the display

//after 5 seconds.

private void startTimer()

 {

 TimerTask task =new TimerTask()

     {public void run()

      {

      parent.setDisplayable(menu);

      }

     };

     timer = new Timer();

     timer.schedule(task, 5000);

 }

}

StarHScroller.java

import javax.microedition.midlet.*;

import javax.microedition.lcdui.*;

import java.util.*;

public class StarHScroller

{

    public final int NUM_STARS = 30;

    public final int WIDTH, HEIGHT;

    public int []posX = new int[NUM_STARS];

    public int []posY = new int[NUM_STARS];

    public int []size = new int[NUM_STARS];

    int[] raw;

    Image image = null;

    Graphics g;

    Random r = new Random();

    int bgColor = 0x00;

    int fgColor = 0xFFFFFF;

    public StarHScroller(int w, int h)

    {

        WIDTH = w;

        HEIGHT = h;

        try

        {

            image = Image.createImage(WIDTH, HEIGHT);

            g = image.getGraphics();

        }

        catch(Exception e)

        {

            e.printStackTrace();

        }

        raw = new int[image.getWidth() * image.getHeight()];

        for(int i=0; i<NUM_STARS; i++)

        {

            size[i] = r.nextInt(2)+1;

            posX[i] = r.nextInt(WIDTH);

            posY[i] = r.nextInt(HEIGHT) + 1;

        }

    }

    private void initStar(int index)

    {

        size[index] = r.nextInt(2)+1;

        posX[index] = -10 + r.nextInt(10);;

        posY[index] = r.nextInt(HEIGHT) + 1;

    }

    public void draw()

    {

        g.setColor(fgColor);

        for(int i=0; i<NUM_STARS; i++)

        {

            g.fillRect(posX[i], posY[i], size[i], size[i]);

            switch(size[i])

            {

                case 1:

                    posX[i] +=1;

                    break;

                case 2:

                    posX[i] +=2;

                    break;

            }

            if(posX[i] > WIDTH)

            {

                initStar(i);

            }

        }

    }

    public byte[] getByteArray(Image image)

    {

     int raw[] = new int[image.getWidth() * image.getHeight()]; 

     image.getRGB(raw, 0, image.getWidth(), 0, 0, image.getWidth(), image.getHeight()); 

     byte rawByte[] = new byte[image.getWidth() * image.getHeight() * 4];  int n = 0; 

     for(int i = 0; i < raw.length; i++) 

     {  

      // break up into channels  

      int ARGB = raw[i];  

      int a = (ARGB & 0xff000000) >> 24; // alpha channel!  

      int r = (ARGB & 0xff0000) >> 16;   // red channel!  

      int g = (ARGB & 0x0000ff00) >> 8;  // green channel!  

      int b = ARGB & 0x000000ff;     // blue channel !     

      rawByte[n] = (byte)b;  

      rawByte[n + 1] = (byte)g;  

      rawByte[n + 2] = (byte)r;  

      rawByte[n + 3] = (byte)a;    

      // you can see these codes 

      // from "http://forum.java.sun.com/thread.jspa?forumID=76&threadID=629677"  

      // put the color back together  

      //argb = ((a << 24) | (r << 16) | (g << 8) | b);  

      n += 4; 

     }  

     raw = null; 

     return rawByte;

    }

    public void updateImage()

    { 

     g.setColor(bgColor);

        g.fillRect(0, 0, image.getWidth(), image.getHeight());

        g.setColor(fgColor);

        draw();

    }

    public Image getImage()

    { 

     g.setColor(bgColor);

        g.fillRect(0, 0, image.getWidth(), image.getHeight());

        g.setColor(fgColor);

        draw();

        return image;

    }

}