楚河汉界
——战斗系统分析
人物和技能:
楚河汉界中人物和技能是绑定的,放在同一个资源中。人物动画使用位图序列制作,技能效果使用矢量动画使效果更炫,更平滑。
打斗效果:
楚河汉界中战斗时,技能施加到人物身上之后,的效果是与技能独立的。所有的这些效果放在一个资源中,这些效果也是使用矢量动画制作。
战斗中就是轮流播放人物的技能和添加技能伤害效果到目标上面。
人物状态:
不同状态分别在不同的层,通过控制层来显示状态。
游戏的主体操作UI都是通过页面构建出来的,只有一些打斗、地图、场景等等效果是使用Flash。游戏的控制逻辑都写在JavaScript脚本里面,Flash在主文件中注册了一系列回调函数供JavaScript调用。JavaScript负责与后台(PHP)交互,当需要Flash显示效果,如战斗,JavaScript根据PHP的返回结果调用Flash回调函数。
private function addCallBack() : void
{
ExternalInterface.addCallback("is_loaded", Face.is_loaded);
ExternalInterface.addCallback("set_var", Face.set_var);
ExternalInterface.addCallback("get_var", Face.get_var);
ExternalInterface.addCallback("set_cookie", Face.setCookie);
ExternalInterface.addCallback("get_cookie", Face.getCookie);
ExternalInterface.addCallback("set_pos", Scene.set_pos);
ExternalInterface.addCallback("show_scene", Scene.show_scene);
ExternalInterface.addCallback("move_scene", Scene.move_scene);
ExternalInterface.addCallback("add_monster", Scene.add_monster);
ExternalInterface.addCallback("del_monster", Scene.del_monster);
ExternalInterface.addCallback("add_npc", Scene.add_npc);
ExternalInterface.addCallback("del_npc", Scene.del_npc);
ExternalInterface.addCallback("update_npc", Scene.update_npc);
ExternalInterface.addCallback("update_player", Scene.update_player);
ExternalInterface.addCallback("update_over", Scene.last_over);
ExternalInterface.addCallback("story_role", Scene.story_role);
ExternalInterface.addCallback("story_state", Scene.story_state);
ExternalInterface.addCallback("stage_xy", Scene.stage_xy);
ExternalInterface.addCallback("show_play", Combats.show_play);
ExternalInterface.addCallback("quit_play", Combats.quit_play);
ExternalInterface.addCallback("is_play", Combats.is_play);
return;
}// end function
黑色粗体几个回调即战斗相关回调。
战斗设计到九宫格排兵布阵、技能/装备、打斗顺序、胜负结果等等。
楚河汉界使用九宫格方式排兵布阵,给9个位置分别编号(代码中用0、1、2、3、4、5、6、7、8)如下图所示:
排兵布阵会直接影响到战斗胜负,因为:
l 排兵位置直接影响到怪物攻打我们队友的顺序;
l 施展辅组技能(如加攻击、防御)队员位置,影响到哪些队友会受益,因此攻击力、防御值会收到影响
进入战斗模式时,后台会下发两边初始的排兵布阵,如玩家打野猪的时候(http://s326.sh.ch.qq.com/do.php?c=duty&a=lineup&r=0.7727291548204278),返回以下布阵数据:
"tpl_data": {
"members": {
"4": {
"type": 1,
"skill": "61:2,",
"avatar": "2",
"swf": "1003",
"position": 4,
"level": 26,
"role_name": "吴秦",
"role_id": 0
}
},
"monster": {
"group_id": 90054,
"type": 17,
"monster_num": 1,
"level": 20,
"exp": 0,
"money": 0,
"borad_reward": 0,
"contribute_reward": 0,
"fight_limit": 2,
"dialog": "我是可爱小野猪,皮肤比较黑,毛发比较粗,牙齿比较长,鼻子粉嘟嘟……",
"img_id": 100529,
"monster_units": {
"monster_id": "90113",
"img_id": "100003",
"swf": "2001",
"level": "20",
"description": "猪未必是这个世界上最蠢的生物",
"monster_name": "野猪"
"tpl": [
"duty_lineup"
],
"tpl_ver": "032314",
"tpl_arg": [
4,
"_duty_lineup_",
true
]
以上数据表示左边编号为4的格子有一个玩家:"4":{"type":1,"skill":"61:2,","avatar":"2","swf":"1003","position":4,"level":26,"role_name":"吴秦","role_id":0};右边编号为4的格子有一个怪物:"4":{"monster_id":"90113","img_id":"100003","swf":"2001","level":"20","description":"猪未必是这个世界上最蠢的生物","monster_name":"野猪"}
然而玩家可以改变布阵数据,如将玩家从编号为4的位置拖到编号为8的位置:
http://s326.sh.ch.qq.com/do.php?c=duty&a=lineup_change&f=4&t=7&r=0.03912129900640776,
返回结果:<script type="text/javascript">_CALLBACK([["mt_cl",["0:7",":4",0]]]);</script>
多人布阵也是类似。
当点击“攻击”按钮之后,Javascript告诉后台开始战斗(http://s326.sh.ch.qq.com/do.php?c=duty&a=attack&r=0.02707068482358438),后台计算战斗顺序、胜负等详细信息,然后返回给Javascript,Javascript调用Flash回调播放战斗效果。后台计算返回结果如下:
[["cbt_py",["17282197",{"role_info":[[[{"cell_pos":7,"role_id":212640,"level":26,"life_max":1031,"life_now":1031,"vigour_max":100,"clique_id":2,"vigour_skill":"53:2:25:0","anger_skill":"","vigour_sec":1,"avatar":2,"swf":1003,"role_name":"吴秦"}]],
[[{"cell_pos":4,"role_id":90113,"level":20,"life_max":330,"life_now":330,"vigour_max":100,"clique_id":0,"vigour_skill":"2001:1:30:0","anger_skill":"","vigour_sec":1,"avatar":100003,"swf":2001,"role_name":"野猪"}]]],
"start_time":1333244413,"round_num":1,"result":-1,"combat_type":25,"total_time":30,"max_time":500,"monster_id":90054,"frame":140,"left":[7555,0],"bg":5,"item_drop":[],"item_get":[],"item_team":[],"good_item":[],"task_item":[],"role_exp":[],"role_money":[],
"data":{"0":[[0,0,0]],"14":[[1,0,1,1,0,53,1],[13,0,75],[12,0,5],[12,1,5],[2,1,1,192,0],0],"18":[[1,1,1,1,0,2001,1],[3,1,5,-13],[13,1,70],[12,1,10],[12,0,10],[2,0,1,252,1],0],"28":[[1,0,1,1,0,53,1],[13,0,64],[12,0,15],[12,1,15],[2,1,1,186,0],[5,1],0],"29":[0]}}]],["r_u",[{"9":2,"36":0,"10":"17282197","21":369}]]]
这些数据包含了所有的打斗信息,包括胜负"result":-1(-1胜,0负),"data":{"0":[[0,0,0]]….}打斗顺序、技能、伤害值,等等。
JavaScript拿到这些数据之后,调用Flash的回调(重播也是调用的该回调,实际上是一个东西):
public static function show_play(param1:Object) : void
var data:* = param1;
try
if (m_combats[data.combat_id] == null)
{//第一次
m_combats[data.combat_id] = new Combat(data);
else if (m_combats[data.combat_id].is_finished)
{//重播效果
m_combats[data.combat_id].replay();
else
{//播放效果
show_combat(data.combat_id);
catch (e:Error)
Face.debug("Combats.show_play(" + data + ")");
Face.debug(e);
宝宝可以使用该方式,开始打斗时通知后台,后台将计算结果返回给前台,前台根据后台返回的数据播放战斗效果。
楚河汉界,在副本打怪的时候,可以直接在浏览器中输入http://s326.sh.ch.qq.com/do.php?c=duty&a=attack&r=0.02707068482358438,完成击杀怪物的动作,绕过去组队、布阵等操作,还可以连续击杀几个怪物。很容易做外挂
精灵猎手中人物、技能是分开的,所有的技能单独一个资源文件,宠物共享所有这些技能。当使用技能的时候,简单的两边的宠物替换为相应的即可。
技能打斗控制做在一个时间轴上(这点跟楚河汉界不一样,楚河是坐在不同的图层),同跳转帧标签来控制状态。
宠物资源使用矢量图制作:
技能效果也使用矢量图制作:
技能打斗中两个怪物使用两个位图表示,然后根据实际替换为相应宠物。
性能对比:
精灵猎手,所有资源都采用矢量动画制作,相比楚河汉界部分使用位图序列,CPU相对不稳定有时会达到30+:
(精灵猎手CPU占用,峰值在30左右)
楚河汉界的CPU占用稳定在20以内:
(楚河汉界CPU占用峰值在20左右)
当然这个技能的效果也有一定关系,两个游戏的技能效果不同,对CPU也有响应,不能完全反应问题。
综合上面两款游戏,网页游戏打斗系统可以采用以下方式:
技能效果使用矢量动画制作,使效果更好
人物动作动画,使用位图序列,减少CPU占用
人物打斗过程中的不同状态,可以使用楚河汉界的方式,把状态坐在不同的图层,通过控制图层来显示不同的动作
战斗数据通过后台计算下发,前台解析数据播放战斗效果即可
……
作者:吴秦 出处:http://www.cnblogs.com/skynet/ 本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名吴秦(包含链接).