2010-5-19 22:12
lufy
用AS3.0开发flash版曹操传-初级
以前也曾因为研究曹操传MOD而废寖忘食,却没想到曹操传MOD已经发展到现在这种地步,但是,修改永远是修改,总会遇到各种限制,想要突破,当然要自己动手,开发自己的引擎。
但是,在这里,我研究flash版的曹操传,目的并不是想要有任何突破,只是单纯的为了研究一下,熟悉一下用flash完成各种游戏的制作而已。
那下面就开始了。
2楼:建立战场
3楼:人物显示
4楼:控制人物移动和菜单的显示
5楼:2,3,4楼的源代码
7楼:显示一下地形
8楼:多地形下的寻路
9楼:加入敌军,攻击范围的显示
10楼:敌军行动
11楼:在战场上显示人物属性
12楼:我军攻击
15楼:敌军攻击
19楼:伤害显示
21楼:撤退
22楼:反击
23楼:双击和致命一击
24楼:23楼之前的源代码
[img]http://i818.photobucket.com/albums/zz104/lufy_photo/1-14.jpg?t=1275438367[/img]
[img]http://i818.photobucket.com/albums/zz104/lufy_photo/1-13.jpg?t=1275266318[/img]
[img]http://i818.photobucket.com/albums/zz104/lufy_photo/2-6.jpg?t=1275028342[/img]
[img]http://i818.photobucket.com/albums/zz104/lufy_photo/1-11.jpg?t=1274951753[/img]
[img]http://i818.photobucket.com/albums/zz104/lufy_photo/2-5.jpg?t=1274951783[/img]
[img]http://i818.photobucket.com/albums/zz104/lufy_photo/1-10.gif?t=1274858549[/img]
[img]http://i818.photobucket.com/albums/zz104/lufy_photo/2-4.gif?t=1274858568[/img]
[img]http://i818.photobucket.com/albums/zz104/lufy_photo/3-1.jpg?t=1274599983[/img]
[img]http://i818.photobucket.com/albums/zz104/lufy_photo/2-3.jpg?t=1274600017[/img]
[img]http://i818.photobucket.com/albums/zz104/lufy_photo/4.jpg?t=1274600044[/img]
[img]http://i818.photobucket.com/albums/zz104/lufy_photo/1-7.jpg?t=1274279890[/img]
[img]http://i818.photobucket.com/albums/zz104/lufy_photo/2-2.jpg?t=1274328399[/img]
[color=Silver][[i] 本帖最后由 lufy 于 2010-6-2 08:53 编辑 [/i]][/color]
2010-5-19 22:19
lufy
首先,先建立一个战场,显示一张地图吧,
导出一张曹操传第一关颖川的地图,把它转化成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 用来控制地图移动的速度,然后只要控制地图不移出指定的范围就可以了
这样,运行一下,就可以让地图自由的移动位置了
2010-5-19 22:20
lufy
接下来,让地图上显示一个人物
导出曹操传中曹操的三个图片,去除背景,并保存为gif格式,就像下面这样
[img]http://i818.photobucket.com/albums/zz104/lufy_photo/1-3.gif?t=1274277470[/img]
首先,在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);
}
运行就可以看到曹操出现在战场上了
[img]http://i818.photobucket.com/albums/zz104/lufy_photo/1-5.jpg?t=1274278162[/img]
下面,开始控制曹操移动
2010-5-19 22:41
lufy
首先,先在CS4里,建立一个MC,加入三个按钮,如图
[img]http://i818.photobucket.com/albums/zz104/lufy_photo/2-1.jpg?t=1274278938[/img]
我暂时把地形全都设定成为可移动,且地形全都消耗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;
}
[img]http://i818.photobucket.com/albums/zz104/lufy_photo/1-6.jpg?t=1274279680[/img]
最大路径找好后,点击目标点,利用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;
效果如下图
[img]http://i818.photobucket.com/albums/zz104/lufy_photo/1-7.jpg?t=1274279890[/img]
[color=Silver][[i] 本帖最后由 lufy 于 2010-5-19 22:54 编辑 [/i]][/color]
2010-5-19 22:43
moyanxiawei123
:hz1024:又有一位高人出现了,:hz1024:又有一种新形式的曹操传MOD出现了,:hz1024:又有一场新浪潮要被挂起来了,又有..
2010-5-19 22:47
lufy
这是以上的源代码,有兴趣的一起研究下:):)
2010-5-20 12:16
lufy
接下来,显示一下地形,
准备一个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,如下,用来显示地形
[img]http://i818.photobucket.com/albums/zz104/lufy_photo/1-8.jpg?t=1274328381[/img]
剩下的就简单了,
在战场的鼠标点击事件中,当状态为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);
}
}
看吧,效果如下图
[img]http://i818.photobucket.com/albums/zz104/lufy_photo/2-2.jpg?t=1274328399[/img]
因为地形我全都设定成了0,所以现在点哪里都是平原
剩下的就是把1S.xml的地形好好设定下了
下次,研究在各种地形下行走的范围^0^!
2010-5-21 12:58
lufy
下面,来继续在不同地形下的寻路问题
首先,准备好兵种数据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;
就是减去下一个点的消耗移动力,这个消耗移动力在兵种数据文件中已经设定好了,直接读取就可以了
运行代码,效果如下
[img]http://i818.photobucket.com/albums/zz104/lufy_photo/z.jpg?t=1274416976[/img]
下次,该研究一下,加入敌军的人物问题了
[color=Silver][[i] 本帖最后由 lufy 于 2010-5-21 13:04 编辑 [/i]][/color]
2010-5-23 15:27
lufy
其实,加入敌军人物,只需要在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
[img]http://i818.photobucket.com/albums/zz104/lufy_photo/CaoCao.jpg?t=1274599201[/img]
然后,在相应的兵种数据中加上攻击范围的控制
如英雄
<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
然后,在寻找最大行动范围的时候,调用这个函数
就可以显示攻击范围了,效果如图
[img]http://i818.photobucket.com/albums/zz104/lufy_photo/1-9.jpg?t=1274599466[/img]
接下来,研究一下回合控制,和敌军回合的时候,敌军的行动:wink:
[color=Silver][[i] 本帖最后由 lufy 于 2010-5-23 15:51 编辑 [/i]][/color]
2010-5-23 15:36
lufy
这次除了添加一些东西外,改动也比较大
具体改了哪里,也忘了做记录了
最后成形的战场类代码如下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;
}
}
}
效果如下图
[img]http://i818.photobucket.com/albums/zz104/lufy_photo/3-1.jpg?t=1274599983[/img]
[img]http://i818.photobucket.com/albums/zz104/lufy_photo/2-3.jpg?t=1274600017[/img]
[img]http://i818.photobucket.com/albums/zz104/lufy_photo/4.jpg?t=1274600044[/img]
暂时,敌军只会跟随我军某个人物移动,等下面再慢慢研究敌方的AI
下次,在战场上显示人物的攻击防御等属性:)
2010-5-26 15:42
lufy
要显示人物属性了,把相应的人物数据和兵种数据改好,如下<?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
[img]http://i818.photobucket.com/albums/zz104/lufy_photo/hpmp.gif?t=1274858499[/img]
[img]http://i818.photobucket.com/albums/zz104/lufy_photo/CaoCao0.gif?t=1274858588[/img]
在读取完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,可以看到下面的图
[img]http://i818.photobucket.com/albums/zz104/lufy_photo/1-10.gif?t=1274858549[/img]
[img]http://i818.photobucket.com/albums/zz104/lufy_photo/2-4.gif?t=1274858568[/img]
2010-5-27 17:42
lufy
该研究攻击了,这个比较复杂,先来看,我军方面的攻击
当然,首先要把攻击动作等补全
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;
}
主要是这些修改,其他的都是些小改动
目前,只写了我军的攻击,而且只是攻击动作,敌人也不掉血,不过加个掉血并不难,
难的是敌军的攻击,现在敌军回合,敌军依然只会跟随我军某一个人物移动,等研究完敌军攻击之后,把代码放出来,
好了,现在先看一下效果吧
[img]http://i818.photobucket.com/albums/zz104/lufy_photo/1-11.jpg?t=1274951753[/img]
[img]http://i818.photobucket.com/albums/zz104/lufy_photo/2-5.jpg?t=1274951783[/img]
下次,研究一下敌人的攻击
[color=Silver][[i] 本帖最后由 lufy 于 2010-5-27 17:45 编辑 [/i]][/color]
2010-5-28 09:38
klyz505
顶你没商量啊~!!!强人!
我一直在思考,是用c+++dx开发好,还是flash好,最近想通了:用flash更好!
原因有三:
1、flash开发,webGame是当前的潮流,说不定还可以因为兴趣而找到工作,既赚钱又满足兴趣;
2、flash入门比dx快速、简单;
3、任何flash里的游戏资源,只要你想要,基本都是手到擒来,要是其它游戏,基本都要对压缩的游戏资源折腾一番才能拿到。
哥们,继续,加油,呵呵
2010-5-28 12:19
lufy
回复 #13 klyz505 的帖子
是啊,flash开发有它的优势
如果把做好的东西上传到服务器,玩家都不用下载就能玩了
如果做网游的话,不但有socket支持,还可以省了玩家下载几G的游戏资源
利用平台更是不用说,下载个Adobe Flash Player就能玩了,当然iPad和iPhone除外
2010-5-28 14:45
lufy
到了复杂的地方了,敌军的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();
}
好了,运行下程序,可以看到敌军也会进行攻击了
当然攻击是不掉血的,嘿嘿
敌军步兵的攻击
[img]http://i818.photobucket.com/albums/zz104/lufy_photo/1-12.jpg?t=1275028374[/img]
敌军弓兵的攻击
[img]http://i818.photobucket.com/albums/zz104/lufy_photo/2-6.jpg?t=1275028342[/img]
下次,该研究掉血和掉血的时候显示一下了
2010-5-30 19:01
klyz505
又学习了,楼主请继续~~~
2010-5-30 19:05
klyz505
楼主,这是你自己开发的吗?怎么这么牛~
是否已经开发完了?能不能放出来耍耍~~看着就馋
2010-5-30 19:07
主席
flash版啊!
可以放在移动设备上玩了!:hz1020:
2010-5-31 09:03
lufy
因为已经写好了伤害计算,所以,要加入伤害显示就相当简单了
首先,先来让鼠标移动到敌方人物时显示伤害数值
在显示HP和MP的框架上,另外复制一个spHP,改变一下颜色与spHP区别,命名为spHP1
然后,在显示HP和MP的时候,加上伤害判断与显示,具体如下
if(_clickCtrl != "HPMP_HERT"){
if(!queryPeople){
_hpmp.visible = false;
}else{
//定义伤害数值,初始值是0
var hp2:int = 0;
_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 = _character.nowHP + "/" + _character.HP;
_hpmp.spHP.width = 100 * (_character.nowHP/_character.HP);
_hpmp.txtMP.text = _character.nowMP + "/" + _character.MP;
_hpmp.spMP.width = 100 * (_character.nowMP/_character.MP);
if(_clickCtrl == "ATTACK" ){
//如果目前战场状态是攻击的话,则开始判断是否鼠标在敌方人物身上,是的话,则开始计算伤害数值
for(i=0;i<_roadSprite.numChildren;i++){
var childSprite:Sprite = Sprite(_roadSprite.getChildAt(i));
if(_character.their == "ENEMY" &&_mouseBox.x == Math.floor(childSprite.x/48)*48 && _mouseBox.y == Math.floor(childSprite.y/48)*48){
//调用物理伤害计算方法,开始计算伤害数值
hp2 = getAttHurt(_nowChatacter,_character);
}
}
}
//若伤害数值>0,则显示伤害数值]
if(hp2 > 0){
_hpmp.spHP1.width = 100 * (hp2/_character.HP);
_hpmp.spHP1.x = _hpmp.spHP.x + _hpmp.spHP.width - _hpmp.spHP1.width;
}else{
_hpmp.spHP1.width = 0;
}
}
这样,就可以看到伤害显示了,如图
[img]http://i818.photobucket.com/albums/zz104/lufy_photo/1-13.jpg?t=1275266318[/img]
然后,再来处理受到攻击的时候,显示伤害值
在战场上,加上两个变量
//伤害值
private var _hertHp:int;
//伤害值显示控制用
private var _hertHpIndex:int;
_hertHpIndex这个变量,是在显示伤害值时,让HP动态减少时控制用的
接下来,在控制敌军行动事件中,敌军攻击时,自定义函数里,不直接结束行动,
而是,加上伤害值显示,在伤害值显示完之后,再行动结束
原来是
_nowChatacter.character._fun = function(){
_clickCtrl = "NULL";
_nowChatacter.actionCtrl = true;
_enemyActionCtrl = 0;
addEventListener(Event.ENTER_FRAME, onEn
}
改为-〉
_nowChatacter.character._fun = function(){
_clickCtrl = "HPMP_HERT";
_hpmp.visible = true;
_hpmp.x = _nowChatacter.character._rival.x - 102;
_hpmp.y = _nowChatacter.character._rival.y - 48;
if(_hpmp.x < 0){
_hpmp.x = 0;
}
if(_hpmp.y < 0){
_hpmp.y = 0;
}
_hpmp.txtHP.text = _nowChatacter.character._rival.nowHP + "/" + _nowChatacter.character._rival.HP;
_hpmp.spHP.width = 100 * ( _nowChatacter.character._rival.nowHP/ _nowChatacter.character._rival.HP);
_hpmp.txtMP.text = _nowChatacter.character._rival.nowMP + "/" + _nowChatacter.character._rival.MP;
_hpmp.spMP.width = 100 * ( _nowChatacter.character._rival.nowMP/ _nowChatacter.character._rival.MP);
_hpmp.spHP1.width = 0;
}
相同的地方,我军攻击的时候,也进行相同的处理
改完后是
_nowChatacter.character._fun = function(){
_clickCtrl = "HPMP_HERT";
_hpmp.visible = true;
_hpmp.x = _nowChatacter.character._rival.x - 102;
_hpmp.y = _nowChatacter.character._rival.y - 48;
if(_hpmp.x < 0){
_hpmp.x = 0;
}
if(_hpmp.y < 0){
_hpmp.y = 0;
}
_hpmp.txtHP.text = _character.nowHP + "/" + _character.HP;
_hpmp.spHP.width = 100 * (_character.nowHP/_character.HP);
_hpmp.txtMP.text = _character.nowMP + "/" + _character.MP;
_hpmp.spMP.width = 100 * (_character.nowMP/_character.MP);
_hpmp.spHP1.width = 0;
}
然后在贞事件中,将伤害动态显示
//如果状态是伤害显示,则动态显示伤害值
if(_clickCtrl == "HPMP_HERT"){
//判断一下_hertHpIndex,如果小于伤害值,则动态减少HP,否则结束行动
if(_hertHpIndex < _hertHp){
_nowChatacter.rival.nowHP -= 1;
_hpmp.txtHP.text = _nowChatacter.rival.nowHP + "/" + _nowChatacter.rival.HP;
_hpmp.spHP.width = 100 * (_nowChatacter.rival.nowHP/_nowChatacter.rival.HP);
_hertHpIndex++;
}else{
//根据我方攻击还是敌方攻击,结束行动,并加上相应的事件
if(_roundCtrl == "我方回合"){
_clickCtrl = "NULL";
_nowChatacter.actionCtrl = true;
addEventListener(Event.ENTER_FRAME, onClickFrame);
}else{
_clickCtrl = "NULL";
_nowChatacter.actionCtrl = true;
_enemyActionCtrl = 0;
addEventListener(Event.ENTER_FRAME, onEnemyFrame);
}
}
}
好了,可以显示伤害值了 ^0^!
2010-5-31 09:08
lufy
[quote]原帖由 [i]klyz505[/i] 于 2010-5-30 19:05 发表
楼主,这是你自己开发的吗?怎么这么牛~
是否已经开发完了?能不能放出来耍耍~~看着就馋 [/quote]
是自己开发的阿,练习用的,这里御览的部分就是目前开发完的部分,
等稍微成型的时候,就把代码和程序发上来
目前,只是实现了简单的功能,人物撤退,战斗结束等都还没写
下次,研究一下人物撤退的问题:)
2010-6-1 10:28
lufy
下面来研究一下撤退
就是在每个人行动完之后,加一个HP判断就可以了
HP=0的时候,就让人物不显示,因为曹操传中,还有武将复活等指令,所以不可以从人物数组中删除,只将人物隐藏就可以了
为了方便,我把伤害值动态显示分离出一个方法来
//动态显示伤害值
private function hpmpHert():void{
//判断一下_hertHpIndex,如果小于伤害值,则动态减少HP,否则结束行动
if(_hertHpIndex < _hertHp){
_nowChatacter.rival.nowHP -= 1;
_hpmp.txtHP.text = _nowChatacter.rival.nowHP + "/" + _nowChatacter.rival.HP;
_hpmp.spHP.width = 100 * (_nowChatacter.rival.nowHP/_nowChatacter.rival.HP);
_hertHpIndex++;
}else{
//根据我方攻击还是敌方攻击,结束行动,并加上相应的事件
if(_roundCtrl == "我方回合"){
_clickCtrl = "CHECK";
_nowChatacter.actionCtrl = true;
}else{
_clickCtrl = "CHECK";
_nowChatacter.actionCtrl = true;
_enemyActionCtrl = 0;
}
}
}
这里,结束行动后,_clickCtrl由NULL变为了CHECK,用来判断HP
贞事件中
if(_clickCtrl == "CHECK"){
if(_nowChatacter.rival.nowHP <= 0){
//人物撤退
characterRemove();
}
}
//人物撤退
private function characterRemove():void{
if(_retreatCtrl == 0){
_nowChatacter.rival.setAlpha(0);
}else if(_retreatCtrl == 3){
_nowChatacter.rival.setAlpha(1);
}else if(_retreatCtrl == 6){
_nowChatacter.rival.setAlpha(0);
}else if(_retreatCtrl == 9){
_nowChatacter.rival.setAlpha(1);
}else if(_retreatCtrl == 12){
_nowChatacter.rival.setAlpha(0);
if(_roundCtrl == "我方回合"){
_clickCtrl = "NULL";
_retreatCtrl = -1;
addEventListener(Event.ENTER_FRAME, onClickFrame);
this.contextMenu = _roundMenu;
}else{
_clickCtrl = "NULL";
_retreatCtrl = -1;
addEventListener(Event.ENTER_FRAME, onEnemyFrame);
}
}
_retreatCtrl++;
}
这里的_retreatCtrl,用来让人物闪烁
挺简单的,运行下程序,当人物HP变成0的时候,会闪烁几下,然后消失
2010-6-1 10:29
lufy
下面研究反击,反击进行的时间,是在攻击之后,也就是在进行HP判断之后,如果HP还大于0的话,那么这个武将的反击目标又恰好在他的攻击范围之内,那么进行反击
好了,那就在贞事件中判断HP的地方
if(_clickCtrl == "CHECK"){
if(_nowChatacter.rival.nowHP <= 0){
//人物撤退
characterRemove();
}else{
//反击判断
counterCheck();
}
}
//反击判断
private function counterCheck():void{
var isOK:Boolean = false;
var attRoundArr:Array;
//检验反击目标是否在他的攻击范围之内
for each ( var roundment:XML in _arms["Arms" + _nowChatacter.rival.armsIndex]["RangeAttack"].elements( ) ) {
attRoundArr = roundment.toString().split(",");
if((int(attRoundArr[0]) + _nowChatacter.rival.locationX) == _nowChatacter.locationX &&
(int(attRoundArr[1]) + _nowChatacter.rival.locationY) == _nowChatacter.locationY){
isOK = true;
break;
}
}
if(_roundCtrl == "我方回合"){
if(!_counter && isOK){
_counter = true;
_clickCtrl = "COUNTER";
}else{
_clickCtrl = "NULL";
_counter = false;
addEventListener(Event.ENTER_FRAME, onClickFrame);
this.contextMenu = _roundMenu;
}
}else{
if(!_counter && isOK){
_counter = true;
_clickCtrl = "COUNTER";
}else{
_clickCtrl = "NULL";
_counter = false;
addEventListener(Event.ENTER_FRAME, onEnemyFrame);
}
}
//满足反击条件,进行反击
if(_clickCtrl == "COUNTER"){
_character = _nowChatacter;
_nowChatacter = _nowChatacter.rival;
_nowChatacter.rival = _character;
_hertHp = Math.floor(getAttHurt(_nowChatacter,_nowChatacter.rival)*0.75);
_hertHpIndex = 0;
_nowChatacter.character._fun = function(){
_clickCtrl = "HPMP_HERT";
_hpmp.visible = true;
_hpmp.x = _nowChatacter.character._rival.x - 102;
_hpmp.y = _nowChatacter.character._rival.y - 48;
if(_hpmp.x < 0){
_hpmp.x = 0;
}
if(_hpmp.y < 0){
_hpmp.y = 0;
}
_hpmp.txtHP.text = _nowChatacter.rival.nowHP + "/" + _nowChatacter.rival.HP;
_hpmp.spHP.width = 100 * ( _nowChatacter.rival.nowHP/ _nowChatacter.rival.HP);
_hpmp.txtMP.text = _nowChatacter.rival.nowMP + "/" + _nowChatacter.rival.MP;
_hpmp.spMP.width = 100 * ( _nowChatacter.rival.nowMP/ _nowChatacter.rival.MP);
_hpmp.spHP1.width = 0;
}
_nowChatacter.attack();
}
}
这里进行反击很简单,只需要把原来的攻击和被攻击人员交换一下,就可以了
运行代码,一切OK
下次,该试着研究下双击和挡格以及爆击等事件了,!^0^!
2010-6-2 08:53
lufy
下面研究双击和致命一击
根据曹操传的计算公式
先来写两个方法
/*
双击概率计算
如果Sa/Sd<1,那么H=1;
如果1<=Sa/Sd<2,那么H=2+18*(Sa/Sd-1);
如果2<=Sa/Sd<=3,那么H=20+80*(Sa/Sd-2);
如果Sa/Sd>=3,那么H=100;
*/
private function getDoubleAtt(attChara:Character,hertChara:Character):int{
var h:int;
//得到双方的爆发力
var attBreakout:int = int(_pXml["peo" + attChara.charaIndex].Breakout);
var hertBreakout:int = int(_pXml["peo" +hertChara.charaIndex].Breakout);
var rate:Number = attBreakout/hertBreakout;
if(rate < 1){
h = 1;
}else if(rate >= 1 && rate < 2){
h = 2 + 18*(rate - 1);
}else if(rate >= 2 && rate < 3){
h = 20 + 80*(rate - 2);
}else if(rate >= 3){
h = 100;
}
if(Math.random()*100 <= h){
return 2;
}
return 1;
}
/*
致命概率计算
如果Sa/Sd<1,那么H=1;
如果1<=Sa/Sd<2,那么H=2+18*(Sa/Sd-1);
如果2<=Sa/Sd<=3,那么H=20+80*(Sa/Sd-2);
如果Sa/Sd>=3,那么H=100;
*/
private function getFatalAtt(attChara:Character,hertChara:Character):Boolean{
var h:int;
//得到双方的士气
var attMorale:int = int(_pXml["peo" + attChara.charaIndex].Morale);
var hertMorale:int = int(_pXml["peo" +hertChara.charaIndex].Morale);
var rate:Number = attMorale/hertMorale;
if(rate < 1){
h = 1;
}else if(rate >= 1 && rate < 2){
h = 2 + 18*(rate - 1);
}else if(rate >= 2 && rate < 3){
h = 20 + 80*(rate - 2);
}else if(rate >= 3){
h = 100;
}
if(Math.random()*100 <= h){
return true;
}
return false;
}
方法定义好了,现在就是在哪里使用的问题了
双击判断,我是在攻击之前判断攻击次数,这样做的好处是以后如果弄个绝招三连击五连击什么的,就可以直接将这个攻击次数设为相应的数字,就可以变成连击绝招了
而致命判断,是在攻击或者反击的时候都发生的,于是把它放在攻击的方法里,
只要发生攻击,就判断是否发生致命一击
在敌军或者我军攻击之前,都先进行双击判断
//判断双击
_attCount = getDoubleAtt(_nowChatacter,_nowChatacter.rival);
然后,修改攻击方法
这里考虑到反击的时候不双击,所以要另外加一个控制
}
//进行攻击
private function toAttack(hert:Boolean = true):void{
//是否是反击判断
if(hert){
_hertHp = getAttHurt(_nowChatacter,_nowChatacter.rival);
}
if(_clickCtrl == "ATTACK"){
_attCount -= 1;
}
_hertHpIndex = 0;
//判断致命一击
_nowChatacter.fatal = getFatalAtt(_nowChatacter,_nowChatacter.rival);
if(_nowChatacter.fatal){
_hertHp = Math.floor(_hertHp*1.25);
if(_hertHp > _nowChatacter.rival.nowHP){
_hertHp = _nowChatacter.rival.nowHP;
}
}
_nowChatacter.character._fun = function(){
_clickCtrl = "HPMP_HERT";
_hpmp.visible = true;
_hpmp.x = _nowChatacter.rival.x - 102;
_hpmp.y = _nowChatacter.rival.y - 48;
if(_hpmp.x < 0){
_hpmp.x = 0;
}
if(_hpmp.y < 0){
_hpmp.y = 0;
}
_hpmp.txtHP.text = _nowChatacter.rival.nowHP + "/" + _nowChatacter.rival.HP;
_hpmp.spHP.width = 100 * ( _nowChatacter.rival.nowHP/ _nowChatacter.rival.HP);
_hpmp.txtMP.text = _nowChatacter.rival.nowMP + "/" + _nowChatacter.rival.MP;
_hpmp.spMP.width = 100 * ( _nowChatacter.rival.nowMP/ _nowChatacter.rival.MP);
_hpmp.spHP1.width = 0;
}
_nowChatacter.attack();
}
这样就可以判断双击和致命了
然后在动作显示的时候,加上相应的显示
致命一击的时候,人物要发光
先把发光的颜色设定好
_fatalColor = new Color;
_fatalColor.brightness = 0.5;
//转为致命一击
public function startFatalColor():void{
this.transform.colorTransform = _fatalColor;
}
//结束致命一击
public function endFatalColor():void{
this.transform.colorTransform = _runColor;
}
然后人物攻击的时候,判断是否显示致命的颜色
//当人物攻击时
if(dir == CharacterIndex.ATTACK_UP || dir == CharacterIndex.ATTACK_DWON ||
dir == CharacterIndex.ATTACK_LEFT || dir == CharacterIndex.ATTACK_RIGHT ){
_peopleBitmap.x = -8;
_peopleBitmap.y = -8;
//在攻击的第一个动作,判断是否是致命一击
if(_fatal){
if(_pointer == 0 && _fatalCtrl < 10){
if(_fatalCtrl == 0){
startFatalColor();
}
_pointer = 0;
_count = 0;
_fatalCtrl++;
}else{
_fatal = false;
_fatalCtrl = 0;
endFatalColor();
}
}
//在攻击的第三个动作,被攻击人物显示被攻击动作
if(_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);
}
}else{
_peopleBitmap.x = 0;
_peopleBitmap.y = 0;
}
好了,大致就是这样运行一下,我把曹操的爆发力和士气改为很高,很容易看到效果了
[img]http://i818.photobucket.com/albums/zz104/lufy_photo/1-14.jpg?t=1275438367[/img]
2010-6-2 08:56
lufy
这是23楼之前的源代码,想看效果的,可以直接打开bin文件夹下的CaoCao.swf
2010-7-16 13:49
lewulezo
下载了楼主的包,用IE打开一看画面不停的闪动。
2010-7-16 13:53
lewulezo
下载了楼主的包,用IE打开一看画面不停的闪动。
2010-7-29 11:33
将来的mod达人
回复 #26 lewulezo 的帖子
请问是否有FLASH?
2010-7-30 13:13
血牛嘎嘎
跪求楼主有所突破啊,不过我想到一个问题,就是FLASH游戏大小有限制,界面效果可能不太好啊
2010-7-30 16:00
wakin98
太牛了,不知楼主能否整个完整的游戏出来让吾辈感受一下
2010-7-30 23:31
Axie89
能否试试制作一个类似于金群的復刻版.从而提高ccz的多样性?
2010-7-30 23:33
Axie89
ccz引擎时代已经过去了.希望楼主能制作出一套自己的引擎突破ccz的各种限制.
2010-7-31 07:18
lufy
[quote]原帖由 [i]血牛嘎嘎[/i] 于 2010-7-30 13:13 发表
跪求楼主有所突破啊,不过我想到一个问题,就是FLASH游戏大小有限制,界面效果可能不太好啊 [/quote]
用flash做手机等游戏的时候有大小限制,如果做单机游戏或者网络游戏的话,是没有什么限制的,如果美工好的话,界面是可以相当漂亮的,做3D也是不成问题的,如果参考一下其他成品的flash就会知道,可以十分完美的
[color=Silver][[i] 本帖最后由 lufy 于 2010-7-31 07:23 编辑 [/i]][/color]
2010-7-31 07:20
lufy
[quote]原帖由 [i]Axie89[/i] 于 2010-7-30 23:33 发表
ccz引擎时代已经过去了.希望楼主能制作出一套自己的引擎突破ccz的各种限制. [/quote]
在下纯属研究,至于突破嘛,并不是没有,可能会在制作其他游戏的时候找突破,毕竟做游戏是我的兴趣
2010-7-31 20:43
Axie89
回复 #33 lufy 的帖子
支持你.~
2010-8-2 19:53
我爱王丽霞
。。这种东西 不是懂一点就能搞出来的啊。。汗
2010-8-9 15:40
Axie89
頂上去... ..:hz1019:
2010-8-10 15:18
Axie89
每天都给高手顶一次!:hz1019:
2010-8-11 09:57
northwind_x
楼主V5,我也准备做一个在线版的SLG引擎,多多向你学习
2010-8-11 20:10
Axie89
给高手每天顶一次,唔唔唔,轩辕的修改区冷清了。。van大和金圭子回来就好了
2010-8-22 21:59
northwind_x
等待楼主更新
2010-8-22 23:55
northwind_x
现在轩辕春秋的下载速度太慢了,楼主能把你的源码给个外链吗?或者发到我的邮箱norristong_x#qq.com,多谢
2010-8-30 23:36
Axie89
对了.牛人,你有方法更换ccz的meff法术类吗?
2010-8-31 08:36
lufy
[quote]原帖由 [i]Axie89[/i] 于 2010-8-30 23:36 发表
对了.牛人,你有方法更换ccz的meff法术类吗? [/quote]
其实无论是法术也好,攻击也好,或者是走路等,都是将一些连续的图片一张一张的显示出来,用眼睛看起来就成了一组组动画,跟电影是一个道理的,如果能看懂我的代码的话,很明显可以看出,我把人物四个方向的不同动作都装进了一个个的数组,然后按照顺序显示这个数组里的每个元素,就成了走路,攻击等动作,如果你把一些更复杂的动作装进数组来显示,那么你就可以实现改变曹操传动作的贞数,可以做特殊攻击,在特殊攻击的时候,显示一些特殊的攻击动作,法术也一样,如果我做的话,也是将不同的法术图片装进不同的数组,来调用它们,并且按照顺序显示,这样就成了法术效果,你只要准备不同的图片,就可以变成不同的法术,伤害名称等,只不过是个定义而已,比如想弄得华丽一些,可以在使用法术的时候,先调用一个类似四神一样的动画,然后再调用普通法术攻击的动画,其实原理都是很简单的:)
[color=Silver][[i] 本帖最后由 lufy 于 2010-8-31 08:37 编辑 [/i]][/color]
2010-9-5 19:55
Axie89
回复 #43 lufy 的帖子
╮(╯▽╰)╭忙死了最近,其实我是一个美工,之前跟一个高手谈论过这个话题,并且尝试把meff里面的动画(那堆bmp。。)替换另外的东西(什么太极啊。一堆乱七八糟的东西。。)发现RV和周瑜导入器都没法导入新的bmp动画文件,为此,我尝试请教了star,godtype,才发现那些ue地址是包括了这张bmp里面播放的声音,帧数,那些又是乱七八遭的东西。你有方法可以找到Ue地址包含的信息么?万分感谢:hz1024:
2010-9-5 20:01
Axie89
对了,这是星哥的原话
Meff.e5的增加比较繁琐,
我以前略微研究过一下,这个文件里的图片不仅仅是单纯的图片形象,还包含了一段信息,用来表示这个图片的帧数,以及使用这个图片时播放的声音,也就是这个对应策略的声音,另外可能还有其他一些信息。
具体做法要先作好一段信息,再和图片信息拼接成一个文件,这样就可以导入到Meff.e5中去了。
但是导入并没有现成的工具,周瑜的导入器也不行,我的方法是先用周瑜的导入器随便导入一个文件,这样在Meff.e5中就可以增加一个区段,然后用Ue打开事先拼接好的文件和Meff,如果了解LS文件的格式就不难了,先查找到新区段的起始位置,再把拼接好的文件复制的这个位置就行了
Mcall00.e5的增加方法不详
2010-9-6 07:05
lufy
[quote]原帖由 [i]Axie89[/i] 于 2010-9-5 19:55 发表
╮(╯▽╰)╭忙死了最近,其实我是一个美工,之前跟一个高手谈论过这个话题,并且尝试把meff里面的动画(那堆bmp。。)替换另外的东西(什么太极啊。一堆乱七八糟的东西。。)发现RV和周瑜导入器都没法导入新的 ... [/quote]
说实话,我c和c++方面虽然能写一些简单代码,但基本属于空白,当年做曹操传MOD的时候引擎修改等也是拜托了其他高手,UE等更是依葫芦画瓢
我上面说的原理简单,其实是说自己做游戏的时候实现这个功能并不难,
最近在给公司挺忙的,等闲下来后,
继续研究下flash版曹操传的法术功能
2010-9-6 07:47
‰舍得
123123123123
2010-9-14 11:28
northwind_x
楼主用FLASH绘图时效率如何啊?
2010-9-14 13:55
天机
那个,问一下,楼主能做出一个剧本编辑器或者引擎修改器一类的东西吗?我们就能对你的引擎做mod了:hz1016:
2010-9-15 08:27
lufy
[quote]原帖由 [i]northwind_x[/i] 于 2010-9-14 11:28 发表
楼主用FLASH绘图时效率如何啊? [/quote]
用flash绘图,我觉得效率是绝对没有问题的,
现在用flash开发的游戏越来越多了,大型的游戏也数不胜数,
在我看来是不存在什么效率问题的。
2010-9-15 08:29
lufy
[quote]原帖由 [i]天机[/i] 于 2010-9-14 13:55 发表
那个,问一下,楼主能做出一个剧本编辑器或者引擎修改器一类的东西吗?我们就能对你的引擎做mod了:hz1016: [/quote]
在下一开始就说了,只是研究一下,没打算做成引擎或是突破一些什么东西,
要是做引擎的话,我会做一个新的,不想模仿曹操传等,那样就没什么意思了
2010-9-15 13:12
前田庆次
搞个千人战棋出来
2010-9-18 15:32
northwind_x
下载的FLASH一直不停抖动,期待楼主发布一个稳定版本
2010-11-22 15:04
lufy
[quote]原帖由 [i]northwind_x[/i] 于 2010-9-18 15:32 发表
下载的FLASH一直不停抖动,期待楼主发布一个稳定版本 [/quote]
如果有Flash CS4的话,把源码重新发布一下应该没什么问题的
测试的话,这里倒是可以看到
[url]http://lufy.hp2.jp/computer/html/caocao.html[/url]
2010-11-28 11:30
wwt1118
强帖,留名待用
2010-12-14 19:24
破天银狼
不能不顶啊,楼主,咱支持你,希望咱们网络对战CCZ的愿望能早点实现,看你了!还有希望你能做个比现在CCZ的战棋类游戏更强更好的游戏引擎出来,顶!
页:
[1]
Powered by Discuz! Archiver 5.0.0
© 2001-2006 Comsenz Inc.