/**
* <p>Title: CarmackMIDlet</p>
*
* <p>Description: Carmack Buffer </p>
*
* <p>Copyright: Copyright (c) 2009</p>
*
* <p>Company: sharejoy CD</p>
*
* @author fengsheng.yang
* @version 1.0
*/
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
public class CarmackMapBuffer {
/** 缓冲区宽高,命名方式为:Carmack width or height */
private final int carWidth, carHeight;
/** 缓冲区宽的图块数,与高的图块数,命名方式为:Carmack title width or height num */
private final int carTitleWidthNum, carTitleHeightNum;
/** 屏幕宽高命名方式为:screen width or height */
private final int scrWidth, scrHeight;
/** 缓冲区增大的大小(上下大小是一样的) */
private final int buffSize;
/** 图块大小,宽高一致 */
private int titleSize;
/** 缓冲区,命名方式为:Carmack buffer */
private Image carBuffer;
/** 缓冲区画笔,命名方式为:Carmack Graphics */
private Graphics carGp;
/** 图片宽度的所切割的图块数量。 */
private int imageTitleWidthNum;
/** 缓冲区的宽度图块数量,与高度图块数量 */
private int bufWNum, bufHNum;
/** 地图的宽高 */
private int bufW, bufH;
/** 地图在缓冲区的X 、Y偏移量,命名方式为:map offset x or y */
private int mapOffx, mapOffy;
/** 缓冲切割线,命名方式为:Carmack x or y */
private int carx, cary;
// ////////////////////////////////////////////////////////////
// 临时数据
/** 地图图片 */
private Image mapImage;
/** 地图数组 */
private byte mapArray[][];
/***************************************************************************/
/***************************************************************************/
/***************************************************************************/
/**
* 创建缓冲区
*
* @param scrW
* 屏幕宽度
* @param scrH
* 屏幕高度
* @param titleSize
* 图块大小
*/
public CarmackMapBuffer(int scrW, int scrH, int titleSize) {
scrWidth = scrW;
scrHeight = scrH;
this.titleSize = titleSize;
buffSize = titleSize * 2;
int temp = 0;
while (temp < scrWidth) {
temp += titleSize;
}
carWidth = buffSize + temp;
temp = 0;
while (temp < scrHeight) {
temp += titleSize;
}
carHeight = buffSize + temp;
carTitleWidthNum = carWidth / titleSize;
carTitleHeightNum = carHeight / titleSize;
carBuffer = Image.createImage(carWidth, carHeight);
carGp = carBuffer.getGraphics();
}
/**
* 设置地图片数据
*
* @param image
* 地图图片
* @param map
* 地图的二维数组
*/
public void setMap(Image image, byte[][] map) {
this.mapImage = image;
this.mapArray = map;
this.bufHNum = mapArray.length;
this.bufWNum = mapArray[0].length;
bufW = bufWNum * titleSize - scrWidth;
bufH = bufHNum * titleSize - scrHeight;
imageTitleWidthNum = image.getWidth() / titleSize;
initBuffer();
}
/**
* 初始化Buffer
*
*/
private void initBuffer() {
int x, y, cx, cy;
for (int i = 0; i < carTitleHeightNum; i++) { // 遍历缓冲区,其中carTitleHeightNum图片X方法切块数
for (int j = 0; j < carTitleWidthNum; j++) {
x = getMapX(i, j); // 得到该图片切块在图片中的X方向位置
y = getMapY(i, j); // 得到该图片切块在图片中的Y方向位置
cx = j * titleSize; // 缓冲区当前X方向位置
cy = i * titleSize; // 缓冲区当前Y方向位置
carGp.setClip(cx, cy, titleSize, titleSize);
carGp.drawImage(mapImage, cx - x, cy - y, 0); // 将图片切块绘制到缓冲区
}
}
}
/**
* 绘制地图
*
*/
public void darwMap(Graphics g, int x, int y) {
// 地图在缓冲中的坐标
int tempx = mapOffx % carWidth;
int tempy = mapOffy % carHeight;
// 切割线右下角的宽与高
int rightWidth = carWidth - tempx;
int rightHeight = carHeight - tempy;
drawRegion(g, carBuffer, tempx, tempy, rightWidth, rightHeight, 0, x,
y, 0);
drawRegion(g, carBuffer, 0, tempy, scrWidth - rightWidth, rightHeight,
0, x + rightWidth, y, 0);
drawRegion(g, carBuffer, tempx, 0, rightWidth, scrHeight - rightHeight,
0, x, y + rightHeight, 0);
drawRegion(g, carBuffer, 0, 0, scrWidth - rightWidth, scrHeight
- rightHeight, 0, x + rightWidth, y + rightHeight, 0);
}
/**
* 卷轴滚动
*
* @param x
* X轴滚动
* @param y
* Y轴滚动
*/
public void scroll(int x, int y) {
x += mapOffx;
y += mapOffy;
if (x < 0 || y < 0) {
return;
}
if (x > bufW) {
mapOffx = bufW;
return;
}
if (y > bufH) {
mapOffy = bufH;
return;
}
updateBuffer(x, y);
}
/**
* 更新缓冲区
*
* @param x
* 缓冲区新的地图X坐标
* @param y
* 缓冲区新的地图Y坐标
*/
private void updateBuffer(int x, int y) {
/** 改变偏移量 */
mapOffx = x;
mapOffy = y;
// 右移
if (x > carx + buffSize) {
int indexMapLastX = getIndexBuffLastX();
if (indexMapLastX < bufWNum) {
copyBufferX(indexMapLastX, getIndexCarY(), getTitleHeight(),
getBufferCarX(), getBufferCarY());
carx += titleSize;
}
}
// 左移
if (x < carx) {
carx -= titleSize;
copyBufferX(getIndexCarX(), getIndexCarY(), getTitleHeight(),
getBufferCarX(), getBufferCarY());
}
// 下移
if (y > cary + buffSize) {
int indexMapLastY = getIndexBuffLastY();
if (indexMapLastY < bufHNum) {
copyBufferY(getIndexCarX(), indexMapLastY, getTitelWidth(),
getBufferCarX(), getBufferCarY());
cary += titleSize;
}
}
// 上移
if (y < cary) {
cary -= titleSize;
copyBufferY(getIndexCarX(), getIndexCarY(), getTitelWidth(),
getBufferCarX(), getBufferCarY());
}
}
/**
* 获得地图图片的X坐标
*
* @param row
* map数组的横坐标
* @param col
* map数组的纵坐标
* @return 地图图片的X坐标
*/
private int getMapX(int row, int col) {
if (row < 20 && col < 20) {
return (mapArray[row][col] % imageTitleWidthNum) * titleSize;
} else {
return 0;
}
}
/**
* 获得地图图片的Y坐标
*
* @param row
* map数组的横坐标
* @param col
* map数组的纵坐标
* @return 地图图片的Y坐标
*/
private int getMapY(int row, int col) {
if (row < 20 && col < 20) {
return (mapArray[row][col] / imageTitleWidthNum) * titleSize;
} else {
return 0;
}
}
/**
* 获得缓冲画笔。
*
* @return 缓冲画笔
*/
public Graphics getGraphics() {
return carGp;
}
/**
* 获得缓冲区
*
* @return 缓冲
*/
public Image getImage() {
return carBuffer;
}
/**
* 画图
*
* @param g
* 目标屏幕的画笔
* @param img
* 原图片
* @param x_src
* 原图片X坐标
* @param y_src
* 原图片Y坐标
* @param width
* 原图片宽度
* @param height
* 原图片高度
* @param transform
* 旋转角度
* @param x_dest
* 目标屏幕的X坐标
* @param y_dest
* 目标屏幕的Y坐标
* @param anchor
* 画笔的锚点
*/
private void drawRegion(Graphics g, Image img, int x_src, int y_src,
int width, int height, int transform, int x_dest, int y_dest,
int anchor) {
// 作宽度检测
if (width <= 0 || height <= 0) {
return;
}
// 作超屏幕宽度检测
if (width > scrWidth) {
width = scrWidth;
// 作超屏幕高度检测
}
if (height > scrHeight) {
height = scrHeight;
}
g.drawRegion(img, x_src, y_src, width, height, transform, x_dest,
y_dest, anchor);
}
private void copyBufferX(int indexMapx, int indexMapy, int titleHeight,
int destx, int desty) {
int mapImagex, mapImagey, vy;
// 拷贝地图上面到缓冲的下面
for (int j = 0; j < titleHeight; j++) {
mapImagex = getMapX(indexMapy + j, indexMapx);
mapImagey = getMapY(indexMapy + j, indexMapx);
vy = j * titleSize + desty;
carGp.setClip(destx, vy, titleSize, titl