如何给人物加Ai,内容基础,高手绕道或围观,附现成ai加法...
[复制链接]
|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
3295
如何给人物加Ai,内容基础,高手绕道或围观,附现成ai加法...
鲁鲁修
2012-12-4 23:25
1
鉴于我了解mugen绕过很多远路,希望给对mugen有爱,又找不到头绪的人提供找到快速有效的方法,特开此帖。水平有限,大都为自己现阶段对mugen的理解。如有什么说的不对的地方,请高手们犀利的指出。
要学跑,必须先要学会走。要给人物加ai就要从最基本的东西入手。首先,是添加新人物。相信很多人都会了。其实添加人物的就是让mugen的主程序能够读取一个人物信息的过程。人物包与主程序连接的主要桥梁就是主程序date文件夹下的select.def。这里出现了def,mugen不需要什么程序基础。我们只要知道.def文件是模块定义文件的意思就可以了,那么在mugen里def基本上就是模块定义的意思了。def这三个字母在之后还会出现的。select.def顾名思义就是选择模块定义文件了。在这里让你设置你的mugen要用哪些人物、背景和音乐,以及人物出场顺序等。一般我们加人物的时候会直接复制人物文件夹的名字,然后粘贴到select.def的[Characters]下面。其实是用到了mugen的一个默认功能:不指定人物路径就默认为读取与人物文件夹同名的人物模块def文件。举个例子打开一个叫kyo的人物文件夹,然后在文件夹内发现一个kyo.def的文件。复制这个文件再重命名为kyo1.def放到人物文件夹中,然后再到select.def里,把原来[Characters]下面的kyo改成kyo/kyo1.def,进入游戏,发现人物还是会正常运行,而删掉这个kyo1.def的文件后,kyo这个人物就不能读取了。这说明,select.def读取的是人物模块文件---def。
打开人物的def文件你会发现里面指定了人物要调用哪些文件。可以说是一个人物包的指挥调度中心。[Info]下面是人物的介绍和人物名的定义等。其中author一栏都知道吧,作者!!别乱改哈。[Files]下面就是该人物所调用的文件了。Cmd就是人物的指令操作文件,人物的招怎么按基本上都是在这里设置的。在一个人物里我偶然知道,原来cmd也可以指定为txt文件的。这样方便修改的时候打开,你们也可以试试。就是把[Files]下面的cmd = kyo.cmd改成cmd = kyo.txt然后把文件kyo.cmd的后缀改成txt。接着往下看,就是cns文件,cns不知道是不是central nervous system的缩写,总之是一个人物的核心文件就是了。在下面的st、st1、st2、、、、、、是存放模块代码的文件,有些人物可能没有,那可能是都写在cns里了。Stcommon是公共模块,人物的一些基本动作模块代码就在这里呢,既然是公共模块,在主程序的date文件下就有一个公共的common,不写common的话可以指定为那个common为Stcommon。在下去就是图片(sprite) 动画(anim)声音(sound)的文件指定了。人物就是由这些文件组成的。
首先说图片和动画,图片的修改就不说了,没那个能力。图片是由动作(action)调用的,每一组动作代码都保存在动画文件air里,用记事本打开air文件,就会看到里面有很多Begin Action的字样,比如 :[Begin Action 100],每组动作都是由一个类似这样的标志作分段。其中100是这组动作的动画编号。在其他地方出现时会以anim = 100来调用。在[Begin Action 100]下面有着类似Clsn2Default: 1
Clsn2[0] = -22, -76, 36, -13
的,这些是人物的判定框,先不去管它们。
再往下看,看到
100,0, 0,0, 3
100,1, 0,0, 3
100,2, 0,0, 3
100,3, 0,0, 3
这里每行表示对一张图片的描述,前面两位表示图片在sff中的编号,如100,0; 100,1; 100,2 ;中间两位是图片在air中的利用时的坐标设定。最后一位是这张图片所显示的桢数。所有[Begin Action 100]下面的图片组显示完毕就表示一个动作的结束。图片最后的数字用-1,表示这图的动作不会结束。
跳过cns的基本设置,接着说动作代码,动作代码主要写在cns和st文件中是构成人物代码的基本单位。所谓动作代码,就是人物当前动作所对应的模块定义代码。在文件中以[statedef XXX]作为分段标志。一个[statedef XXX]表示一个动作。当然人物的一个动作或技能可能是由好几个[statedef XXX]组成的。
以[statedef 200]为例:
[Statedef 200]
type = S
movetype = A
physics = S
anim = 200
juggle= 8
velset= 0,0
ctrl= 0
poweradd = 20
sprpriority = 2
首先type = S;表示这个动作人物的位置状态是在地上站立的。
S站立、C蹲着、A空中、L躺在地上、U不清楚。这个位置的设定对于ai的判定是有很大的影响的。比如明明是下段的攻击,你设置个type = S的话ai可能会出现判断失误而保持站立防御。
movetype = A;表示这个人物的动作属性是攻。
A攻击、H受击、I发呆
这个也可以作为ai判定的一个条件
physics = S;表示这个动作的物理状态是站着的。
S站立、C蹲着、A空中、N不设置
如果physics =A的话会受到人物重力加速度(yaccel)的影响,physics =N的话需要自己在下面加上速度设置。
anim = 200;就是之前在说air的时候提到的调用动画了。表示这个代码模块对应的动作(action)是200
juggle= 8;表示所需要的浮空连击值为8,当人物被打到浮空时,程序会以累加的形式自动记录浮空连击值(一共好像是16),当所需要浮空连击值大于当前所剩的浮空连击值时,攻击就会无效。
velset= 0,0;表示初始速度x/y速度都设置为0
ctrl= 0;表示人物不可控,人物一共有可控与不可控两种状态。可控是ctrl= 1,这个要在动作里标明,比如在[Statedef 20]中,因为20一般表示是向前走的动作,人物应该处于可以控制,可以出招的所以应该设置为ctrl= 1,而向这个[Statedef 200]就是一个轻攻击的动作,在动作的过程中人物应该处于不可马上出其他招的状态(不然就乱套了),所以要设置成ctrl= 0,所以在写ai的一般判定的时候也都应该加上ctrl= 1这个条件,以免ai抽风。
poweradd = 20;转到这个动作时就加20power点
sprpriority = 2;这个应该是动画所占图层的位置
有些动作在空中或躺地上的,动画播完后会自动转到其他state。一般不会自动转的statedef我们就需要为它添加一个转换state的代码------ ChangeState,比如这个站立攻击的[Statedef 200],当动画200所有图片显示完了后,它会重复播放动画的,就需要为它加上个转换state的代码如下:
[State 200, 4]
type = ChangeState
trigger1 = AnimTime = 0
value = 0
ctrl = 1
[State 200, 4];这个是模块内分段标志,以state开头(后面要跟一空格),后面写什么就随你了,但要用[]框起来,比如[State 孙悟空]也可以。但一般为了美观和方便查找什么的都是向上面的以模块编号为段内分段标志命名的,段内分段标志重复也没关系。但模块定义代码分段标志[Statedef 200]就不能和别的重复了,不然就会以写最在前面的为准,忽略其他的模块定义代码。
type = ChangeState;这是定义这段代码的类型为state转换,其实人物在游戏中的动作变化就是在不同state之间的切换。ai的主要内容也就是转换不同的state,只是加上了一些判定条件,来限制什么时候来转换state而已。
trigger1 = AnimTime = 0;这段代码的触发条件只有一个,就是AnimTime = 0;这里提到了触发条件trigger,在muegn中各种代码的实现都需要有至少一个触发条件。Trigger分为triggerall、trigger1、trigger2、trigger3、、、、、、其中triggerall、trigger1比较特殊,triggerall可以说是一个必要不充分条件,既加上一个triggerall那么所有的触发条件都必须要满足这个triggerall才行。但光有triggerall是不行的任何段都要至少有一个trigger1才能运行。比如上面的代码段写成这样就会报错。
[State 1]
type = ChangeState
triggerall = AnimTime = 0
value = 0
ctrl = 1
同时每个trigger都可以同时写多个,如下:
[State 1]
type = ChangeState
triggerall= statetype = S
triggerall= pos y = 0
trigger1= pos y = 0
trigger1= animelm = 5,>= 1
trigger2= time >= 30
trigger2= animelm = 5,>= 1
trigger2= pos y = 0
value = 0
每个trigger要按顺序,比如不能跳过trigger2,直接写trigger3,那样会程序被忽略这个触发条件trigger3的。
value = 0;就是指ChangeState转换到哪个state,值为动0就表示是站立动作[statedef 0],这样你按一个轻拳,打完后它就回到站立动作了。最后的ctrl = 1表示回到可控状态。
一般在定义模块要发出声音的话还要加上调用声音的代码type = PlaySnd;
[State 200, 1]
type = PlaySnd;代码类型为播放声音文件
trigger1 = animelm = 1;触发条件为动画播放到到第一张图
value = 1,0;声音在snd中的编号为1,0
channel = 0;应该是声道
volume = 255;音量
既然是攻击动作,就还要加上攻击定义的代码段:这个对于人物的打击感和操作感影响很大。当然对ai也就有影响。
以200的攻击定义的代码为例:
[State 200, 2]
type = HitDef
trigger1 = AnimElem = 3 ;攻击有效条件
attr = S, NA ;攻击类型为站立,普通攻击
damage = 20 ;攻击力
animtype = Light/Medium/Hard ;动画类型,分为轻中重,还有up和down是特殊的
hitflag = MAF ;攻击的范围,可以叠加,一共有MAFDP,M表示可以打到站立和蹲着的,A表示空中的,F表示浮空的,D是倒地的,P是飞行道具
guardflag = MA ;防御类型,可以叠加,一共有MAHL,M表示站立和蹲防都可,A表示可在空中防御,H表示站防,L表示蹲防
getpower = 40 ;自己可以得到的power
givepower = 20 ;对方得到的power
pausetime = 10,10 ;攻击暂停时间,前面的是自己,后面的是给对方
guard.pausetime = 10,10 ;防御暂停时间,前面的是自己,后面的是给对方
airguard.pausetime = 10,10 ;空中防御暂停时间,前面的是自己,后面的是给对方
sparkno = S7000 ;火花号
guard.sparkno = S7100 ;防御火花号
sparkxy = -10,-73 ;火花坐标
hitsound = -1 ;攻击声音
guardsound = S5,0+(Random%2) ;防御声音
ground.type = low ;不太清楚,有high和low,low好象收招比较快,还有trip是击倒
ground.slidetime = 5 ;被攻击者滑行时间,对方退后的时间
ground.hittime = 10 ;被攻击者受击时间
ground.velocity = -5 ;被攻击者滑行速度
air.velocity = -4,-4 ;被攻击者空中滑行速度
guard.slidetime = 6 ;被攻击者防御后滑行时间,对方退后的时间
guard.hittime = 10 ;被攻击者防御后受击时间
guard.velocity = -6 ;被攻击者防御后退速度
airguard.velocity = -4,-4 ;被攻击者空中防御后退速度
ground.cornerpush.veloff = -7 ;角落被防御后自己反弹速度
airguard.cornerpush.veloff = -7 ;角落空中防御后自己反弹速度
yaccel = .6 ;被攻击者下落加速度
加ai要先修改人物的操作和打击感,攻击定义这块可以参考下面的设置修改,是以kof风格为基准的,当然不同的人物air的设置是不同的,一般在普通攻击基本连段设置好以后以轻攻击能连3次为基准作微调:
1.修改所有普通攻击juggle为4
2.轻攻击以下四项按这个数值改
ground.slidetime = 5 ;被攻击者滑行时间,对方退后的时间
ground.hittime = 10 ;被攻击者受击时间
ground.velocity = -5 ;被攻击者滑行速度
air.velocity = -4,-4 ;被攻击者空中滑行速度
3.轻攻击以下四项按这个数值改,或者直接再这些前面加个;屏蔽,那样的话就是默认和上面的四个一样了
guard.slidetime = 5 ;被攻击者防御后滑行时间,对方退后的时间
guard.hittime = 10 ;被攻击者防御后受击时间
guard.velocity = -5 ;被攻击者防御后退速度
airguard.velocity = -4,-4 ;被攻击者空中防御后退速度
4.重攻击以下四项按这个数值改
ground.slidetime = 7 ;被攻击者滑行时间,对方退后的时间
ground.hittime = 14 ;被攻击者受击时间
ground.velocity = -5 ;被攻击者滑行速度
air.velocity = -4,-5 ;被攻击者空中滑行速度
5.重攻击以下四项按这个数值改,或者直接再这些前面加个;屏蔽,那样的话就是默认和上面的四个一样了
guard.slidetime = 7 ;被攻击者防御后滑行时间,对方退后的时间
guard.hittime = 14 ;被攻击者防御后受击时间
guard.velocity = -5 ;被攻击者防御后退速度
airguard.velocity = -4,-5 ;被攻击者空中防御后退速度
6.
轻攻击damage改成20-25的范围
重攻击damage改成60-85的范围
轻攻击pausetime改成10,10
重攻击pausetime改成13,15或13,16
(如有guard.pausetime等就删掉)
ground.type = 都改成low
7.修改hitflag = MAF
8.guardflag = L的攻击动作最上面的type设置为c、修改为attr = C…. (防止ai误判)
动作模块定义就讲到这里,接下来说cmd。一般我都把ai写在cmd里,找起来方便,写起来也方便。
Cmd是保存出招指令command和[statedef -1]的地方。说到[statedef -1],mugen有3个特殊的statedef,就是-1、-2和-3凡是写在这三个statedef下面的代码,人物几乎是时时都在扫描执行的。区别好象是-2是在对方的state下还是会执行的,-3是在对方的state下不执行,-1不太清楚。反正cmd中[statedef -1]下基本上都是changestate的代码,也就是前面提到过的转换state。比较特殊的是这里的changestate大都是有一个带有command的触发条件,也就是说要你输入一定的操作指令后,changestate才会执行。其实ai的判定和
statedef -1]下出招的设定非常相似,最大的不同就是没有command这样的触发条件(不需要你输入指令)。先来看一下,出招指令的 ChangeState:以200为例
[State -1, Stand Light Punch]
type = ChangeState
value = 200
triggerall = command = "x" ;这个有command,说明要输入指令"x"
triggerall = command != "holddown";这个前面有个!说明同时指令不能为"holddown";mugen中!一般表示否定的意思
triggerall = statetype != A;人物不在空中,这个挺重要的
trigger1 = ctrl; 人物为可控状态
trigger2 = stateno = 200 && movecontact;在动作200中,碰到对方
trigger3 = stateno = 210 && movecontact;在动作210中,碰到对方
trigger4 = stateno = 215 && movecontact;
trigger5 = stateno = 230 && movecontact;
trigger6 = stateno = 235 && movecontact;
stateno = 200中200就是[statedef 200]中的200,表示动作的编号
movecontact是碰到,接触的意思
同类的判定条件还有movehit命中、moveguarded被防御
&&是并列条件的意思,表示同时还要满足的条件。||是或的意思,满足其中一个的意思。但用||的话还是尽量写成两个trigger比较好。
但这个是操作用的changestate,如何把它变成Ai呢?前面说过了,ai主要也就是各种changestate的**。那到底如何来为人物添加合适的ai呢。首先我们就要来了解一下ai开关。所谓的ai开关其实也就是一个var,最简单的ai开关就是在cmd添加一定数量的command,然后在[statedef -1]下面加一个type = varset的代码段。Mugen人物在电脑控制的情况下会自动随机执行所有command,利用这点就可以为人物添加一个ai开关了
[Command]
name = "AI0"
command = a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a
time = 0
这个指令是人输入不能的吧,但电脑能用出这样的指令然后把这个指令作为触发条件,把这指令加到[statedef -1]上面,然后把它加到刚才说的varset下面作为触发条件
[State -1, AIstart];
type = VarSet; Var设置
TriggerAll = Var(59) = 0;设 Var(59)为ai开关,当其值为0时
TriggerAll = RoundState = [1,2];开局和战斗时
trigger1 = Command = "AI0";有指令输入"AI0"
v = 59; Var的编号为59(总共有1-59)
value = 1; Var(59)的值为1
这样在当电脑随机到这个指令时Var(59)的值就为1,我们就可以
用TriggerAll = Var(59) >= 1之类的当作ai开关了。
但只有这么一个指令的话,电脑随机到的几率比较小,所以一般就多添加一些类似的指令
[State -1, AIstart]
type = VarSet
TriggerAll = Var(59) = 0
TriggerAll = RoundState = [1,2]
trigger1 = Command = "AI0" || Command = "AI1" || Command = "AI2"
trigger2 = Command = "AI3" || Command = "AI4" || Command = "AI6"
trigger3 = Command = "AI7" || Command = "AI8" || Command = "AI9"
trigger4 = Command = "AI10" || Command = "AI11" || Command = "AI12"
trigger5 = Command = "AI13" || Command = "AI14" || Command = "AI15"
trigger6 = Command = "AI16" || Command = "AI17" || Command = "AI18"
trigger7 = Command = "AI19" || Command = "AI20" || Command = "AI21"
trigger8 = Command = "AI22" || Command = "AI23" || Command = "AI24"
trigger9 = Command = "AI25" || Command = "AI26" || Command = "AI27"
trigger10 = Command = "AI28" || Command = "AI29" || Command = "AI30"
trigger11 = Command = "AI31" || Command = "AI32" || Command = "AI33"
trigger12 = Command = "AI34" || Command = "AI35" || Command = "AI36"
trigger13 = Command = "AI37" || Command = "AI38" || Command = "AI39"
trigger14 = Command = "AI40" || Command = "AI41" || Command = "AI42"
trigger15 = Command = "AI43" || Command = "AI44" || Command = "AI45"
trigger16 = Command = "AI46" || Command = "AI47" || Command = "AI48"
trigger17 = Command = "AI49" || Command = "AI50"
v = 59
value = 1
这样ai启动的就会比较快了。当然以开局召唤援助的方法可能可以更快的开启ai但,那个对援助人物和可控性有一定影响就不说
了。
有了ai开关var就可以用这个var代替command,把操作用的ChangeState变成ai了
[State -1, Stand Light Punch]
type = ChangeState
value = 200
TriggerAll = Var(59) >=1
triggerall = statetype = S
trigger1 = ctrl
trigger2 = stateno = 200 && movecontact
trigger3 = stateno = 210 && movecontact
trigger4 = stateno = 215 && movecontact
trigger5 = stateno = 230 && movecontact
trigger6 = stateno = 235 && movecontact
这样就是一个简单的ai判定了。当然,这样人物只会连续的出200而已。
所以我们要设置各种触发条件限制
[State -3, 1]
Type = ChangeState
Value = 200
TriggerAll = Var(59) >= 1;ai开关var开启
TriggerAll = RoundState = 2;在战斗中
TriggerAll = statetype != A;不在空中
TriggerAll = p2statetype != A;敌人不在空中
TriggerAll = p2statetype != L; 敌人不在倒地中
triggerall = p2dist x = [35,135];敌人x距离为35-135
trigger1 = ctrl;在可控状态下
这样出招的条件就有了一定的限制,要写出更严谨的判定ai可以参考那些ai比较好的人物。提供一些比较常见的触发条件
Ai连招的话基本上就是movecontact、movehit等触发条件配合stateno= xx和animelem = xx等完成的
比如:
[State -3, 1]
Type = ChangeState
Value = 200
TriggerAll = Var(59) >= 1;ai开关var开启
TriggerAll = RoundState = 2;在战斗中
TriggerAll = statetype != A;不在空中
trigger1 = stateno = 400 && movecontact;在动作400中,碰到对方
trigger1 = p2movetype = A
对方处于攻击中
trigger1 = p2movetype = H
对方处于受击中
trigger1 = p2stateno < 1000
对方动作模块编号小于1000
Trigger1 = random < 100
随机值小于100
trigger1 = stateno = xxx && movecontact
在xxx动作模块中,碰到对方
trigger1 = stateno = xxx && movehit
在xxx动作模块中,命中对方
trigger1 = stateno = xxx && moveguarded
在xxx动作模块中,对方防御成功
trigger1 = stateno = xxx && animtime = 0
在xxx动作模块中,动画结束后
trigger1 = stateno = xxx && animelem = X,>= 1
在xxx动作模块中,动画图片在第几张出现之后
trigger1 = var(xx) = a
在var值为a时,这个要varset或vaadd设定好某个var的变化
trigger1 = enemynear,ctrl = 0
对方为不可控状态
trigger1 = enemynear, vel x <= a
对方x速度小于a
trigger1 = enemynear, vel y <= a
对方y速度小于a
Trigger1 = Backedgebodydist > 100
身后版边距离大于100
Trigger1 = frontedgebodydist > 100
前面版边距离大于100
trigger1 = enemy,numproj >= 1
对方存在飞行道具
Trigger1 = (Enemy, HitDefAttr = SAC, AP)
对方攻击类型为飞行道具
Trigger1 = inguarddist
在防御距离 |
|