代码改变世界

《楚河汉界分析》

2012-04-01 16:37  吴秦  阅读(4998)  评论(1编辑  收藏

楚河汉界

——战斗系统分析

1.  战斗资源

人物和技能:

楚河汉界中人物和技能是绑定的,放在同一个资源中。人物动画使用位图序列制作,技能效果使用矢量动画使效果更炫,更平滑。

打斗效果:

楚河汉界中战斗时,技能施加到人物身上之后,的效果是与技能独立的。所有的这些效果放在一个资源中,这些效果也是使用矢量动画制作。

 

战斗中就是轮流播放人物的技能和添加技能伤害效果到目标上面。

人物状态:

不同状态分别在不同的层,通过控制层来显示状态。

clip_image002

2.  战斗控制

 

游戏的主体操作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个位置分别编号(代码中用012345678)如下图所示:

clip_image004

排兵布阵会直接影响到战斗胜负,因为:

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": {

                "4": {

                    "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>

多人布阵也是类似。

 

打斗顺序

clip_image006

当点击“攻击”按钮之后,Javascript告诉后台开始战斗(http://s326.sh.ch.qq.com/do.php?c=duty&a=attack&r=0.02707068482358438),后台计算战斗顺序、胜负等详细信息,然后返回给JavascriptJavascript调用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);

        }

        return;

    }// end function

宝宝可以使用该方式,开始打斗时通知后台,后台将计算结果返回给前台,前台根据后台返回的数据播放战斗效果。

 

楚河汉界,在副本打怪的时候,可以直接在浏览器中输入http://s326.sh.ch.qq.com/do.php?c=duty&a=attack&r=0.02707068482358438,完成击杀怪物的动作,绕过去组队、布阵等操作,还可以连续击杀几个怪物。很容易做外挂

clip_image008

 

 

3.  战斗资源(对比精灵猎手)

精灵猎手中人物、技能是分开的,所有的技能单独一个资源文件,宠物共享所有这些技能。当使用技能的时候,简单的两边的宠物替换为相应的即可。

clip_image010

技能打斗控制做在一个时间轴上(这点跟楚河汉界不一样,楚河是坐在不同的图层),同跳转帧标签来控制状态。

宠物资源使用矢量图制作:

clip_image011

技能效果也使用矢量图制作:

clip_image013

技能打斗中两个怪物使用两个位图表示,然后根据实际替换为相应宠物。

 

性能对比:

精灵猎手,所有资源都采用矢量动画制作,相比楚河汉界部分使用位图序列,CPU相对不稳定有时会达到30+

clip_image014(精灵猎手CPU占用,峰值在30左右)

楚河汉界的CPU占用稳定在20以内:

clip_image015(楚河汉界CPU占用峰值在20左右)

当然这个技能的效果也有一定关系,两个游戏的技能效果不同,对CPU也有响应,不能完全反应问题。

 

 

总结

 

综合上面两款游戏,网页游戏打斗系统可以采用以下方式:

clip_image001  技能效果使用矢量动画制作,使效果更好

clip_image001[1]  人物动作动画,使用位图序列,减少CPU占用

clip_image001[2]  人物打斗过程中的不同状态,可以使用楚河汉界的方式,把状态坐在不同的图层,通过控制图层来显示不同的动作

clip_image001[3]  战斗数据通过后台计算下发,前台解析数据播放战斗效果即可

clip_image001[4]  ……