📄 sprite.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 + -