作者:潇潇  出处:www.j2mefans.com


   在前面的例子里我们都是使用面向过程的方法,根据游戏的状态来绘制游戏中的元素,更新显示屏幕。当然我们也可以将每一种角色编写一个类,在其中实现定位, 绘制,移动,甚至动画效果。但是每一种角色写一遍的话,工作量还是不小。所以我们可以抽取各种角色的共性,做一个通用的类,然后在这个基础上对该类进行扩 充,得到不同的角色。

   幸运的是,以上的工作都不用我们去做了,在MIDP2.0中,我们已经有了一个现成的类可供使用。这就是MIDP中Layer类和Sprite类,使用这两个类,可以使得精灵动画成为可能。
其 中Layer类提供了获得图层或精灵的坐标位置,宽高属性的函数,同时还可以对图像进行移动,设定可见性,绘制等功能。而Sprite类不但继承了 Layer类的这些功能,还提供了许多额外的功能:可以实现在对精灵使用图形的基础上,通过支持多帧图像来实现动画效果。更重要的是提供了精灵之间的3种 冲突检测功能(关于这部分我们将在专门的文章里讲解)。

那么精灵类怎样使用呢?
(1)先准备图片。可以是一张只包括一帧的图像,也可以是包括多帧的一张图片
 

比如我们以这样一张图片为例,(该图片来自网络,不知道舍不涉及到版权的问题)图片中包括了一个角色的3帧图片,连起来可以组成一个完整的行走动画。
(2)创建一个图像,将该图片载入内存,并将该图像类的实例作为参数传递给精灵类的构造函数,同时传递每一帧得宽高,这样我们就得到了一个精灵类的实例了。
(3)还可以使用setPosition方法,设定精灵的位置。
try {
    hero = new Sprite(Image.createImage("/hero.png"), 17, 26);
    hero.setPosition(0, 0);
} catch (IOException e) {
    System.err.println("Failed loading image!");
}

(4)要想让精灵移动,可以使用move方法。参数表示想对当前位置移动的坐标
hero.move(XSpeed, YSpeed);

(5)移动的同时要想更换当前帧只需要使用nextFrame()和prevFrame方法。
hero.nextFrame();
hero.prevFrame();

例如我们控制应用向下走可是使用下面语句:
if ((keyState & RIGHT_PRESSED) != 0) {
    hero.nextFrame();
    hero.move(XSpeed, 0);
}

(6)前面所作的都是在内存中的改动,要想显示出来,还得使用paint方法。
hero.paint(g);
怎么样是否很简单呢?
再多的理论也不如一个好的实例。所以我们以一个简单的任务走动为例,看一看怎样使用MIDP2.0中的精灵类。下面的他的所有代码,有注释的,再加上前面的讲解,不用说了吧~~~~

/**
 *  文件名:Ocanvas.java
 *  画布类
 */

import javax.microedition.lcdui.*;
import javax.microedition.lcdui.game.*;
import java.util.*;
import java.io.*;

public class Ocanvas extends GameCanvas implements Runnable {

    //定义变量
    private Display display;
    private boolean sleeping;
    private long frameDelay;

    private Sprite hero;
    private int XSpeed, YSpeed;
    private int x, y;

    public Ocanvas(Display d) {
        //类构造函数,初始化类变量
        super(true);
        display = d;

        // 设置帧频(30 fps)
        frameDelay = 33;
    }

    public void start() {

        // 设置这个画布为当前屏幕
        display.setCurrent(this);

        // 初始化一些游戏中的变量,载入相关图片

        x = getWidth() / 2 - 10;
        y = getHeight() / 2 - 10;
        XSpeed = YSpeed = 3;
        try {
            hero = new Sprite(Image.createImage("/hero.png"), 17, 26);
            hero.setPosition(x, y);
        } catch (IOException e) {
            System.err.println("Failed loading image!");
        }
        // 开始动画线程
        sleeping = false;
        Thread t = new Thread(this);
        t.start();
    }

    public void stop() {
        // 停止动画线程
        sleeping = true;
    }

    public void run() {
        // 动画线程开始后运行
        Graphics g = getGraphics();

        // 主游戏循环
        while (!sleeping) {
            //更新游戏中的数据变量
            //update();
            input();
            //更新屏幕显示
            draw(g);
            //线程休眠
            try {
                Thread.sleep(frameDelay);
            } catch (InterruptedException ie) {}
        }
    }


    //在这里对屏幕进行绘制
    private void draw(Graphics g) {
        // 清除屏幕
        g.setColor(0xffffffff);
        g.fillRect(0, 0, getWidth(), getHeight());

        // 重绘屏幕
        hero.paint(g);

        // 刷新屏幕缓冲区
        flushGraphics();
    }

    /**
     * 键盘输入
     */
    private void input() {
        int keyState = getKeyStates();
        if ((keyState & LEFT_PRESSED) != 0) {
            hero.prevFrame();
            hero.move( -XSpeed, 0);
        } else if ((keyState & RIGHT_PRESSED) != 0) {
            hero.nextFrame();
            hero.move(XSpeed, 0);
        }
        if ((keyState & UP_PRESSED) != 0) {
            hero.prevFrame();
            hero.move(0, -YSpeed);
        } else if ((keyState & DOWN_PRESSED) != 0) {
            hero.nextFrame();
            hero.move(0, YSpeed);
        }
    }
}