说到九宫格战斗,就不能不提一款游戏《神仙道》,在神仙道之前,九宫格战斗的模式就在几款游戏里面有应用,但神仙道是真真正正把这种战斗模式发扬光大的里程碑,当时无论口碑,还是市场占有率都可以说是空前的,这款游戏我玩到150级,可以说是投入精力比较大的一款游戏,在游戏里面也交了很多朋友,虽然最近这种游戏模式因为一些原因走下坡路(现阶段刀塔传奇这种模式的游戏很吃香),不过既然说回合制游戏,那么就还是讨论一下。
一、 | 战斗系统概述 | |||||
1 | 此战斗系统适用于PVE(玩家与怪物战斗)和PVP(玩家与玩家战斗) | |||||
2 | 游戏为横版,攻守双方分部屏幕左右两边 | |||||
3 | 战场上攻防双方各有一个3*3的9宫格方阵 | |||||
4 | 回合制战斗,按双方各自的出手顺序 |
二、 | 战斗内容 | ||||||
2.1 | 战斗单位 | ||||||
2.1.1 | 战场上的一方最多只能有五个战斗单位,战斗单位包括主角和伙伴(这个在后期改为有一个伙伴作为后备,当前排角色死亡后来填补空缺【不过反响并不好】) | ||||||
2.1.2 | 每场战斗可以派遣数个伙伴随主角一起参与,最高参与人数与奇术系统相关 | ||||||
2.2 | 战斗触发 | ||||||
2.2.1 | 战斗触发入口 | 多人副本入口、开启活动副本入口 | |||||
2.2.2 | 触碰明雷怪 | 在单人副本中行走进入明雷怪触发战斗范围后,切换至战斗画面 | |||||
2.3 | 战斗规则 | ||||||
2.3.1 | 回合制 | 每场战斗20回合,如果回合满则自动结束战斗 | |||||
2.3.2 | 攻击顺序 | ||||||
A. | 按照双方先攻值判断队伍出手先后顺序 | ||||||
B. | 按本方出手顺序依次筛选出第N个出手的战斗单位 | ||||||
C. | 死亡的战斗单位不参与筛选,如果本方第N个出手的战斗单位死亡,则本轮次轮空 | ||||||
2.4 | 战场形势 | ||||||
2.4.1 | 战场位置 | 战场上攻防双方各有一个3*3的9宫格方阵,根据阵型不同,玩家可以布置 | |||||
2.4.2 | 战斗位置编号 | 为9宫格每个格子进行编号,阵型系统根据编号,给予上场的单位出手顺序 |
2.5 | 战斗带入属性 | ||||||
2.5.1 | 玩家等级 | 1-100(这里用100是因为100级之前神仙道的概率公式直接使用百分数,110之后更新,概率由百分数改为概率等级,参考魔兽世界600等级==1%) | |||||
2.5.2 | 职业 | 剑灵、飞羽、将星、武圣、方士、术士 | |||||
2.5.3 | HP | 每个战斗单位的总血量值 | |||||
2.5.4 | 普通攻击力/法术攻击力 | 物理职业读取普通攻击力值,法师职业读取法术攻击力值 | |||||
2.5.5 | 普通防御力/法术防御力 | 物理职业读取普通防御力值,法师职业读取法术防御力值 | |||||
2.5.6 | 绝技攻击力 | 士气达到100时,释放绝技时读取的绝技攻击力值 | |||||
2.5.7 | 绝技防御力 | 受到绝技伤害时,读取的绝技防御力值 | |||||
2.5.8 | 命中概率、闪避概率 | (出手战斗单位命中概率-防御方闪避)是一个在[0,1]区间的概率值(110之后改为概率等级),决定是否成功命中对方或被对方躲避掉此次伤害 | |||||
2.5.9 | 暴击概率 | 成功触发暴击事件的概率(110之后改为概率等级) | |||||
2.5.10 | 减少对方暴击 | 减少对方触发暴击事件的概率(110之后改为概率等级) | |||||
2.5.11 | 必杀 | 增加触发暴击事件后产生的伤害值(110之后改为概率等级) | |||||
2.5.12 | 格挡概率 | 成功触发格挡事件的概率(110之后改为概率等级) | |||||
2.5.13 | 减少对方格挡 | 减少对方触发格挡事件的概率(110之后改为概率等级) | |||||
2.5.14 | 士气值 | 士气值累积达到100时,触发绝技(110之后改为概率等级) |
2.6 | 攻击事件 | |||||||
2.6.1 | 普通攻击 | 物理攻击型战斗单位在士气未达到100时的攻击方式 | ||||||
2.6.2 | 法术攻击 | 法术攻击型战斗单位在士气未达到100时的攻击方式 | ||||||
2.6.3 | 绝技攻击 | 战斗单位的士气值达到100时的攻击方式 | ||||||
2.6.4 | 血量减少 | 攻击放成功给予目标战斗单位伤害后,目标战斗单位血量减少 | ||||||
2.6.5 | 暴击 | 按暴击概率是否成功触发暴击事件,若成功触发则产生(1+0.5+必杀值)*E的伤害,失败则伤害值仍为E(E为按攻防公式产生的非绝技伤害值) | ||||||
2.6.6 | 命中 | 出手战斗单位成功对目标战斗单位造成单次伤害 | ||||||
2.6.7 | 闪避 | 目标战斗单位成功躲避出手战斗单位造成的单次伤害 | ||||||
2.6.8 | 格挡 | 按概率成功触发格挡事件后,受到的伤害值减半,状态维持1回合 | ||||||
2.6.9 | 反击 | 被近战单体攻击并触发格挡之后,触发反击对对方造成数值为E的伤害 | ||||||
2.6.10 | 士气 | |||||||
A. | 获得:初始值及获得士气值见下表(身上有特殊BUFF时也会获得士气值) | |||||||
职业 | 初始默认值 | 物理攻击 | 被物理攻击 | 法术攻击 | 被法术攻击 | 绝技攻击 | 被绝技攻击 | BUFF增加 |
剑灵 | 50 | 25 | 25 | 25 | 25 | 0 | 0 | 参见BUFF表 |
武圣 | 50 | 25 | 25 | 25 | 25 | 0 | 0 | 参见BUFF表 |
飞羽 | 50 | 25 | 25 | 25 | 25 | 0 | 0 | 参见BUFF表 |
将星 | 50 | 25 | 25 | 25 | 25 | 0 | 0 | 参见BUFF表 |
方士 | 50 | 25 | 25 | 25 | 25 | 0 | 0 | 参见BUFF表 |
术士 | 50 | 25 | 25 | 25 | 25 | 0 | 0 | 参见BUFF表 |
B. | 消耗 | |||||||
每次士气值达到或超过100触发绝技后,士气值减少至0 | ||||||||
受到减少士气值的技能攻击,士气值减少 | ||||||||
2.7 | 战斗结果 | |||||||
2.7.1 | 一方的所有战斗单位的血量和为0,战斗结束。战斗单位血量和大于0的一方获胜 | |||||||
2.7.2 | 每场战斗只有20回合,如果20回合后双方没有分出胜负,则防守方(战斗画面右方)胜利 | |||||||
2.8 | 战斗奖励 | |||||||
2.8.1 | 战斗之后根据配置文件处理战斗获得 | |||||||
2.8.2 | 战斗中死亡的战斗单位也可以获得经验奖励。经验奖励只与战斗结果有关,即战斗胜利, | |||||||
胜利方的所有参战的战斗单位都可以获得经验奖励,战斗胜利,所有战斗单位没有经验 | ||||||||
奖励 | ||||||||
2.9 | 战斗结束后的血量补充 | |||||||
2.9.1 | 战斗单位升级 血量自动补满 | |||||||
2.9.2 | 战斗单位未升级 | |||||||
A. | 主角身上有血池buff | |||||||
a. | 血池足够 | 所有参战的战斗单位血量补满(补给血量值为A),血池血量减少A | ||||||
b. | 血池不足 | 按照战斗单位的出手顺序为战斗单位依次补给血量 | ||||||
实例: | ||||||||
战斗单位 | 出手顺序 | 总HP | 当前HP | 血池血量 | 需要的补给 | 实际的补给 | ||
A | 1 | 4000 | 1000 |
| 3000 | 3000 | ||
B | 2 | 4000 | 2000 | 18462 | 2000 | 2000 | ||
C | 3 | 4000 | 1000 | 3000 | 3000 | |||
D | 4 | 4000 | 1500 | 2500 | 2500 | |||
c. | 特殊情况: | |||||||
D当前HP为0,在恢复C血时已经消耗掉血池的全部存余血量,默认为D增加1点HP | ||||||||
B. | 主角身上无血池buff | |||||||
战斗单位血量为0,自动为其增加1点血量 | ||||||||
战斗单位剩余血量不为0,不增加血量 |
三、 | 战斗表现形式 | ||||||
3.1 | 状态说明 | ||||||
状态 | 说明 | ||||||
普通近程攻击 | 出手战斗单位从原地消失→播放向目标战斗单位前进的动作→播放出手战斗单位的攻击动作以及目标战斗单位被攻击的动作→目标战斗单位损失血量→出手战斗单位消失→播放出手战斗单位退回原地的动作→出手战斗单位出现在原位 | ||||||
普通远程攻击 | 播放出手战斗单位的攻击动作及特效→播放目标战斗单位的被攻击动作及特效→目标战斗单位损失血量 | ||||||
普通法术攻击 | 播放出手战斗单位的攻击动作及特效→播放目标战斗单位的被攻击动作及特效→目标战斗单位损失血量 | ||||||
绝技攻击 | 播放出手战斗单位的攻击动作及特效→播放目标战斗单位的被攻击动作及特效→目标战斗单位损失血量 | ||||||
闪避 | 播放出手战斗单位的攻击动作及特效→播放目标战斗单位的被攻击动作及特效,同时在目标战斗单位出现“闪避”字样 | ||||||
暴击 | 播放出手战斗单位的攻击动作及特效,同时在出手战斗单位出现“暴击”字样→播放目标战斗单位的被攻击动作及特效→目标战斗单位损失血量 | ||||||
格挡 | 播放出手战斗单位的攻击动作及特效→播放目标战斗单位的被攻击动作及特效,同时在目标战斗单位出现“格挡”字样→目标战斗单位损失血量 | ||||||
损失血量 | 目标战斗单位显示减少的血量数值 | ||||||
反击 | 目标战斗单位在格挡状态下,在目标战斗单位处出现“反击”字样→目标战斗单位从原地消失→播放向原出手战斗单位前进的动作→播放目标战斗单位的攻击动作以及出手战斗单位被攻击的动作→原出手战斗单位损失血量→目标战斗单位消失→播放目标战斗单位退回原地的动作→目标战斗单位出现在原位 |
四、 | 流程图 |
4.1战斗回合流程
4.4战斗进行阶段流程4.5战斗结束阶段流程
4.6buffer流程
4.7选择攻击方式流程4.8战斗单位死亡流程
4.9战斗替补单位流程
战斗流程中的
命中、暴击、必杀、格挡计算流程 |
好了,战斗系统就这些,好家伙,真佩服策划的工作能力(上面这些是某公司山寨神仙道
时候的策划文档摘抄,这里感谢原作者)
好了,我们的文档这样就完成了,也就是说我们的战斗系统要做到上面文档要求的效果,那会是什么样的呢?这里感谢as3页游方面的专家leo老兄提供战斗系统源码,因为这里代码有现成的,我们只是做代码分析,因为这个战斗系统代码不是我写的这里就不公开散布了,所以需要源码的小伙伴可以私信给我。我们这里只做分析。
我们先看看配置文件,战斗的battle数据文件(本来应该是服务器即使生成)
<?xml version="1.0" encoding="UTF-8"?>
<root>
<battle id="1" name="战役1" exp="1000" gold="200" itemID="1001" battleMapID="BattleMap100">
<!-- item中type 1为玩家,2为敌人 place值从0—8中随便填 -->
<item actionName="Action_AddObject" type="1" roleType="1" roleID="1001"
objID="3000" place="1" hp="1000" name="简雨"/>
<item actionName="Action_AddObject" type="1" roleType="2" roleID ="2001"
objID="4000" place="5" hp="1000" name="测试怪1"/>
<item actionName="Action_AddObject" type="1" roleType="2" roleID ="2003"
objID="4001" place="6" hp="1000" name="测试怪2"/>
<!-- 战斗攻击指令,技能可以攻击一个目标或多个目标,技能没有MISS,普通攻击只能攻击一个目标,会有反击/抵挡/暴击/闪避
-->
<item actionName="Action_Attack" type="2" fire="3000" target="4000" damage="200"
isSkill="0" skillID="0" isBackAttack="0" backAttackDamage="0" isResis="0" isCrucial="0"
isJink="0"/>
<item actionName="Action_Attack" type="2" fire="4000" target="3000" damage="100"
isSkill="0" skillID="0" isBackAttack="0" backAttackDamage="0" isResis="0" isCrucial="0"
isJink="0"/>
<item actionName="Action_Attack" type="2" fire="4001" target="3000" damage="0"
isSkill="0" skillID="0" isBackAttack="0" backAttackDamage="0" isResis="0" isCrucial="0"
isJink="1"/>
<item actionName="Action_Attack" type="2" fire="3000" target="4000,4001" damage="400,480"
isSkill="1" skillID="100" isBackAttack="0" backAttackDamage="0" isResis="0" isCrucial="0"
isJink="0"/>
<item actionName="Action_Attack" type="2" fire="4000" target="3000" damage="150"
isSkill="1" skillID="200" isBackAttack="0" backAttackDamage="0" isResis="0" isCrucial="0"
isJink="0"/>
<item actionName="Action_Attack" type="2" fire="4001" target="3000" damage="80"
isSkill="0" skillID="0" isBackAttack="0" backAttackDamage="0" isResis="0" isCrucial="0"
isJink="0"/>
<item actionName="Action_Attack" type="2" fire="3000" target="4000" damage="400"
isSkill="0" skillID="0" isBackAttack="0" backAttackDamage="0" isResis="0" isCrucial="1"
isJink="0"/>
<item actionName="Action_Attack" type="2" fire="4001" target="3000" damage="160"
isSkill="0" skillID="0" isBackAttack="0" backAttackDamage="0" isResis="0" isCrucial="1"
isJink="0"/>
<item actionName="Action_Attack" type="2" fire="3000" target="4001" damage="400"
isSkill="0" skillID="0" isBackAttack="0" backAttackDamage="0" isResis="0" isCrucial="1"
isJink="0"/>
<item actionName="Action_Attack" type="2" fire="4001" target="3000" damage="70"
isSkill="0" skillID="0" isBackAttack="1" backAttackDamage="50" isResis="0" isCrucial="0"
isJink="0"/>
<item actionName="Action_Attack" type="2" fire="3000" target="4001" damage="150"
isSkill="0" skillID="0" isBackAttack="0" backAttackDamage="0" isResis="1" isCrucial="0"
isJink="0"/>
</battle>
<battle id="2" name="战役2" exp="2000" gold="400" itemID="1004" battleMapID="BattleMap101">
<!-- item中type 1为玩家,2为敌人 place值从0—8中随便填 -->
<item actionName="Action_AddObject" type="1" roleType="1" roleID="1001"
objID="3000" place="1" hp="1000" name="简雨"/>
<item actionName="Action_AddObject" type="1" roleType="2" roleID ="2001"
objID="4000" place="5" hp="1000" name="测试怪1"/>
<item actionName="Action_AddObject" type="1" roleType="2" roleID ="2002"
objID="4001" place="0" hp="1000" name="测试怪2"/>
<item actionName="Action_AddObject" type="1" roleType="2" roleID ="2003"
objID="4002" place="6" hp="1000" name="测试怪3"/>
<!-- 战斗攻击指令,技能可以攻击一个目标或多个目标,技能没有MISS,普通攻击只能攻击一个目标,会有反击/抵挡/暴击/闪避
-->
<item actionName="Action_Attack" type="2" fire="3000" target="4000" damage="200"
isSkill="0" skillID="0" isBackAttack="0" backAttackDamage="0" isResis="0" isCrucial="0"
isJink="0"/>
<item actionName="Action_Attack" type="2" fire="4000" target="3000" damage="100"
isSkill="0" skillID="0" isBackAttack="0" backAttackDamage="0" isResis="0" isCrucial="0"
isJink="0"/>
<item actionName="Action_Attack" type="2" fire="4001" target="3000" damage="0"
isSkill="0" skillID="0" isBackAttack="0" backAttackDamage="0" isResis="0" isCrucial="0"
isJink="1"/>
<item actionName="Action_Attack" type="2" fire="4002" target="3000" damage="50"
isSkill="0" skillID="0" isBackAttack="0" backAttackDamage="0" isResis="1" isCrucial="0"
isJink="0"/>
<item actionName="Action_Attack" type="2" fire="3000" target="4000" damage="900"
isSkill="1" skillID="101" isBackAttack="0" backAttackDamage="0" isResis="0" isCrucial="0"
isJink="0"/>
<item actionName="Action_Attack" type="2" fire="4001" target="3000" damage="210"
isSkill="1" skillID="201" isBackAttack="0" backAttackDamage="0" isResis="0" isCrucial="0"
isJink="0"/>
<item actionName="Action_Attack" type="2" fire="4002" target="3000" damage="200"
isSkill="1" skillID="202" isBackAttack="0" backAttackDamage="0" isResis="0" isCrucial="0"
isJink="0"/>
<item actionName="Action_Attack" type="2" fire="3000" target="4001" damage="300"
isSkill="0" skillID="0" isBackAttack="0" backAttackDamage="0" isResis="0" isCrucial="1"
isJink="0"/>
<item actionName="Action_Attack" type="2" fire="4001" target="3000" damage="160"
isSkill="0" skillID="0" isBackAttack="0" backAttackDamage="0" isResis="0" isCrucial="1"
isJink="0"/>
<item actionName="Action_Attack" type="2" fire="4002" target="3000" damage="90"
isSkill="0" skillID="0" isBackAttack="1" backAttackDamage="90" isResis="0" isCrucial="0"
isJink="0"/>
<item actionName="Action_Attack" type="2" fire="3000" target="4001" damage="200"
isSkill="0" skillID="0" isBackAttack="0" backAttackDamage="0" isResis="0" isCrucial="0"
isJink="0"/>
<item actionName="Action_Attack" type="2" fire="4001" target="3000" damage="90"
isSkill="0" skillID="0" isBackAttack="0" backAttackDamage="0" isResis="0" isCrucial="0"
isJink="0"/>
<item actionName="Action_Attack" type="2" fire="4002" target="3000" damage="50"
isSkill="0" skillID="0" isBackAttack="0" backAttackDamage="0" isResis="1" isCrucial="0"
isJink="0"/>
<item actionName="Action_Attack" type="2" fire="3000" target="4001" damage="770"
isSkill="1" skillID="101" isBackAttack="0" backAttackDamage="0" isResis="0" isCrucial="0"
isJink="0"/>
<item actionName="Action_Attack" type="2" fire="4002" target="3000" damage="200"
isSkill="1" skillID="203" isBackAttack="0" backAttackDamage="0" isResis="0" isCrucial="0"
isJink="0"/>
</battle>
<battle id="3" name="战役3" exp="3000" gold="600" itemID="1008" battleMapID="BattleMap102">
<!-- item中type 1为玩家,2为敌人 place值从0—8中随便填 -->
<item actionName="Action_AddObject" type="1" roleType="1" roleID="1002"
objID="3001" place="6" hp="1000" name="测试人2"/>
<item actionName="Action_AddObject" type="1" roleType="1" roleID="1001"
objID="3000" place="1" hp="1000" name="简雨"/>
<item actionName="Action_AddObject" type="1" roleType="2" roleID ="2001"
objID="4000" place="1" hp="1000" name="测试怪1"/>
<item actionName="Action_AddObject" type="1" roleType="2" roleID ="2002"
objID="4001" place="4" hp="1000" name="测试怪2"/>
<item actionName="Action_AddObject" type="1" roleType="2" roleID ="2003"
objID="4002" place="8" hp="1000" name="测试怪3"/>
<!-- 战斗攻击指令,技能可以攻击一个目标或多个目标,技能没有MISS,普通攻击只能攻击一个目标,会有反击/抵挡/暴击/闪避
-->
<item actionName="Action_Attack" type="2" fire="3000" target="4000" damage="100"
isSkill="0" skillID="0" isBackAttack="1" backAttackDamage="50" isResis="0" isCrucial="0"
isJink="0"/>
<item actionName="Action_Attack" type="2" fire="3001" target="4000" damage="150"
isSkill="0" skillID="0" isBackAttack="0" backAttackDamage="0" isResis="0" isCrucial="0"
isJink="0"/>
<item actionName="Action_Attack" type="2" fire="4000" target="3000" damage="150"
isSkill="1" skillID="200" isBackAttack="0" backAttackDamage="0" isResis="0" isCrucial="0"
isJink="0"/>
<item actionName="Action_Attack" type="2" fire="4001" target="3000,3001" damage="100,100"
isSkill="1" skillID="201" isBackAttack="0" backAttackDamage="0" isResis="0" isCrucial="0"
isJink="0"/>
<item actionName="Action_Attack" type="2" fire="4002" target="3001" damage="0"
isSkill="0" skillID="0" isBackAttack="0" backAttackDamage="0" isResis="0" isCrucial="0"
isJink="1"/>
<item actionName="Action_Attack" type="2" fire="3000" target="4000,4001,4002" damage="200,250,300"
isSkill="1" skillID="101" isBackAttack="0" backAttackDamage="0" isResis="0" isCrucial="0"
isJink="0"/>
<item actionName="Action_Attack" type="2" fire="3001" target="4000" damage="150"
isSkill="0" skillID="0" isBackAttack="0" backAttackDamage="0" isResis="0" isCrucial="0"
isJink="0"/>
<item actionName="Action_Attack" type="2" fire="4000" target="3001" damage="150"
isSkill="0" skillID="0" isBackAttack="0" backAttackDamage="0" isResis="0" isCrucial="0"
isJink="0"/>
<item actionName="Action_Attack" type="2" fire="4001" target="3001" damage="50"
isSkill="0" skillID="0" isBackAttack="0" backAttackDamage="0" isResis="1" isCrucial="0"
isJink="0"/>
<item actionName="Action_Attack" type="2" fire="4002" target="3000" damage="170"
isSkill="1" skillID="202" isBackAttack="0" backAttackDamage="0" isResis="0" isCrucial="0"
isJink="0"/>
<item actionName="Action_Attack" type="2" fire="3000" target="4001" damage="300"
isSkill="0" skillID="0" isBackAttack="0" backAttackDamage="0" isResis="0" isCrucial="1"
isJink="0"/>
<item actionName="Action_Attack" type="2" fire="3001" target="4001" damage="100"
isSkill="0" skillID="0" isBackAttack="0" backAttackDamage="0" isResis="0" isCrucial="0"
isJink="0"/>
<item actionName="Action_Attack" type="2" fire="4000" target="3000" damage="200"
isSkill="1" skillID="203" isBackAttack="0" backAttackDamage="0" isResis="0" isCrucial="0"
isJink="0"/>
<item actionName="Action_Attack" type="2" fire="4001" target="3001" damage="100"
isSkill="0" skillID="0" isBackAttack="1" backAttackDamage="80" isResis="0" isCrucial="0"
isJink="0"/>
<item actionName="Action_Attack" type="2" fire="4002" target="3001" damage="100"
isSkill="0" skillID="0" isBackAttack="0" backAttackDamage="0" isResis="0" isCrucial="0"
isJink="0"/>
<item actionName="Action_Attack" type="2" fire="3000" target="4000" damage="200"
isSkill="0" skillID="0" isBackAttack="0" backAttackDamage="0" isResis="0" isCrucial="0"
isJink="0"/>
<item actionName="Action_Attack" type="2" fire="3001" target="4000,4001,4002" damage="230,150,290"
isSkill="1" skillID="104" isBackAttack="0" backAttackDamage="0" isResis="0" isCrucial="0"
isJink="0"/>
<item actionName="Action_Attack" type="2" fire="4001" target="3001" damage="300"
isSkill="1" skillID="204" isBackAttack="0" backAttackDamage="0" isResis="0" isCrucial="0"
isJink="0"/>
<item actionName="Action_Attack" type="2" fire="4002" target="3001" damage="250"
isSkill="0" skillID="0" isBackAttack="0" backAttackDamage="0" isResis="0" isCrucial="1"
isJink="0"/>
<item actionName="Action_Attack" type="2" fire="3000" target="4001,4002" damage="240,200"
isSkill="1" skillID="105" isBackAttack="0" backAttackDamage="0" isResis="0" isCrucial="0"
isJink="0"/>
<item actionName="Action_Attack" type="2" fire="4002" target="3000" damage="150"
isSkill="0" skillID="0" isBackAttack="1" backAttackDamage="100" isResis="0" isCrucial="0"
isJink="0"/>
<item actionName="Action_Attack" type="2" fire="3000" target="4002" damage="250"
isSkill="0" skillID="0" isBackAttack="0" backAttackDamage="0" isResis="0" isCrucial="1"
isJink="0"/>
</battle>
</root>
接着看下文档类
package leo
{
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.profiler.showRedrawRegions;
import leo.controller.util.LayerUtil;
import leo.proxy.GameConst;
import leo.proxy.transmission.LoaderUtil;
import leo.view.ui.BtnBattle;
import leo.view.ui.BtnBattleTips;
import leo.view.ui.UIBattleList;
[SWF(width="1250",height="650",frameRate="24",backgroundColor="0")]
public class BattlePlayer extends Sprite
{
private var curView :*;
private var battleLayer :Sprite;
private var popLayer :Sprite;
private var btnBattle :BtnBattle;
private var btnBattleTips :BtnBattleTips;
public function BattlePlayer()
{
init();
}
private function init():void
{
LoaderUtil.I.loadConfig();
this.battleLayer = new Sprite();
this.popLayer = new Sprite();
this.addChild(battleLayer);
this.addChild(popLayer);
LayerUtil.I.layerDict[GameConst.BATTLE_LAYER] = this.battleLayer;
LayerUtil.I.layerDict[GameConst.POP_LAYER] = this.popLayer;
GameConst.main = this;
}
/*
public function rhand():void
{
btnBattle = new BtnBattle();
this.addChild(btnBattle);
btnBattleTips = new BtnBattleTips();
btnBattleTips.x = btnBattle.x + btnBattle.width - 20;
btnBattleTips.y = btnBattle.y + btnBattle.height - 20;
btnBattleTips.mouseChildren = btnBattleTips.mouseEnabled = false;
this.addChild(btnBattleTips);
btnBattle.addEventListener(MouseEvent.MOUSE_UP,mouseHandler);
}
*/
public function setStage(view :*):void
{
if(this.curView && this.battleLayer && this.battleLayer.contains(this.curView))
{
this.curView.destroy;
this.battleLayer.removeChild(this.curView);
}
battleLayer.addChild(view);
}
public function show():void
{
//btnBattle.visible = true;
//btnBattle.mouseChildren = btnBattle.mouseEnabled = true;
//btnBattleTips.play();
}
public function hide():void
{
//btnBattle.visible = false;
//btnBattle.mouseChildren = btnBattle.mouseEnabled = false;
//btnBattleTips.stop();
}
public function mouseHandler():void
//private function mouseHandler(e :MouseEvent):void
{
trace("load");
var view :UIBattleList = new UIBattleList(null);
setStage(view);
//hide();
}
}
}
init方法中有LoaderUtil.I.loadConfig();我们看下LoaderUtil这个静态类
package leo.proxy.transmission
{
import flash.display.BitmapData;
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.system.ApplicationDomain;
import flash.system.LoaderContext;
import flash.utils.Dictionary;
import flash.utils.getDefinitionByName;
import leo.proxy.GameConst;
import leo.proxy.battles.action.Action_AddObject;
import leo.proxy.battles.action.Action_Attack;
import leo.proxy.battles.action.IBattleAction;
import leo.proxy.battles.vo.BattleVO;
import leo.proxy.vo.BaseUI;
import leo.proxy.vo.RoleAssetsVO;
/**
* 加载工具
* @author leo
*
*/
public class LoaderUtil
{
private static var _I :LoaderUtil = null;
/**
* 加载器缓存
*/
public var loaderDict :Dictionary = new Dictionary();
/**
* 所有加载过的UI的VO
*/
public var fileList :Dictionary = new Dictionary();
/**
* 缓存的战斗VO表
*/
public var battleVOList :Dictionary = new Dictionary();
/**
* 缓存战斗地图
*/
public var battleMapDict :Dictionary = new Dictionary();
/**
* 总加载数
*/
private var sum :int;
/**
* 当前已加载数
*/
private var index :int;
/**
* 加载列表成功函数
*/
private var rhand :Function;
/**
* 加载列表失败函数
*/
private var fhand :Function;
/**
* 加载UI成功函数
*/
private var uiRhand :Function;
/**
* 加载UI失败函数
*/
private var uiFhand :Function;
public function LoaderUtil(prv :PrivateClass)
{
}
/**
* 加载UI列表
* @param list 完整路径列表
* @param rhand
* @param fhand
*
*/
public function loadList(list :Array,rhand :Function = null,fhand :Function = null):void
{
if(!list || list.length == 0)
{
return;
}
this.rhand = rhand;
this.fhand = fhand;
this.sum = 0;
this.sum = list.length;
for(var i :int = 0; i < list.length; i++)
{
var url :String = list[i] as String;
var loader :CustomLoader = new CustomLoader();
loader.id = url;
loader.contentLoaderInfo.addEventListener(Event.COMPLETE,completeHandler);
loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR,errorHandler);
var loaderContext :LoaderContext = new LoaderContext(false,ApplicationDomain.currentDomain);
loader.load(new URLRequest(url),loaderContext);
this.loaderDict[loader.id] = loader;
}
}
/**
* 加载UI列表成功
* @param e
*
*/
private function completeHandler(e :Event):void
{
this.index++;
var loader :CustomLoader = (e.target as LoaderInfo).loader as CustomLoader;
loader.contentLoaderInfo.removeEventListener(Event.COMPLETE,completeHandler);
loader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR,errorHandler);
if(this.loaderDict[loader.id])
{
loader.unload();
delete this.loaderDict[loader.id];
loader = null;
}
if(this.index == this.sum)
{
if(this.rhand != null)
{
rhand();
rhand = null;
fhand = null;
}
}
}
/**
* 加载UI列表失败
* @param e
*
*/
private function errorHandler(e :IOErrorEvent):void
{
if(this.fhand != null)
{
fhand();
rhand = null;
fhand = null;
}
var loader :CustomLoader = (e.target as LoaderInfo).loader as CustomLoader;
loader.contentLoaderInfo.removeEventListener(Event.COMPLETE,completeHandler);
loader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR,errorHandler);
trace("加载组ui出错");
}
/**
* 加载单个UI
* @param vo
* @param rhand
* @param fhand
*
*/
public function loadUI(vo :BaseUI,rhand :Function,fhand :Function = null):void
{
if(!vo)
{
return;
}
this.uiRhand = rhand;
this.uiFhand = fhand;
var url :String = vo.swfPath;
var loader :CustomLoader = new CustomLoader();
loader.id = url;
loader.contentLoaderInfo.addEventListener(Event.COMPLETE,uiComplete);
loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR,uiError);
var loaderContext :LoaderContext = new LoaderContext(false,ApplicationDomain.currentDomain);
loader.load(new URLRequest(url),loaderContext);
this.loaderDict[loader.id] = loader;
this.fileList[vo.swfPath] = vo;
}
/**
* 加载单个UI成功
* @param e
*
*/
private function uiComplete(e :Event):void
{
var loader :CustomLoader = (e.target as LoaderInfo).loader as CustomLoader;
loader.contentLoaderInfo.removeEventListener(Event.COMPLETE,completeHandler);
loader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR,errorHandler);
if(this.fileList[loader.id])
{
var vo :BaseUI = this.fileList[loader.id] as BaseUI;
vo.isComplete = true;
vo.isLoading = false;
}
if(this.loaderDict[loader.id])
{
loader.unload();
delete this.loaderDict[loader.id];
loader = null;
}
if(this.uiRhand != null)
{
this.uiRhand();
this.uiRhand = null;
uiFhand = null;
}
}
/**
* 加载单个UI失败
* @param e
*
*/
private function uiError(e :IOErrorEvent):void
{
var loader :CustomLoader = (e.target as LoaderInfo).loader as CustomLoader;
loader.contentLoaderInfo.removeEventListener(Event.COMPLETE,completeHandler);
loader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR,errorHandler);
if(this.uiFhand != null)
{
uiFhand();
this.uiRhand = null;
uiFhand = null;
}
trace("加载单个ui出错");
}
/**
* 加载config.xml
*
*/
public function loadConfig():void
{
var str :String = GameConst.CONFIG_XML;
var loader :URLLoader = new URLLoader();
loader.addEventListener(Event.COMPLETE,configComplete);
loader.addEventListener(IOErrorEvent.IO_ERROR,configError);
loader.load(new URLRequest(str));
}
/**
* 加载config.xml成功
* @param e
*
*/
private function configComplete(e :Event):void
{
var xml :XML = new XML(((e.target) as URLLoader).data);
GameConst.uiDir = xml.uiDir;
GameConst.itemDir = xml.itemDir;
GameConst.roleDir = xml.roleDir;
GameConst.mapDir = xml.mapDir;
GameConst.battleXML = xml.battleXML;
var str :String = xml.ui;
var ary :Array = str.split(",");
while(ary.length > 0)
{
var url :String = GameConst.uiDir + ary.pop() + ".swf";
GameConst.uiList.push(url);
}
((e.target) as URLLoader).removeEventListener(Event.COMPLETE,configComplete);
((e.target) as URLLoader).removeEventListener(IOErrorEvent.IO_ERROR,configError);
loadBattleData();
}
/**
* 加载config.xml失败
* @param e
*
*/
private function configError(e :IOErrorEvent):void
{
((e.target) as URLLoader).removeEventListener(Event.COMPLETE,configComplete);
((e.target) as URLLoader).removeEventListener(IOErrorEvent.IO_ERROR,configError);
trace("加载config出错");
}
/**
* 加载战斗XML
*
*/
private function loadBattleData():void
{
var loader :URLLoader = new URLLoader();
var url :String = GameConst.battleXML;
loader.addEventListener(Event.COMPLETE,battleXMLComplete);
loader.addEventListener(IOErrorEvent.IO_ERROR,battleXMLError);
loader.load(new URLRequest(url));
}
/**
* 加载战斗XML成功
* @param e
*
*/
private function battleXMLComplete(e :Event):void
{
var loader :URLLoader = e.target as URLLoader;
var xml :XML = new XML(loader.data);
for each(var battleXML :XML in xml.battle)
{
var battleVO :BattleVO = new BattleVO();
battleVO.battleInfoVO.parse(battleXML,battleVO);
for each(var actionXML :XML in battleXML.item)
{
var actionName :String= actionXML.@actionName;
//注意一定要导入要实例化的类才能getDefinitionByName,要不然会报错
importClass();
var path :String = GameConst.PACKAGE_ACTION;
var actionCls:Class = getDefinitionByName(path + actionName) as Class;
var action:IBattleAction = new actionCls() as IBattleAction;
action.parse(actionXML,battleVO);
battleVO.actions.push(action);
}
this.battleVOList[battleVO.battleInfoVO.id] = battleVO;
}
loader.removeEventListener(Event.COMPLETE,battleXMLComplete);
loader.removeEventListener(IOErrorEvent.IO_ERROR,battleXMLError);
loader = null;
//loadList(GameConst.uiList, GameConst.main.rhand);
loadList(GameConst.uiList,GameConst.main.mouseHandler);
}
/**
* 加载战斗XML失败
* @param e
*
*/
private function battleXMLError(e :IOErrorEvent):void
{
var loader :URLLoader = e.target as URLLoader;
loader.removeEventListener(Event.COMPLETE,battleXMLComplete);
loader.removeEventListener(IOErrorEvent.IO_ERROR,battleXMLError);
trace("加载战斗XML出错");
}
public function checkIsLoad(swfPath :String):Boolean
{
var vo :BaseUI = this.fileList[swfPath] as BaseUI;
if(vo && (vo.isLoading || vo.isComplete))
{
return true;
}
return false;
}
private function importClass():void
{
var cls1 :Action_AddObject;
var cls2 :Action_Attack;
}
public static function get I():LoaderUtil
{
if(_I == null)
{
_I = new LoaderUtil(new PrivateClass());
}
return _I;
}
}
}
class PrivateClass{}
public function loadConfig():void{}方法里面有这样一句var str :String = GameConst.CONFIG_XML;而得到xml的外部链接
package leo.proxy
{
import flash.filters.GlowFilter;
import leo.BattlePlayer;
/**
* 游戏常用的常量
* @author leo
*
*/
public class GameConst
{
public static var main :BattlePlayer = null;
public static const CONFIG_XML :String = "leo/assets/data/config.xml";
// public static const CONFIG_XML :String = "http://www.longsihao.com/games/BattlePlayer/assets/data/netConfig.xml";
public static var itemDir :String;
public static var uiDir :String;
public static var roleDir :String;
public static var mapDir :String;
public static var battleXML :String;
public static var uiList :Array = [];
public static var smallLoading :String = "smallLoading";
public static const POP_LAYER :String = "pop_layer";
public static const BATTLE_LAYER :String = "battle_layer";
public static const PACKAGE_ACTION :String = "leo.proxy.battles.action.";
public static const ROLE_ACTION_ARY :Array = ["attack","be_hit","fighting_idle"];
public static const SPEED :int = 3;
public static const MOUSE_ON :Array = [new GlowFilter(0xffff00,1,2,2,2,2)];
public static const SKILL_NAME :Array = ["天魔杀星","冰凌剑空","灵木刺阵","十方剑气","天魔斩","八方棍法","雷动八方","琥珀冲杀","毒龙蚀天","地狱之火","葬林狂舞"];
public function GameConst()
{
}
}
}
private function configComplete(e :Event):void{}方法中的
GameConst.uiDir = xml.uiDir;
GameConst.itemDir = xml.itemDir;
GameConst.roleDir = xml.roleDir;
GameConst.mapDir = xml.mapDir;
GameConst.battleXML = xml.battleXML;
trace得到xml.uiDir;=leo/assets/ui/
xml.itemDir=leo/assets/ui/
xml.roleDir=leo/assets/role/
xml.mapDir=leo/assets/map/
xml.battleXML=leo/assets/data/battles.xml
然后private function loadBattleData():void{}加载这战斗xml,我们可以看到trace("actionName=" + actionName);得到的xml文件数据
方法最后loadList(GameConst.uiList,GameConst.main.mouseHandler);加载进入游戏的控制列表
回到文档类中的public function mouseHandler():void{}方法中var view :UIBattleList = new UIBattleList(null);setStage(view);调用battleLayer.addChild(view);
将view加载到舞台上面,UIBattleList中的baseUI = new BaseUI("BattleList","BattleList");来加载battlelist.swf文件文件截图
override protected function swfLoadComplete():void{}中的this.itemList = new Vector.<UIBattleListItem>();
package leo.proxy.vo
{
import leo.proxy.GameConst;
/**
* 加载UIVO基类
* @author Leo
*
*/
public class BaseUI
{
public var fileName :String;
public var linkName :String;
public var isLoading :Boolean = true;
public var isComplete :Boolean = false;
public function BaseUI(fileName :String , linkName :String)
{
this.fileName = fileName;
this.linkName = linkName;
}
public function get swfPath():String
{
return GameConst.uiDir + this.fileName + ".swf";
}
public function complete():void
{
this.isComplete = true;
this.isLoading = false;
}
}
}
package leo.view.ui
{
import flash.display.SimpleButton;
import flash.events.MouseEvent;
import flash.text.TextField;
import flash.utils.Dictionary;
import leo.controller.util.UIUtil;
import leo.proxy.GameConst;
import leo.proxy.battles.vo.BattleVO;
import leo.proxy.transmission.LoaderUtil;
import leo.proxy.vo.BaseUI;
/**
* 战斗列表UI
* @author Leo
*
*/
public class UIBattleList extends UILoadingBase
{
public static var I :UIBattleList;
public var btnClose :SimpleButton;
public var itemList :Vector.<UIBattleListItem>;
public var btnLeft :SimpleButton;
public var btnRight :SimpleButton;
public var txtPage :TextField;
public function UIBattleList(baseUI:BaseUI)
{
if(!baseUI)
{
baseUI = new BaseUI("BattleList","BattleList");
}
super(baseUI);
}
override protected function swfLoadComplete():void
{
super.swfLoadComplete();
if(!content)
{
return;
}
this.itemList = new Vector.<UIBattleListItem>();
binding(content,itemList,UIBattleListItem);
btnClose = content.btnClose;
this.btnLeft = content.btnLeft;
this.btnRight = content.btnRight;
this.txtPage = content.txtPage;
data = [];
var list :Dictionary = LoaderUtil.I.battleVOList;
for (var key :* in list)
{
var vo :BattleVO = list[key] as BattleVO;
if(vo)
{
data.push(vo);
}
}
var index :int = 0;
for each(var item :UIBattleListItem in itemList)
{
if(data[index])
{
item.data = data[index];
}else
{
item.data = null;
}
index++;
}
addEventListener(MouseEvent.MOUSE_UP,mouseHandler);
I = this;
}
private function mouseHandler(e :MouseEvent):void
{
trace("btn_close========");
switch(e.target)
{
case this.btnClose:
trace("btn_close");
destroy();
break;
case this.btnLeft:
trace("left");
break;
case this.btnRight:
trace("right");
break;
}
}
override public function destroy():void
{
super.destroy();
removeEventListener(MouseEvent.MOUSE_UP,mouseHandler);
unBinding(itemList);
if(this.parent)
{
this.parent.removeChild(this);
}
I = null;
if(GameConst.main)
{
GameConst.main.show();
}
}
}
}
binding(content,itemList,UIBattleListItem);绑定了数据和战斗播放按钮,super.swfLoadComplete();调用了父类的方法中的content = BitmapUtil.I.getMCByName(baseUI.linkName);
package leo.view.ui
{
import flash.display.DisplayObject;
import flash.display.MovieClip;
import flash.display.SimpleButton;
import flash.events.MouseEvent;
import flash.filters.GlowFilter;
import flash.text.TextField;
import flash.utils.ByteArray;
import leo.controller.util.LayerUtil;
import leo.proxy.GameConst;
import leo.proxy.battles.vo.BattleVO;
import leo.proxy.vo.BaseUI;
/**
* 战役列表子项
* @author Leo
*
*/
public class UIBattleListItem extends SimpleButton
{
public var txtBattleName :TextField;
public var txtBattleContent :TextField;
public var txtBattleAward :TextField;
public var mcContent :MovieClip;
public var btnShow :SimpleButton;
private var mc :MovieClip;
private var _data :BattleVO;
public function UIBattleListItem(mc :* = null)
{
if(mc)
{
this.mc = mc;
this.txtBattleAward = mc.txtBattleAward;
this.txtBattleContent = mc.txtBattleContent;
this.txtBattleName = mc.txtBattleName;
this.mcContent = mc.mcContent;
this.btnShow = mc.btnShow;
mc.addEventListener(MouseEvent.MOUSE_OVER,mouseHandler);
mc.addEventListener(MouseEvent.MOUSE_OUT,mouseHandler);
mc.addEventListener(MouseEvent.MOUSE_UP,mouseHandler);
}
super();
}
private function mouseHandler(e :MouseEvent):void
{
switch(e.type)
{
case MouseEvent.MOUSE_OVER:
if(this.mcContent)
{
this.mcContent.filters = GameConst.MOUSE_ON;
}
break;
case MouseEvent.MOUSE_OUT:
if(this.mcContent)
{
this.mcContent.filters = null;
}
break;
case MouseEvent.MOUSE_UP:
switch(e.currentTarget)
{
case this.mc:
case this.btnShow:
show();
}
break;
}
}
private function show():void
{
if(UIBattleList.I)
{
UIBattleList.I.destroy();
}
trace("开始播放战役");
if(data)
{
var view :UIBattleView = new UIBattleView(data);
LayerUtil.I.layerDict[UIBattleView.NAME] = view;
GameConst.main.setStage(view);
}
if(GameConst.main)
{
GameConst.main.hide();
}
}
public function get data():BattleVO
{
return _data;
}
public function set data(vo:BattleVO):void
{
_data = vo;
if(vo == null)
{
this.mc.visible = false;
return;
}
this.txtBattleName.text = vo.battleInfoVO.name;
this.txtBattleContent.htmlText = "经验: " + "<font color='#fff000'>" + vo.battleInfoVO.exp + "</font>" + " " +
"金币: " + "<font color='#fff000'>" + vo.battleInfoVO.gold + "</font>" + " " +
"物品: " + "<font color='#fff000'>" + vo.battleInfoVO.itemID + "</font>";
}
public function destroy():void
{
mc.addEventListener(MouseEvent.MOUSE_OVER,mouseHandler);
mc.addEventListener(MouseEvent.MOUSE_OUT,mouseHandler);
mc.addEventListener(MouseEvent.MOUSE_UP,mouseHandler);
mc = null;
txtBattleName = null;
txtBattleContent = null;
txtBattleAward = null;
mcContent = null;
btnShow = null;
}
}
}
mc.addEventListener(MouseEvent.MOUSE_OVER,mouseHandler);
mc.addEventListener(MouseEvent.MOUSE_OUT,mouseHandler);
mc.addEventListener(MouseEvent.MOUSE_UP,mouseHandler);
这3行来控制生成之后的mc按键case MouseEvent.MOUSE_UP:
switch(e.currentTarget)
{
case this.mc:
case this.btnShow:
show();
}
break;
鼠标按下时show方法
var view :UIBattleView = new UIBattleView(data);
LayerUtil.I.layerDict[UIBattleView.NAME] = view;
GameConst.main.setStage(view);之后进入战斗图层
package leo.view.ui
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.SimpleButton;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.TimerEvent;
import flash.utils.Timer;
import ghostcat.manager.SoundManager;
import leo.controller.util.BitmapUtil;
import leo.controller.util.LayerUtil;
import leo.controller.util.PlayerUtil;
import leo.controller.util.RoleManage;
import leo.proxy.GameConst;
import leo.proxy.battles.action.BaseBattleAction;
import leo.proxy.battles.action.IBattleAction;
import leo.proxy.battles.vo.BattleVO;
import leo.proxy.transmission.LoaderUtil;
import leo.proxy.vo.BaseUI;
import leo.proxy.vo.RoleAssetsVO;
import leo.view.role.MapObject;
/**
* 战斗视图层
* @author Leo
*
*/
public class UIBattleView extends Sprite
{
public static const NAME :String = "UIBattleView";
public var battleMap :UIBattleMap;
public var battlePlace :UIBattlePlace;
public var battleRoleLayer :UIBattleRoleLayer;
public var btnStartBattle :SimpleButton;
public var btnExitBattle :SimpleButton;
public var battleVO :BattleVO;
private var timer :Timer;
public function UIBattleView(battleVO :BattleVO)
{
this.battleVO = battleVO;
super();
if(!this.battleVO)
{
return;
}
if(stage)
{
init();
}else
{
addEventListener(Event.ADDED_TO_STAGE,init);
}
}
private function init(e :* = null):void
{
removeEventListener(Event.ADDED_TO_STAGE,init);
this.battleMap = new UIBattleMap(this.battleVO.battleInfoVO.battleMapID);
this.addChild(this.battleMap);
this.battlePlace = new UIBattlePlace();
this.addChild(this.battlePlace);
this.battleRoleLayer = new UIBattleRoleLayer(this.battleVO,battlePlace);
this.addChild(this.battleRoleLayer);
this.btnExitBattle = BitmapUtil.I.getBtnByName("BtnExitBattle");
if(this.btnExitBattle)
{
this.addChild(this.btnExitBattle);
this.btnExitBattle.x = stage.stageWidth - 150;
this.btnExitBattle.y = stage.stageHeight - 70;
}
this.btnStartBattle = BitmapUtil.I.getBtnByName("BtnStartBattle");
if(this.btnStartBattle)
{
this.addChild(this.btnStartBattle);
this.btnStartBattle.x = stage.stageWidth - 250;
this.btnStartBattle.y = stage.stageHeight - 70;
}
this.timer = new Timer(30);
this.timer.addEventListener(TimerEvent.TIMER,timerHandler);
this.timer.start();
addEventListener(MouseEvent.MOUSE_UP,clickHandler);
//播放战斗音乐
PlayerUtil.I.playBattleMusic();
}
private function clickHandler(e :MouseEvent):void
{
switch(e.target)
{
case this.btnExitBattle:
trace("退出战斗");
destroy();
break;
case this.btnStartBattle:
trace("开始战斗");
startBattle();
this.btnStartBattle.visible = false;
break;
}
}
/**
* timer更新显示对象
* @param e
*
*/
private function timerHandler(e :TimerEvent):void
{
var list :Vector.<MapObject> = RoleManage.I.roleList;
if(!list || list.length == 0)
{
return;
}
for each(var mapObj :MapObject in list)
{
mapObj.update();
}
PlayerUtil.I.update();
}
/**
* 开始战役
*/
private function startBattle():void
{
PlayerUtil.I.playBattle(this.battleVO.actions);
}
/**
* 销毁
*
*/
public function destroy():void
{
removeEventListener(MouseEvent.MOUSE_UP,clickHandler);
this.timer.stop();
this.timer.removeEventListener(TimerEvent.TIMER,timerHandler);
this.timer = null;
RoleManage.I.destroyRoleObj();
PlayerUtil.I.resetAction();
delete LayerUtil.I.layerDict[UIBattleView.NAME];
if(this.parent)
{
this.parent.removeChild(this);
}
if(GameConst.main)
{
GameConst.main.show();
}
PlayerUtil.I.stopBattleMusic();
}
}
}
private function startBattle():void{}方法中PlayerUtil.I.playBattle(this.battleVO.actions);
package leo.controller.util
{
import flash.geom.Point;
import ghostcat.manager.SoundManager;
import leo.proxy.battles.action.BaseBattleAction;
import leo.proxy.battles.vo.AddObjectVO;
import leo.view.role.MapObject;
import leo.view.ui.UIBattleResult;
import leo.view.ui.UIBattleView;
/**
* 播放器工具
* @author Leo
*
*/
public class PlayerUtil
{
private static var _I :PlayerUtil = null;
/**
* 开始播放
*/
private var start :Boolean = false;
/**
* 当前正在播放的动作
*/
private var curAction :BaseBattleAction;
/**
* 当前播放的序列
*/
private var curIndex :int;
/**
* 需要播放的列表
*/
private var actionList :Array;
public function PlayerUtil(prv :PrivateClass)
{
}
/**
* 开始播放战斗
* @param actionList
*
*/
public function playBattle(actionList :Array):void
{
if(!actionList || actionList.length == 0)
{
return;
}
this.actionList = actionList;
this.curIndex = 0;
this.start = true;
curAction = actionList[curIndex];
curAction.exec();
}
/**
* 更新播放序列
*
*/
public function update ():void
{
if(!start || !this.actionList || this.actionList.length == 0)
{
return;
}
if(curAction.allActionFinish)
{
this.curIndex++;
if(this.curIndex > this.actionList.length - 1)
{
//播放完成,战斗结束
this.start = false;
resetAction();
winOrlose();
return;
}
this.curAction = this.actionList[this.curIndex];
this.curAction.exec();
}
}
/**
* 获取近身攻击后人物返回的点
* @param fireObj
* @return
*
*/
public function getGoBackPoint(fireObj :MapObject):Point
{
var battleView :UIBattleView = LayerUtil.I.layerDict[UIBattleView.NAME] as UIBattleView;
var home :Boolean = fireObj.addObjVO.roleType == AddObjectVO.TYPE_HERO ? true : false;
var p :Point = battleView.battlePlace.getPlacePosition(fireObj.addObjVO.place,home);
return p;
}
/**
* 停止战斗音乐
*/
public function stopBattleMusic():void
{
//停止战斗音乐
SoundManager.instance.stop("BattleMusic");
}
/**
* 播放战斗音乐
*/
public function playBattleMusic():void
{
//停止战斗音乐
SoundManager.instance.play("BattleMusic",-1);
}
/**
* 播放受伤音乐
*/
public function playHurtMusic():void
{
SoundManager.instance.play("HurtMusic");
}
/**
* 播放技能效果音乐
*/
public function playSkillMusic():void
{
SoundManager.instance.play("SkillMusic");
}
/**
* 重置战斗命令
*
*/
public function resetAction():void
{
for each(var baseBattleAction :BaseBattleAction in this.actionList)
{
if(baseBattleAction.allActionFinish)
{
baseBattleAction.allActionFinish = false;
}
if(baseBattleAction.queue)
{
baseBattleAction.queue.halt();
}
}
}
private function winOrlose():void
{
var roleList :Vector.<MapObject> = RoleManage.I.roleList;
var result :Boolean = false;
for each(var mapObj :MapObject in roleList)
{
if(mapObj && mapObj.isAlive)
{
if(mapObj.addObjVO.roleType == AddObjectVO.TYPE_HERO)
{
result = true;
break;
}
}
}
var uiBattleView :UIBattleView = LayerUtil.I.getLayer(UIBattleView.NAME) as UIBattleView;
if(uiBattleView)
{
if(result) //战斗胜利
{
uiBattleView.battleRoleLayer.addChild(new UIBattleResult(true));
}else // 战斗失败
{
uiBattleView.battleRoleLayer.addChild(new UIBattleResult(false));
}
}else
{
trace("PlayerUtil 战斗UI查找出错");
}
}
public static function get I():PlayerUtil
{
if(_I == null)
{
_I = new PlayerUtil(new PrivateClass());
}
return _I;
}
}
}
class PrivateClass{}
private function winOrlose():void{}来获得战斗结果,最后交由
var uiBattleView :UIBattleView = LayerUtil.I.getLayer(UIBattleView.NAME) as UIBattleView;
if(uiBattleView)
{
if(result) //战斗胜利
{
uiBattleView.battleRoleLayer.addChild(new UIBattleResult(true));
}else // 战斗失败
{
uiBattleView.battleRoleLayer.addChild(new UIBattleResult(false));
}
}else
{
trace("PlayerUtil 战斗UI查找出错");
}
上面只是走了一遍基本流程,整个战斗系统相对庞大(这里就不都贴出来了,不是我的作品,开源别人的东西不道德),需要源码的小伙伴私信给我就好。我们看下战斗效果。
好了,这一篇就到这,后面我会考虑讨论下slg(策略战棋--这个是我最喜欢的游戏类型,不过我手头没有战棋游戏源码【其实是有一份的cocos2dx写的,不过作者不知道是谁,所以不好贴出来】,所以我们以我2006年拿到的一份slg类j2me的源码来看,只是个小框架,所以只做讨论,比如游戏相关的寻路呀等等吧,我们后面见)