⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sprite.java

📁 j2me 横版过关游戏工程。(demo).可以参考下
💻 JAVA
字号:

import javax.microedition.lcdui.*;

/**
 * 文件名: WestGameCanvas.java <br>
 * 作者: 汪霞 <br>
 * 创建日期: 2005-12-1 <br>
 * 文件功能: <br>
 * 版本:1.0 <br>
 * 编译环境:CLDC1.0, MIDP1.0 <br>
 * 实现环境:NOKIA60 <br>
 * 注释: <br>
 * 修改者姓名: <br>
 * 版权声明:Copyright (c) 2000 GameFactory .All rights reserved. <br>
 */
public class Sprite
{

    protected int     x, y;                 //在屏幕上,需要绘制图片的位置

    protected boolean visible;               //设置当前图片的显示与否

    int               id;

    // 动画起始索引
    private int       sequenceIndex;

    // 自定义动画顺序
    private boolean   customSequenceDefined;

    // 动画源图像
    Image             sourceImage;

    // 动画帧数
    int               numberFrames;

    // 帧的左上角相对于源图像的x坐标数组
    int               frameCoordsX[];

    // 帧的左上角相对于源图像的y坐标数组
    int               frameCoordsY[];

    // 帧的宽度
    int               srcFrameWidth;

    // 帧的高度
    int               srcFrameHeight;

    // 动画帧的顺序数组
    int               frameSequence[];

    // 碰撞检测块的左上角x坐标 (相对于一帧)
    int               collisionRectX;

    // 碰撞检测块的左上角y坐标 (相对于一帧)
    int               collisionRectY;

    // 碰撞检测块的宽度
    int               collisionRectWidth;

    // 碰撞检测块的高度
    int               collisionRectHeight;

    // 用 单帧图像 生成sprite的constructor
    public Sprite(int id, Image image)
    {
        // 调用layer类构造函数,只有一帧的sprite,图像的大小就是帧的大小
        visible = true;
        // 调用初始化帧相关事项的函数,对sequenceIndex不做更改(false)
        initializeFrames(image, image.getWidth(), image.getHeight(), false);
        // 调用初始化碰撞检测块的函数
        initCollisionRecBounds();
    }

    // 用 多帧图像 生成sprite的constructor
    public Sprite(int id, Image image, int frameWidht, int frameHeight)
    {
        // 调用layer类构造函数,初始化帧的大小
        visible = true;
        // 参数合法化检测
        if (frameWidht < 1 || frameHeight < 1
                || image.getWidth() % frameWidht != 0
                || image.getHeight() % frameHeight != 0)

        {
            System.out.println("imgWidth=" + image.getWidth() + ", imgHeight="
                    + image.getHeight());
            System.out.println("frameWidth=" + frameWidht + ", frameHeight="
                    + frameHeight);
            throw new IllegalArgumentException();
        }
        else
        {
            // 调用初始化帧相关事项的函数,对sequenceIndex不做更改(false)
            initializeFrames(image, frameWidht, frameHeight, false);
            // 调用初始化碰撞检测块的函数
            initCollisionRecBounds();
            this.id = id;
        }
    }

    // 设定动画起始索引
    public void setFrame(int sequenceIndex)
    {
        // 动画起始索引范围限定
        if (sequenceIndex < 0 || sequenceIndex >= frameSequence.length)
            throw new IndexOutOfBoundsException();
        else
        {
            this.sequenceIndex = sequenceIndex;
        }
    }

    // 取得动画起始索引
    public int getFrame()
    {
        return sequenceIndex;
    }

    // 取得动画顺序数组的长度
    public int getFrameSequenceLength()
    {
        return frameSequence.length;
    }

    // 设定动画顺序数组
    public void setFrameSequence(int[] sequence)
    {
        // 动画顺序数组如果为空
        if (null == sequence)
        {
            // 设定动画起始索引为0
            sequenceIndex = 0;
            // 设定自定义动画顺序为fasle
            customSequenceDefined = false;
            // 按帧的自然顺序,设定动画顺序数组
            frameSequence = new int[numberFrames];
            for (int i = numberFrames - 1; i >= 0; i--)
                frameSequence[i] = i;
            return;
        }
        // 出错处理
        if (sequence.length < 1)
            throw new IllegalArgumentException();
        // 出错处理:动画索引范围检测
        for (int i = sequence.length - 1; i >= 0; i--)
            if (sequence[i] < 0 || sequence[i] >= numberFrames)
                throw new ArrayIndexOutOfBoundsException();
        // 设定自定义动画顺序为true
        customSequenceDefined = true;
        // 拷贝形参数组 到 动画顺序数组
        frameSequence = new int[sequence.length];
        System.arraycopy(sequence, 0, frameSequence, 0, sequence.length);
        // 设定动画起始索引为0
        sequenceIndex = 0;
    }

    // 设定碰撞检测块范围 (相对于一帧)
    public void defineCollisionRectangle(int x, int y, int w, int h)
    {
        // 设定碰撞检测块各值(左上角是相对于帧的)
        collisionRectX = x;
        collisionRectY = y;
        collisionRectWidth = w;
        collisionRectHeight = h;
    }

    // 与sprite的碰撞检测
    public final boolean collidesWith(Sprite s)
    {
        // 如果有一方不可见,忽略检测,返回false
        if (!this.visible || !s.visible)
            return false;
        // 由形参sprite的位置和碰撞检测块计算四边范围
        int thatLeft = s.x + s.collisionRectX;
        int thatTop = s.y + s.collisionRectY;
        int thatRight = thatLeft + s.collisionRectWidth;
        int thatBottom = thatTop + s.collisionRectHeight;
        // 由本sprite的位置和碰撞检测块计算四边范围
        int thisLeft = x + collisionRectX;
        int thisTop = y + collisionRectY;
        int thisRight = thisLeft + collisionRectWidth;
        int thisBottom = thisTop + collisionRectHeight;
        // 返回碰撞检测函数的值,true为碰,false为没碰
        return intersectRect(thatLeft, thatTop, thatRight, thatBottom,
                thisLeft, thisTop, thisRight, thisBottom);
    }

    // 与图片的碰撞检测
    public final boolean collidesWith(Image image, int imgX, int imgY)
    {
        if (!visible)
            return false;
        // 由image的位置和宽高计算四边范围
        int thatLeft = imgX;
        int thatTop = imgY;
        int thatRight = thatLeft + image.getWidth();
        int thatBottom = thatTop + image.getHeight();
        // 由本sprite的位置和碰撞检测块计算四边范围
        int thisLeft = x + collisionRectX;
        int thisTop = y + collisionRectY;
        int thisRight = thisLeft + collisionRectWidth;
        int thisBottom = thisTop + collisionRectHeight;
        // 返回碰撞检测函数的值,true为碰,false为没碰
        return intersectRect(thatLeft, thatTop, thatRight, thatBottom,
                thisLeft, thisTop, thisRight, thisBottom);
    }

    // 碰撞检测处理(针对 矩形范围)
    private boolean intersectRect(int r1Left, int r1Top, int r1Right,
            int r1Bottom, int r2Left, int r2Top, int r2Right, int r2Bottom)
    {
        // 碰撞检测原理:碰撞的充分必要条件(一下所做的比较是是坐标x,y值的比较)
        // rec2的左边必然小于rec1的右边
        // rec2的右边必然大于rec1的左边
        // rec2的上边必然小于rec1的下边
        // rec2的下边必然大于rec1的上边
        return r2Left < r1Right && r2Right > r1Left && r2Top < r1Bottom
                && r2Bottom > r1Top;
    }

    // 初始化帧相关事项
    private void initializeFrames(Image image, int frameWidth, int frameHeight,
            boolean maintainCurFrame)
    {
        // 计算源图像大小
        int imageWidth = image.getWidth();
        int imageHeight = image.getHeight();
        // 计算源图像行和列的帧数
        int numHorizontalFrames = imageWidth / frameWidth;
        int numVerticalFrames = imageHeight / frameHeight;
        // 更新旧的源图像
        sourceImage = image;
        // 更新帧的高宽值
        srcFrameWidth = frameWidth;
        srcFrameHeight = frameHeight;
        // 计算源图像中帧的总数
        numberFrames = numHorizontalFrames * numVerticalFrames;
        // 如果maintainCurFrame为false就不改变sequenceIndex
        if (maintainCurFrame)
            sequenceIndex = 0;
        // 更新帧相对于源图像的x,y坐标数组
        frameCoordsX = new int[numberFrames];
        frameCoordsY = new int[numberFrames];
        // 如果不是自定义顺序,更新动画帧的顺序数组
        if (!customSequenceDefined)
            frameSequence = new int[numberFrames];
        // 数组索引值
        short currentFrame = 0;
        // 这里还可以用单层for循环来完成,不过会用到乘法,而下面的算法只有加法
        for (short yy = 0; yy < imageHeight; yy += frameHeight)
        {
            for (short xx = 0; xx < imageWidth; xx += frameWidth)
            {
                //************************************************************
                //                System.out.println("xx=" + xx + ", yy+" + yy);
                // 纪录帧相对于源图像的x坐标
                frameCoordsX[currentFrame] = xx;
                // 纪录帧相对于源图像的y坐标
                frameCoordsY[currentFrame] = yy;
                // 如果不是自定义顺序,那就按自然顺序更新动画帧的顺序数组
                if (!customSequenceDefined)
                    frameSequence[currentFrame] = currentFrame;
                // 数组索引值自加一
                currentFrame++;
            }
        }
    }

    // 初始化碰撞检测块
    private void initCollisionRecBounds()
    {
        // 检测块的边界是相对于帧的左上角
        collisionRectX = 0;
        collisionRectY = 0;
        collisionRectWidth = srcFrameWidth;
        collisionRectHeight = srcFrameHeight;
    }

    // 取得源图像包含帧的总和
    public int getRawFrameCount()
    {
        return numberFrames;
    }

    // 计算下一帧的索引值
    public void nextFrame()
    {
        sequenceIndex = (sequenceIndex + 1) % frameSequence.length;
    }

    // 计算上一帧的索引值
    public void prevFrame()
    {
        if (0 == sequenceIndex)
            sequenceIndex = frameSequence.length - 1;
        else
            sequenceIndex--;
    }

    // 画出动画
    public final void paint(Graphics g)
    {
        // 出错检测
        if (null == g)
            throw new NullPointerException();
        // 如果本sprite可见,就可以画
        if (visible)
        {
            //************************************************************
            //            System.out.println("x=" + x + ", y=" + y + ", srcFrameWidth="
            //                    + srcFrameWidth + ", srcFrameHeight=" + srcFrameHeight);
            // 设定画笔区域
            g.setClip(x, y, srcFrameWidth, srcFrameHeight);
            //************************************************************
            //            System.out.println("frameCoordsX="
            //                    + frameCoordsX[frameSequence[sequenceIndex]]
            //                    + ", frameCoordxY="
            //                    + frameCoordsY[frameSequence[sequenceIndex]]);
            // 用动画索引(sequenceIndex),从动画帧的顺序数组(frameSequence),取得帧号
            // 用帧号取得该帧相对于源图像的位置(frameCoordsX,frameCoordsY)
            // 向画笔的x,y位置,在平移(frameCoordsX,frameCoordsY),画源图像
            g.drawImage(sourceImage, x
                    - frameCoordsX[frameSequence[sequenceIndex]], y
                    - frameCoordsY[frameSequence[sequenceIndex]], Graphics.TOP
                    | Graphics.LEFT);

        }
    }

    //  设定动画顺序数组
    public void setFrameSequenceWX(int[] sequence)
    {
        // 动画顺序数组如果为空
        if (null == sequence)
        {
            // 设定动画起始索引为0
            setFrame(0);
            // 按帧的自然顺序,设定动画顺序数组
            frameSequence = new int[numberFrames];
            for (int i = numberFrames - 1; i >= 0; i--)
                frameSequence[i] = i;
            return;
        }
        // 出错处理
        if (sequence.length < 1)
            throw new IllegalArgumentException();
        // 出错处理:动画索引范围检测
        for (int i = sequence.length - 1; i >= 0; i--)
            if (sequence[i] >= numberFrames)
                throw new ArrayIndexOutOfBoundsException();
        // 拷贝形参数组 到 动画顺序数组
        frameSequence = new int[sequence.length];
        System.arraycopy(sequence, 0, frameSequence, 0, sequence.length);
        // 设定动画起始索引为0
        setFrame(0);
    }

    /**
     * 需要绘制图片的位置
     */
    public void setPosition(int x, int y)
    {
        this.x = x;
        this.y = y;
    }

    public void move(int dx, int dy)
    {
        x += dx;
        y += dy;
    }

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -