j2me游戏教程(2)什么是状态机,怎样在上次的代码中建立状态机,什么是FPS?

在讲述如何构建一个无限循环,来反复不停的往屏幕上绘图的程序之前,
先说一下什么是状态机。
(都是按我自己的理解来的,和实际可能有出入!)
首先需要一台不断提供能量的机器。
一个while循环就可以做到这一点。
while (true) {
  做事。
}

那么不管这事是什么,都可以一直做下去。
机器就有了。
那么状态是咋回事?
就是你把好多事放到这个机器里,一会叫做这个,一会叫做那个。
如果增添一套比较成熟的管理方式,那么就是一个非常完整的状态机了.
举个例子:
while (true) {
        第一, 画一个三角。
  第二,画一个方块。
}

程序先画三角,再画方块,每一次循环中,两件事同时做。
加个控制变量把他们分开。
state = 第一
while (true) {
        if (state == 第一) {
                画三角。
        } else if (state == 第二) {
                画方块。
        }
}

(Java里,用=号来赋值,用==来做比较)
现在程序总是在画三角,因为每一次循环总是在画三角。
如果在画了三角有5分钟左右,就想让画方块,代码这样写:
state = 第一
while (true) {
        if (state == 第一) {
                画三角。
                if (画了五分钟) {
                  state = 第二
                }
        } else if (state == 第二) {
                画方块。
        }
}

这样,程序会先画5分钟三角,再一直画方块.
大概清楚了么?
一个while循环,然后使用"状态"来控制做不同事,就构成了状态机。
整个游戏都是一个状态机。
比如,游戏一开始画logo
按了5键,转到画菜单。
再按5,转到画场景。
还有所谓的AI,也是一个状态机的方式,以后再说了。
————————————–
现在先看一下再JBuilder的那个项目中,如果构造这样一个状态机,要这么这么这么:
加个方法,
  public void run() {
    while (true) {
System.out.println("xx");//这句话的意思是在控制台打印xx
      //以后可以自在这里面可以写自己的事情.
    }
  }
然后在类名处,写成这样一个:
以前是这样
public class Game extends Canvas implements CommandListener {
现在变成这样:
public class Game extends Canvas implements Runnable, CommandListener {
多加了一个Runnable接口.
然后在
GameMidlet这一句
    Display.getDisplay(this).setCurrent(displayable);
后面添上
                new Thread(displayable).start();
就行了.
现在运行一下,然后按模拟器上的Select按钮。
如果看到控制台不断有xx打印出来,就是成功了。
————————————-
刚才这几个步骤的意思是,
通过implements Runnable 把Game这个Canvas变成一个线程。
然后通过
new Thread(displayable).start();
使这个线程运行。
这个线程运行之后,就会自动调用run方法。
而我们在run里面搞了一个无限的循环,这就构成了一个状态机了。

等于说,我们的状态机,是运行在另一个线程之中。
而不会干扰系统的方法调用。

如果你用一个普通的方法构建状态机,然后调用,类似这样:

在class Game不实现Runnable接口
只在里面加一个gogogo()方法:
public void gogogo() {
        while (true) {

        }

 
}

然后在GameMidlet这一句
    Display.getDisplay(this).setCurrent(displayable);
后面添上
                displayable.gogogo();

这就完蛋了.因为gogogo里面有个无限循环,系统永远退不出
startApp()这个方法了。

如果使用线程,就不会产生这种情况。无限循环是在另一个线程独立运行的。
(java怎么实现的,估计还要看点儿线程之类的书了,可以不用搞那么深入。)

这样系统该掉其他方法,还会掉其他方法。

先动手做一下,再往下看。

————————————————

现在可以说说桢的概念了。英文叫做Frame.
可以这样理解:
while (true) {
开始

如果 (***) 干这干那
否则如果 (yyy) 干那干这

结束

 
}

这从 开始,到 结束
的一个过程,也就是一次循环,叫做一桢。
每一桢用的时间,叫做SPF (Second per frame)
倒过来,每秒运行的桢数,叫FPS (Frame per second)

打CS的时候,有的版本可以看到屏幕上画着 FPS:
后面一个数字,不停的变。
这个东西越高越好,表示游戏速度越快。

怎么计算FPS:
在开始的时候记录一下系统时间,在结束的时候又记录一下系统时间,
两个时间一减,就知道这一桢用的时间了(SPF)。 1/SPF
就是FPS.

限桢的概念:
有时候一个循环奇快,有时候一个循环奇慢.
打游戏的时候, 你看着画面时快时慢, 肯定不中.
就要限制一下.
先规定好一个FPS,假如是每秒20桢,那么一桢用的时间就是50毫秒。
在 结束
的地方,判断,如果这一桢用的时间小于50毫秒,记录下还差多少时间到50毫秒,
然后就让程序睡觉,睡够这个差值,使这一桢整体使用的时间达到50毫秒。

这样平均下来游戏的FPS就是20,很稳定。

如果一桢的时间超出了50毫秒,那就没办法了。这就是游戏运行慢的原因,这时要想办法看看是做了什么事,导致程序运行缓慢。

魔兽肯定采用了比较高级的控制FPS的方法,如果卡,他就使用很低的FPS,不卡了之后,他就用很快的FPS补上。
这样看起来游戏
在网络速度不好的情况下,很迟钝的样子,然后再网络速度好了以后,刷刷刷运行的飞快。
神奇的是,他们能计算出桢的速度变化。

都是我的猜测而已了。

大概明白了没有?没有就说。

作业来了,试着写一下计算FPS的代码,把FPS打印到控制台。
有啥问题问哦。

下次,讲一下绘图的系统方法是怎么个调用流程。如何绘制图形到屏幕上。怎么察看相关的API文档。

 

 加个方法,
 public void run() {
   while (true) {

System.out.println("xx");//这句话的意思是在控制台打印xx
     //以后可以自在这里面可以写自己的事情.
   }
 }

的意思是在Game.java里加。