📄 map.java
字号:
import javax.microedition.lcdui.*;
import java.io.*;
import java.util.*;//该包包含随机数
public class Map {
private byte m_CellWidth; //单元格的宽
private byte m_CellHeight; //单元格的高
private byte m_Width; //地图宽(几列)
private byte m_Height; //地图高(几行)
private FloorUnit[] m_FloorUnit; //地表单元的数组
private TileUnit[] m_TileUnit;//建筑的单元块数组
private Role m_Role;//角色对象
private Role[] m_RoleArr;//角色种类对象数组
private Role[] m_ActionRoleArr;//当前地图中存在的角色对象数组
private int mapOffX;//地图坐标相对与屏幕坐标的偏移
private int mapOffY;//
private boolean bRunEvent;//是否在执行脚本事件
private String cmd[]=new String[10];//存放脚本命令的临时变量
byte[][] mapArr0; //地表数组
byte[][] mapArr1; //建筑层的数组
byte[][] mapArr2; //人物层的数组
byte[][] mapArr3; //数据层的数组
private Random rnd=new Random ();//随机变量
private int []npcAction; //非玩家角色的行为
private final int NPC_STAND = 0, NPC_UP = 1, NPC_DOWN = 2, NPC_LEFT = 3,
NPC_RIGHT = 4; //角色行为状态
private long[] time_npcChangeAction;//非玩家角色行为的开始执行时间
private int npcActionChangeTime=10000;//10秒切换一次行为
private String[] m_StrEvents;//脚本数组
private String[][]m_strGate;//门的数据
private final int GATE_MIN=-122,GATE_MAX=-100;//地图切换的门的触发点区间
public Map() {
initMap();
}
int _startX,_startY,_endX,_endY;//绘制的起始位置和宽高
/**
* 获得区间内的任意随机数
*/
public int getRnd(int _s, int _e) {
return Math.abs(rnd.nextInt() % (_e - _s + 1)) + _s;
}
/**
* 绘制地表和建筑
* @param g Graphics
*/
public void drawMap(Graphics g) {
mapOffX = m_Role.getIX() - Data.ScreenWidth / 2; //计算要保持人物居中显示的地图原点坐标
mapOffY = m_Role.getIY() - Data.ScreenHeight / 2;
if (mapOffX < 0) { //当地图向右越出屏幕 原点偏移为负
mapOffX = 0; //偏移为0 防止显示地图外的画面
}
else if (mapOffX > m_Width * 16 - Data.ScreenWidth) { //当地图向左越出屏幕
mapOffX = m_Width * 16 - Data.ScreenWidth; //地图原点偏移就等于临界值
}
if (mapOffY < 0) { //当地图向下越出屏幕 原点偏移为负
mapOffY = 0; //偏移为0 防止显示地图外的画面
}
else if (mapOffY > m_Height * 16 - Data.ScreenHeight) { //当地图向上越出屏幕
mapOffY = m_Height * 16 - Data.ScreenHeight; //地图原点偏移就等于临界值
}
_startX = mapOffX / m_CellWidth; //X轴绘制的其始位置
_endX = (mapOffX + Data.ScreenWidth) / m_CellWidth + 1; //X轴绘制的结束位置
if (_endX > m_Width) { //超出地图边界
_endX = m_Width;
}
_startY = mapOffY / m_CellHeight; //Y轴绘制的其始位置
_endY = (mapOffY + Data.ScreenHeight) / m_CellHeight + 1; //Y轴绘制的结束位置
if (_endY > m_Height) { //超出地图边界
_endY = m_Height;
}
for (int i = _startY; i < _endY; i++) { //循环绘制地表
for (int j = _startX; j < _endX; j++) {
if (mapArr0[i][j] != 0) { //为0时候代表改块为空
m_FloorUnit[mapArr0[i][j]-1].drawUnit(g,j * m_CellWidth - mapOffX, i * m_CellHeight - mapOffY);
}
}
}
for (int i = _startY; i < _endY; i++) { //循环绘建筑和人物
for (int j = _startX; j < _endX; j++) {
if (mapArr1[i][j] != 0) { //如果数值为0那么表示没建筑单元
m_TileUnit[mapArr1[i][j] - 1]. //数组m_TileUnit是从0开始而mapArr1是从1所以要-1
drawTileUnit(g, j * m_CellWidth - mapOffX,
i * m_CellHeight - mapOffY); //绘制建筑
}
if (mapArr2[i][j] != 0) { //循环到人物所在的位置时 绘制人物
int _id=mapArr2[i][j]-1;
m_ActionRoleArr[_id].drawRole(g, mapOffX, mapOffY); //绘制人物
if (m_ActionRoleArr[_id].getRoleState() ==
Data.ROLE_ATTACK) { //判断是否处于攻击状态
checkAttackHit(_id); //判断是否攻击到角色
}
if (_id != 0 ) { //主角除外
npcAction(_id );//调用Npc行为函数
}
}
}
}
g.setColor(0x000000);
g.setClip(0, 0, Data.ScreenWidth, Data.ScreenHeight);
if (bRunEvent) { //执行事件
if (cmd[0].equals("AutoRunX")) { //当命令是自动行走时
AutoRunX(Integer.parseInt(cmd[1])); //人物移动到地图的第5个格子处
}
else if (cmd[0].equals("a")) { //当命令是旁白时
g.drawString(cmd[1] + ":" + cmd[2], 5, Data.ScreenHeight - 20, 0); //绘制说话内容
if (System.currentTimeMillis() - eventTime > 2000) { //显示二秒钟后
nextCmd(); //取下一条命令
}
}
}
}
/**
* 处理非玩家角色的行为
* @param id int
*/
long []npcAttackTime;//NPC开始攻击的时间
public void npcAction(int id){
if (Math.abs(m_Role.getIX() - m_ActionRoleArr[id].getIX()) <
m_ActionRoleArr[id].getAttackArea()&&
Math.abs(m_Role.getIY() - m_ActionRoleArr[id].getIY()) <
m_ActionRoleArr[id].getAttackArea()) { //是否在攻击范围内
if (System.currentTimeMillis() - npcAttackTime[id] >
m_ActionRoleArr[id].getAttTime()) {//攻击间隔满足否
npcAttackTime[id] = System.currentTimeMillis();
attack(id); //攻击
}
}
if (m_ActionRoleArr[id].getRoleState() != Data.ROLE_ATTACK) {
//判断主角是否在NPC视野范围内
if (Math.abs(m_Role.getIX() - m_ActionRoleArr[id].getIX()) <
m_ActionRoleArr[id].getTraceArea()
&&
Math.abs(m_Role.getIY() - m_ActionRoleArr[id].getIY()) <
m_ActionRoleArr[id].getTraceArea()) {
//x方向的跟踪
if (m_Role.getIX() > m_ActionRoleArr[id].getIX()) {
keyEvent(id, Data.MYKEY_RIGHT);
}
else if (m_Role.getIX() < m_ActionRoleArr[id].getIX()) {
keyEvent(id, Data.MYKEY_LEFT);
}
else
//y方向的跟踪
if (m_Role.getIY() > m_ActionRoleArr[id].getIY()) {
keyEvent(id, Data.MYKEY_DOWN);
}
else if (m_Role.getIY() < m_ActionRoleArr[id].getIY()) {
keyEvent(id, Data.MYKEY_UP);
}
}
else { //否则一般行为
if (System.currentTimeMillis() - time_npcChangeAction[id] >
npcActionChangeTime) { //判断一个行为的执行时间是否已经超过时间间隔
npcAction[id] = getRnd(NPC_STAND, NPC_RIGHT); //获得新行为
time_npcChangeAction[id] = System.currentTimeMillis();
}
switch (npcAction[id]) { //根据不同的行为来执行
case NPC_UP: //NPC向上
keyEvent(id, Data.MYKEY_UP);
break;
case NPC_DOWN: //NPC向下
keyEvent(id, Data.MYKEY_DOWN);
break;
case NPC_LEFT: //NPC向左
keyEvent(id, Data.MYKEY_LEFT);
break;
case NPC_RIGHT: //NPC向右
keyEvent(id, Data.MYKEY_RIGHT);
break;
}
}
}
}
/**
* 脚本命令 AutoRunX(n)的解析函数
* @param n int 0<= n < m_Width
*/
private void AutoRunX(int n) {
if ( m_Role.getIX() / m_CellWidth< n) { //角色在目标点左边
keyEvent(0,Data.MYKEY_RIGHT); //角色向右走
if (m_Role.getIX() / m_CellWidth >= n) {
nextCmd();//取下一条命令
}
}
else if (m_Role.getIX() / m_CellWidth > n) { //角色在目标点右边
keyEvent(0,Data.MYKEY_LEFT); //角色向左走
if (m_Role.getIX() / m_CellWidth <= n) {
nextCmd();//取下一条命令
}
}
}
private void initMap() {
loadRole(); //载入角色
loadMap("1");
loadTitleUnit(); //载入建筑单元
m_Role = m_ActionRoleArr[0];//主角操作对象的赋值
m_ActionRoleArr[1].setActionID(0,0,2);
}
private void loadTitleUnit() {
InputStream fi = getClass().getResourceAsStream("/title.bin");//打开文件
DataInputStream din = new DataInputStream(fi);
try {
int titleImgNum = din.readByte();//读取图片数量
int titleNum=din.readByte();//读取建筑单元数量
Data.imgTile=new Image[titleImgNum];//
for (int i = 0; i < titleImgNum; i++) {//载入图片
Data.imgTile[i]=Image.createImage("/"+din.readUTF() );
}
m_TileUnit=new TileUnit[titleNum];
for (int i = 0; i < titleNum; i++) {
m_TileUnit[i]=new TileUnit();
m_TileUnit[i].loadTileData(din);//读取每个建筑单元的详细数据
}
din.close();
}
catch (IOException ex) {
ex.printStackTrace();
}
}
private void loadMap(String str){
InputStream fi = getClass().getResourceAsStream("/" + str + ".map"); //打开文件
DataInputStream di = new DataInputStream(fi);
try {
di.readLong(); //人物的存在标志
m_Width = di.readByte(); //地图宽
m_Height = di.readByte(); //地图高
m_CellWidth = di.readByte(); //单元格宽
m_CellHeight = di.readByte();
int imgTNum = di.readByte(); //地表单元图片数
int roleNum = di.readByte(); //角色数
mapArr0 = new byte[m_Height][m_Width];
mapArr1 = new byte[m_Height][m_Width];
mapArr2 = new byte[m_Height][m_Width];
mapArr3 = new byte[m_Height][m_Width];
Data.imgFloorTitle = new Image[imgTNum]; //地表单元图片数组建立
for (int i = 0; i < imgTNum; i++) { //载入图片
Data.imgFloorTitle[i] = Image.createImage("/" + di.readUTF());
}
int _num = di.readByte(); //地表单元的数量
m_FloorUnit = new FloorUnit[_num];
for (int i = 0; i < _num; i++) {
m_FloorUnit[i] = new FloorUnit();
m_FloorUnit[i].loadUnit(di); //创建和读取所有地表单元的数据
}
int roleIndex = 0; //角色索引
m_ActionRoleArr = new Role[roleNum]; //创建地图中的角色数组
npcAction = new int[roleNum]; //创建角色行为数组
time_npcChangeAction = new long[roleNum]; //非玩家角色行为的开始执行时间数组
npcAttackTime = new long[roleNum]; //角色攻击开始时间的数组
//地图数据
for (int i = 0; i < m_Height; i++)
for (int j = 0; j < m_Width; j++) { //读取每层数据的信息
mapArr3[i][j] = di.readByte(); //数据层
mapArr2[i][j] = di.readByte(); //人物层
mapArr1[i][j] = di.readByte(); //建筑
mapArr0[i][j] = di.readByte(); //地表
if (mapArr2[i][j] > 0) { //角色数组>0则有角色存在
m_ActionRoleArr[roleIndex] = new Role(this);
System.out.println( (mapArr2[i][j] - 1) + " ");
m_ActionRoleArr[roleIndex].copyRoll(m_RoleArr[mapArr2[i][j] - 1],
i, j); //Copy角色数据
mapArr2[i][j] = (byte) (roleIndex + 1); //让人物数组值==人物的ID号+1
roleIndex++;
}
}
int triggerNum = di.readByte(); //读取地图脚本出发器数量
m_StrEvents = new String[triggerNum]; //创建脚本数组
for (int i = 0; i < triggerNum; i++) {
m_StrEvents[i] = di.readUTF(); //读取脚本内容
}
di.readByte(); //读取角色脚本数量
//读入门数据
int gateNum = di.readByte();
m_strGate = new String[gateNum][5];//第二维为5 保存每个门的5个数据
for (int j = 0; j < gateNum; j++) {
for (int i = 0; i < m_strGate[j].length; i++) {
m_strGate[j][i] = di.readUTF();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -