终于到了攻击部分了,战棋游戏中的攻击,主要分为物理攻击和法术攻击,本章就先从物理攻击讲起。物理攻击又分为普通攻击,连击(双击),以及致命攻击,再复杂一点的还有其他特殊攻击,比如我的《三国记-乱世群雄》游戏里面,张飞的三次攻击,关羽的多人攻击等特殊的技能攻击。我依然从简单开始,先来看看如何来实现一下普通攻击,攻击的过程是,1,A对B进行攻击。2,B受伤或者档格。3,如果A在B的攻击范围之内,则B会进行一次反击。4,A受伤或者档格。
上一章发布之后,隔的时间比较长了,主要是工作忙,没太多时间整理这些东西,下面我主要介绍一下代码的核心部分,最后有源码下载,大家可以对照着文章看一下,方便理解。
上一章已经解决了人物移动,接下来当人物移动结束的时候,需要弹出一个攻击选择,先看看攻击菜单的制作。
ffunction LSouSouSMapMenuCtrl(x,y){
var self = this;
base(self,LSprite,[]);
self.addMenu(x,y);
}
LSouSouSMapMenuCtrl.prototype.addMenu = function(x,y){
var self = this;
LSouSouObject.sMap.smapClick.removeClickEvent();
var menuLayer = new LSprite();
var buttonAtk = new LButtonSample1("攻击");
buttonAtk.backgroundCorl = "red";
buttonAtk.x = 15;
buttonAtk.y = 15;
menuLayer.addChild(buttonAtk);
var buttonTactics = new LButtonSample1("策略");
buttonTactics.x = 15;
buttonTactics.y = buttonAtk.getHeight() + buttonAtk.y;
menuLayer.addChild(buttonTactics);
var buttonProps = new LButtonSample1("道具");
buttonProps.x = 15;
buttonProps.y = buttonAtk.getHeight()*2 + buttonAtk.y;
menuLayer.addChild(buttonProps);
var buttonStop = new LButtonSample1("停止");
buttonStop.x = 15;
buttonStop.y = buttonAtk.getHeight()*3 + buttonAtk.y;
menuLayer.addChild(buttonStop);
var buttonCancel = new LButtonSample1("取消");
buttonCancel.backgroundCorl = "red";
buttonCancel.x = 15;
buttonCancel.y = buttonAtk.getHeight()*4 + buttonAtk.y;
menuLayer.addChild(buttonCancel);
var selfWidth = buttonAtk.getWidth()+30;
var selfHeight = buttonAtk.getHeight()*5+30;
var bar = LSouSouObject.getBar(selfWidth,selfHeight);
menuLayer.addChild(bar);
self.addChild(menuLayer);
x += LSouSouObject.sMap.nodeLength;
if(x + LSouSouObject.sMap.backLayer.x + selfWidth > LSouSouObject.sMap.SCREEN_WIDTH){
x -= (selfWidth + LSouSouObject.sMap.nodeLength);
}
if(y + LSouSouObject.sMap.backLayer.y + selfHeight > LSouSouObject.sMap.SCREEN_HEIGHT){
y = LSouSouObject.sMap.SCREEN_HEIGHT - selfHeight - LSouSouObject.sMap.backLayer.y;
}
self.x = x + LSouSouObject.sMap.backLayer.x;
self.y = y + LSouSouObject.sMap.backLayer.y;
buttonAtk.addEventListener(LMouseEvent.MOUSE_UP,self.onclickAtk);
buttonCancel.addEventListener(LMouseEvent.MOUSE_UP,self.onclickCancel);
};
LSouSouSMapMenuCtrl.prototype.onclickAtk = function(e){
};
LSouSouSMapMenuCtrl.prototype.onclickCancel = function(e){
};
下面的一行代码是上一章中移动结束事件的添加
LSouSouObject.charaSNow.addEventListener(LSouSouEvent.CHARACTER_MOVE_COMPLETE,self.onShowAttackMenu);
修改如下
LSouSouObject.charaSNow.addEventListener(LSouSouEvent.CHARACTER_MOVE_COMPLETE,self.onMoveComplete);
相应的回调函数onMoveComplete如下。
LSouSouSMap.prototype.onMoveComplete = function(){
var self = LSouSouObject.sMap;
LSouSouObject.charaSNow.removeEventListener(LSouSouEvent.CHARACTER_MOVE_COMPLETE,self.onMoveComplete);
//移动结束
if(LSouSouObject.charaSNow.belong == LSouSouObject.BELONG_SELF){
self.showCtrlMenu();
}else{
//敌军AI,暂略
}
};
上面代码,当移动结束的人物所属是我军的时候,调用showCtrlMenu函数,如下
LSouSouSMap.prototype.showCtrlMenu = function(){
var self = this;
self.menu = LSouSouSMapMenu.addSMenu(LSouSouObject.charaSNow.x,LSouSouObject.charaSNow.y,"ctrl");
self.menuLayer.addChild(self.menu);
};
这样就添加了攻击菜单了,效果如下
点击上面的选择列表中的攻击按钮,首先应该确定攻击范围。
在arms.json兵种设定文件中,攻击范围主要是由两个属性决定,RangeAttack是攻击的范围,RangeAttackTarget是攻击时一次攻击能攻击到的人数范围,比如下面的游戏截图中,红色区域由RangeAttack决定,绿色区域由RangeAttackTarget决定。
首先来显示攻击范围,修改LSouSouSMapMenuCtrl类的onclickAtk函数,如下。
LSouSouSMapMenuCtrl.prototype.onclickAtk = function(e){
var i,nodeChild;
LSouSouObject.sMap.menu.parent.removeChild(LSouSouObject.sMap.menu);
LSouSouObject.sMap.menu = null;
var attackRange = LSouSouObject.sMap.attackRange = LSouSouObject.charaSNow.member.getRangeAttack();
for(i=0;i
其中的一行
LSouSouSMapMenu.addSMenu(LSouSouObject.charaSNow.x,LSouSouObject.charaSNow.y,"cancel");
是添加一个取消按钮,用处是当点击攻击按钮之后,可以取消之后重新选择,在flash版三国记中取消按钮是被我添加到了右侧的按钮列表,如下
这样的话,用户体验上不太好,所以这次我把取消按钮添加到攻击者的位置上,取消按钮代码如下。
function LSouSouSMapMenuCancel(x,y){
var self = this;
base(self,LSprite,[]);
self.clickEvent = null;
self.addMenu(x,y);
}
LSouSouSMapMenuCancel.prototype.addMenu = function(x,y){
var self = this;
var menuLayer = new LSprite();
var buttonCancel = new LButtonSample1("×");
menuLayer.addChild(buttonCancel);
self.addChild(menuLayer);
self.x = x + LSouSouObject.sMap.backLayer.x + (LSouSouObject.sMap.nodeLength - buttonCancel.getWidth())*0.5;
self.y = y + LSouSouObject.sMap.backLayer.y + (LSouSouObject.sMap.nodeLength - buttonCancel.getHeight())*0.5;
buttonCancel.addEventListener(LMouseEvent.MOUSE_UP,self.onclickCancel);
};
LSouSouSMapMenuCancel.prototype.onclickCancel = function(e){
var self = LSouSouObject.sMap.menu;
if(self.clickEvent)self.clickEvent();
};
运行程序后,效果如下。
攻击
最后,就是当点击攻击的范围,并且点击的位置有敌军存在的话,就开始攻击,点击事件如下
LSouSouSMapClick.prototype.onAtkClickUp = function(e){
trace("onAtkClickUp is click");
var mx = e.selfX;
var my = e.selfY;
var intX = ((mx - LSouSouObject.sMap.backLayer.x)/LSouSouObject.sMap.nodeLength) >>> 0;
var intY = ((my - LSouSouObject.sMap.backLayer.y)/LSouSouObject.sMap.nodeLength) >>> 0;
var nodeStr;
var nodeArr;
var _characterS;
var list = LSouSouObject.sMap.enemylist;
for(i=0;i _characterS.x + LSouSouObject.sMap.backLayer.x &&
mx < _characterS.x + LSouSouObject.sMap.backLayer.x + LSouSouObject.sMap.nodeLength &&
my > _characterS.y + LSouSouObject.sMap.backLayer.y &&
my < _characterS.y + LSouSouObject.sMap.backLayer.y + LSouSouObject.sMap.nodeLength){
LSouSouObject.sMap.menu.parent.removeChild(LSouSouObject.sMap.menu);
LSouSouObject.sMap.menu = null;
LSouSouObject.sMap.attackRangeLayer.graphics.clear();
LSouSouObject.charaSNow.targetCharacter = _characterS;
trace("LSouSouObject.charaSNow.targetCharacter="+LSouSouObject.charaSNow.targetCharacter);
//攻击
LSouSouObject.charaSNow.setAttackNumber();
LSouSouObject.charaSNow.attackCalculate();
}
}
};
上面的代码,当点击到敌军的时候,首先调用LSouSouCharacterS类的setAttackNumber函数,然后调用attackCalculate函数,setAttackNumber函数是决定攻击次数,比如双击等多次攻击的判定是在这个函数中决定的,本次不考虑多次攻击,所以setAttackNumber函数中的攻击次数是默认为1的,如下
LSouSouCharacterS.prototype.setAttackNumber = function(){
var self = this;
//双击判定 暂略
self.attackNumber = 1;
self.attackIndex = 0;
self.targetCharacter.attackIndex = 0;
self.targetCharacter.attackNumber = 1;
};
attackCalculate函数,包含攻击之前的特技等判断,暂时也不考虑,如下
LSouSouCharacterS.prototype.attackCalculate = function(){
var self = this;
//特技判定 暂略
//物理攻击
self.toAttackStart();
};
然后调用toAttackStart函数,开始物理攻击,代码如下。
LSouSouCharacterS.prototype.toAttackStart = function(){
var self = this;
trace("self.targetCharacter="+self.targetCharacter);
if(!self.targetCharacter)return;
if(self.x > self.targetCharacter.x){
self.action = LStaticSouSouCharacterS.ATK_LEFT;
}else if(self.x < self.targetCharacter.x){
self.action = LStaticSouSouCharacterS.ATK_RIGHT;
}else if(self.y > self.targetCharacter.y){
self.action = LStaticSouSouCharacterS.ATK_UP;
}else{
self.action = LStaticSouSouCharacterS.ATK_DOWN;
}
self.action_mode = LStaticSouSouCharacterS.MODE_ATTACK;
self.addEventListener(LSouSouEvent.ANIMATION_COMPLETE,self.attackOver);
};
attackOver函数是当攻击结束时调用的,代码如下。
LSouSouCharacterS.prototype.attackOver = function(){
var self = this;
var charas,i;
var target = self.targetCharacter;
var checkBelong = LSouSouObject.sMap.belong_mode;
self.removeEventListener(LSouSouEvent.ANIMATION_COMPLETE,self.attackOver);
self.attackIndex++;
//双击或双击以上攻击 暂略
//对方没有混乱,兵力大于0,并且可以反击
if(self.targetCharacter.member.getTroops() > 0
&& self.targetCharacter.attackIndex < self.targetCharacter.attackNumber){
self.action = LStaticSouSouCharacterS.DOWN + self.direction;
for(i=0;i if(self.action_mode == LStaticSouSouCharacterS.MODE_ATTACK){
self.toAttackTargets();
}
就是说当人物处在攻击动作时,调用toAttackTargets函数,相关代码如下。
LSouSouCharacterS.prototype.toAttackTargets = function(){
var self = this,charas,_charalist,i;
if(!self.targetCharacter)return;
if(self.actionIndex == 2){
_charalist = {};
if(self.belong == LSouSouObject.BELONG_SELF || self.belong == LSouSouObject.BELONG_FRIEND){
for(i=0;i= charas.member.getTroops()){
hertValue = charas.member.getTroops();
//获取经验值计算 暂略
}
//特技修正 暂略
//减HP 暂略
charas.action = LStaticSouSouCharacterS.HERT;
//减HP显示
var numberShow = new LSouSouSMapNumber(-hertValue);
numberShow.x = charas.x + (charas.getWidth() - numberShow.getWidth())*0.5;
numberShow.y = charas.y + (charas.getHeight() - numberShow.getHeight())*0.5;
LSouSouObject.sMap.charaLayer.addChild(numberShow);
}else{
//档格
if(charas.member.getIndex() == self.targetCharacter.member.getIndex()){
charas.targetCharacter = self;
}
if(self.x > charas.x){
charas.action = LStaticSouSouCharacterS.BLOCK_RIGHT;
}else if(self.x < charas.x){
charas.action = LStaticSouSouCharacterS.BLOCK_LEFT;
}else if(self.y > charas.y){
charas.action = LStaticSouSouCharacterS.BLOCK_DOWN;
}else{
charas.action = LStaticSouSouCharacterS.BLOCK_UP;
}
}
//升级判定 暂略
}
下面是攻击效果
测试连接如下
http://lufylegend.com/demo/test/lsharp/11/game/index.html
以上,本章就先讲这么多了,下一章会讲一下我方,敌方和友方回合之间的切换,以及敌军和友军方面简单的攻击AI
本章为止的源码如下,不包含lufylegend.js引擎源码,请自己到官网下载
http://lufylegend.com/demo/test/lsharp/11/11.rar
※源码运行说明:需要服务器支持,详细请看本系列文章《序》和《第一章》
《游戏脚本的设计与开发》系列文章目录
http://blog.csdn.net/lufy_legend/article/details/8888787
本章就讲到这里,欢迎继续关注我的博客
转载请注明:转自lufy_legend的博客http://blog.csdn.net/lufy_legend
你可能感兴趣的:(《游戏脚本的设计与开发》-(战棋部分)第十章 物理攻击)