用AS3.0开发flash版SLG游戏-1

说到经典的战棋游戏,我还是最痴迷于曹操传,以前也曾因为研究曹操传MOD而废寖忘食,也做过一个曹操传的MOD小热一时,

却没想到曹操传MOD已经发展到现在这种地步,无论是画面还是技术都有了大规模的突破

但是,修改永远是修改,总会遇到各种限制,想要突破,当然要自己动手,开发自己的引擎。
但是,在这里,我研究flash版的曹操传,目的并不是想要有任何突破,只是单纯的为了研究一下,熟悉一下用flash完成各种游戏的制作而已。

先看几个预览

预览

预览

预览

 

下面开始制作过程

首先,先建立一个战场,显示一张地图吧,
导出一张曹操传第一关颖川的地图,把它转化成gif格式,命名为1.gif待用
然后,建立1S.xml,作为S剧本,内容
<?xml version="1.0" encoding="GB2312"?>
<data>
    <Map>1</Map>
</data>
里面的1就是地图的代号,对应的地图就是1.gif了
要显示它,就很简单了
建立两个Sprite,
//最底层Sprite
private var _bakSprite:Sprite;
//地图Sprite
private var _mapSprite:Sprite;
将地图建立在底层的Sprite,方便之后操作
_bakSprite.addChild(_mapSprite);

//加载地图
_pic_loader = new Loader();
_pic_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onCompleteMap);
var mapName:String = "Images/HM/" + _fightXml.Map + ".gif";
_pic_loader.load(new URLRequest(mapName));

//加载地图完毕
private function onCompleteMap(event:Event):void {
    _pic_loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onCompleteMap);
    _image = Bitmap(_pic_loader.content);
    _mapSprite.addChild(_image);
}
然后,一张地图,就可以显示出来了
当然,光显示出来还不行,因为地图很大,窗口显示不了全部的地图,这样,就要像曹操传中的那样,当鼠标移动到边界的时候,地图就发生移动,看到自己想看的位置
所以,需要加入鼠标移动事件
   //鼠标移动事件
   this.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);

  //鼠标移动事件
  private function mouseMoveHandler(event:MouseEvent):void{
   var intX:int = event.currentTarget.mouseX;
   var intY:int = event.currentTarget.mouseY;
   if(intX < 48){
     _mapXadd = 48;
   }else if(intX > Sav.gamedata["stageWidth"] - 48){
    _mapXadd = -48;
   }else{
    _mapXadd = 0;
   }
   if(intY < 48){
    _mapYadd = 48;
   }else if(intY > Sav.gamedata["stageHeight"] - 48){
    _mapYadd = -48;
   }else{
    _mapYadd = 0;
   }
  }
Sav.gamedata["stageWidth"] 是flash窗口的宽度,我把它存在了静态变量里了,方便用的时候取出来
这样,根据鼠标和地图位置,先来确定地图移动的x,y的方向和步长
然后,加入一个贞事件,来控制地图的移动
   //贞事件
   this.addEventListener(Event.ENTER_FRAME, mapMoveHandler);
  //贞事件
  private function mapMoveHandler(event:Event):void{
   if(_mapMoveCtrl > 5){
    //根据地图移动用xy步长移动地图
    _bakSprite.x += _mapXadd;
    _bakSprite.y += _mapYadd;
    _mapMoveCtrl = 0;
   }
   //控制地图不移出指定范围
   if(_bakSprite.x > 0){
    _bakSprite.x = 0;
   }else if( _bakSprite.x < Sav.gamedata["stageWidth"] - _bakSprite.width){
    _bakSprite.x = Sav.gamedata["stageWidth"] - _bakSprite.width;
   }
   if(_bakSprite.y > 0){
    _bakSprite.y = 0;
   }else if( _bakSprite.y < Sav.gamedata["stageHeight"] - _bakSprite.height){
    _bakSprite.y = Sav.gamedata["stageHeight"] - _bakSprite.height;
   }
   _mapMoveCtrl ++;
  }
_mapMoveCtrl 用来控制地图移动的速度,然后只要控制地图不移出指定的范围就可以了
这样,运行一下,就可以让地图自由的移动位置了

 

接下来,让地图上显示一个人物
导出曹操传中曹操的三个图片,去除背景,并保存为gif格式,就像下面这样

素材

首先,在1S.xml中加入
    <Our>
        <List>Caocao</List>
    </Our>
建立一个用来显示人物动作的类CharacterMC,
在类里面,读取完图片之后,将其按照规律拆分成数组,和之前我在做flashRPG游戏的时候一样,用的同样的方法,
  //Unit_mov图片加载完成
  public function onCompleteUnit_mov(event:Event):void {
   _image = Bitmap(_loader.content);
   //初始化显示数组
   _bitShowArr = new Array();
   //将位图数据拆分成小块,装入bitmapArr
   _bitmapArr=ImageCtrl.divide(_image,1,11);
   var newArr:Array;
   //得到向上行走数组
   newArr = new Array(_bitmapArr[2][0],_bitmapArr[3][0]);
   //将向上行走数组加入到显示数组 编号:0
   _bitShowArr.push(newArr);
   //得到向下行走数组
   newArr = new Array(_bitmapArr[0][0],_bitmapArr[1][0]);
   //将向下行走数组加入到显示数组 编号:1
   _bitShowArr.push(newArr);
   //得到向左行走数组
   newArr = new Array(_bitmapArr[4][0],_bitmapArr[5][0]);
   //将向左行走数组加入到显示数组 编号:2
   _bitShowArr.push(newArr);
   //得到向右行走数组
   newArr = new Array(ImageCtrl.bitHorizontal(_bitmapArr[4][0]),ImageCtrl.bitHorizontal(_bitmapArr[5][0]));
   //将向右行走数组加入到显示数组 编号:3
   _bitShowArr.push(newArr);
   
   startFrame();
  }
然后显示的时候,只需要调用不同的编号,就可以显示不同的动作了
新建一个人物属性类,Character ,存放人物的属性
 public class Character {
  //人物显示控制类
  private var _characterMC:CharacterMC;
  //人物移动力
  private var _moveLong:int;
  //人物编号
  private var _charaIndex:int;

然后在战场上,再另建一个Sprite,用来显示人物
  //人物Sprite
  private var _characterSprite:Sprite;
然后,在读取S剧本完成时,把人物加入
   //我军人物添加
   _ourArr = new Array();
   //根据xml内容,得到我军人物,添加至战场
   for each ( var ourment:XML in _fightXml.Our.elements( ) ) {
    var ourName:String = ourment.toString();
    var ourchara:XML = XML(_pXml[ourName]);
    _characterMC = new CharacterMC(int(ourchara.Id));
    _character = new Character(_characterMC,int(ourchara.Move),int(ourchara.Id));
    _characterSprite.addChild(_characterMC);
    _ourArr.push(_character);
   }
运行就可以看到曹操出现在战场上了
预览

下面,开始控制曹操移动

首先,先在CS4里,建立一个MC,加入三个按钮,如图
素材

我暂时把地形全都设定成为可移动,且地形全都消耗1,1S.xml中
    <DataMap>
 <list>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</list>
 <list>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</list>
 <list>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</list>
 <list>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</list>
 <list>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</list>
 <list>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</list>
 <list>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</list>
 <list>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</list>
 <list>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</list>
 <list>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</list>
 <list>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</list>
 <list>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</list>
 <list>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</list>
 <list>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</list>
 <list>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</list>
 <list>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</list>
 <list>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</list>
 <list>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</list>
 <list>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</list>
 <list>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</list>
    </DataMap>

加入鼠标点击事件
   //鼠标点击事件
   addEventListener(MouseEvent.CLICK,onClick);

  //鼠标点击事件
  private function onClick(event:Event):void{
   var __mouseX:Number = event.currentTarget.mouseX;
   var __mouseY:Number = event.currentTarget.mouseY;
   var i:int;
   if(_clickCtrl == "NULL"){
    for(i=0;i<_ourArr.length;i++){
     _character = _ourArr[i] as Character;
     _characterMC = _character.characterMC;
     if(Math.floor(_characterMC.x/48) == Math.floor(__mouseX/48) && Math.floor(_characterMC.y/48) == Math.floor(__mouseY/48)){
      _nowChatacter = _character;
      setRoad(_nowChatacter);
      _clickCtrl = "ROAD_SHOW";
      removeEventListener(MouseEvent.CLICK,onClick);
      _roadSprite.addEventListener(MouseEvent.CLICK,onClick);
      break;
     }
    }
   }else if(_clickCtrl == "ROAD_SHOW"){
    _characterMC = _nowChatacter.characterMC;
    for(i=0;i<_roadShowArray.length;i++){
      _nowPoint = new Point(Math.floor(_characterMC.x/48),Math.floor(_characterMC.y/48));
      _nowDirection = _characterMC.getDir();
      _toPoint = new Point(Math.floor(__mouseX/48),Math.floor(__mouseY/48));
      _roadArray = _roadQuery.path4(_nowPoint,_toPoint,_roadShowArray);
      if(_roadArray != null && _roadArray.length > 0){
       addEventListener(Event.ENTER_FRAME, onFrame);
       _clickCtrl == "MOVE_NOW"
       SpriteRemove.removeAllChildren(_roadSprite);
       _roadSprite.removeEventListener(MouseEvent.CLICK,onClick);
      }
    }
   }
   
   
  }
_clickCtrl 用来控制点击鼠标时,战场上的状态,当为NULL的时候,寻找点击的人物,然后开始寻找最大可移动的范围
    //循环搜寻可到达的点
    public function loopPath(thisPoint:Object):void{
     if(thisPoint.moveLong <= 0){
      return;
     }
     
      if(! thisPoint.isChecked){
      _path.push(thisPoint);
       thisPoint.isChecked = true;
      }
                    var checkList:Array = [];
                    //获取周围四个点
                    if (thisPoint.y>0) {
                       checkList.push(_map[(thisPoint.y-1)][thisPoint.x]);
                    }
                    if (thisPoint.x>0) {
                        checkList.push(_map[thisPoint.y][(thisPoint.x-1)]);
                    }
                    if (thisPoint.x<_w-1) {
                         checkList.push(_map[thisPoint.y][(thisPoint.x+1)]);
                    }
                    if (thisPoint.y<_h-1) {
                         checkList.push(_map[(thisPoint.y+1)][thisPoint.x]);
                    }
     for(var i=0;i<checkList.length;i++){
      if(!checkList[i].isChecked || checkList[i].moveLong < thisPoint.moveLong){
       checkList[i].moveLong = thisPoint.moveLong - 1;
       loopPath(checkList[i]);
      }
     } 
    }
    //搜寻最大路径
                public function makePath(star:Point, moveLong:int):Array {
                    _path = [];
                    var isOver:Boolean = false;
                    setStart();
                    _starPoint = _map[star.y][star.x];
     _starPoint.moveLong = moveLong;
     loopPath(_starPoint);
     return _path;
    }

预览

最大路径找好后,点击目标点,利用A*算法,走到目标点
_clickCtrl 用来控制点击鼠标时,战场上的状态,当为ROAD_SHOW的时候,查找路径,并走到目标点
A*算法,比较麻烦,就不多解释了,想了解的,可以看源代码
然后,行走完毕后,要显示出选择菜单,
  //人物移动事件贞控制
  private function onFrame(event:Event):void {
   _characterMC = _nowChatacter.characterMC;
   if(_roadArray != null && _roadArray.length > 1){
    if(_characterMC.x % 48 == 0 && _characterMC.y % 48 == 0){
      if(_roadArray[0].x == _roadArray[1].x){
      if(_roadArray[0].y > _roadArray[1].y){
       _characterMC.setDir(0);
       _xadd = 0;
       _yadd = -_addLeng;
      }else{
       _characterMC.setDir(1);
       _xadd = 0;
       _yadd = _addLeng;
      }
     }else{
      if(_roadArray[0].x > _roadArray[1].x){
       _characterMC.setDir(2);
       _xadd = -_addLeng;
       _yadd = 0;
      }else{
       _characterMC.setDir(3);
       _xadd = _addLeng;
       _yadd = 0;
      }
     }     

     _roadArray.splice(0,1);
                                       
    }
    _characterMC.x += _xadd;
    _characterMC.y += _yadd;
                               
   }else if(_characterMC.x % 48 == 0 && _characterMC.y % 48 == 0){
    removeEventListener(Event.ENTER_FRAME, onFrame);
    _selectBox.visible = true;
    _selectBox.x = _characterMC.x + 48;
    _selectBox.y = _characterMC.y;
   }else{
   
    _characterMC.x += _xadd;
    _characterMC.y += _yadd;
   }
  }
所以在战场初始化的时候,加入菜单按钮等事件
   
   //点击停止事件
   _selectBox.btnStop.addEventListener(MouseEvent.CLICK, charaStopHandler);
   //点击取消事件
   _selectBox.btnCan.addEventListener(MouseEvent.CLICK, charaCanHandler);
   //菜单隐藏
   _selectBox.visible = false;
效果如下图
预览

接下来,显示一下地形,
准备一个Terrain.xml
<?xml version="1.0" encoding="GB2312"?>
<data>
    <Terrain0>
 <Name>平原</Name>
 <Image></Image>
    </Terrain0>
    <Terrain1>
 <Name>草原</Name>
 <Image></Image>
    </Terrain1>
    <Terrain2>
 <Name>树林</Name>
 <Image></Image>
    </Terrain2>
</data>
暂时添加这三个地形,等有时间了之后,再慢慢加
然后,在CS4里,建立一个MC,如下,用来显示地形

素材

剩下的就简单了,
在战场的鼠标点击事件中,当状态为NULL的时候,
   if(_clickCtrl == "NULL"){
    var queryPeople:Boolean = false;
    //点击我军人物判断
    for(i=0;i<_ourArr.length;i++){
     _character = _ourArr[i] as Character;
     _characterMC = _character.characterMC;
     if(Math.floor(_characterMC.x/48) == Math.floor(__mouseX/48) && Math.floor(_characterMC.y/48) == Math.floor(__mouseY/48)){
      _nowChatacter = _character;
      setRoad(_nowChatacter);
      _clickCtrl = "ROAD_SHOW";
      removeEventListener(MouseEvent.CLICK,onClick);
      _roadSprite.addEventListener(MouseEvent.CLICK,onClick);
      queryPeople = true;
      break;
     }
    }
    //点击敌军人物判断
    for(i=0;i<_enemyArr.length;i++){
     //点击敌军人物动作
    }
    if(!queryPeople){
     //点击地图,显示地形
     _clickCtrl = "TERRAIN_SHOW";
     var mapX:int = Math.floor((__mouseX - _bakSprite.x)/48);
     var mapY:int = Math.floor((__mouseY - _bakSprite.y)/48);
     var showX:int = Math.floor(__mouseX/48);
     var showY:int = Math.floor(__mouseY/48);
     var terrainId:int = _mapDate[mapX][mapY];
     var terrainName:String = "Terrain" + terrainId;
     _terrainBox.x = showX*48 - 48;
     _terrainBox.y = showY*48 - 48;
     if(_terrainBox.x < 0){
      _terrainBox.x = 0;
     }else if(_terrainBox.x > Sav.gamedata["stageWidth"] - 144){
      _terrainBox.x = Sav.gamedata["stageWidth"] - 144;
     }
     if(_terrainBox.y < 0){
      _terrainBox.y = 0;
     }else if(_terrainBox.y > Sav.gamedata["stageHeight"] - 144){
      _terrainBox.y = Sav.gamedata["stageHeight"] - 144;
     }
     _terrainBox.TerrainName.text = _terrain[terrainName].Name;
     SpriteRemove.removeAllChildren(_terrainBox.TerrainShow);
     _terrainBox.TerrainShow.addChild(ImageCtrl.getImage(_bmapimage,mapX*48,mapY*48,48,48));
     removeEventListener(MouseEvent.CLICK,onClick);
     _terrainBox.visible = true;
    }
   }else if(_clickCtrl == "ROAD_SHOW"){
就是说,点击的地方如果没有人,则显示地形框
然后,在鼠标移动的时候,把地形框隐藏掉
  //鼠标移动事件
  private function mouseMoveHandler(event:MouseEvent):void{
   var intX:int = event.currentTarget.mouseX;
   var intY:int = event.currentTarget.mouseY;
   if(intX < 48){
     _mapXadd = 48;
   }else if(intX > Sav.gamedata["stageWidth"] - 48 && intX <= Sav.gamedata["stageWidth"]){
    _mapXadd = -48;
   }else{
    _mapXadd = 0;
   }
   if(intY < 48){
    _mapYadd = 48;
   }else if(intY > Sav.gamedata["stageHeight"] - 48 && intY <= Sav.gamedata["stageHeight"]){
    _mapYadd = -48;
   }else{
    _mapYadd = 0;
   }
   if(_terrainBox.visible){
    _clickCtrl = "NULL";
    _terrainBox.visible = false;
    addEventListener(MouseEvent.CLICK,onClick);
   }
  }
看吧,效果如下图

预览

因为地形我全都设定成了0,所以现在点哪里都是平原

剩下的就是把1S.xml的地形好好设定下了

下次,研究在各种地形下行走的范围^0^!

下面,来继续在不同地形下的寻路问题
首先,准备好兵种数据Arms.xml
<?xml version="1.0" encoding="GB2312"?>
<data>
    <Arms1>
 <Name>英雄</Name>
 <Property>
     <Attack>A</Attack>
     <Spirit>A</Spirit>
     <Defense>A</Defense>
     <Breakout>A</Breakout>
     <Morale>A</Morale>
 </Property>
 <Terrain>
     <Terrain0>1</Terrain0>
     <Terrain1>1</Terrain1>
     <Terrain2>2</Terrain2>
     <Terrain3>100</Terrain3>
     <Terrain4>100</Terrain4>
     <Terrain5>1</Terrain5>
     <Terrain6>1</Terrain6>
     <Terrain7>1</Terrain7>
 </Terrain>
    </Arms1>
</data>
地形数据Terrain.xml
<?xml version="1.0" encoding="GB2312"?>
<data>
    <Terrain0>平原</Terrain0>
    <Terrain1>草原</Terrain1>
    <Terrain2>树林</Terrain2>
    <Terrain3>大河</Terrain3>
    <Terrain4>栅栏</Terrain4>
    <Terrain5>城池</Terrain5>
    <Terrain6>村庄</Terrain6>
    <Terrain7>帐篷</Terrain7>
</data>
人物属性上当然要对应好兵种
<?xml version="1.0" encoding="GB2312"?>
<data>
    <Caocao>
 <Id>1</Id>
 <Name>曹操</Name>
 <Arms>1</Arms>
 <Lv>1</Lv>
 <Exp>0</Exp>
 <HP>100</HP>
 <MP>50</MP>
 <Move>5</Move>
    </Caocao>
</data>
其中,Arms是兵种ID,Move是移动力
最后,设定下战场文件1S.xml
<?xml version="1.0" encoding="GB2312"?>
<data>
    <Map>1</Map>
    <DataMap>
 <list>1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1</list>
 <list>3,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1</list>
 <list>3,3,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1</list>
 <list>3,3,3,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,3,3</list>
 <list>3,3,3,3,1,1,1,0,0,0,0,1,1,1,1,1,1,3,3,3</list>
 <list>3,3,3,3,3,1,1,0,0,0,0,0,1,1,1,1,1,3,3,3</list>
 <list>3,3,3,3,3,4,4,4,4,0,0,4,4,4,4,1,1,3,3,3</list>
 <list>3,3,3,3,3,4,6,0,0,0,0,0,0,6,4,1,3,3,3,3</list>
 <list>3,3,3,3,3,4,6,0,0,0,0,0,0,6,4,1,3,3,3,3</list>
 <list>3,3,3,3,0,4,6,0,0,0,0,0,0,0,4,1,3,3,3,3</list>
 <list>3,3,3,0,0,0,0,0,0,4,4,0,0,0,4,3,3,3,3,3</list>
 <list>3,3,0,0,0,0,0,0,0,5,7,0,0,0,4,3,3,3,3,3</list>
 <list>3,0,0,0,0,4,0,0,0,0,0,0,0,0,4,3,3,3,3,3</list>
 <list>0,0,0,0,0,4,6,6,0,0,0,0,0,7,4,0,3,3,3,3</list>
 <list>0,0,0,0,0,4,4,4,4,0,0,4,4,4,4,0,1,1,3,3</list>
 <list>0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,3</list>
 <list>1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1</list>
 <list>1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1</list>
 <list>1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1</list>
 <list>1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1</list>
    </DataMap>
    <Our>
        <List x="10" y="5">Caocao</List>
    </Our>
    <Enemy />
</data>

然后开始利用这些数据,完成寻路
首先在添加战场人物的时候,要把相应的兵种和移动力都得到
   //我军人物添加
   _ourArr = new Array();
   //根据xml内容,得到我军人物,添加至战场
   for each ( var ourment:XML in _fightXml.Our.elements( ) ) {
    var ourName:String = ourment.toString();
    var ourchara:XML = XML(_pXml[ourName]);
    _characterMC = new CharacterMC(int(ourchara.Id));
    _characterMC.x = int(ourment.@x)*48;
    _characterMC.y = int(ourment.@y)*48;
    _character = new Character(_characterMC,int(ourchara.Move),int(ourchara.Id),int(ourchara.Arms));
    _characterSprite.addChild(_characterMC);
    _ourArr.push(_character);
   }
Character类中,加入兵种ID属性就可以了

然后,寻路的时候,把当前人物传到makePath方法中

  //寻找最大移动范围
  private function setRoad(chara:Character){
   _roadShowArray = _roadQuery.makePath(chara);
   
   if(_roadShowArray != null && _roadShowArray.length > 0){
    var sign:Sign;
    for(var i:int = 0;i<_roadShowArray.length;i++){
     sign = new Sign();
     sign.x = _roadShowArray[i].x * 48;
     sign.y = _roadShowArray[i].y * 48;
     _roadSprite.addChild(sign);
    }
   }
  }

_roadQuery方法中,移动力和起始坐标都根据当前人物得到
                public function makePath(chara:Character):Array {
     _chara = chara;
                    _path = [];
                    var isOver:Boolean = false;
                    setStart();
                    _starPoint = _map[Math.floor(chara.characterMC.y/48)][Math.floor(chara.characterMC.x/48)];
     _starPoint.moveLong = chara.moveLong;
     loopPath(_starPoint);
     return _path;
    }
然后,在loopPath方法中,做最后的修改
checkPoint.moveLong = thisPoint.moveLong - 1;是用来计算下一个点的剩余移动力的,
之前,所有点的移动力都是由当前点的移动力-1
把它改为
var cost:int = int(XML(Sav.gamedata["Arms"])["Arms" + _chara.armsIndex]["Terrain"]["Terrain" + _map[checkPoint.y][checkPoint.x].value]);
       checkPoint.moveLong = thisPoint.moveLong - cost;
就是减去下一个点的消耗移动力,这个消耗移动力在兵种数据文件中已经设定好了,直接读取就可以了
运行代码,效果如下

预览

下次,该研究一下,加入敌军的人物问题了

其实,加入敌军人物,只需要在1S.xml中加入几个人物就可以了
    <Our>
        <List x="10" y="4">1</List>
        <List x="10" y="5">98</List>
    </Our>
    <Enemy>
        <List x="12" y="5">100</List>
        <List x="16" y="5">103</List>
    </Enemy>
然后配置好,相应的兵种数据和人物数据,就可以在战场上显示了
剩下的还要改动一下寻路的方法,把战场上有人物的地方,改为消耗移动力100

                public function makePath(chara:Character):Array {
     _chara = chara;
                    _path = [];
                    var isOver:Boolean = false;
                    setStart();
     _enemyCost = new Object();
     var i:int = 0;
     var objarr:Array;
     objarr = _fightMap.enemyArr;
     for(i=0;i<objarr.length;i++){
      _enemyCost[objarr[i].locationX + "-" +objarr[i].locationY] = 100;
     }
     objarr = _fightMap.ourArr;
     for(i=0;i<objarr.length;i++){
      _enemyCost[objarr[i].locationX + "-" +objarr[i].locationY] = 100;
     }
                    _starPoint = _map[Math.floor(chara.character.y/48)][Math.floor(chara.character.x/48)];
     _starPoint.moveLong = chara.moveLong;
     loopPath(_starPoint);
     
     return _path;
    }

    public function loopPath(thisPoint:Object):void{
     if(thisPoint.moveLong <= 0){
      return;
     }
     
      if(! thisPoint.isChecked){
      _path.push(thisPoint);
       thisPoint.isChecked = true;
      }
                    var checkList:Array = [];
                    //获取周围四个点
                    if (thisPoint.y>0) {
                       checkList.push(_map[(thisPoint.y-1)][thisPoint.x]);
                    }
                    if (thisPoint.x>0) {
                        checkList.push(_map[thisPoint.y][(thisPoint.x-1)]);
                    }
                    if (thisPoint.x<_w-1) {
                         checkList.push(_map[thisPoint.y][(thisPoint.x+1)]);
                    }
                    if (thisPoint.y<_h-1) {
                         checkList.push(_map[(thisPoint.y+1)][thisPoint.x]);
                    }
     for(var i=0;i<checkList.length;i++){
                         var checkPoint:Object = checkList[i];
      if(!checkPoint.isChecked || checkPoint.moveLong < thisPoint.moveLong){
       var cost:int = int(XML(Sav.gamedata["Arms"])["Arms" + _chara.armsIndex]["Terrain"]["Terrain" + _map[checkPoint.y][checkPoint.x].value]);
       cost += _enemyCost[checkPoint.x + "-" + checkPoint.y] == null ? 0:_enemyCost[checkPoint.x + "-" + checkPoint.y];
       checkPoint.moveLong = thisPoint.moveLong - cost;
       loopPath(checkPoint);
      }
     } 
    }
这样战场上有人的地方就移动不过去了

接下来,来给每个人加上攻击范围的光标
准备好攻击范围显示的光标MC

素材

然后,在相应的兵种数据中加上攻击范围的控制
如英雄
    <Arms1>
 <Name>英雄</Name>
 <Property>
     <Attack>A</Attack>
     <Spirit>A</Spirit>
     <Defense>A</Defense>
     <Breakout>A</Breakout>
     <Morale>A</Morale>
 </Property>
 <Terrain>
     <Terrain0>1</Terrain0>
     <Terrain1>1</Terrain1>
     <Terrain2>2</Terrain2>
     <Terrain3>100</Terrain3>
     <Terrain4>100</Terrain4>
     <Terrain5>1</Terrain5>
     <Terrain6>1</Terrain6>
     <Terrain7>1</Terrain7>
 </Terrain>
 <RangeAttack>
     <List>0,-1</List>
     <List>0,1</List>
     <List>-1,0</List>
     <List>1,0</List>
 </RangeAttack>
    </Arms1>
其中RangeAttack代表以当前人物为坐标的相对攻击范围
然后在战场类中加一个函数
  //攻击范围显示
  private function setAttRound(armIndex:int):void{
   var attRoundArr:Array;
   var attRound:AttBox;
   for each ( var roundment:XML in _arms["Arms" + armIndex]["RangeAttack"].elements( ) ) {
    attRound = new AttBox();
    attRoundArr = roundment.toString().split(",");
    attRound.x = (int(attRoundArr[0]) + _nowChatacter.locationX )*48;
    attRound.y = (int(attRoundArr[1]) + _nowChatacter.locationY) *48;
    _roadSprite.addChild(attRound);
   }
   
  }
其中AttBox是预先准备好的攻击范围显示的光标MC
然后,在寻找最大行动范围的时候,调用这个函数
就可以显示攻击范围了,效果如图

预览

接下来,研究一下回合控制,和敌军回合的时候,敌军的行动

这次除了添加一些东西外,改动也比较大
具体改了哪里,也忘了做记录了
最后成形的战场类代码如下FightMap .as

package Caocao.Mains{
 import Lufy.Images.ImageCtrl;
 import Lufy.Sprite.SpriteRemove;
 import Caocao.Character.CharacterMC;
 import Caocao.Character.Character;
 import Caocao.ot.RoadQuery;
 import Lufy.Xml.XMLLoader;
 
 import flash.net.URLLoader;
 import flash.display.Sprite;
 import flash.display.Bitmap;
 import flash.display.BitmapData;
 import flash.display.Loader;
 import flash.events.Event;
 import flash.net.URLRequest;
 import flash.geom.Point;
 import flash.events.MouseEvent;
    import flash.utils.Timer;
 import flash.events.KeyboardEvent;
 import flash.text.*;
 
 public class FightMap extends Sprite {
  //最底层Sprite
  private var _bakSprite:Sprite;
  //地图Sprite
  private var _mapSprite:Sprite;
  //人物Sprite
  private var _characterSprite:Sprite;
  //通路Sprite
  private var _roadSprite:Sprite;
  //战场Xml
  private var _fightXml:XML;
  //地形数组
  private var _mapData:Array;
  //图片载入器
  private var _pic_loader:Loader;
  //xml载入器
  private var _xml_loader:XMLLoader;
  //声明Bitmap
  private var _image:Bitmap;
  //大地图Bitmap
  private var _bmapimage:Bitmap;
  //人物类
  private var _character:Character;
  private var _characterMC:CharacterMC;
  private var _nowChatacter:Character;
  //我军数组
  private var _ourArr:Array;
  //敌军数组
  private var _enemyArr:Array;
  //寻路类
  private var _roadQuery:RoadQuery;
  //储存路径数组
  private var _roadArray:Array;
  //表示路径数组
  private var _roadShowArray:Array;
  //人物移动控制
  private var _xadd:int = 0;
  private var _yadd:int = 0;
  //人物移动步长
  private var _addLeng:int = 4;
  //移动起始坐标
  private var _nowPoint:Point;
  //移动起始方向
  private var _nowDirection:int;
  //移动目的地坐标
  private var _toPoint:Point;
  //点击动作控制
  private var _clickCtrl:String = "NULL";
  //人物数据
  private var _pXml:XML;
  //地形数据
  private var _terrain:XML;
  //兵种数据
  private var _arms:XML;
  //选择菜单
  private var _selectBox:SelectBox;
  //地图移动速度控制
  private var _mapMoveCtrl:int = 0;
  //地图移动用xy步长
  private var _mapXadd:int = 0;
  private var _mapYadd:int = 0;
  //地形框
  private var _terrainBox:TerrainShowBox;
  //回合控制
  private var _roundCtrl:String = "我方回合";
  //回合数
  private var _roundIndex:int = 1;
  //鼠标框
  private var _mouseBox:MouseBox;
  //敌方行动控制用
  private var _enemyActionCtrl:int = 0;
  //回合显示信息
  private var _roundShow:TextField ;
  //回合显示信息控制用
  private var _roundShowCtrl:int = 0;
  public function FightMap(mapXmlSrc:String,fun:Function,gameMap:GameStart) {
   //添加显示Sprite
   _bakSprite = new Sprite();
   addChild(_bakSprite);
   _mapSprite = new Sprite();
   _bakSprite.addChild(_mapSprite);
   _characterSprite = new Sprite();
   _bakSprite.addChild(_characterSprite);
   _roadSprite = new Sprite();
   _bakSprite.addChild(_roadSprite);
   
   _mouseBox = new MouseBox();
   _bakSprite.addChild(_mouseBox);
   
   _selectBox = new SelectBox();
   _bakSprite.addChild(_selectBox);
   
   _terrainBox = new TerrainShowBox();
   addChild(_terrainBox);
   
   textInit();
   
   //菜单事件
   //点击停止事件
   _selectBox.btnStop.addEventListener(MouseEvent.CLICK, charaStopHandler);
   //点击取消事件
   _selectBox.btnCan.addEventListener(MouseEvent.CLICK, charaCanHandler);
   //菜单隐藏
   _selectBox.visible = false;
   
   
   //地形显示框隐藏
   _terrainBox.visible = false;
   
   //得到所有人物数据
   _pXml = Sav.gamedata["people"] as XML;
   //得到所有地形数据
   _terrain = Sav.gamedata["Terrain"] as XML;
   //得到所有兵种数据
   _arms = Sav.gamedata["Arms"] as XML;
   
   //鼠标点击事件
   _bakSprite.addEventListener(MouseEvent.CLICK,onClick);
   //贞事件
   this.addEventListener(Event.ENTER_FRAME, mapMoveHandler);
   
   //鼠标移动事件
   addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
   //鼠标移动事件
   _bakSprite.addEventListener(MouseEvent.MOUSE_MOVE, mouseBakMoveHandler);
   
   //载入人物属性Xml
   _xml_loader = new XMLLoader();
   _xml_loader.onLoadComplete      = initStage;
   _xml_loader.load(mapXmlSrc, XMLLoader.GB2312);
  }
  //文本格式
  private function textInit():void{
  
   _roundShow = new TextField();
   _roundShow.autoSize = TextFieldAutoSize.LEFT;
   var formatter:TextFormat = new TextFormat( );
   formatter.color = 0xCCCCCC;
   formatter.size = 60;
   formatter.bold = true;
   _roundShow.defaultTextFormat = formatter;
   _roundShow.text = "";
   addChild(_roundShow);
  }
  //贞事件
  private function mapMoveHandler(event:Event):void{
   if(_mapMoveCtrl > 5){
    //根据地图移动用xy步长移动地图
    _bakSprite.x += _mapXadd;
    _bakSprite.y += _mapYadd;
    _mapMoveCtrl = 0;
   }
   //控制地图不移出指定范围
   if(_bakSprite.x > 0){
    _bakSprite.x = 0;
   }else if( _bakSprite.x < Sav.gamedata["stageWidth"] - _bakSprite.width){
    _bakSprite.x = Sav.gamedata["stageWidth"] - _bakSprite.width;
   }
   if(_bakSprite.y > 0){
    _bakSprite.y = 0;
   }else if( _bakSprite.y < Sav.gamedata["stageHeight"] - _bakSprite.height){
    _bakSprite.y = Sav.gamedata["stageHeight"] - _bakSprite.height;
   }
   if(_roundShowCtrl == 0){
    _roundShow.text = "第" + _roundIndex + "回合/n";
    _roundShow.x = (Sav.gamedata["stageWidth"] - _roundShow.width)/2;
    _roundShow.y = (Sav.gamedata["stageHeight"] - _roundShow.height)/2;
   }else if(_roundShowCtrl == 40){
    _roundShow.text = "/n" + _roundCtrl;
    _roundShow.x = (Sav.gamedata["stageWidth"] - _roundShow.width)/2;
    _roundShow.y = (Sav.gamedata["stageHeight"] - _roundShow.height)/2;
   }else if(_roundShowCtrl == 80){
    _roundShow.text = "";
    if(_roundCtrl == "我方回合"){
     _bakSprite.addEventListener(MouseEvent.CLICK,onClick);
    }else if(_roundCtrl == "敌方回合"){
     addEventListener(Event.ENTER_FRAME, onEnemyFrame);
    }
   }
   _roundShowCtrl++;
   _mapMoveCtrl ++;
  }
  //鼠标移动事件
  private function mouseBakMoveHandler(event:MouseEvent):void{
   var intX:int = event.currentTarget.mouseX;
   var intY:int = event.currentTarget.mouseY;
   _mouseBox.x = Math.floor(intX/48)*48;
   _mouseBox.y = Math.floor(intY/48)*48;
  }
  //鼠标移动事件
  private function mouseMoveHandler(event:MouseEvent):void{
   var intX:int = event.currentTarget.mouseX;
   var intY:int = event.currentTarget.mouseY;
   if(intX < 48){
     _mapXadd = 48;
   }else if(intX > Sav.gamedata["stageWidth"] - 48 && intX <= Sav.gamedata["stageWidth"]){
    _mapXadd = -48;
   }else{
    _mapXadd = 0;
   }
   if(intY < 48){
    _mapYadd = 48;
   }else if(intY > Sav.gamedata["stageHeight"] - 48 && intY <= Sav.gamedata["stageHeight"]){
    _mapYadd = -48;
   }else{
    _mapYadd = 0;
   }
   if(_terrainBox.visible){
    _clickCtrl = "NULL";
    _terrainBox.visible = false;
    _bakSprite.addEventListener(MouseEvent.CLICK,onClick);
   }
   if(_clickCtrl == "ENEMY_ROUND_SHOW"){
    _clickCtrl = "NULL";
    SpriteRemove.removeAllChildren(_roadSprite);
    _bakSprite.addEventListener(MouseEvent.CLICK,onClick);
   }
  }
  
  //用来重新载入点击事件
  private function onClickFrame(event:Event):void {
   removeEventListener(Event.ENTER_FRAME, onClickFrame);
   var ctrl:Boolean = false;
   var i:int;
   for(i = 0;i<_ourArr.length;i++){
    if(!_ourArr[i].actionCtrl){
     ctrl = true;
     break;
    }
   }
   if(!ctrl){
    _roundCtrl = "敌方回合";
    for(i=0;i<_enemyArr.length;i++){
     _enemyArr[i].actionCtrl = false;
    }
    _enemyActionCtrl = 0;
    //addEventListener(Event.ENTER_FRAME, onEnemyFrame);
    _roundShowCtrl  = 40;
   }else{
    _bakSprite.addEventListener(MouseEvent.CLICK,onClick);
   }
  }
  
  //控制敌军行动事件
  private function onEnemyFrame(event:Event):void {
   var i:int;
   var toDistance:int;
   var checkDistance:int;
   if(_clickCtrl == "NULL"){
    _nowChatacter = null;
    //寻找未行动人员
    for(i=0;i<_enemyArr.length;i++){
     if(!_enemyArr[i].actionCtrl){
      _nowChatacter = _enemyArr[i];
      break;
     }
    }
    //如果全部行动完毕,则进入我军回合
    if(_nowChatacter == null){
     _roundCtrl = "我方回合";
     for(i=0;i<_ourArr.length;i++){
      _ourArr[i].actionCtrl = false;
     }
     removeEventListener(Event.ENTER_FRAME, onEnemyFrame);
     _roundIndex ++;
     _roundShowCtrl  = 0;
     return;
    }
    if(_enemyActionCtrl == 0){
     //得到为行动人员,开始寻路显示
     _clickCtrl = "ROAD_SHOW";
     setRoad(_nowChatacter);
    }
   }
   if(_clickCtrl == "ROAD_SHOW" && _enemyActionCtrl == 10){
    //开始行动
    _toPoint = new Point(_roadShowArray[0].x,_roadShowArray[0].y);
    i = Math.random() * _ourArr.length;
    _character = _ourArr[i];
    toDistance = Math.abs(_character.locationX - _toPoint.x) + Math.abs(_character.locationY - _toPoint.y) ;
    for(i=1;i<_roadShowArray.length;i++){
     checkDistance = Math.abs(_character.locationX - _roadShowArray[i].x) + Math.abs(_character.locationY - _roadShowArray[i].y) ;
     if(checkDistance < toDistance){
      toDistance = checkDistance;
      _toPoint.x = _roadShowArray[i].x;
      _toPoint.y = _roadShowArray[i].y;
     }
    }
    _nowPoint = new Point( _nowChatacter.locationX, _nowChatacter.locationY);
    _nowDirection = _characterMC.getDir();
    charaToMove();
   }
   _enemyActionCtrl ++;
   
  }
  //点击停止事件
  private function charaStopHandler(event:MouseEvent):void{
   _clickCtrl = "NULL";
   _nowChatacter.actionCtrl = true;
   _selectBox.visible = false;
   addEventListener(Event.ENTER_FRAME, onClickFrame);
  }
  //点击取消事件
  private function charaCanHandler(event:MouseEvent):void{
   _clickCtrl = "NULL";
   _selectBox.visible = false;
   _characterMC = _nowChatacter.character;
   _characterMC.x = _nowPoint.x * 48;
   _characterMC.y = _nowPoint.y * 48;
   _characterMC.setDir(_nowDirection);
   addEventListener(Event.ENTER_FRAME, onClickFrame);
  }
  
  //寻找最大移动范围
  private function setRoad(chara:Character){
   _roadShowArray = _roadQuery.makePath(chara);
   
   if(_roadShowArray != null && _roadShowArray.length > 0){
    var sign:Sign;
    for(var i:int = 0;i<_roadShowArray.length;i++){
     sign = new Sign();
     sign.x = _roadShowArray[i].x * 48;
     sign.y = _roadShowArray[i].y * 48;
     _roadSprite.addChild(sign);
    }
    setAttRound(_pXml["peo" + _nowChatacter.charaIndex].Arms);
   }
  }
  //攻击范围显示
  private function setAttRound(armIndex:int):void{
   var attRoundArr:Array;
   var attRound:AttBox;
   for each ( var roundment:XML in _arms["Arms" + armIndex]["RangeAttack"].elements( ) ) {
    attRound = new AttBox();
    attRoundArr = roundment.toString().split(",");
    attRound.x = (int(attRoundArr[0]) + _nowChatacter.locationX )*48;
    attRound.y = (int(attRoundArr[1]) + _nowChatacter.locationY) *48;
    _roadSprite.addChild(attRound);
   }
   
  }
  //鼠标点击事件
  private function onClick(event:Event):void{
   var __mouseX:Number = event.currentTarget.mouseX;
   var __mouseY:Number = event.currentTarget.mouseY;
   var i:int;
   if(_clickCtrl == "NULL"){
    var queryPeople:Boolean = false;
    //点击我军人物判断
    for(i=0;i<_ourArr.length;i++){
     _character = _ourArr[i] as Character;
     _characterMC = _character.character;
     if(Math.floor(_characterMC.x/48) == Math.floor(__mouseX/48) && Math.floor(_characterMC.y/48) == Math.floor(__mouseY/48)){
      _nowChatacter = _character;
      setRoad(_nowChatacter);
      _clickCtrl = "ROAD_SHOW";
      _bakSprite.removeEventListener(MouseEvent.CLICK,onClick);
      _roadSprite.addEventListener(MouseEvent.CLICK,onClick);
      queryPeople = true;
      break;
     }
    }
    //点击敌军人物判断
    for(i=0;i<_enemyArr.length && !queryPeople;i++){
     _character = _enemyArr[i] as Character;
     _characterMC = _character.character;
     if(Math.floor(_characterMC.x/48) == Math.floor(__mouseX/48) && Math.floor(_characterMC.y/48) == Math.floor(__mouseY/48)){
      _nowChatacter = _character;
      setRoad(_nowChatacter);
      _clickCtrl = "ENEMY_ROUND_SHOW";
      _bakSprite.removeEventListener(MouseEvent.CLICK,onClick);
      queryPeople = true;
      break;
     }
    }
    if(!queryPeople){
     //点击地图,显示地形
     _clickCtrl = "TERRAIN_SHOW";
     var mapX:int = Math.floor(__mouseX/48);
     var mapY:int = Math.floor(__mouseY/48);
     var terrainId:int = _mapData[mapY][mapX];
     var terrainName:String = "Terrain" + terrainId;
     _terrainBox.x = mapX *48 - 48 + _bakSprite.x;
     _terrainBox.y = mapY*48 - 48 + _bakSprite.y;
     if(_terrainBox.x < 0){
      _terrainBox.x = 0;
     }else if(_terrainBox.x > Sav.gamedata["stageWidth"] - 144){
      _terrainBox.x = Sav.gamedata["stageWidth"] - 144;
     }
     if(_terrainBox.y < 0){
      _terrainBox.y = 0;
     }else if(_terrainBox.y > Sav.gamedata["stageHeight"] - 144){
      _terrainBox.y = Sav.gamedata["stageHeight"] - 144;
     }
     _terrainBox.TerrainName.text = _terrain[terrainName];
     SpriteRemove.removeAllChildren(_terrainBox.TerrainShow);
     _terrainBox.TerrainShow.addChild(ImageCtrl.getImage(_bmapimage,mapX*48,mapY*48,48,48));
     _bakSprite.removeEventListener(MouseEvent.CLICK,onClick);
     _terrainBox.visible = true;
    }
   }else if(_clickCtrl == "ROAD_SHOW"){
    _characterMC = _nowChatacter.character;
    for(i=0;i<_roadShowArray.length;i++){
      _nowPoint = new Point(_nowChatacter.locationX,_nowChatacter.locationY);
      _nowDirection = _characterMC.getDir();
      _toPoint = new Point(Math.floor(__mouseX/48),Math.floor(__mouseY/48));
      charaToMove();
    }
   }
   
   
  }
  //当前人物开始移动
  private function charaToMove():void{
   _roadArray = _roadQuery.path4(_nowPoint,_toPoint,_roadShowArray);
   if(_roadArray != null && _roadArray.length > 0){
    addEventListener(Event.ENTER_FRAME, onFrame);
    _clickCtrl == "MOVE_NOW"
    SpriteRemove.removeAllChildren(_roadSprite);
    if(_roundCtrl == "我方回合"){
     _roadSprite.removeEventListener(MouseEvent.CLICK,onClick);
    }
   }
  }
  //人物移动事件贞控制
  private function onFrame(event:Event):void {
   _characterMC = _nowChatacter.character;
   if(_roadArray != null && _roadArray.length > 1){
    if(_characterMC.x % 48 == 0 && _characterMC.y % 48 == 0){
      if(_roadArray[0].x == _roadArray[1].x){
      if(_roadArray[0].y > _roadArray[1].y){
       _characterMC.setDir(0);
       _xadd = 0;
       _yadd = -_addLeng;
      }else{
       _characterMC.setDir(1);
       _xadd = 0;
       _yadd = _addLeng;
      }
     }else{
      if(_roadArray[0].x > _roadArray[1].x){
       _characterMC.setDir(2);
       _xadd = -_addLeng;
       _yadd = 0;
      }else{
       _characterMC.setDir(3);
       _xadd = _addLeng;
       _yadd = 0;
      }
     }     

     _roadArray.splice(0,1);
                                       
    }
    _characterMC.x += _xadd;
    _characterMC.y += _yadd;
                               
   }else if(_characterMC.x % 48 == 0 && _characterMC.y % 48 == 0){
    removeEventListener(Event.ENTER_FRAME, onFrame);
    if(_roundCtrl == "我方回合"){
     _selectBox.visible = true;
     _selectBox.x = _characterMC.x + 48;
     _selectBox.y = _characterMC.y;
    }else if(_roundCtrl == "敌方回合"){
     _nowChatacter.actionCtrl = true;
     _enemyActionCtrl = 0;
     _clickCtrl = "NULL";
     addEventListener(Event.ENTER_FRAME, onEnemyFrame);
    }
   }else{
   
    _characterMC.x += _xadd;
    _characterMC.y += _yadd;
   }
  }

  //得到战场xml信息
  private function initStage(xml:XML):void{
   _fightXml = xml;
   _mapData= new Array();
   //根据xml内容,得到地形数组
   for each ( var datement:XML in _fightXml.DataMap.elements( ) ) {
    var dates:Array = ("" + datement).split( ",");
    _mapData.push(dates);
   }
   _roadQuery = new RoadQuery(this);
   
   //我军人物添加
   _ourArr = new Array();
   //根据xml内容,得到我军人物,添加至战场
   for each ( var ourment:XML in _fightXml.Our.elements( ) ) {
    var ourId:int = int(ourment);
    var ourchara:XML = XML(_pXml["peo" + ourId]);
    _characterMC = new CharacterMC(ourId);
    _characterMC.x = int(ourment.@x)*48;
    _characterMC.y = int(ourment.@y)*48;
    _character = new Character(_characterMC,int(ourchara.Move),int(ourchara.sImage),int(ourchara.Arms));
    _characterSprite.addChild(_characterMC);
    _ourArr.push(_character);
   }
   //敌军人物添加
   _enemyArr = new Array();
   //根据xml内容,得到敌军人物,添加至战场
   for each ( var enemyment:XML in _fightXml.Enemy.elements( ) ) {
    var enemyId:int = int(enemyment);
    var enemychara:XML = XML(_pXml["peo" + enemyId]);
    _characterMC = new CharacterMC(enemyId);
    _characterMC.x = int(enemyment.@x)*48;
    _characterMC.y = int(enemyment.@y)*48;
    _character = new Character(_characterMC,int(enemychara.Move),int(enemychara.sImage),int(enemychara.Arms));
    _characterSprite.addChild(_characterMC);
    _enemyArr.push(_character);
   }
   //加载地图
   _pic_loader = new Loader();
   _pic_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onCompleteMap);
   var mapName:String = "Images/HM/" + _fightXml.Map + ".gif";
   _pic_loader.load(new URLRequest(mapName));
  }
  //加载地图完毕
  private function onCompleteMap(event:Event):void {
   _pic_loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onCompleteMap);
   _bmapimage = Bitmap(_pic_loader.content);
   _mapSprite.addChild(_bmapimage);
   
  }
  public function get map():Array{
   return _mapData;
  }
  public function get roundCtrl():String{
   return _roundCtrl;
  }
  public function get enemyArr():Array{
   return _enemyArr;
  }
  public function get ourArr():Array{
   return _ourArr;
  }
  
 }
}

效果如下图
预览

预览

预览

暂时,敌军只会跟随我军某个人物移动,等下面再慢慢研究敌方的AI
下次,在战场上显示人物的攻击防御等属性:)

要显示人物属性了,把相应的人物数据和兵种数据改好,如下<?xml version="1.0" encoding="GB2312"?>
<data>
    <peo1>
 <Name>曹操</Name>
 <Arms>1</Arms>
 <Lv>1</Lv>
 <Exp>0</Exp>
 <HP>124</HP>
 <MP>85</MP>
 <Move>5</Move>
 <Face>1</Face>
 <sImage>1</sImage>
 <Force>80</Force>
 <Intelligence>96</Intelligence>
 <Command>98</Command>
 <Agile>83</Agile>
 <Luck>88</Luck>
 <Attack>82</Attack>
 <Spirit>92</Spirit>
 <Defense>80</Defense>
 <Breakout>85</Breakout>
 <Morale>80</Morale>
 <Introduction></Introduction>
    </peo1>
......
<?xml version="1.0" encoding="GB2312"?>
<data>
    <Arms1>
 <Name>英雄</Name>
 <Property>
     <Attack>A</Attack>
     <Spirit>A</Spirit>
     <Defense>A</Defense>
     <Breakout>A</Breakout>
     <Morale>A</Morale>
 </Property>
 <Weapon>剑</Weapon>
 <Equipment>铠甲</Equipment>
 <Terrain>
     <Terrain0>1</Terrain0>
     <Terrain1>1</Terrain1>
     <Terrain2>2</Terrain2>
     <Terrain3>100</Terrain3>
     <Terrain4>100</Terrain4>
     <Terrain5>1</Terrain5>
     <Terrain6>1</Terrain6>
     <Terrain7>1</Terrain7>
 </Terrain>
 <RangeAttack>
     <List>0,-1</List>
     <List>0,1</List>
     <List>-1,0</List>
     <List>1,0</List>
 </RangeAttack>
 <Introduction></Introduction>
    </Arms1>
......
在data.xml中设定升级所需EXP和能力上限值
<?xml version="1.0" encoding="GB2312"?>
<data>
 <varlable>255</varlable>
 <MaxExp>100</MaxExp>
 <MaxAbility>1000</MaxAbility>
</data>
然后,就像.net编辑From一样,开始准备所需要的MC
素材

素材

在读取完data.xml时,把需要的升级所需EXP和能力上限值保存,方便随时取用
   Sav.gamedata["MaxAbility"] = xml.MaxAbility;
   Sav.gamedata["MaxExp"] = xml.MaxExp;
战场上,把整个战场向下移动48个像素,用来仿照曹操传放置按钮,
在曹操传中,左击鼠标用来察看人物属性,但是flash中是没有办法弄成这样的,至少现在不能,因为flash左击鼠标,会弹出flash菜单
所以,我在最上面的菜单上,放置了两个按钮,用来察看我军和敌军属性,按钮用了普通的士兵S形象,点击我军或者敌军的S形象按钮就能察看我军和敌军的属性了
   //查看武将-我军按钮
   _ourShow = new PeopleShow();
   _ourShow.x = 500;
   addChild(_ourShow);
   _ourShow.addEventListener(MouseEvent.CLICK, ourShowHandler);
   //查看武将-敌军按钮
   _enemyShow = new PeopleShowEnemy();
   _enemyShow.x = 548;
   addChild(_enemyShow);
   _enemyShow.addEventListener(MouseEvent.CLICK, enemyShowHandler);

然后添加现实HP,MP和人物属性的MC
   _hpmp = new HPMP();
   _bakSprite.addChild(_hpmp);
   _hpmp.visible = false;
这个HPMP,是用来显示当前的HP和MP的MC,就是上面一开始准备的第一个图
   //查看武将MC
   _peopleShow = new CharacterProperty();
   _peopleShow.x = (Sav.gamedata["stageWidth"] - _peopleShow.width)/2;
   _peopleShow.y = (Sav.gamedata["stageHeight"] - _peopleShow.height)/2;
   this.addChild(_peopleShow);
   _peopleShow.btnGenerals.visible = false;
   _peopleShow.visible = false;
这个CharacterProperty就是准备好的显示人物属性的MC,就是上面的第二个图


当鼠标移动到我军或敌军身上时,就显示其HP和MP

  //鼠标移动事件
  private function mouseBakMoveHandler(event:MouseEvent):void{
   var intX:int = event.currentTarget.mouseX;
   var intY:int = event.currentTarget.mouseY;
   _mouseBox.x = Math.floor(intX/48)*48;
   _mouseBox.y = Math.floor(intY/48)*48;
   var queryPeople:Boolean = false;
   var i:int;
   for(i=0;i<_ourArr.length;i++){
    _character = _ourArr[i] as Character;
    if(_character.x == _mouseBox.x && _character.y == _mouseBox.y){
     _nowChatacter = _character;
     queryPeople = true;
     break;
    }
   }
   
   for(i=0;i<_enemyArr.length && !queryPeople;i++){
    _character = _enemyArr[i] as Character;
    if(_character.x == _mouseBox.x && _character.y == _mouseBox.y){
     _nowChatacter = _character;
     queryPeople = true;
     break;
    }
   }
   if(!queryPeople){
    _hpmp.visible = false;
   }else{
     _hpmp.visible = true;
     _hpmp.x = _mouseBox.x  - 102;
     _hpmp.y = _mouseBox.y - 48;
     if(_hpmp.x < 0){
      _hpmp.x = 0;
     }
     if(_hpmp.y < 0){
      _hpmp.y = 0;
     }
    _hpmp.txtHP.text = _nowChatacter.nowHP + "/" + _nowChatacter.HP;
    _hpmp.spHP.width = 100 * (_nowChatacter.nowHP/_nowChatacter.HP);
    _hpmp.txtMP.text = _nowChatacter.nowMP + "/" + _nowChatacter.MP;
    _hpmp.spMP.width = 100 * (_nowChatacter.nowMP/_nowChatacter.MP);
   }
  }

 

添加好点击事件,显示人物属性时,实现相应的切换

   _peopleShow.visible = false;
   //添加各个按钮点击事件
   _peopleShow.btnGenerals.addEventListener(MouseEvent.CLICK, onClickGenerals);
   _peopleShow.btnForce.addEventListener(MouseEvent.CLICK, onClickForce);
   _peopleShow.btnAbility.addEventListener(MouseEvent.CLICK, onClickAbility);
   _peopleShow.btnEquipment.addEventListener(MouseEvent.CLICK, onClickEquipment);
   _peopleShow.btnTactics.addEventListener(MouseEvent.CLICK, onClickTactics);
   _peopleShow.btnClose.addEventListener(MouseEvent.CLICK, onClickClose);
   _peopleShow.btnLast.addEventListener(MouseEvent.CLICK, onClickLast);
   _peopleShow.btnNext.addEventListener(MouseEvent.CLICK, onClickNext);


  //察看武将-按钮全部显示
  private function _peopleBtnToTrue(){
   _peopleShow.btnGenerals.visible = true;
   _peopleShow.btnForce.visible = true;
   _peopleShow.btnAbility.visible = true;
   _peopleShow.btnEquipment.visible = true;
   _peopleShow.btnTactics.visible = true;
  
  }
  //察看武将-点击上一武将
  private function onClickLast(event:MouseEvent):void{
   peopleShowFromIndex(-1);
  }
  //察看武将-点击下一武将
  private function onClickNext(event:MouseEvent):void{
   peopleShowFromIndex(1);
  }
  //察看武将-点击关闭
  private function onClickClose(event:MouseEvent):void{
   if(_peopleShow.btnGenerals.visible){
    _peopleShow.gotoAndStop(1);
   }
   _peopleShow.visible = false;
  }
  //察看武将-点击武将列传
  private function onClickGenerals(event:MouseEvent):void{
   _peopleShow.gotoAndStop(1);
   _peopleBtnToTrue();
   _peopleShow.btnGenerals.visible = false;
   setGenerals();
  }
  //察看武将-点击部队属性
  private function onClickForce(event:MouseEvent):void{
   _peopleShow.gotoAndStop(2);
   _peopleBtnToTrue();
   _peopleShow.btnForce.visible = false;
   setForce();
  }
  //察看武将-点击能力
  private function onClickAbility(event:MouseEvent):void{
   _peopleShow.gotoAndStop(3);
   _peopleBtnToTrue();
   _peopleShow.btnAbility.visible = false;
   setAbility();
  }
  //察看武将-点击装备
  private function onClickEquipment(event:MouseEvent):void{
   _peopleShow.gotoAndStop(4);
   _peopleBtnToTrue();
   _peopleShow.btnEquipment.visible = false;
   setEquipment();
  }
  //察看武将-点击策略
  private function onClickTactics(event:MouseEvent):void{
   _peopleShow.gotoAndStop(5);
   _peopleBtnToTrue();
   _peopleShow.btnTactics.visible = false;
   setTactics();
  }


  //察看我军
  private function ourShowHandler(event:MouseEvent):void{
   _peopleShowIndex= 0;
   _peopleShowCtrl = "Our";
   peopleShowFromIndex(0);
  }
  //察看敌军
  private function enemyShowHandler(event:MouseEvent):void{
   _peopleShowIndex = 0;
   _peopleShowCtrl = "Enemy";
   peopleShowFromIndex(0);
  }
  //根据人物序号显示人物属性
  private function peopleShowFromIndex(addIndex:int):void{
   _peopleShowIndex += addIndex;
   if(_peopleShowCtrl == "Our"){
    if(_peopleShowIndex < 0){
     _peopleShowIndex = _ourArr.length - 1;
    }else if(_peopleShowIndex >= _ourArr.length){
     _peopleShowIndex = 0;
    }
    _nowChatacter = _ourArr[_peopleShowIndex] as Character;
   _peopleShow.txtForceShow.text = "我军";
   }else if(_peopleShowCtrl == "Enemy"){
    if(_peopleShowIndex < 0){
     _peopleShowIndex = _enemyArr.length - 1;
    }else if(_peopleShowIndex >= _enemyArr.length){
     _peopleShowIndex = 0;
    }
    _nowChatacter = _enemyArr[_peopleShowIndex] as Character;
    _peopleShow.txtForceShow.text = "敌军";
   }
   _peopleShow.txtName.text = _pXml["peo" + _nowChatacter.charaIndex].Name.toString();
   _peopleShow.txtArms.text = _pXml["peo" + _nowChatacter.charaIndex].Arms.toString();
   _peopleShow.txtLv.text = _pXml["peo" + _nowChatacter.charaIndex].Lv.toString();
   _peopleShow.txtExp.text = _pXml["peo" + _nowChatacter.charaIndex].Exp + "/" + Sav.gamedata["MaxExp"];
   _peopleShow.spExp.width = 50 * (int(_pXml["peo" + _nowChatacter.charaIndex].Exp)/int(Sav.gamedata["MaxExp"]));
   _peopleShow.txtHP.text = _nowChatacter.nowHP + "/" + _nowChatacter.HP;
   _peopleShow.spHP.width = 100 * (_nowChatacter.nowHP/_nowChatacter.HP);
   _peopleShow.txtMP.text = _nowChatacter.nowMP + "/" + _nowChatacter.MP;
   _peopleShow.spMP.width = 100 * (_nowChatacter.nowMP/_nowChatacter.MP);
   _peopleShow.txtStatus.text = _nowChatacter.getfStatus();
   for(var i:int = 0;i<_nowChatacter.statusArr.length;i++){
    _peopleShow.txtStatus.appendText(_nowChatacter.statusArr[0] + " ");
   }
   
   //加载人物头像
   var faceStr:String = "Images/Face/" + _pXml["peo" + _nowChatacter.charaIndex].Face.toString().split(",")[0] + ".gif";
   _pic_loader = new Loader();
   _pic_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onCompleteFace);
   _pic_loader.load(new URLRequest(faceStr));
   if(!_peopleShow.btnGenerals.visible){
    setGenerals();
   }else if(!_peopleShow.btnForce.visible){
    setForce();
   }else if(!_peopleShow.btnAbility.visible){
    setAbility();
   }else if(!_peopleShow.btnEquipment.visible){
    setEquipment();
   }else if(!_peopleShow.btnTactics.visible){
    setTactics();
   }
  }
  //加载人物头像完毕
  private function onCompleteFace(event:Event):void {
   _pic_loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onCompleteFace);
   _image = Bitmap(_pic_loader.content);
   SpriteRemove.removeAllChildren(_peopleShow.faceImage);
   _peopleShow.faceImage.addChild(_image);
   _peopleShow.visible = true;
  }
  //察看武将-显示武将列传
  private function setGenerals():void{
   _peopleShow.txtForce.text = _pXml["peo" + _nowChatacter.charaIndex].Force.toString();
   _peopleShow.txtIntelligence.text = _pXml["peo" + _nowChatacter.charaIndex].Intelligence.toString();
   _peopleShow.txtCommand.text = _pXml["peo" + _nowChatacter.charaIndex].Command.toString();
   _peopleShow.txtAgile.text = _pXml["peo" + _nowChatacter.charaIndex].Agile.toString();
   _peopleShow.txtLuck.text = _pXml["peo" + _nowChatacter.charaIndex].Luck.toString();
   _peopleShow.txtIntroduction.text = _pXml["peo" + _nowChatacter.charaIndex].Introduction.toString();
  }
  //察看武将-显示部队属性
  private function setForce():void{
   _peopleShow.txtAttack.text = _arms["Arms" + _nowChatacter.armsIndex].Property.Attack.toString();
   _peopleShow.txtSpirit.text = _arms["Arms" + _nowChatacter.armsIndex].Property.Spirit.toString();
   _peopleShow.txtDefense.text = _arms["Arms" + _nowChatacter.armsIndex].Property.Defense.toString();
   _peopleShow.txtBreakout.text = _arms["Arms" + _nowChatacter.armsIndex].Property.Breakout.toString();
   _peopleShow.txtMorale.text = _arms["Arms" + _nowChatacter.armsIndex].Property.Morale.toString();
   _peopleShow.txtArmsPro.text = _arms["Arms" + _nowChatacter.armsIndex].Introduction.toString();
   _peopleShow.txtArms2.text = _pXml["peo" + _nowChatacter.charaIndex].Arms.toString();
   _peopleShow.txtWeapon.text = _arms["Arms" + _nowChatacter.armsIndex].Weapon.toString();
   _peopleShow.txtEquipment.text = _arms["Arms" + _nowChatacter.armsIndex].Equipment.toString();
   SpriteRemove.removeAllChildren(_peopleShow.armsImage);
   _peopleShow.armsImage.addChild(new Bitmap(_nowChatacter.character.getBitmapData()));
  }
  //察看武将-显示能力
  private function setAbility():void{
   _peopleShow.txtAttack1.text = _pXml["peo" + _nowChatacter.charaIndex].Attack.toString();
   _peopleShow.txtSpirit1.text = _pXml["peo" + _nowChatacter.charaIndex].Spirit.toString();
   _peopleShow.txtDefense1.text = _pXml["peo" + _nowChatacter.charaIndex].Defense.toString();
   _peopleShow.txtBreakout1.text = _pXml["peo" + _nowChatacter.charaIndex].Breakout.toString();
   _peopleShow.txtMorale1.text = _pXml["peo" + _nowChatacter.charaIndex].Morale.toString();
   _peopleShow.spAttack1.width = 100 * int(_pXml["peo" + _nowChatacter.charaIndex].Attack) / int(Sav.gamedata["MaxAbility"]);
   _peopleShow.spSpirit1.width = 100 * int(_pXml["peo" + _nowChatacter.charaIndex].Spirit) / int(Sav.gamedata["MaxAbility"]);
   _peopleShow.spDefense1.width = 100 * int(_pXml["peo" + _nowChatacter.charaIndex].Defense) / int(Sav.gamedata["MaxAbility"]);
   _peopleShow.spBreakout1.width = 100 * int(_pXml["peo" + _nowChatacter.charaIndex].Breakout) / int(Sav.gamedata["MaxAbility"]);
   _peopleShow.spMorale1.width = 100 * int(_pXml["peo" + _nowChatacter.charaIndex].Morale) / int(Sav.gamedata["MaxAbility"]);
  }
  //察看武将-显示装备
  private function setEquipment():void{}
  //察看武将-显示策略
  private function setTactics():void{}

就是这样了,然后,运行一下flash,可以看到下面的图
预览

预览

该研究攻击了,这个比较复杂,先来看,我军方面的攻击
当然,首先要把攻击动作等补全
CharacterMC中,把攻击图片和被攻击图片等全部载入
  //Unit_mov图片加载完成
  public function onCompleteUnit_mov(event:Event):void {
   _image = Bitmap(_loader.content);
   //初始化显示数组
   _bitShowArr = new Array();
   //将位图数据拆分成小块,装入bitmapArr
   _bitmapArr=ImageCtrl.divide(_image,1,11);
   var newArr:Array;
   //得到向上行走数组
   newArr = new Array(_bitmapArr[2][0],_bitmapArr[3][0]);
   //将向上行走数组加入到显示数组 编号:0
   _bitShowArr.push(newArr);
   //得到向下行走数组
   newArr = new Array(_bitmapArr[0][0],_bitmapArr[1][0]);
   //将向下行走数组加入到显示数组 编号:1
   _bitShowArr.push(newArr);
   //得到向左行走数组
   newArr = new Array(_bitmapArr[4][0],_bitmapArr[5][0]);
   //将向左行走数组加入到显示数组 编号:2
   _bitShowArr.push(newArr);
   //得到向右行走数组
   newArr = new Array(ImageCtrl.bitHorizontal(_bitmapArr[4][0]),ImageCtrl.bitHorizontal(_bitmapArr[5][0]));
   //将向右行走数组加入到显示数组 编号:3
   _bitShowArr.push(newArr);
   //得到向上站立数组
   newArr = new Array(_bitmapArr[7][0]);
   //将向上站立数组加入到显示数组 编号:4
   _bitShowArr.push(newArr);
   //得到向下站立数组
   newArr = new Array(_bitmapArr[6][0]);
   //将向下站立数组加入到显示数组 编号:5
   _bitShowArr.push(newArr);
   //得到向左站立数组
   newArr = new Array(_bitmapArr[8][0]);
   //将向左站立数组加入到显示数组 编号:6
   _bitShowArr.push(newArr);
   //得到向右站立数组
   newArr = new Array(ImageCtrl.bitHorizontal(_bitmapArr[8][0]));
   //将向右站立数组加入到显示数组 编号:7
   _bitShowArr.push(newArr);
   //得到喘气数组
   newArr = new Array(_bitmapArr[9][0],_bitmapArr[10][0]);
   //将喘气数组加入到显示数组 编号:8
   _bitShowArr.push(newArr);
   
             //Unit_atk图片加载;          
     _loader = new Loader(); 
   _loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onCompleteUnit_atk);
   var atkName:String = "Images/Unit_atk/" + _imageIndex + ".gif";
   _loader.load(new URLRequest(atkName));
  }
  //Unit_atk图片加载完成
  public function onCompleteUnit_atk(event:Event):void {
   _image = Bitmap(_loader.content);
   //将位图数据拆分成小块,装入bitmapArr
   _bitmapArr=ImageCtrl.divide(_image,1,12);
   var newArr:Array;
   //得到向上攻击数组
   newArr = new Array(_bitmapArr[4][0],_bitmapArr[5][0],_bitmapArr[6][0],_bitmapArr[7][0]);
   //将向上攻击数组加入到显示数组 编号:9
   _bitShowArr.push(newArr);
   //得到向下攻击数组
   newArr = new Array(_bitmapArr[0][0],_bitmapArr[1][0],_bitmapArr[2][0],_bitmapArr[3][0]);
   //将向下攻击数组加入到显示数组 编号:10
   _bitShowArr.push(newArr);
   //得到向左攻击数组
   newArr = new Array(_bitmapArr[8][0],_bitmapArr[9][0],_bitmapArr[10][0],_bitmapArr[11][0]);
   //将向左攻击数组加入到显示数组 编号:11
   _bitShowArr.push(newArr);
   //得到向右攻击数组
   newArr = new Array(ImageCtrl.bitHorizontal(_bitmapArr[8][0]),ImageCtrl.bitHorizontal(_bitmapArr[9][0]),ImageCtrl.bitHorizontal(_bitmapArr[10][0]),ImageCtrl.bitHorizontal(_bitmapArr[11][0]));
   //将向右攻击数组加入到显示数组 编号:12
   _bitShowArr.push(newArr);
   
             //Unit_spc图片加载;          
     _loader = new Loader(); 
   _loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onCompleteUnit_spc);
   var spcName:String = "Images/Unit_spc/" + _imageIndex + ".gif";
   _loader.load(new URLRequest(spcName));
  }
  //Unit_spc图片加载完成
  public function onCompleteUnit_spc(event:Event):void {
   _image = Bitmap(_loader.content);
   //将位图数据拆分成小块,装入bitmapArr
   _bitmapArr=ImageCtrl.divide(_image,1,5);
   var newArr:Array;
   //得到向上挡格数组
   newArr = new Array(_bitmapArr[1][0]);
   //将向上挡格数组加入到显示数组 编号:13
   _bitShowArr.push(newArr);
   //得到向下挡格数组
   newArr = new Array(_bitmapArr[0][0]);
   //将向下挡格数组加入到显示数组 编号:14
   _bitShowArr.push(newArr);
   //得到向左挡格数组
   newArr = new Array(_bitmapArr[2][0]);
   //将向左挡格数组加入到显示数组 编号:15
   _bitShowArr.push(newArr);
   //得到向右挡格数组
   newArr = new Array(ImageCtrl.bitHorizontal(_bitmapArr[2][0]));
   //将向右挡格数组加入到显示数组 编号:16
   _bitShowArr.push(newArr);
   //得到受攻击数组
   newArr = new Array(_bitmapArr[3][0]);
   //将受攻击数组加入到显示数组 编号:17
   _bitShowArr.push(newArr);
   //得到升级数组
   newArr = new Array(_bitmapArr[4][0]);
   //将升级数组加入到显示数组 编号:18
   _bitShowArr.push(newArr);
   
   startFrame();
  }

CharacterIndex中,把相应的动作代号补全,以方便使用
package Caocao.Character {
 public class CharacterIndex {
  public static const UP:int = 0;
  public static const DOWN:int = 1;
  public static const LEFT:int = 2;
  public static const RIGHT:int = 3;
  public static const UP_STOP:int = 4;
  public static const DOWN_STOP:int = 5;
  public static const LEFT_STOP:int = 6;
  public static const RIGHT_STOP:int = 7;
  public static const PANT:int = 8;
  public static const ATTACK_UP:int = 9;
  public static const ATTACK_DWON:int = 10;
  public static const ATTACK_LEFT:int = 11;
  public static const ATTACK_RIGHT:int = 12;
  public static const WARD_UP:int = 13;
  public static const WARD_DWON:int = 14;
  public static const WARD_LEFT:int = 15;
  public static const WARD_RIGHT:int = 16;
  public static const TAKE_A_BEAT:int = 17;
  public static const UPGRADE:int = 18;
  public function CharacterIndex() { }
 }
}
然后,继续在人物动作类CharacterMC中加入一个被攻击人员和一个可以随时改变值的自定义函数
  //对手
  public var _rival:Character;
  private var _rivalMC:CharacterMC;
  //执行函数
  public var _fun:Function;

然后,在战场类FightMap中把战斗按钮上加上点击事件
   //点击攻击事件
   _selectBox.btnAttAck.addEventListener(MouseEvent.CLICK, charaAttHandler);
  //点击攻击事件
  private function charaAttHandler(event:MouseEvent):void{
   _clickCtrl = "ATTACK";
   _selectBox.visible = false;
   _roadSprite.addEventListener(MouseEvent.CLICK,onClick);
   setAttRound2(_pXml["peo" + _nowChatacter.charaIndex].Arms);
  }
这里的setAttRound2,用红色半透明MC来显示攻击范围
  //攻击范围显示
  private function setAttRound2(armIndex:int):void{
   var attRoundArr:Array;
   var attRound:AttShow;
   for each ( var roundment:XML in _arms["Arms" + armIndex]["RangeAttack"].elements( ) ) {
    attRound = new AttShow();
    attRoundArr = roundment.toString().split(",");
    attRound.x = (int(attRoundArr[0]) + _nowChatacter.locationX )*48;
    attRound.y = (int(attRoundArr[1]) + _nowChatacter.locationY) *48;
    _roadSprite.addChild(attRound);
   }
   
  }
这时候,点击状态已经改变为"ATTACK"
在点击事件中,加上攻击事件
......
else if(_clickCtrl == "ATTACK"){
    //寻找攻击目标
    for(i=0;i<_enemyArr.length && !queryPeople;i++){
     _character = _enemyArr[i] as Character;
     _characterMC = _character.character;
     if(Math.floor(_characterMC.x/48) == Math.floor(__mouseX/48) && Math.floor(_characterMC.y/48) == Math.floor(__mouseY/48)){
      
      SpriteRemove.removeAllChildren(_roadSprite);
      _nowChatacter.character._rival = _character;
      _nowChatacter.character._fun = function(){
       _clickCtrl = "NULL";
       _nowChatacter.actionCtrl = true;
       addEventListener(Event.ENTER_FRAME, onClickFrame);
      }
      _nowChatacter.attack();
      
      break;
     }
     
    }
   }
这里的_fun很重要,用来处理攻击完之后的事件代码
当然,给函数赋了值就要有执行的地方,
下面修改人物动作类CharacterMC的动态显示贞事件
  //动态显示
  public function onFrame(event:Event):void {
   var dir:int = _showIndex;
   _peopleBitmap.bitmapData = _bitShowArr[dir][_pointer];
   _count += _speed;
   _pointer += int(_count) ;
   _count=_count%1;
   //当人物攻击时,在攻击的第三个动作,被攻击人物显示被攻击动作
   if((dir == CharacterIndex.ATTACK_UP || dir == CharacterIndex.ATTACK_DWON ||
    dir == CharacterIndex.ATTACK_LEFT || dir == CharacterIndex.ATTACK_RIGHT ) && _pointer == 2){
    //得到被攻击人物动作显示类
    _rivalMC = _rival.character;
    //根据攻击人物方向,设定攻击和被攻击完毕之后的人物方向
    if(_rivalMC.x - this.x > 0){
     this._direct = CharacterIndex.RIGHT;
     _rivalMC._direct = CharacterIndex.LEFT;
    }else if(_rivalMC.x - this.x < 0){
     this._direct = CharacterIndex.LEFT;
     _rivalMC._direct = CharacterIndex.RIGHT;
    }else if(_rivalMC.y - this.y > 0){
     this._direct = CharacterIndex.DOWN;
     _rivalMC._direct = CharacterIndex.UP;
    }else if(_rivalMC.y - this.y < 0){
     this._direct = CharacterIndex.UP;
     _rivalMC._direct = CharacterIndex.DOWN;
    }
    _rivalMC.setDir(CharacterIndex.TAKE_A_BEAT);
   }
   if(_pointer >= _bitShowArr[dir].length){
    //人物动作不是移动动作的时候,动作结束后,根据动作前的方向,显示移动动作
    switch(dir){
     case CharacterIndex.TAKE_A_BEAT:
      _showIndex = _direct;
      break;
     case CharacterIndex.ATTACK_UP:
      _showIndex = _direct;
      _fun();
     case CharacterIndex.ATTACK_DWON:
      _showIndex = _direct;
      _fun();
     case CharacterIndex.ATTACK_LEFT:
      _showIndex = _direct;
      _fun();
     case CharacterIndex.ATTACK_RIGHT:
      _showIndex = _direct;
      _fun();
      break;
    }
    
    _pointer = 0;
    _count = 0;
   }
  }
之后,在动作类中,加入两个函数,用来控制人物行动前和行动后的亮度,就像曹操传里的行动完之后,人物会变暗
  //转为静态
  public function stand():void{
   switch(_showIndex){
    case CharacterIndex.UP:
     setDir(CharacterIndex.UP_STOP);
     break;
    case CharacterIndex.DOWN:
     setDir(CharacterIndex.DOWN_STOP);
     break;
    case CharacterIndex.LEFT:
     setDir(CharacterIndex.LEFT_STOP);
     break;
    case CharacterIndex.RIGHT:
     setDir(CharacterIndex.RIGHT_STOP);
     break;
   }
   this.transform.colorTransform = _standColor;
  }
  //转为动态
  public function run():void{
   switch(_showIndex){
    case CharacterIndex.UP_STOP:
     setDir(CharacterIndex.UP);
     break;
    case CharacterIndex.DOWN_STOP:
     setDir(CharacterIndex.DOWN);
     break;
    case CharacterIndex.LEFT_STOP:
     setDir(CharacterIndex.LEFT);
     break;
    case CharacterIndex.RIGHT_STOP:
     setDir(CharacterIndex.RIGHT);
     break;
   }
   this.transform.colorTransform = _runColor;
  }
主要是这些修改,其他的都是些小改动

目前,只写了我军的攻击,而且只是攻击动作,敌人也不掉血,不过加个掉血并不难,
难的是敌军的攻击,现在敌军回合,敌军依然只会跟随我军某一个人物移动,等研究完敌军攻击之后,把代码放出来,

好了,现在先看一下效果吧
预览

预览

下次,研究一下敌人的攻击

到了复杂的地方了,敌军的AI问题了

曹操传中敌军的行动方针有很多种,敌军根据相应的行动方针进行不同的行为
所以,我们首先在人物类中,加上行动方针一项
  //行动方针
  private var _mission:String;
默认是"DEFAULT",现在不研究太复杂,目前只考虑这一个行动方针
并且,默认下就选择攻击
敌人选择攻击目标的时候,会优先选择一击可以杀死的人物,
这里就要在选择攻击目标之前,先来判断一下攻击的这个人能否被杀死
那么,就要有物理攻击计算
那就利用曹操传中的物理攻击公式在战场类中写一个方法
  /*物理攻击的伤害值计算
   X代表攻击方的攻击力,Y代表被攻击方的防御力,Lv表示攻击方的等级。R表示伤害值
   首先会根据地形修正攻击和防御力为X',Y'
   if (x'>y')
   r=Lv+25+(X'-Y')/2;
   else
   r=Lv+25-(Y'-X')/2
   然后再根据兵种相克和宝物进行修正
  */
  public function getAttHurt(attChara:Character,hertChara:Character):int{
   var r:int;
   //得到攻击方的攻击力和等级
   var attLv:int =  int(_pXml["peo" + attChara.charaIndex].Lv);
   var attAttack:int = int(_pXml["peo" + attChara.charaIndex].Attack);
   //得到防御方的防御力
   var hertDefense:int = int(_pXml["peo" + hertChara.charaIndex].Defense);
   //计算攻击方所在地形
   var attTerrain:String = "Terrain" + _mapData[attChara.locationY][attChara.locationX];
   //计算防御方所在地形
   var hertTerrain:String = "Terrain" + _mapData[hertChara.locationY][hertChara.locationX];
   //根据地形修正攻击和防御力
   var attAttackAddition:int = Math.floor((int(_arms["Arms" + attChara.armsIndex].Terrain[attTerrain].@Addition)/100) * attAttack);
   var hertDefenseAddition:int = Math.floor((int(_arms["Arms" + hertChara.armsIndex].Terrain[hertTerrain].@Addition)/100) * hertDefense);
   //物理攻击的伤害值计算
   if(attAttackAddition > hertDefenseAddition){
    r = attLv + 25 + (attAttackAddition - hertDefenseAddition)/2;
   }else{
    r = attLv + 25 + (hertDefenseAddition - attAttackAddition)/2;
   }
   return r;
  }
好了,有了伤害计算了,在攻击的时候,先寻找到所有可以攻击到的位置,
  //计算所有攻击范围
  private function getAttRange(chara:Character):Object{
   var attArr:Array = new Array();
   var attRoundArr:Array;
   var i:int;
   var j:int;
   var objAll:Object = new Object();
   var objCheck:Object = new Object();
   var obj:Object = new Object();
   var attRound:Array = new Array();
   //兵种攻击范围
   for each ( var roundment:XML in _arms["Arms" + chara.armsIndex]["RangeAttack"].elements( ) ) {
    attRoundArr = roundment.toString().split(",");
    attRound.push(new Point(int(attRoundArr[0]), int(attRoundArr[1])));
   }
   //根据移动范围来计算所有攻击范围
   for(i=0;i<_roadShowArray.length;i++){
    for(j=0;j<attRound.length;j++){
     obj = new Object();
     obj.x = _roadShowArray[i].x + attRound[j].x;
     obj.y = _roadShowArray[i].y + attRound[j].y;
     if(objAll[obj.x + "," + obj.y] == null){
      obj.nodeparent = _roadShowArray[i];
      objAll[obj.x + "," + obj.y] = obj;
      attArr.push(obj);
     }
    }
   }
   objAll.attArr = attArr;
   return objAll;
  }
这里,添加了一个obj.nodeparent,用来确定攻击的时候所移动的位置

好了,现在就简单了,因为可以利用上面的两个方法轻松找到攻击目标了
  //计算攻击目标
  public function getAttTarget(chara:Character,peoArr:Array):Object{
   var i:int;
   var objResult:Object;
   var obj:Object;
   //计算所有攻击范围
   var objAll:Object = getAttRange(chara);
   var attArr:Array = new Array();
   var intHert:int;
   for(i=0;i<peoArr.length;i++){
    var checkChara:Character = peoArr[i];
    obj = objAll[checkChara.locationX + "," + checkChara.locationY];
    if(obj != null){
     intHert = getAttHurt(chara,checkChara);
     obj.chara = checkChara;
     //判断是否有一击可以杀死的人,有的话直接确立目标
     if(intHert >= checkChara.nowHP){
      return obj;
     }
     attArr.push(obj);
    }
   }
   //没有一击可以杀死的人的时候,如果有可以攻击到的人,则随即抽取可以攻击到的人,确立目标
   if(attArr.length > 0 ){
    i = Math.random() * attArr.length;
    return attArr[i];
   }
   //没有可以攻击到的人,没有找到目标
   return null;
  }
然后,在敌军寻路完成后,就可以判断下行动方针,当然这里的行动方针只有一个,哈哈
    if(_nowChatacter.mission == "DEFAULT"){
     //查找攻击目标
     var obj:Object = getAttTarget(_nowChatacter,_ourArr);
     if(obj != null){
      _nowChatacter.character._rival = obj.chara;
      _toPoint = new Point(obj.nodeparent.x,obj.nodeparent.y);
     }else{
      //开始行动
      _toPoint = new Point(_roadShowArray[0].x,_roadShowArray[0].y);
      i = Math.random() * _ourArr.length;
      _character = _ourArr[i];
      toDistance = Math.abs(_character.locationX - _toPoint.x) + Math.abs(_character.locationY - _toPoint.y) ;
      for(i=1;i<_roadShowArray.length;i++){
       checkDistance = Math.abs(_character.locationX - _roadShowArray[i].x) + Math.abs(_character.locationY - _roadShowArray[i].y) ;
       if(checkDistance < toDistance){
        toDistance = checkDistance;
        _toPoint.x = _roadShowArray[i].x;
        _toPoint.y = _roadShowArray[i].y;
       }
      }
      _nowChatacter.character._rival = null;
     }
     _nowPoint = new Point( _nowChatacter.locationX, _nowChatacter.locationY);
     _characterMC = _nowChatacter.character;
     _nowDirection = _characterMC.getDir();
     charaToMove();
    }

看,obj.nodeparent.x,obj.nodeparent.y就是之前确定好的移动位置

然后,在敌军武将移动完毕时,判断一下是不是有攻击目标
没有的话,结束行动,有的话,进入攻击状态
     if(_nowChatacter.rival == null){
      _nowChatacter.actionCtrl = true;
      _enemyActionCtrl = 0;
      _clickCtrl = "NULL";
     }else{
      _clickCtrl = "ATTACK";
     }
     addEventListener(Event.ENTER_FRAME, onEnemyFrame);
然后,在控制敌军行动事件中,加上攻击代码,和我军攻击的时候是一样的,不同的是,攻击完毕的时候,所调用的方法不一样,我方攻击的时候,需要调用鼠标点击事件,这次需要调用控制敌军行动事了
 if(_clickCtrl == "ATTACK"){
    removeEventListener(Event.ENTER_FRAME, onEnemyFrame);
    _nowChatacter.character._fun = function(){
     _clickCtrl = "NULL";
     _nowChatacter.actionCtrl = true;
     _enemyActionCtrl = 0;
     addEventListener(Event.ENTER_FRAME, onEnemyFrame);
    }
    _nowChatacter.attack();
   }

好了,运行下程序,可以看到敌军也会进行攻击了
当然攻击是不掉血的,嘿嘿

敌军步兵的攻击
预览

预览

下次,该研究掉血和掉血的时候显示一下了

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值