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

📄 map.java

📁 JAVAME手机RPG游戏设计最终演示代码
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
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 + -