频道直达:新闻 - 组网 - 安全 - 服务器 - 存储 - 系统 - 应用 - 开发 - 数据库 - 前沿 - 技术人 - 培训 - 求职 - 读书 - 教程 - 专题 - 产品 - 案例 - 技术圈 - 博客 - BBS
51CTO.COM_中国领先的IT技术网站
找资料:

J2ME专业手机游戏开发基础(1)

作者: N5 出处:Csdn博客 2007-08-06 10:10    砖    好    评论   进入论坛
阅读提示:本文从游戏的基本结构讲起,接着说明了游戏循环的实现和基本进入界面的基本实现原理,供大家参考!

【引自N5的博客】游戏的基本结构

游戏是什么呢?在游戏中,往往是显示各种各样的画面,玩家可以做一些设定好的控制,画面根据玩家的控制有所变化。从这儿可以看出,游戏至少需要三个功能-显示画面,接受玩家输入和对输入产生反馈。这就是常说的渲染,输入输出和逻辑三个模块。将这三个模块组合在一起有很多方法。比如事件驱动-画面保持不变直到接受到输入事件,程序进行逻辑运算然后改变画面。而游戏往往不是这样,游戏是时间驱动的。也就是说无论有没有输入,游戏都在不停的循环-检查是否有输入,运行逻辑,渲染画面。这里我多说一句,其实什么样的结构并不能区别一个程序是不是游戏,其实只要可以互动娱乐的程序就可以称为游戏,也不一定要用时间驱动,但采用时间驱动是专业游戏的普遍做法,也是很容易接受的方法-因为从一定程度上讲,游戏很像电影,随着时间流逝画面在改变。

既然是时间驱动,游戏中就会有帧的概念。所谓帧就是某个时刻显示在屏幕上的画面。从整体上看,游戏就是一系列的帧不断播放着,像动画片一样,不过玩家可以通过交互改变播放的内容。而我们开发游戏的主要任务就是安排每一帧的内容。在每一次游戏循环中,我们需要搜集玩家的输入、运行逻辑以更新游戏的数据、根据更新后的数据安排下一帧显示的内容。 所以一个最简单的游戏结构就是:

0 初始化游戏
1 是否结束游戏(Yes:转到6)
2 搜集玩家输入信息
3 运行游戏逻辑
4 更新下一帧,显示下一帧
5 回到1
6 清理,结束游戏

这是一个最基本的结构,特别对于比较简单的J2ME游戏来说,这个结构更加有代表性。下面我们将分别讲述专业手机游戏如何实现这个结构中的各个内容。

游戏循环的实现

我们需要一个进入后就一直循环下去直到游戏结束的结构。线程正好可以实现。最通常的做法是让Canvas实现Runnable接口。于是我们就可以实现run方法。下面是一个run方法简化版:

public void run()
{
exitMidlet = false ;
long startTime = 0 ;
long timeCount = 0 ;
gameInit() ;
int curKey = 0 ;
while (!exitMidlet) {
startTime = System.currentTimeMillis();
//acquire key
acquireKey() ;
//call game loop
gameLoop() ;
//repaint the screen
repaint();
serviceRepaints(); 

frameCount++ ;  

//lock fps 
timeCount = MIN_DELAY - (System.currentTimeMillis() - startTime);
timeCount = (timeCount<1)?1:timeCount ; 
try {
Thread.sleep(timeCount);
} catch (InterruptedException ex) {}
}
endMidlet() ;
}

看到我们的while循环了吗?除非在程序逻辑中设定exitMidlet为true-那是当玩家选择了退出游戏,我们的游戏将一直运行下去。在while循环之前,gameInit方法的作用是进行游戏初始化-比如初始化变量值,载入全局数据,生成全局对象等。在while循环中,我们先是调用了acquireKey方法,这个方法将键盘输入信息进行缓冲以便逻辑中判断按键状态,下面讲会讲到键盘缓冲。gameLoop是我们游戏的主体,每帧中的逻辑运算,图形处理都在这里面进行。然后是repaint和serviceRepaints,刷新屏幕-新的一帧呈现在屏幕上。最后当跳出while之后,我们执行endMidlet结束这个Midlet。endMidlet的内容只是调用了destroyApp和notifyDestroyed方法。好了整个游戏循环就是这样了,下面讲分别讲述键盘缓冲和gameLoop如何组织。不过再这之前先让我解释下lock fps。FPS就是Frame per second。为了防止游戏在不同的机器上速度变化太大,我们设定一个最大的FPS值,或者说设置一个每帧至少要花费的时间(这里的MIN_DELAY)。比如我们设置MIN_DELAY=50,那么max FPS = 1000/50 = 20 帧/秒。锁定FPS有多种方法,这里的方法是判断如果一帧所有的时间还没达到最大时间,那么就让线程sleep一会儿。顺便在说一下FPS的计算,顾名思义用1000除以一帧所有时间即可,不过要注意的是,一般计算的FPS是平均FPS,所以FPS=累计帧数*1000/累计花费时间。

键盘缓冲

搜集玩家输入信息是一个很重要的内容,我们知道J2ME中可以在keyPressed和keyReleased事件中处理按键内容,但这样势必将逻辑代码分散与gameLoop和keyPressed中。如果你说将所有逻辑代码放在keyPressed中,那可不行,因为keyPressed只有在按键的时候才产生,而即使没有按键游戏也有很多逻辑运算要做。所以专业游戏开发中采用键盘缓冲将按键信息存起来,然后在gameLoop中就可以判断这一帧按键的状态,利用按键缓冲,除了可以判断一个键是否按下松开,还可以判断一个键是否一直被按住了,甚至可以判断组合键。不过在这里,我只介绍一种最简单的按键缓冲。由于篇幅所限,只讲述原理并不给出具体代码。

首先我们需要一个数据结构存储按键信息。你可以为每个键用一个bool值存储它的状态,不过专业一点的做法是用一个位表示一个键的状态,一个int有32个位,足够表示大多数手机的所有按键了。因为我们要判断键是否按下或松开,为了方便,我们再用2个整数记录这两种状态。所以现在我们一共有三个int了:

static int key , pressedKey, releasedKey ;

OK! 有了存储的地方,我们还需要一些常量表示每个位,我们设定key中某个位为0表示某键没有按下,为1表示按下。如果用第1位表示0键,第2位表示1键,那么可以这样设置常量:

final static int GKEY_0=1<<0, GKEY_1=1<<1 ;

明白了吗?这些常量是用来指定某个位用的,比如GKEY_1其实就是第2为1其它位均为0的一个整数。如果还不明白,先看下面的。

keyPressed和keyReleased里将分别将按下的键和松开的键进行记录。

public void keyPressed(int keyCode)
{
int value = getKeyValue(keyCode) ;
key |= value ;
pressedKey |= value ;
}

public void keyReleased(int keyCode)
{
int value = getKeyValue(keyCode) ;
key ^= value ;
releasedKey |= value ;
}

在keyPressed里面,我们先将keyCode转换成我们的按键常量,就是上面的GKEY_0等。因为keyCode可不是像我们的常量那样可以用某个位表示的,而且不同手机的keyCode是有可能不一样的,所以我们必须用一个函数getKeyValue进行转化。得到常量后key|=value的作用是将key里面常量所代表的位置1,现在你应该明白常量的作用了吧!pressedKey|=value同理。不过keyReleased有些不同,由于releasedKey只记录这一帧里哪些键“被松开”了,所以仍然用或运算。但key是记录整个按键的状态,所以用异或。

接下来就是如何判断按键状态了:

private static void acquireKey()
{
frameKey = key ;
framePressedKey = pressedKey ;
frameReleasedKey = releasedKey ;    
pressedKey = 0 ;
releasedKey = 0 ;
}    

public static boolean keyHold(int gameKey)
{
return ((frameKey & gameKey)!=0) ;
}    

public static boolean keyDown(int gameKey)
{    
return ((framePressedKey & gameKey)!=0) ;
}    

public static boolean keyUp(int gameKey)
{
return ((frameReleasedKey & gameKey)!=0) ;
}

还记得acquireKey吧,我们在while循环中首先要调用它,其作用就是记录下这一帧的按键状态,所有我们用了三个新int变量记录他们,分别是frameKey,framePressedKey和frameReleasedKey。acquireKey所做的就是将按键状态记录在这3个变量中,其实framePressedKey和frameReleasedKey不是必须的,只是这样看上去比较清楚。记录完后我们将pressedKey和releasedKey清空,以便下次有键按下或松开时记录新的信息。关键的三个函数登场了,keyDown判断某个键是否在这一帧里被按下,参数gameKey是我们定义的按键常量中的某个值。如果对位运算还算明白的话,很容易看懂这3个函数。唯一要说明的就是keyHold和keyDown的区别,keyHold表示某个键一直被按着,也就是至少从前一帧开始它就被按下了,而不是在这一帧里被按下的。现在你应该明白我们为什么要清空pressedKey和releasedKey了。

说到这里也差不多了,有了这个按键缓冲我们就可以在gameLoop中调用keyDown等方法判断按键的状态了。不过我还是要说一句,这只是最简单的按键缓冲,只能缓冲一次按键,如果一个键被多次按下就不行啦。更专业的内容需要你在实际工作中探索。


共2页: 1 [2] 下一页
【内容导航】
专题
J2ME手机开发技术基础
手机病毒揭密
J2ME游戏开发应用
J2ME开发应用
初探敏捷开发
我也说两句

匿名发表

(如果看不清请点击图片进行更换)


中 国 领 先 的 IT 技 术 网 站 ·
技 术 成 就 梦 想
·Java基础教程 (查看81024次)
·UML类图详解 (查看72498次)
·C++是垃圾语言?! (查看42631次)
·C#技术开发指南 (查看40232次)
·UML统一建模语言 (查看39205次)
·Java编程开发手册 (1198个砖)
·Java基础教程 (431个砖)
·C#技术开发指南 (311个砖)
·.NET开发手册 (254个砖)
·PB开发教程 (223个砖)
·Java编程开发手册 (658个好)
·Java基础教程 (578个好)
·.NET开发手册 (282个好)
·PB开发教程 (213个好)
·Delphi开发技术手册 (200个好)
订阅技术快讯
电子杂志下载
名称:SQL Server数据库管理精品黄皮书
简介:书中文章经过精挑细选,便于用户能根据自己的实际工作和学习,快速在本书寻找到相关资料。内容涵盖了SQL Server的安装与升级、语句查询、数据备份和恢复、自动化任务、数据同步、数据字典、安全和预防、性能和优化、集群等各方面应用信息,以及DBA管理人员在数据库管理工作中
名称:2007路由技术大全
简介:《2007路由技术大全》由51CTO.com网站特别策划制作,该书包括路由器技术、路由器产品、路由器配置、安全设置、路由器故障处理、路由器密码恢复,以及广大网友在实践使用中的心得经验和技巧文章,内容注重实用性,适用于初学者入门,也适合多年从业者提高,是一本实践和理论完
名称:网络安全精品应用黄皮书
简介:《2007精品网络安全黄皮书》包括了9个大类24个小类, 800余篇文章,内容包含了熊猫烧香病毒、DDOS攻击、ARP病等热点问题的介绍及解决方案。从病毒查杀、防范、系统、数据等各方面的安全设置到黑客技术的了解、防范,涉及到了安全应用的全部领域, 由浅至深内容全面。