冰浪

哥已不再年轻 - 坚定梦想,毕生追求!
posts - 85, comments - 90, trackbacks - 0, articles - 3
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

j2me游戏引擎程序结构

Posted on 2009-04-09 09:15 冰浪 阅读(120) 评论(0)  编辑  收藏 所属分类: J2ME

唐良

       游戏引擎的结构很多,不过基本上都是在一个游戏主循环内实现。程序里面的主循环包含了程序框架的最主要的结构体。J2me的程序一般都包含两个class文件,一个是MIDlet,一个是Displayable。一般我都是把游戏的主要代码放在Displayable这个类里面。这个类是基于事件驱动的程序,有三个主要相应函数void paint(Graphics g),void keyPressed(int keyCode),void keyReleased(int keyCode)

 

1.         使用Runnable和创建线程的主循环

一般主体的做法就是让Displayable这个类实现Runnable这个接口,然后在其构造函数中创建一个线程,启动其run()函数,run函数里面就包含了游戏的主循环。下面是我在仙剑里面的片断代码。

 

public class GameMIDlet extends MIDlet {

 static GameMIDlet instance;

 Display display;

 GameDisplayable displayable = null;

 

 public GameMIDlet() {

    instance = this;

    display = Display.getDisplay(this);

    displayable = new GameDisplayable();

 }

 

 public void startApp() {

    display.setCurrent(displayable);

 }

 

 public void pauseApp() {

 }

 

 public void destroyApp(boolean unconditional) {

    displayable.running = false;

 }

 

 public static void quitApp() {

    instance.destroyApp(true);

    instance.notifyDestroyed();

    instance = null;

 }

}

 

public class GameDisplayable extends FullCanvas implements Runnable {

 /** 主控制线程 */

 Thread MainThread = null;

 /** 游戏时钟间隔 毫秒为单位 */

 public static long timeinterval = 20;

 public static boolean Isstable = true;

 

 /* 用于游戏时钟的变量 */

 public static long timeold = 0;

 public static long timenow = 0;

 public long interval = 0;

 public static long frames_per_second = 0;

 int count = 0;

 long second = 0;

 public static boolean running = true;

public GameDisplayable() {

     // 开始主线程

    Thread MainThread = new Thread(this);

    MainThread.start();

 }

public void run() {

    while (running) {

      timenow = System.currentTimeMillis();

      interval = timenow - timeold;

 

      if (interval >= timeinterval) {

        timeold = timenow;

        Game_Process();

        if (second != (System.currentTimeMillis() / 1000)) {

          second = System.currentTimeMillis() / 1000;

          frames_per_second = count;

          count = 1;

        }

        else

          count++;

      }

      lib.sleep(30);

    }

 

 }

 

其中关于控制主循环速度的代码可以不要,但是lib.sleep(30)必须保留,因为在Nokia 60的手机上,如果去除了sleep(30),那么游戏将无法切换回来。同时,在游戏中任何一个内部循环中,也必须加入sleep(30)这个等待,才能让游戏可以切换回来,至于为什么这样做,我暂时还不清楚。30ms是我测试过没有问题的数值,可能比30ms还小的值也是没有问题的。

 

同时,在MOTO的手机上,必须将游戏的主循环放在一个线程中,游戏才能切换回来,不过可以不加上面说的sleep(30)延时。

 

2.         不使用线程的主循环办法

这个办法只能在Nokia的平台上实现,而我只建议在Nokia 40的平台上做,这样不需要线程,道理上来说节约了一些内存,如果不是内存很紧张的机型,那么最好还是使用上一种办法。

 

游戏的主循环放在MIDletclass里面,具体做法如下:

public class GameMIDlet extends MIDlet {

 GameDisplayable displayable = null;

 

 /** 游戏时钟间隔 毫秒为单位 */

 public static long timeinterval = 0;

 //用于游戏时钟的变量

 public static long timeold = 0;

 public static long timenow = 0;

 public long interval = 0;

 public static long frames_per_second=0;

 int count=0;

 long second =0;

 public static boolean running = false;

 static boolean exitApp =false;

 

 public GameMIDlet() {

    displayable = new GameDisplayable();

    running =true;

 }

 

 public void startApp() {

    running =true;

    Display.getDisplay(this).setCurrent(displayable);

    while(running) {

      timenow = System.currentTimeMillis();

      interval = timenow - timeold;

      if (interval >= timeinterval) {

        timeold = timenow;

        displayable.Game_Process();

        if(second != (System.currentTimeMillis() /1000)){

            second = System.currentTimeMillis()/1000;

            frames_per_second = count;

            count = 1;

          }else

            count ++;

      }

    }

    if(exitApp) {

      destroyApp(true);

      notifyDestroyed();

    }

 

 }

 

 public void pauseApp() {

    running =false;

 }

 

 public void destroyApp(boolean unconditional) {

    running = false;

 }

 

 public static void quitApp() {

    running =false;

    exitApp =true;

 }

 

}


只有注册用户登录后才能发表评论。


网站导航: