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类相关推荐

  1. Android游戏开发教程------(绘制屏幕)

    游戏开发的基本原理: 启动一个Activity对象,然后让其显示一个GameCanvas对象(setContentView(GameCanvas));, GameCanvas 里面做游戏逻辑,用户键盘 ...

  2. 基于java的俄罗斯方块游戏系统设计与实现(项目报告+答辩PPT+源代码+数据库+截图+部署视频)

    基于Java的俄罗斯方块游戏的设计与实现 俄罗斯方块是一款风靡全球,从一开始到现在都一直经久不衰的电脑.手机.掌上游戏机产品,是一款游戏规则简单,但又不缺乏乐趣的简单经典小游戏,上手容易,适用范围广泛 ...

  3. 手机游戏软件开发的前景 The future of development of game software on mobiles

    一.     课题名称 手机游戏软件开发的前景 The future of development of game software on mobiles 二.     课题分析 计算机领域的方向很多 ...

  4. 使用NetBeans进行J2ME开发(五):揭开游戏开发的神秘面纱

    游戏开发,好大的一个命题哦.无论是游戏的剧情设计,还是游戏的美工制作,那都不是一两下子能够完成的事,而编程,只是其中的一小部分.但是,就算是这一小部分,我也不可能把它掌握得很透彻.这篇随笔,大部分都是 ...

  5. java实现俄罗斯方块项目

    导读:俄罗斯方块项目,基本功能包括:游戏主界面显示模块.方块及数据显示模块.方块移动控制模块.游戏界面颜色控制模块.游戏进度.等级控制模块等.本项目结构如下: (1)游戏主界面显示模块:     显示 ...

  6. 【java毕业设计】基于java+swing+Eclipse的俄罗斯方块游戏GUI设计与实现(毕业论文+程序源码)——俄罗斯方块游戏

    基于java+swing+Eclipse的俄罗斯方块游戏GUI设计与实现(毕业论文+程序源码) 大家好,今天给大家介绍基于java+swing+Eclipse的俄罗斯方块游戏GUI设计与实现,文章末尾 ...

  7. 手机游戏毕业设计论文

    1  绪论 1.1 手机软件现状 在信息社会中,手机及其他无线设备越来越多的走进普通百姓的工作和生活,随着信息网络化的不断进展,手机及其他无线设备上网络势在必行.但是传统手机存在以下弊端: 1.  传 ...

  8. 无缝移植J2ME程序到OPhone平台解决方案

    目录 • 为 什么需要移植J2ME程序 • J2ME 适配包之架构 • J2ME 适配包之界面 • J2ME 适配包之按键映射 • J2ME 适配包之数据持久存储 • J2ME 适配包总结 • 关 于 ...

  9. ios辅助功能_iOS辅助功能标签

    ios辅助功能 This blog was inspired by Jeff Watkins' series of blogs on UIButton. UIButton is a fundament ...

最新文章

  1. HTML5-响应式的实现方式-弹性布局浅谈
  2. 10分钟让你明白什么是ERP
  3. LeetCode 64最小路径和65有效数字66加一
  4. 八、深入Go 编程语言接口
  5. flat在java中的含义_Java 9中Collectors.flatMapping()方法的重要性?
  6. optimized mysql_MySQL解释计划中“Select tables optimized away”的含义
  7. dao generator for php and mysql_mybatis generator 自动生成dao层映射代码
  8. 【Python3】待解决的疑问
  9. 美团技术leader:写给工程师的十条精进原则
  10. 计算机视觉中,目前有哪些经典的目标跟踪算法?
  11. 【收藏】十大Webserver漏洞扫描工具
  12. CDA I 级 备考之 PART 1
  13. 【学习笔记】吉司机线段树
  14. windows C++ 解决Office打开文件提示“您尝试打开的文件xxx.xls的格式与文件扩展名指定的格式不一致”
  15. 如何在CSDN上删除博客、删除自己上传的资源
  16. 【C语言】已知三角形三边长,求三角形面积
  17. Web 实时消息推送详解
  18. python 中画球体_python – 有效地绘制许多球体
  19. Linux文件系统:minix文件系统二进制分析2
  20. 推荐一款基于docker部署的个人免费笔记工具wiznote

热门文章

  1. matlab鸢尾花的数据可视化,matplotlib可视化练习 -- 鸢尾花数据集
  2. DSP的程序加载与运行方式
  3. 密码分析学——Md4碰撞代码实现
  4. 关于福昕软件公司的控件使用-Foxit PDF SDK ActiveX
  5. js判断手机端还是电脑PC端(以及注意事项)
  6. 【第68篇】多目标跟踪:文献综述
  7. 有哪些比较好的wince 播放器 支持硬解的
  8. RKISP_Driver_User_Manual
  9. Setup Factory9设置图标
  10. 什么是蓝筹股?哪些是蓝筹股?蓝筹股票的好处是什么?