第三章 用精灵实现动画
屏幕快照
在这一章你将创建你的第一个
MIDlet
程序来学习如何用精灵来创建简单的动画。
(
图
8)
展示了模拟器上运行的完整的
MIDlet
程序的一系列屏幕快照。
(图8)
螺旋运动的精灵
我们的
MIDlet
程序的精灵如
(
图
9)
所示:
(图9)
这个精灵由4行4列,16张独立的帧组成。每一帧按次序显示以创建动画效果。
创建精灵类:AnimationSprite.java
在本教程中,对于你要开发的每一个MIDlet程序,当使用Wieless Toolkit(WTK)开发时,都遵循一组相同的开发步骤:
1. 创建工程.
2. 书写源代码.
3. 编译和预校验源代码.
4. 运行MIDlet.
创建工程
创建一个新的工程
1. 点击New Project.
2. 输入工程名和MIDlet类名,如(图10)所示.
3. 点击Create Project.
(图10)
编写代码:第一步
在这个MIDlet程序中你将发现3个源代码文件:
° AnimationSprite.java: 精灵类
° AnimationCanvas.java: 显示精灵的GameCanvas
° Animation.java: MIDlet程序启动和停止的代码
将下面的AnimationSprite.java代码拷贝粘贴到文本编辑器:
/**//*---------------------------------------------
* AnimationSprite.java
*----------------------------------------------*/
import javax.microedition.lcdui.game.*;
import javax.microedition.lcdui.*;
public class AnimationSprite extends Sprite{
public AnimationSprite(Image image, int frameWidth, int frameHeight){
// 调用Sprite的构造函数
super(image, frameWidth, frameHeight);
}
}
当你创建了一个新工程,
WTK
会为你创建适当的目录结构。本例中,
WTK
创建了目录
C:\WTK20\apps\Animation
以及必要的子目录。将
AnimationSprite.java
等
Java
源文件保存到
src
目录下
(
如图
11)
所示:
(图11)
注意:启动器盘符和WTK目录会根据Toolkit安装目录的不同而不同。
编写代码:第二步
把下面的AnimationCanvas.java的代码拷贝到文本编辑器中,把文件保存到上一节中的相同的目录下。
/**//*--------------------------------------------------
* AnimationCanvas.java
*-------------------------------------------------*/
import javax.microedition.lcdui.game.*;
import javax.microedition.lcdui.*;
public class AnimationCanvas extends GameCanvas implements Runnable{
// 一帧精灵图像的尺寸
private static final int FRAME_WIDTH = 57;
private static final int FRAME_HEIGHT = 53;
private AnimationSprite spSpiral; // 动画精灵
private LayerManager lmgr; // 图层管理器
private boolean running = false; // 线程是否启动
public AnimationCanvas(){
// 游戏画布构造函数
super(true);
try{
// 创建动画精灵
spSpiral = new AnimationSprite(Image.createImage("/spiral.png");
// 将精灵的参考象素移到精灵的中间
spSpiral.defineReferencePixel(FRAME_WIDTH / 2, FRAME_HEIGHT / 2);
// 将精灵放置在屏幕中心
// (精灵的中心和屏幕的中心重合)
spSpiral.setRefPixelPosition(getWidth() / 2, getHeight() / 2);
// 创建图层管理器
lmgr = new LayerManager();
lmgr.append(spSpiral);
}catch (Exception e){
System.out.println("Unable to read PNG image");
}
}
/**//*--------------------------------------------------
* 启动线程
*-------------------------------------------------*/
public void start(){
running = true;
Thread t = new Thread(this);
t.start();
}
/**//*--------------------------------------------------
* 主循环
*-------------------------------------------------*/
public void run(){
Graphics g = getGraphics();
while (running){
// 刷新屏幕
drawDisplay(g);
try{
Thread.sleep(150);
} catch (InterruptedException ie) {
System.out.println("Thread exception");
}
}
}
/**//*--------------------------------------------------
* 刷新屏幕
*-------------------------------------------------*/
private void drawDisplay(Graphics g){
// 显示下一帧精灵图像
spSpiral.nextFrame();
// 绘制图层
lmgr.paint(g, 0, 0);
// 将屏幕缓冲刷新到屏幕
flushGraphics();
}
/**//*--------------------------------------------------
* 停止线程
*-------------------------------------------------*/
public void stop(){
running = false;
}
} 编写代码:第三步
最后一部分代码如下所示。复制到文本编辑器中并另存为Animation.java:
/**//*--------------------------------------------------
* Animation.java
**
显示动画精灵
*-------------------------------------------------*/
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class Animation extends MIDlet implements CommandListener{
private Display display;
private AnimationCanvas canvas; // 游戏画布
private Command cmExit; // 退出按钮
public Animation(){
display = Display.getDisplay(this);
cmExit = new Command("Exit", Command.EXIT, 1);
// 创建游戏画布和退出按钮
if ((canvas = new AnimationCanvas()) != null){
canvas.addCommand(cmExit);
canvas.setCommandListener(this);
}
}
public void startApp(){
if (canvas != null){
display.setCurrent(canvas);
canvas.start();
}
}
public void pauseApp(){
}
public void destroyApp(boolean unconditional){
canvas.stop();
}
public void commandAction(Command c, Displayable s){
if (c == cmExit){
destroyApp(true);
notifyDestroyed();
}
}
}
编译和预校验
单击
Build
按钮完成编译、预校验和打包。入图
12
所示。然后点击
Run
启动应用管理器。
(图12)
启动MIDlet
(图13)
单击Launch启动Aninate MIDlet,如图13所示。启动以后你将会看到如图14所示的一系列屏幕输出画面。
(图14)
代码回顾:创建精灵
让我们回去一下创建动画精灵的代码。这一节以及后面
3
节的代码片段均来自
AnimationCanvas.java.
文件
//
一帧精灵图像的尺寸
private
static
final
int
FRAME_WIDTH
=
57
;
private
static
final
int
FRAME_HEIGHT
=
53
;
//
创建动画精灵
spSpiral
=
new
AnimationSprite(Image.createImage(
"
/spiral.png
"
);
精灵通过一个已经存在的
PNG
文件创建。
FRAME_WIDTH
和
FRAME_HEIGTH
表示图像中每一帧的宽度和高度。图
15
是同于创建精灵的实际图片,而图
16
把图像拆分成一个个独立的帧。
(图15)(图16)
代码回顾:设置参考像素
下面代码的第一行将精灵的参考像素移到了精灵的中间,紧接着调用setRefPixelPosition()将新的参考像素放置到设备屏幕的中心,最后的结果就是精灵的参考像素和设备屏幕的中心重合。
//
将精灵的参考象素移到精灵的中间
spSpiral.defineReferencePixel(FRAME_WIDTH
/
2
, FRAME_HEIGHT
/
2
);
//
将精灵放置在屏幕中心
//
(精灵的中心和屏幕的中心重合)
spSpiral.setRefPixelPosition(getWidth()
/
2
, getHeight()
/
2
);
//
创建图层管理器
lmgr
=
new
LayerManager();
lmgr.append(spSpiral);
上面代码的最后两行定义了一个图层管理器
(
layer manager
)
并且将精灵添加到管理器中。图层是游戏开发中的个基本的概念,它允许你灵活的将可视对象呈现在屏幕上。图层管理器处理图层的显示以确保图层能按适当层次显示到屏幕上。深入探讨图层的使用已经超出了本教程的范围,但是本教程却包含了创建
MIDlet
所需的全部知识。
代码回顾:运行动画
万事具备,下一步要做的就是开启一个线程,轮流画出精灵的图像帧。
/**//*--------------------------------------------------
* 启动线程
*-------------------------------------------------*/
public void start(){
running = true;
Thread t = new Thread(this);
t.start();
}
/**//*--------------------------------------------------
* 主循环
*-------------------------------------------------*/
public void run(){
Graphics g = getGraphics();
while (running){
// 刷新屏幕
drawDisplay(g);
try{
Thread.sleep(150);
} catch (InterruptedException ie) {
System.out.println("Thread exception");
}
}
}
线程运行时,RUN()控制着多长时间更新一次屏幕。每一次循环运行到drawDisplay()就画出下一帧图像。下一节你将会看到drawDisplay()的内部细节。
代码回顾:画出图像帧
前面我们用FRAME_WIDTH和FRAME_HEIGHT定义了帧的宽度和高度。利用这些信息MIDlet能够计算出图像中有多少帧图像。知道了有多少帧图像,nextFrame()就能恰当的循环遍历每一帧图像,并且当达到最后一帧时跳回到第一帧重新开始。
/**//*--------------------------------------------------
* 刷新屏幕
*-------------------------------------------------*/
private void drawDisplay(Graphics g){
// 显示下一帧精灵图像
spSpiral.nextFrame();
// 绘制图层
lmgr.paint(g, 0, 0);
// 将屏幕缓冲刷新到屏幕
flushGraphics();
}
图层管理器在指定位置绘制每一个图层,图层的位置取决于图层相对于屏幕的位置。在这个
MIDlet
中,你要求图层绘制在(0,0
)处。
如果你利用屏幕的顶部显示其他信息,例如显示分数,你可以改变传递给
Paint
()函数的
x,y
坐标值来适应这个要求。例如图
17
中,坐标设置在了(
17,
17
)处以便统计附加信息显示到屏幕顶部。这张图片直接从
Sun Microsystems
的
MDIP2.0 API文档里截取而来。
to be continue...
posted on 2006-04-27 09:19
学二的猫 阅读(2746)
评论(6) 编辑 收藏 所属分类:
J2ME