5毛钱的战斗系统设计流程(上)

微信公众号“鬼人的小号” 2018-08-21
前言:

原本这文章的标题是“价值千万的战斗系统设计流程”,后来觉得太标题党了,结果就变成了5毛钱…. 但其实从不同角度来说,都是对的。

我是鬼人,《火柴人联盟》制作人,接下来我将从“根源”去阐述一套战斗系统的设计流程,如果你对动作类游戏感兴趣,那么我相信这篇文章会让你有不少收获的。

(上)篇主要是理论基础,较为枯燥,请在合适的时间点进行阅读,那么我们就开始吧~

1.      先来了解下,战斗系统为何物?

战斗系统其实只是一种叫法,往往是针对动作游戏而言,但其实每个游戏都有这么一套东西,如果要给个通用点的叫法,我觉得“操作系统”会比较合适,虽然有点别扭。

我们先来看看下面这几个游戏~                     

《超级玛丽》

《三国志》

《侍魂》

《极品飞车》

《TapSonic Top》

《黑暗之魂》

你会发现,这些游戏虽然类型差异巨大,但其根本都是需要通过“操作”来进行游戏的:有的是通过键盘操作,有点是通过点击屏幕,有的则是用手柄、或者方向盘~

基于类型的不同,操作对象的反馈也会有所不同,最终表现在“视听效果”的差异上。而这一过程的根本,就是这些游戏都有着自己的一套“操作系统”。


战斗系统实际上是针对ACT而言更具代表性的名称,它本身就是一套操作系统,虽然这是一篇主讲战斗系统的文章,但你可以直接将文中的一些观点和技巧运用到其它类型的游戏中,因为它们的本质没有很大区别。

2.      战斗系统的结构

结构化是一种非常重要的思路和手段,也是本文的一个重点思路,因此,在设计战斗系统之初,我们的首要任务就是分析它的【结构】。

         当我们准备做一个动作游戏的时候,策划会根据项目的需求设计出一些战斗系统相关的“东西”,我们假设今天要做一个《三国志》的手游版:

(就不写的太细了,请自行脑补~)

我们假设上面的文档已经足够清晰了,那程序基本可以开始工作了,不同的程序根据自己的经验往往会有不同的“写”法,而不同“写”法导致的差异往往是巨大的,这些差异主要表现在当策划要修改需求,或添加新功能的时候。

举个例子,现在要实现【移动】和【跳跃】的操作:


上面的代码属于“直观条件式”的写法,即严格的按照实际使用条件来实现功能,使用这种方法可以很快的实现基本操作,如果是做一个俄罗斯方块,或者坦克大战,那么这种写法没什么问题,甚至是非常方便,但如果用在战斗系统上,就不是特别好了。

因为多数情况下,策划是会修改需求、或者添加新功能的,而这个过程就是最容易产生问题的过程,并且随着代码和功能的复杂化,维护也是一个问题。就像这样…

(我觉得这图对于游戏开发来说...很形象...)

那么,什么样的做法更好呢?

首先,不要将焦点停留在表面(那些文字或者描述,多数都是表面产物),而要花一定的时间去分析其“根本”,去分析它的“结构”。

结构分析是一项技巧性工作,其最大的特点就是要通过“表”,看到“里”。

·“表”就是文档中罗列的那些“行为”

·而“里”就是这堆行为的共性

现在就让我们来看看这些“行为”的共性是什么:


(之所以标记“主动”和“被动”,是为了避免大家将“指令输入”认为是共性之一)

1:这些“动作”本质上就是各种动画的播放 ;

2:与动作关联的就是各种位移,也许不只位移;

经过简单的分析可以得出结论,战斗系统的结构主要是:

·动画控制:负责控制对象的载入、动画播放、暂停、跳转、移除等

·属性控制:负责控制对象的各种属性值的变化,比如坐标、颜色、角度、缩放等


推导过程很简单,结论也很简单,但却很重要,因为这种思路会围绕着后续每个点。

现在我们来以《拳皇97》的一些例子来验证一下这个结构的正确性:


·跳跃

1:按下跳跃,播放跳跃动画,带上一定的位移,即有动画控制,也有位移控制;

2:代码一直在判断人物Y轴是否小于地面Y轴,如果是,则播放落地动作,属于动画控制;


·陈国汉抡铁球,左右方向键控制移动

1:通过快速连续输入指令(在一段时间内输入5次),播放抡铁球的动作,属于动画控制;

2:此时,通过按下左右方向键,来控制移动,属于位移控制;

(这里你会发现,按键不仅用来改变动画,同时也可以单独用来改变位移)


·草薙攻击,命中陈国汉

1:草薙下前C,播放攻击动画,并附带位移,同时有动画控制和位移控制;

   陈国汉被先是被推挤,产生向后的位移,因为这里存在body的碰撞检测,从而产生推挤效果,属于位移控制;

2:陈国汉被击中,播放受击动作,身体颜色产生变化,并且有向后的位移,有位移控制和颜色控制;

3:击中时播放受击特效,并且坐标是攻击区域于受击区域集合的范围内,既有动画控制,也有属性控制(坐标、颜色);

4:在击中的瞬间还发生了对象层级的变化,层级也属于属性的一部分,生命值同样也是属性的一部分,因此都是属性控制;


·草薙攻击,陈国汉闪避

1:闪避的效果就是让攻击的碰撞检测,和body的碰撞检测无效化,因此各自播放各自的动画

2:当动作结束,回到stand,发现没有面对敌人时,就会播放trun(转身)的动画

你可以随意去套游戏中的任何“行为”(无所谓游戏类型),最终你会发现都会满足以上所说的动画和属性的控制,即便是镜头特写、镜头震动,也是一样的道理。

“动画控制”和“属性控制”也有自身的特殊结构,接下来我们就要逐步拆解它们。


3.      动画控制的结构

我们将静态对象也当成是只有一帧的动画对象,那么游戏中任何图形化的对象都可以当作动画对象来理解。

动画的控制基本由以下几部分组成:

1:命令,如go、stop、replay、remove、load;

2:指令,如单击、双击、复合指令;

3:条件,如判断是否落地,判断是否面对敌人,判断敌人是否在攻击状态;

4:碰撞,碰撞本身属于条件的一种,但因为比较特殊,所以单独拎出来;

      (指令本身也是条件的一种,也因为比较特殊,所以独立化)


我们来看看具体的使用方法:

1:命令

      go是一个最常规的方法(不同语言写法不同,因为常用所以我把方法简化了)

go(”move”)指的就是播放move动画,循环动画其实就是在动画的最后一帧加上go(self_name),比如move动画的最后一帧插入go(”move”),那么就是基本的循环动画的用法。

2:指令

         通过输入按键,来控制动画的播放,这个在下文会有更详细的说明。

3:条件

         条件的运用在战斗系统中较为常见,根据各种条件判断来实现各种功能需求:


4:碰撞

         运用最频繁的就是攻击框和受击框的碰撞检测,同时场景中的障碍物也属于碰撞的一种,碰撞检测的本质依然是条件判断:


4.    属性控制的结构

如果说动画对象是“可视化”的数据,而属性就是“不可视”的数据,因此,属性的控制方式和动画的控制方式没有太大的区别,主要是概念上有所不同。

属性控制主要由以下几部分组成:

1:赋值,通过命令改变参数的值,如:vx=20,role._y=Ground()

2:指令,通过输入指令改变参数的值,比如陈国汉抡铁球时,依然可以用方向键控制移动;

3:条件,通过条件判断来修改参数的值,比如上面的falldowm;

4:碰撞,通过碰撞检测来改变对象的值

比如这样的推挤效果:


*在这里我们会发现,虽然我们将动画控制和属性控制分开,但在实际使用过程中,它们往往是相互结合在一起的。但我们需要有意识的把它们区别对待,这样会对战斗系统的理解更有帮助。

注意,属性控制中有一个较大的“块”,在实际使用中占有较大比重,那就是“位移控制”。

5.     位移控制

位移在游戏中会有各种丰富的表现,除了人物的位移,还包括抛出物(飞行道具)的位移,而其中往往是抛出物的位移会更为复杂和多样,如果你熟悉lol,就能发现它里面就有着各种各样的抛出物类型,然后不同类型的位移方式也会有所不同:








(请注意下文的推导过程!)

如果把lol的抛出物整理成文档,我相信又是长长的一个列表,想想都觉得可怕。我就先简单的列举一些吧:


通常情况下,我们会单独去处理抛出物,根据不同类型来分类制作,这时候我们往往把抛出物当成一个独立对象,但如果我们换个角度思考,或许会更简单一些:

抛出物既是对象,那么就可以和角色共用同样的位移控制和动画控制,按这样的思路设计的话,人物也可以很简单的实现追踪导弹的位移方式,就像盲审的二段Q一样,你跑到哪,我追到哪。


代码中,我们可以使用相同的位移类来管理对象的位移,比如:

*位移类中包含一套赋值函数,和一套控制位移的函数

Fx_a(10,1):表示水平匀加速运动,初速度=10,加速度=1,X的位移类型=a;

Fy_a(30,2):表示垂直匀加速运动,初速度=30,重力=2,Y的位移类型=b;

Fv_a(10,0,25):表示追踪型加速运动,初速度=10,加速度=0,最大旋转角度=25,速度会根据角度拆成对应的是vx、vy;



可以有各种赋值方法,来表示不同类型的位移方式。

而角色和抛出物都可以共用这套方案:

·角色跳跃动画的赋值就是:

                   Fx_a(5,0)

                   Fy_a(25,1)

·弓箭射出的赋值就是:

                   Fx_a(20,2)

                   Fy_a(5,0.5)

根据这种方式你可以很轻易的创建各种位移类型,并且角色和抛出物都是共用的,甚至场景中的动态对象也可以用这种方式。

*位移采用此种方式,同样的,动画控制也可以是一套共用的动画类,比如虚空的W技能,其核心就是xx条件下执行yy事件:


·球落地后爆炸,调用的也是falldown的方法,落地后播放boom,而人物落地播放的是falldowm;


·炸弹飞出去,击中敌人播放爆炸动画,跟陈国汉大招击中敌人播放后续连击动画的效果是一样,这里我们称为hitGo(击中后播放播放xx动画)


总结:

我们在制作之初将动画控制和属性控制区分开,是为了更方便的去理解战斗系统,然而实际制作过程中,我们又需要把它们结合在一起,并且要有一个“一致性”的概念,这个概念的表现大概是:游戏中角色有着各种丰富的动作,但它们的本质是一样的,都是动画和属性的组合,它们有着一致的数据结构,只是表达方式不同而已。举个例子:

·使用左右键可以控制角色的移动,移动中带有攻击,那么这个动作是移动还是攻击?

·在上图中,金科斯的R技能发射了导弹,如果拳头愿意,当薇在金科斯身边时,金科斯可以将薇发射出去,那么此时的薇是角色还是抛出物?

因此,什么时候区分对待,什么时候视为一体,关键就在于“理解”,不要被表像所迷惑,当你掌握这个技巧的时候,很多事情就会变得更简单。

6.      指令

在上述内容中,我们会发现指令是战斗系统的一个入口,它本身是一种特殊的条件,通过操作将指令由设备传递给逻辑代码, 因此,指令的解读方式就变得尤为重要了。

多数人对指令的认知大概是按下、放开、双击、搓招这些基本的概念,但同样的,这些说的出来、看的到的,也依然是“表面”,既然有“表”的存在,也就有“里”的存在。

接下来,我们尝试将简单指令和复杂指令罗列出来,从中寻找“共性”。

最全面的指令输入方式,莫过于格斗游戏了,我们依然以《拳皇》为例:


也许还有什么遗漏的,但大概就是这么一些操作方式,通常情况下,我们会根据上面的列表逐一实现各种操作,其实这里面有许多的重复,我来举个例子:

移动是一个最基本的操作,但大多数人不会将移动和蓄力理解为相同的东西,然而,它们的本质其实是一模一样的:

     ·在站立状态下,按住前移动,放开前回到站立状态


     ·在站立状态下,按住A蓄力,在不同阶段放开A,会播放不同的动作


那么最终这2个操作,唯一的区别就是togo的值,move动画中的togo仅=”stand”,因此它在任何时候放开,都是播放stand。

*假如move动画是一个由走逐渐变成奔跑的动画:1-60帧是走的动画,61-80奔跑的动画,且动画最终会在61-80循环,那么这就是一个典型的蓄力动作了:

——在1-60帧放开按键,就会播放moveToStand的过渡动画;

——在61-80帧放开按键,就会播放rushToStand的过渡动画;

同样的道理,双击、搓招、狂按,在本质上也是相同的。

·双击可以理解为快速输入2个指令

·搓招可以理解为快速输入不同的指令

·狂按可以理解为快速输入相同指令

结果它们的本质都是快速输入多个指令。

当你理解了上面2个例子,我们就可以来重新认识下“指令”了:

*我们拟定按键同时输入的时间间隔是0-30ms(因为很难在一个相同时间点输入2个指令,因此我们会规定一个容错间隔),而连续输入的时间间隔是30-200ms,最终你可以修改这些值,以调整到最优手感;

·我们用一个字母来表示按键,比如A,就是键盘的A键;

·用A1表示按下A键,A0表示放开A键;

·用A1_500表示按下A持续500毫秒,不填则默认是a1_0

·用“,”隔开多个指令,并将指令组成数值,以表示复合指令,如:

             [A1,D1,J1]=下·前·A

·在“[ ]”中使用“[ ]”将多个指令包在一起,表示同时按下

      [S1,D1,[ J1,K1]]=下·前· AB

最终打包成一个方法,而这个方法可以实现上述所有操作:

         Action([keys],act,[beings])

· keys-数组:表示指令集合,可以是单个,也可以是多个

· act-字符串:表示要播放的动画

· beings-数组:表示动作的前置条件,比如移动的前置条件就是“站立”

那么移动的指令就是:


技能就是:


其中 表示普攻A1,普攻A2,普攻A3,因为在攻击的时候也可以放技能

金家潘的下上B技能就是:

这套方案的实现较为复杂,不一定适用于所用项目,但这个思路很重要。

7.      攻击向量

攻击是战斗系统中一个重要的行为,此时的碰撞检测倒比较简单,难的是各种丰富的击打效果。

为了表现游戏的丰富性,我们往往会给攻击定义几种类型,并且有着对应的受招动作,而这个时候,为了更方便控制,我们引入了一个“攻击向量”的概念。


攻击向量具有以下几种属性:

·类型:决定了攻击时产生的效果,比如击退、击飞、击倒等;

·方向性:决定了攻击方向,这个方向的直接表现就是对象被击中后的运动轨迹;

·长度:决定了攻击的力道,而这个力道的直接表现就是受击对象的移动速度,最终根据角度拆分成vx和vy;

·坐标:一些特殊向量会使用,比如一个引力球,向量的坐标就是引力中心;

你可以在后期很轻易的添加各种攻击向量,而且它在使用起来会非常方便,具体我会在【下】期的视频中实际演示。


8.      打击感

动作游戏离不开打击感一词,网上也有不少文章关于打击感的文章,我自己也写过一点点,但后来我发现,打击感不是玄学,不需要用太多的文字去描绘它,今天我将用“数学”的方式,来教你怎么提高游戏的打击感!







打击感的关键是区分由“轻”到“重”的攻击表现,我们假定有N个攻击级别,如轻击、中击、重击、超重击,那么:

1:击中停顿时间=N*x,根据你游戏的帧率,以及你划分的等级,你可以调整x来实现较好的停顿效果(也可以是fpsDown);

2:镜头震动级别=N,然后你可以简单的制作几个不同程度的镜头震动来匹配对应的攻击级别;

3:击打特效=N,特效是一个很重要的表现,根据不同级别配上不同表现的特效;

4:配合相应的受击动作,一般会定义:击退、击飞、击倒、强击飞等,然后结合攻击向量去使用它们;

当你尝试过后,你就会发现打击感其实就是这么一回事。

其实…

倒也不是,这只是一个快速入门的方法,想要表现出更好的效果还需要各种经验积累,而且,打击感其实不单纯只是“击打”的问题,一般我们所说的打击感其实还包含着另一层意思,就是——操作感!

操作感是完全不一样的领域,它的关键字是节奏,想做好一个动作游戏,对节奏的把控是非常关键的。不过这东西就不是简单的写点东西就能教的会的,如果你有兴趣,可以试着去研究下不同ACT的“节奏感”,我相信一番研究过后也会有一些收获的。(在下一期的视频中,我也稍微说一下)

9.      完成一套战斗系统的流程

上面的内容都是战斗系统的一些关键要点,初步看下来会比较混乱,每个章节相对独立,至于怎么系统的将这些东西结合在一起,这就需要从实践中慢慢探索了,根据你自身的经验,文中所阐述的东西可能需要不等的时间去消化,现在我们来理顺一下,战斗系统的基本制作流程:

1:先确定战斗系统的基本规则,所包含的基本动作,比如你大概是要做超级玛丽,还是三国志,还是鬼泣,大概就是游戏类型了;

2:确定指令的输入方式,是按键还是点击,或者都有;

3:加上动作切换的限制条件,包括是否有台阶、墙壁这些需要互动的东西;

4:设计好位移类,到了这一步,角色的操作基本完成了,只是还不能攻击而已;

5:加上各种碰撞检测,确定攻击类型和对应的受招动作,以及其它需要碰撞检测的对象;

6:加上一些音效、特效等视听相关的东西;

  到了这一步,你的战斗系统雏形基本出来了,按上面的方式来设计,你将会为战斗系统打下一个不错的基础,这时候即便策划想把动作游戏改成射击游戏….

你还是把策划抓起来打一顿吧…. 这项目不靠谱…


  下一期,我会录制一个视频,主要是演示下《火柴人联盟2》flash版本的动作编辑器(本身也是战斗系统主体),以及一些设计、制作上的技巧,理论在于文字,实践在于操作,我相信通过两者的结合,你对战斗系统将会有全新的认识。

最后,如果你觉得这文章还不错,可以分享下,有不同观点,也可以留言~

顺便关注下我的小号,偶尔会有些不错的东西~

谢谢观看~

下期再见~

via:微信公众号“鬼人的小号”

最新评论
暂无评论
参与评论

商务合作 查看更多

编辑推荐 查看更多