GameCanvas类
GameCanvas类
继承于MIDP 1.0的Canvas类的GameCanvas是一个提供了游戏的基本接口的抽象类,除了完全具备原来Canvas类的功能外,还提供了更多开发游戏的便 利,主要为:提供屏幕缓冲绘制机制,并能直接得到设备键盘的物理状态。
3.2.1 GameCanvas概述
GameCanvas(游戏画布)对象能够提供画布的功能,类的定义为:
public abstract class GameCanvas extends Canvas
GameCanvas类是在Canvas类的基础上派生的,并在此之上增加双缓冲和随时查询按键状态的功能。 因为游戏画布类被定义为虚类,所以必须派生新类。GameCanvas类包含的方法如表3-1所示。
表3-1 类GameCanvas方法说明
方 法 名 称 |
方法原型与作用 |
GameCanvas |
protected GameCanvas(boolean suppressKeyEvents) 构造方法,参数 suppressKeyEvents 表示是否需要处理游戏按键之外的其他按键事件。例如数字键,如果此参数为false,那么按键事件处理方法keyPressed、 keyRepeated、keyReleased在程序运行过程中不会被调用,这样可以提高速度和性能 |
getGraphics |
protected Graphics getGraphics( ) 得到画布中脱机屏幕上用于绘制的 Graphics 对象 |
flushGraphics |
public void flushGraphics( ) 要求刷新屏幕,这时脱机屏幕上的图像会被绘制到真实屏幕上 |
flushGraphics |
public void flushGraphics(int x, int y, int width, int height) 要求刷新屏幕上指定区域,这时脱机屏幕上指定区域的图像会被绘制到真实屏幕上 |
getKeyStates |
public int getKeyStates() 得到当前按键状态 |
3.2.2 绘制双缓冲区
要创建一个新的GameCanvas实例,需要通过继承并调用父类的构造函数,如下所示。
protected GameCanvas(boolean suppressKeyEvents);
GameCanvas为这个类的每个实例提供了惟一的图形缓冲区,所有的图形创建和修改都在缓冲区上进行,缓 冲区的大小和GameCanvas全屏幕时的大小一样,但是存在的Ticker或者Command等控件都会影响到GameCanvas的大小。 GameCanvas的当前大小可以通过调用getWidth()和getHeight()方法获得。缓冲区的颜色初始化为白色。
开发者可以调用从GameCanvas实例获得其对应的Graphics对象,而且只有对Graphics对 象操作,才会修改缓冲区的内容,外部资源如其他的MIDlet或者系统级的通知都不会导致缓冲区内容改变。
每一个GameCanvas所拥有的缓冲区都是独立的,考虑到尽量少地使用对象堆栈,最好在游戏中仅仅创建一 个GameCanvas,并且重复利用。
为了将缓冲区中的内容刷新到屏幕上,所需要做的只是先调用getGraphics()方法,获得用来绘制缓冲 区的Graphics对象。刚创建的Graphics对象具有以下默认属性。
n 绘制目标是这个GameCanvas的缓冲区。
n 绘制区域覆盖整个缓冲区。
n 当前颜色是黑色。
n 字体和调用Font.getDefaultFont()返回的相同。
n 绘图模式为SOLID。
n 坐标系统的原点定位在缓冲区的左上角。
返回的Graphics对象将用于绘制属于这个GameCanvas的后备屏幕缓冲区(off-screen buffer),但是绘制后的结果不会立即显示出来,直到调用flushGraphics()方法,将缓冲区中的内容一起绘制到屏幕上去。
注意 |
每一次调用getGraphics()都会返回一个新的Graphics 对象,对于同一个GameCanvas,返回的Graphics 对象都是针对同一个缓冲区,所以应当在游戏运行前获得并保存Graphics 对象,然后在游戏运行时重复使用。getGraphics()返回一个用以绘制GameCanvas缓冲区的Graphics 对象,对于缓冲区的绘制不会改变屏幕的内容,只有调用flushGraphics()才将缓冲区中的内容绘制到屏幕上去。 |
flushGraphics()方法将后备屏幕缓冲区的内容输出到显示屏幕上,输出的区域大小和 GameCanvas的大小相同。
绘制实际屏幕的操作不会改变后备屏幕的内容,这个方法会一直等到绘制操作完成后才返回,因此,当这个方法返回 时,应用程序可以立刻对缓冲区进行下一帧后备屏幕的绘制。
如果GameCanvas当前没有显示,或者系统忙而不能执行绘制请求,该方法不进行任何操作就立刻返回。
这种“双缓冲”的机制将使得游戏动画更加流畅自然。此外,如果知道屏幕上哪些部分需要重新绘制,还可以调用 flushGraphics(int x, int y, int width, int height)方法在自定义的区域内进行绘制,而这会使得代码更加高效。
作为试验,笔者把GameCanvas中的对getGraphics()和flushGraphics()方 法的调用换成Canvas中repaint()以及serviceRepaints()方法的调用,两者没有什么明显的区别,但是如果程序包含了很多复杂 的图形,GameCanvas无疑是一个明智的选择。
3.2.3 实现游戏主循环
一个游戏可能提供自己的线程来运行游戏循环:一个典型的循环将检查输入、实现游戏逻辑,然后绘制更新后的用户 界面。
通常,在MIDP 2.0游戏中,GameCanvas充当了游戏“控制器”的功能。GameCanvas除了完成绘制屏幕的功能外,还负责等待并获得用户的输入,进行相应 的处理(改变游戏的状态和移动图层),绘制改变后的游戏界面。下面给出了一个在MIDP 2.0中使用GameCanvas实现游戏循环的代码框架:
//GameCanvas 的实现的游戏线程
Graphics g = getGraphics(); //获得Graphics对象来绘制后备屏幕缓冲
while (true) {
int keyState = getKeyStates(); //检查是否有用户输入
if ((keyState & LEFT_PRESSED) != 0) { //游戏左键被按下
sprite.move(-1, 0); //进行游戏逻辑操作,这里精灵向左移动
}
else if ((keyState & RIGHT_PRESSED) != 0) { //游戏右键被按下
sprite.move(1, 0); //进行游戏逻辑操作,这里精灵向右移动
}
g.setColor(0xFFFFFF); //将背景填充为白色
g.fillRect(0,0,getWidth(), getHeight());
sprite.paint(g); //绘制精灵
flushGraphics(); //将缓冲区的内容绘制到真实的设备屏幕上
}
3.2.4 获取键盘状态
前面已经提到,GameCanvas和Canvas的按键状态的响应是不一样的。在Canvas时代,如果想 知道按键状态,必须实现keyPressed()/keyReleased()/keyRepeated(),每当有按键被按下时,这个方法就被调用,而 在GameCanvas时代,如果要检查特定的按键是否被按下,只需要将getKeyStates()返回的值与这些键值进行按位与(&),并根 据计算结果来判断即可。
getKeyStates()返回的bit数据分别代表了不同的按键(例如Up、Down、Fire等)。当 按下某个物理键盘时,其对应的位设置为1,否则将被设置为0,这样做的好处是,无论游戏主循环执行得多慢,键盘事件都不会被忽略。
注意 |
除非GameCanvas当前可见(通过调用Display.isShown()方法),否则此方 法返回值为0。一旦GameCanvas变为可见,将初始化所有键为未按下状态(0)。 |
每一次getKeyStates()方法的调用都会清除当前键盘缓冲区,因此理论上说,连续调用两次 getKeyStates(),前一次会清除之前锁定的键盘状态,而后一次会得到反映当前键盘状态的理想值。
当然getKeyStates()的返回值会在另外一个线程中被更新,所以在游戏主循环中最好稍微等一会儿, 以保证这个值被更新。GameCanvas中获得用户输入的代码:
protected void input() {
int keyState = getKeyStates(); //获得键盘状态
if ((keyState & LEFT_PRESSED) != 0) { //如果左键被按下
// do something
}
if ((keyState & RIGHT_PRESSED) != 0) { //如果右键被按下
// do something
}
if ((keyState & FIRE_PRESSED) != 0) { //如果确定键被按下
// do something
}
}
如图3-7所示,将WTK的模拟器中游戏的A、B、C、D键分别映射到 1、3、7、9这4个键上,而Nokia模拟器将A、B、C、D键映射到7、9、#、*这4个键上。这里并没有使用处理按键事件的方式来得到按键输入,如 果采用这种方法获得按键输入,则一定要调用getGameAction()将按键代码转换为游戏代码。
为了使程序能在不同的设备上运行,就一定要考虑不同设备间键盘布局的特点,在开发程序时不能假设按键的布局方 式。具体的映射关系如表3-2所示。
表3-2 getKeyState()方法所返回的键盘值
键 值 |
相对应的KeyStates值 |
UP_PRESSED |
0x0002 = 2 |
DOWN_PRESSED |
0x0040 = 64 |
LEFT_PRESSED |
0x0004 = 4 |
RIGHT_PRESSED |
0x0020 = 32 |
FIRE_PRESSED |
0x0100 = 256 |
GAME_A_PRESSED |
0x0200 = 512(并非所有设备支持) |
GAME_B_PRESSED |
0x0400 = 1024(并非所有设备支持) |
GAME_C_PRESSED |
0x0800 = 2048(并非所有设备支持) |
GAME_D_PRESSED |
0x1000 = 4096(并非所有设备支持) |
注意 |
不同的设备对于getKeyStates()方法的调用会略有不同,主要体现在:有的设备支持检测 多个键同时按下的情况,而有的设备的不支持getKeyStates()方法,仅仅是通过调用keyPressed()/keyReleased()方法 来代替,因此会产生一定的时延。 |
由于GameCanvas能够通过getKeyStates()方法主动查询键盘状态,因此也提供了是否抑制 传统键盘事件的选择。
如果希望当游戏运行时,禁止调用KeyPressed()/keyReleased() /KeyRepeated()方法,那么就可以在构造GameCanvas时,在super()中传入true值。如果传入false值,那么一旦按键按 下,就会调用传统的键盘事件处理方法。
注意 |
键盘抑制只对当前GameCanvas 有效,并且只能抑制Canvas预定义的键盘事件(例如无法抑制手机上的*号键、#号键,以及接听、挂断、Clear等功能键)。 |
本文摘自:http://apps.hi.baidu.com/share/detail/31217091
GameCanvas类相关推荐
- Android游戏开发教程------(绘制屏幕)
游戏开发的基本原理: 启动一个Activity对象,然后让其显示一个GameCanvas对象(setContentView(GameCanvas));, GameCanvas 里面做游戏逻辑,用户键盘 ...
- 基于java的俄罗斯方块游戏系统设计与实现(项目报告+答辩PPT+源代码+数据库+截图+部署视频)
基于Java的俄罗斯方块游戏的设计与实现 俄罗斯方块是一款风靡全球,从一开始到现在都一直经久不衰的电脑.手机.掌上游戏机产品,是一款游戏规则简单,但又不缺乏乐趣的简单经典小游戏,上手容易,适用范围广泛 ...
- 手机游戏软件开发的前景 The future of development of game software on mobiles
一. 课题名称 手机游戏软件开发的前景 The future of development of game software on mobiles 二. 课题分析 计算机领域的方向很多 ...
- 使用NetBeans进行J2ME开发(五):揭开游戏开发的神秘面纱
游戏开发,好大的一个命题哦.无论是游戏的剧情设计,还是游戏的美工制作,那都不是一两下子能够完成的事,而编程,只是其中的一小部分.但是,就算是这一小部分,我也不可能把它掌握得很透彻.这篇随笔,大部分都是 ...
- java实现俄罗斯方块项目
导读:俄罗斯方块项目,基本功能包括:游戏主界面显示模块.方块及数据显示模块.方块移动控制模块.游戏界面颜色控制模块.游戏进度.等级控制模块等.本项目结构如下: (1)游戏主界面显示模块: 显示 ...
- 【java毕业设计】基于java+swing+Eclipse的俄罗斯方块游戏GUI设计与实现(毕业论文+程序源码)——俄罗斯方块游戏
基于java+swing+Eclipse的俄罗斯方块游戏GUI设计与实现(毕业论文+程序源码) 大家好,今天给大家介绍基于java+swing+Eclipse的俄罗斯方块游戏GUI设计与实现,文章末尾 ...
- 手机游戏毕业设计论文
1 绪论 1.1 手机软件现状 在信息社会中,手机及其他无线设备越来越多的走进普通百姓的工作和生活,随着信息网络化的不断进展,手机及其他无线设备上网络势在必行.但是传统手机存在以下弊端: 1. 传 ...
- 无缝移植J2ME程序到OPhone平台解决方案
目录 • 为 什么需要移植J2ME程序 • J2ME 适配包之架构 • J2ME 适配包之界面 • J2ME 适配包之按键映射 • J2ME 适配包之数据持久存储 • J2ME 适配包总结 • 关 于 ...
- ios辅助功能_iOS辅助功能标签
ios辅助功能 This blog was inspired by Jeff Watkins' series of blogs on UIButton. UIButton is a fundament ...
最新文章
- HTML5-响应式的实现方式-弹性布局浅谈
- 10分钟让你明白什么是ERP
- LeetCode 64最小路径和65有效数字66加一
- 八、深入Go 编程语言接口
- flat在java中的含义_Java 9中Collectors.flatMapping()方法的重要性?
- optimized mysql_MySQL解释计划中“Select tables optimized away”的含义
- dao generator for php and mysql_mybatis generator 自动生成dao层映射代码
- 【Python3】待解决的疑问
- 美团技术leader:写给工程师的十条精进原则
- 计算机视觉中,目前有哪些经典的目标跟踪算法?
- 【收藏】十大Webserver漏洞扫描工具
- CDA I 级 备考之 PART 1
- 【学习笔记】吉司机线段树
- windows C++ 解决Office打开文件提示“您尝试打开的文件xxx.xls的格式与文件扩展名指定的格式不一致”
- 如何在CSDN上删除博客、删除自己上传的资源
- 【C语言】已知三角形三边长,求三角形面积
- Web 实时消息推送详解
- python 中画球体_python – 有效地绘制许多球体
- Linux文件系统:minix文件系统二进制分析2
- 推荐一款基于docker部署的个人免费笔记工具wiznote
热门文章
- matlab鸢尾花的数据可视化,matplotlib可视化练习 -- 鸢尾花数据集
- DSP的程序加载与运行方式
- 密码分析学——Md4碰撞代码实现
- 关于福昕软件公司的控件使用-Foxit PDF SDK ActiveX
- js判断手机端还是电脑PC端(以及注意事项)
- 【第68篇】多目标跟踪:文献综述
- 有哪些比较好的wince 播放器 支持硬解的
- RKISP_Driver_User_Manual
- Setup Factory9设置图标
- 什么是蓝筹股?哪些是蓝筹股?蓝筹股票的好处是什么?