• 软件测试技术
  • 软件测试博客
  • 软件测试视频
  • 开源软件测试技术
  • 软件测试论坛
  • 软件测试沙龙
  • 软件测试资料下载
  • 软件测试杂志
  • 软件测试人才招聘
    暂时没有公告

字号: | 推荐给好友 上一篇 | 下一篇

简单的游戏结构

发布: 2007-4-28 23:35 | 作者: fantasydog | 来源: fantasydog的专栏 | 查看: 130次 | 进入软件测试论坛讨论

领测软件测试网

MILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">一般来说,最常用的游戏结构是这样的:游戏开始后即进入一个循环,每次循环做三件事情:

1.       获取玩家的输入。

2.       更新游戏状态。

3.       刷新屏幕。

理论上说,刷屏的频率在24Hz以上,人的眼睛看到的就是动画了。

 

这个例子游戏的主循环是这样的:

public void run() {

Graphics g = getGraphics();

Thread currentThread = Thread.currentThread();

try {

while (currentThread == gameThread) {

long startTime = System.currentTimeMillis();

if (isShown()) {

if (isPlay) {

tick();

}

render(g);

}

long timeTake = System.currentTimeMillis() - startTime;

if (timeTake < MILLIS_PER_TICK) {

synchronized (this) {

wait(MILLIS_PER_TICK - timeTake);

}

} else {

currentThread.yield();

}

}

} catch (InterruptedException ex) {

// won't be thrown

}

}

 

说明:

1.       两个threadcurrentThread当然就是当前执行的这个线程,那么gameThread当然也就是运行这个run方法的线程(不然while一开始就不成立,游戏就没法运行了^_^)。这里它们的作用是控制游戏的循环,当一开始运行时,currentThread==gameThread,循环下去;当游戏需要退出时,将gameThread(类成员)设置为null,那么循环结束,游戏就退出了。强制结束某个线程是很不好的方法,sun的标准库里早就deprecate这个方法了。

2.       tick方法:处理玩家的输入以及游戏状态的变更。

3.       render方法:顾名思义,绘图。这里MIDP2.0相对于1.0有很大的改进,后面说。

4.       几个long型的time的用处。代码看起来很直观,就是考虑到tickrender方法执行时间可能不固定,用time加以计算,得到需要sleep的时间。这样的结果就是游戏画面以一个固定的延时刷新,FixedDelay。当然,还有另外一种控制方式,即固定频率的刷新,FixedRate

a)         FixedDelay:固定延时的好处是画面看起来总是很流畅,而且一定不会出现跳帧的现象。

b)        FixedRate:在一种情况下和FixedDelay有差别,即tickrender方法消耗的时间比预设的时间(MILLIS_PER_TICK)还长。FixedDelay这时不再wait,直接绘制下一幅图;而FixedRate就不能绘了,否则频率不固定。它的选择是不绘这一幅,而是直接进入下一个循环,更新游戏状态,综合计算时间,绘下一幅图——于是产生了跳帧。

CS或星际这样的游戏,跳帧是必须的,因为联机游戏必须保证各方的图像显示的同步,不固定刷新频率会导致错误。而像仙剑之类的单机游戏倒是可以考虑用固定延时,因为不跳帧不会产生什么错误,同时也可以增加游戏画面的流畅性。

      

       绘图:

       private void render(Graphics g) {

        // Set Background color to beige

        g.setColor(0xF8DDBE);

        g.fillRect(0, 0, width, height);

        g.setColor(0x0000ff);

        // LayerManager Paint Graphics

        layerManager.paint(g, 0, 0);

        flushGraphics();

}

MIDP1.0里面,Canvas的绘图只能写在paint(Graphics g)方法里,因为一来g参数在此方法结束后就没有意义了,保留它的副本没有用处;二来此方法由平台调用,而不是由Canvas这个线程调用。因此在MIDP里绘图总是一件很痛苦的事情,特别是需要保证Canvas线程与调用paint的那个线程同步(J2meSpecification说的是,可以保证你repaint了以后,paint方法在之后的某个时刻被调用,但不能保证马上就被调用,因为paint是个比较耗时的方法,它无法确定其他的paint是否及时完成了)。

MIDP2.0里,有所改进了。首先是你可以通过GameCanvas的一个方法getGraphics来获取那个g,然后这个g就永不失效了(当然是在这个GameCanvas的生命周期内)。当然,这个g1.0里的还是有所区别。这个g实际上是画在一块缓冲“画布”上,即内存里。完全画好以后,再用flushGraphics刷到屏幕上。缓冲的好处是可以让屏幕在画时不显得闪烁,很有用的东西。flushGraphics还有另外一个作用,就是强制输出,以达到显示的那个线程与游戏控制线程的同步(这也是为什么做时间协调时,要把显示方法所消耗的时间也计算进来)。

Tick…………暂时先不讨论。



延伸阅读

文章来源于领测软件测试网 https://www.ltesting.net/


关于领测软件测试网 | 领测软件测试网合作伙伴 | 广告服务 | 投稿指南 | 联系我们 | 网站地图 | 友情链接
版权所有(C) 2003-2010 TestAge(领测软件测试网)|领测国际科技(北京)有限公司|软件测试工程师培训网 All Rights Reserved
北京市海淀区中关村南大街9号北京理工科技大厦1402室 京ICP备2023014753号-2
技术支持和业务联系:info@testage.com.cn 电话:010-51297073

软件测试 | 领测国际ISTQBISTQB官网TMMiTMMi认证国际软件测试工程师认证领测软件测试网