2016.06.2309:55

AI 双打部分浅谈

Episode 9 双打部分浅谈

一个比较完整的AI,是要包含双打部分的,里面的概念其实很好理解,队友被打了你看情况去救队友,其中比较远程的话可以大跳或者突进过去救,如果你有飞行道具就出飞行道具技能去救队友,再比如还有队友在打对面两个对手的时候,你去补刀,队友把两个敌人拉了个P2,你可以做一个蓄气的动作来给己方攒气,或者你也可以装逼出个嘲讽啥的,反正用法很多,自己按照实际来理解

下面切入正题,今天用到两个var来记录全部双打情况,var(51)和var(52),如果被占用了就换别的

;━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
; タッグ用 ;TAG(双打模式)下使用
;━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[State -3, 敵が1人] ;对手只有1个人的情况,有两种情况,对手有队友但是队友死了,也可能是本来就1个人
Type = VarSet
Trigger1 = NumEnemy != 2
Trigger2 = !(EnemyNear(0),Alive && EnemyNear(1),Alive)
V = 51
Value = 0

[State -3, 敵が2人かつ前方のみ] ;两个敌人都在你面前的情况
Type = VarSet
TriggerAll = NumEnemy = 2
TriggerAll = EnemyNear(0),Alive
TriggerAll = EnemyNear(1),Alive
Trigger1 = ifelse(Facing = 1,EnemyNear(0),Pos X - Pos X > 0,EnemyNear(0),Pos X - Pos X < 0)
Trigger1 = ifelse(Facing = 1,EnemyNear(1),Pos X - Pos X > 0,EnemyNear(1),Pos X - Pos X < 0)
V = 51
Value = 1

[State -3, 自分、パートナー、敵、敵] ;场上4人分布情况从左到右:自己,队友,两位敌人
Type = VarSet
TriggerAll = NumEnemy = 2
TriggerAll = NumPartner
TriggerAll = EnemyNear(0),Alive
TriggerAll = EnemyNear(1),Alive
TriggerAll = Partner,Alive
Trigger1 = ifelse(Facing = 1,EnemyNear(0),Pos X - Pos X > 0,EnemyNear(0),Pos X - Pos X < 0)
Trigger1 = ifelse(Facing = 1,EnemyNear(1),Pos X - Pos X > 0,EnemyNear(1),Pos X - Pos X < 0)
Trigger1 = ifelse(Facing = 1,EnemyNear(0),Pos X - Partner,Pos X > 0,EnemyNear(0),Pos X - Partner,Pos X < 0)
Trigger1 = ifelse(Facing = 1,EnemyNear(1),Pos X - Partner,Pos X > 0,EnemyNear(1),Pos X - Partner,Pos X < 0)
V = 51
Value = 2

[State -3, 自分、敵、パートナー、敵] ;分布情况:自己,敌人,队友,敌人,此时队友可能有危险,因为队友被两个敌人夹住了
Type = VarSet
TriggerAll = NumEnemy = 2
TriggerAll = NumPartner
TriggerAll = EnemyNear(0),Alive
TriggerAll = EnemyNear(1),Alive
TriggerAll = Partner,Alive
Trigger1 = ifelse(Facing = 1,EnemyNear(0),Pos X - Pos X > 0,EnemyNear(0),Pos X - Pos X < 0)
Trigger1 = ifelse(Facing = 1,EnemyNear(1),Pos X - Pos X > 0,EnemyNear(1),Pos X - Pos X < 0)
Trigger1 = ifelse(Facing = 1,EnemyNear(0),Pos X - Partner,Pos X < 0,EnemyNear(0),Pos X - Partner,Pos X > 0)
Trigger1 = ifelse(Facing = 1,EnemyNear(1),Pos X - Partner,Pos X > 0,EnemyNear(1),Pos X - Partner,Pos X < 0)
V = 51
Value = 3

[State -3, 自分、敵、敵、パートナー] ;分布情况:自己,两位敌人,队友,此时为优势
Type = VarSet
TriggerAll = NumEnemy = 2
TriggerAll = NumPartner
TriggerAll = EnemyNear(0),Alive
TriggerAll = EnemyNear(1),Alive
TriggerAll = Partner,Alive
Trigger1 = ifelse(Facing = 1,EnemyNear(0),Pos X - Pos X > 0,EnemyNear(0),Pos X - Pos X < 0)
Trigger1 = ifelse(Facing = 1,EnemyNear(1),Pos X - Pos X > 0,EnemyNear(1),Pos X - Pos X < 0)
Trigger1 = ifelse(Facing = 1,EnemyNear(0),Pos X - Partner,Pos X < 0,EnemyNear(0),Pos X - Partner,Pos X > 0)
Trigger1 = ifelse(Facing = 1,EnemyNear(1),Pos X - Partner,Pos X < 0,EnemyNear(1),Pos X - Partner,Pos X > 0)
V = 51
Value = 4

[State -3, 背後に敵有り] ;这个就比较尴尬了,背后有敌人的情况,通常背后有敌人的情况就代表你前面还有一个敌人,也就是说你被两位敌人卡住了(苦笑)
Type = VarSet
TriggerAll = NumEnemy = 2
TriggerAll = EnemyNear(0),Alive
TriggerAll = EnemyNear(1),Alive
Trigger1 = ifelse(Facing = 1,EnemyNear(0),Pos X - Pos X < 0,EnemyNear(0),Pos X - Pos X > 0)
Trigger2 = ifelse(Facing = 1,EnemyNear(1),Pos X - Pos X < 0,EnemyNear(1),Pos X - Pos X > 0)
V = 51
Value = 5

;---------------------------------------------------------------------------
[State -3, パートナー不在] ;双打模式,但是队友不在或者队友已经死亡
Type = VarSet
TriggerAll = TeamMode = Simul
Trigger1 = !NumPartner
Trigger2 = !Partner,Alive
V = 52
Value = 0

[State -3, パートナー後衛] ;双打模式下队友在你后面当后卫
Type = VarSet
TriggerAll = TeamMode = Simul
TriggerAll = NumPartner
TriggerAll = Partner,Alive
Trigger1 = ifelse(Facing = 1,Partner,Pos X - Pos X < 0,Partner,Pos X - Pos X > 0)
V = 52
Value = 1

[State -3, パートナー前衛] ;双打模式队友给你当前锋
Type = VarSet
TriggerAll = TeamMode = Simul
TriggerAll = NumPartner
TriggerAll = Partner,Alive
Trigger1 = ifelse(Facing = 1,Partner,Pos X - Pos X > 0,Partner,Pos X - Pos X < 0)
V = 52
Value = 2

[State -3, パートナー被ダメージ] ;双打模式下队友被打,而且这里代表的是普通的被打或者被打防御的状态,可以救
Type = VarSet
TriggerAll = TeamMode = Simul
TriggerAll = NumPartner
TriggerAll = Partner,Alive
TriggerAll = Partner,MoveType = H
TriggerAll = ifelse(Facing = 1,Partner,Pos X - Pos X > 0,Partner,Pos X - Pos X < 0)
Trigger1 = Partner,StateNo = [5000,5100)
Trigger2 = Partner,StateNo = [120,159]
V = 52
Value = 3

[State -3, パートナー攻撃中] ;队友在打敌人的情况,近敌显示被打
Type = VarSet
TriggerAll = TeamMode = Simul
TriggerAll = NumPartner
TriggerAll = Partner,Alive
TriggerAll = Partner,MoveType = A
TriggerAll = Partner,MoveType != H
TriggerAll = EnemyNear(var(58)),MoveType = H
TriggerAll = ifelse(Facing = 1,Partner,Pos X - Pos X > 0,Partner,Pos X - Pos X < 0)
Trigger1 = EnemyNear(var(58)),StateNo = [5000,5100)
V = 52
Value = 4

[State -3, パートナー被ステート奪取] ;这个比较危险,因为是队友被抓了个P2,这个时候如果你有波的话就发波吧,最好别靠近对手,说不定你也会被卷进去
Type = VarSet
TriggerAll = TeamMode = Simul
TriggerAll = NumPartner
TriggerAll = Partner,Alive
TriggerAll = Partner,MoveType = H
TriggerAll = ifelse(Facing = 1,Partner,Pos X - Pos X > 0,Partner,Pos X - Pos X < 0)
Trigger1 = Partner,StateNo != [5000,5500]
Trigger1 = Partner,StateNo != [120,159]
V = 52
Value = 5

[State -3, パートナーステート奪取] ;队友给别人拉了个P2,此时为近敌被拉P2的状态
Type = VarSet
TriggerAll = TeamMode = Simul
TriggerAll = NumPartner
TriggerAll = Partner,Alive
TriggerAll =(Partner,StateNo = [2000,4999]) || Partner,StateNo > 5500
Trigger1 = EnemyNear(var(58)),MoveType = H
Trigger1 = EnemyNear(var(58)),StateNo != [5000,5500]
Trigger1 = EnemyNear(var(58)),StateNo != [120,159]
V = 52
Value = 6

好了先记下来这么多,接下来要怎么用呢

举个例子:比如说你要装逼对吧,我们就说195,挑衅这个动作,什么时候用呢?

考虑下情况,肯定是两个对手都被打,而且都被拉了P2,首先要考虑到的肯定是var(52) = 6的情况

;装逼装逼装逼
[State -3, Taunt]
Type = ChangeState
Value = 195
TriggerAll = var(59) = 1
TriggerAll = StateNo != 195 && PrevStateNo != 195 ;因为有些人195是带ctrlset的,而且不要和前一个动作重复
TriggerAll = RoundState = 2 && EnemyNear(var(58)),Life > 0
TriggerAll = Random <= 150 ;概率你可以自己定,这里是15%概率装个逼
TriggerAll = StateType != A
TriggerAll =!Enemy,NumProj ;对面没有飞行道具
TriggerAll =!InGuardDist && !Helper(31000+ID),InGuardDist ;确保是InGuarddist
TriggerAll = Ctrl || (StateNo = [20,22]) || (StateNo = [100,101]) || (StateNo = [120,149])
Trigger1 = var(52) = 6 && var(51) < 5 ;确定对手是被P2了而且不能被两位队友夹住
Trigger1 = EnemyNear(0),MoveType = H && (EnemyNear(0),StateNo != [120,159]) && (EnemyNear(0),StateNo != [5000,5100))
Trigger1 = EnemyNear(1),MoveType = H && (EnemyNear(1),StateNo != [120,159]) && (EnemyNear(1),StateNo != [5000,5100)) ;上面的2行,因为要同时确保两位敌人同时被打,近敌和远敌,分别代表0,1
Trigger1 = Abs(EnemyNear(var(58)),Pos X - Pos X) > 120; (大概距离可以自己定,Abs(EnemyNear(var(58)),Pos X - Pos X)与P2BodyDist X的换算标准是前者比后者大32)

除了装逼之外,你有可以帮助对手的东西也可以用,比如蓄气,这个换个状态号就行了,不多讲

不要成天只知道装逼,学着点去救队友和自救

先说,比如发个波去辅助队友,或者去营救

;地波
[State -3, Proj]
Type = ChangeState
Value = (地波状态号,如果你有强弱地波的话按照距离选择强弱,远了就强,稍微近一点就弱)
TriggerAll = var(59) = 1
TriggerAll = var(52) = [2,3] ; var(52) = 2代表队友给你当前锋,3代表队友在被普通的攻击
TriggerAll = var(51) < 5 ;首先要确保自己的安全,不能被夹住
TriggerAll = RoundState = 2 && EnemyNear(var(58)),life > 0
TriggerAll = Random <= 100 ;10%概率,自己可以改
TriggerAll = StateType != A
TriggerAll = NumProjID(1000) = 0
TriggerAll = EnemyNear(var(58)),StateType != A
TriggerAll = Ctrl || (StateNo = [20,22]) || (StateNo = [100,101]) || (StateNo = [120,149])
Trigger1 = P2BodyDist X >= 200 ;多远出,自己算好距离

还有一点,就是你被两位对手夹住了怎么办,如果有闪避或者AB之类的技能赶紧闪出去,因为对你来说是大劣势,以AB为例
,尽量以耗气后AB或者无敌闪避技能为主,比如原版KOF的后AB是有挺大责任的,但耗1气防御下AB就是无敌的话,那么

[State -3, 後転]
Type = ChangeState
Value = (后AB状态)
TriggerAll = var(59) = 1
TriggerAll = var(51) = 5 && (var(52) > 0 || Power >= 1000) ;你队友在的时候或者有气就AB出去,没有的话你就认命吧
TriggerAll = RoundState = 2
TriggerAll = StateType != A
Trigger1 = Ctrl || (StateNo = [20,22]) || (StateNo = [100,101]) || (StateNo = [120,149])
Trigger1 = Abs(EnemyNear(var(58)),Pos X - Pos X) <= 100 ;保持一定距离
Trigger1 = EnemyNear(var(58)),StateNo >= 1000 && !EnemyNear(var(58)),Ctrl ;对手攻击状态,通常1000以上为必杀,趁这个时候赶紧跑掉
Trigger1 = var(52) = 5 && BackEdgeBodyDist >= 40 (你和队友都被夹了,此时队友被P2了,你赶紧跑远了,别卖了自己)
Trigger2 = StateNo = 150 || StateNo = 152 ;消耗1气赶紧跑出去,不要管太多
Trigger2 = Power >= 1000 && var(42) >= 120 && BackEdgeBodyDist >= 20 ;自己背离墙角有一段距离
Trigger2 = ifelse(Facing = 1,(EnemyNear(0),Pos X - Pos X = [-100,0]),(EnemyNear(0),Pos X - Pos X = [0,100])) ;记得算好距离,facing = 1表示脸朝右边看,-1表示脸朝左边
Trigger2 = EnemyNear(0),BackEdgeBodyDist >= 40 ;敌人背离墙角有一段距离,不然你AB出不去的,AB完了还是被卡住
Trigger2 = EnemyNear(0),Facing = Facing ;背对敌人
Trigger3 = StateNo = 150 || StateNo = 152 ;同上面的道理
Trigger3 = Power >= 1000 && var(42) >= 120 && BackEdgeBodyDist >= 20
Trigger3 = ifelse(Facing = 1,(EnemyNear(1),Pos X - Pos X = [-100,0]),(EnemyNear(1),Pos X - Pos X = [0,100]))
Trigger3 = EnemyNear(1),BackEdgeBodyDist >= 40
Trigger3 = EnemyNear(1),Facing = Facing

这里提一下,enemynear,或者你用enemynear(var())这种的,只能指定近敌的动作,而不能代表2位敌人,所以判断2位敌人要用到enemynear(0)和enemynear(1),0代表近的那位,1代表远的那位

除了这些外,双打的想法还有很多的,比如创造人工墙角,可以配合相应的队友做出相应的反应,比如你知道你指定的队友哪个动作做出来了,比如知道是可以追打的P2StateNo,而且两位敌人同时被打,赶紧大跳或者闪避到对手后面去用2A点对面,总之好墙角自己造嘛蛤蛤蛤

好了,今天的课就先到这,如果您有什么问题的话可以私信我,我会第一时间给您答复,或者把问题发到我的邮箱

mizore@kotori.moe, 谢谢大家!
2016.05.2810:50

MUGEN活动暂停

人物更新,AI发布先暂停一段时间(大概两个月左右),如果有想来找我学AI或者做人物和修人物的可以私戳我邮箱:mizore@kotori.moe,或者在下面留言,本人不定期上线,人物地址在这里https://onedrive.live.com/?id=187327E866F1B095%21394&cid=187327E866F1B095

PS:我这里写的大多数AI帖子是可以直接用的,最多改个数字就好了,剩下来要怎么用就是自己的问题了

再次感谢大家支持!
2016.05.2809:00

AI 记录硬直时间进行压制和确反

Episode 8 记录硬直时间进行压制和确反

首先看到一招的hitdef,来看看他的ground.hittime,guard.hittime,还有pausetime和guard.pausetime

我先举个例子

[State 200, ヒット定義]
type = HitDef
trigger1 = time = 0
attr = S, NA
damage = 23, 0
animtype = Light
guardflag = MA
hitflag = MAF
priority = 3, Hit
pausetime = 9, 10
sparkno = s4050
guard.sparkno = s4100
sparkxy = -20, -80
hitsound = s1,0
guardsound = s2,0
ground.type = High
ground.slidetime = 8
ground.hittime = 10
ground.velocity = -4.5,0
air.animtype = Back
air.velocity = -4.5,-4
airguard.velocity = -5.5,-2.5
air.hittime = 0
getpower = 35,35
givepower = 16,16

可以看到hittime(包括guard.hittime)是10,pausetime(这里包括guard.pausetime)是9,10

什么意思呢?就是说这一招打中了会给对手造成10帧的被打时间还有10帧的暂停时间,同时还会给自己造成9帧的暂停时间

也就是说,给自己一个11帧的有利时间,我们要这个有什么用呢?

花费两个var记下来hittime和hittime+真实造成的pausetime

比如你可以这么写

[State -3, AI与硬直時間カウント]
type = VarSet
Trigger1 = MoveContact = 1
var(47) = 11+1;(因为是movecontact = 1的时候计算的,所以要多加1帧,这个记录在当前statedef下,后面的statedef也是如此)

这里记录在-3下

;-----------------------------------------------------------------------
; ヒット硬直カウント
;-----------------------------------------------------------------------
[State -3, VarSet]
Type = VarSet
Trigger1 = var(49) != 0
V = 49
Value = 0
IgnoreHitPause = 1

[State -3, ヒット硬直時間]
Type = VarSet
TriggerAll = EnemyNear(var(58)),Ctrl = 0
TriggerAll = EnemyNear(var(58)),StateType != A
TriggerAll = EnemyNear(var(58)),StateType != L
TriggerAll = EnemyNear(var(58)),MoveType = H
Trigger1 = EnemyNear(var(58)),StateNo = [120,160)
Trigger2 = EnemyNear(var(58)),StateNo = [5000,5100)
V = 49
Value = EnemyNear(var(58)),GetHitVar(hittime) + 1 ;这里也是一样的道理
IgnoreHitPause = 1

然后取得了这个var的值有什么用呢?

接下来就可以做到比如一些空中特殊技命中来精准压制的玩意

比如空中特殊技-跑-技能 这样的压制或者确认动作

举个例子,statedef 100(跑步状态号)是4帧以后才开始出现速度,那么你可以这么写

;ダッシュ
[State -3, RUN]
Type = ChangeState
Value = 100
TriggerAll = var(59) = 1
TriggerAll = var(49) > 4 || var(47) > 4 ;确认对面有4帧以上的硬直出跑
TriggerAll = RoundState = 2
TriggerAll = StateNo != 100 ;不能是跑步动作时候出跑
TriggerAll = StateType != A
TriggerAll = EnemyNear(var(58)),StateType != A
TriggerAll = EnemyNear(var(58)),StateType != L
TriggerAll = EnemyNear(var(58)),MoveType = H
TriggerAll = Abs(EnemyNear(var(58)),Pos X - Pos X) <= 110 ;大概多少距离自己算,跑步内部AI里面要保证对面在被打(防御和真被打)情况下一直跑而不停
TriggerAll =!InGuardDist
Trigger1 = Ctrl || (StateNo = [20,22]) || (StateNo = [120,149])

然后跑过去了,可以根据硬直时间出不同的技能,比如5C是3帧的可以这么写

[State -3, Stand Strong Punch]
Type = ChangeState
Value = (5C状态号)
TriggerAll = var(59) = 1
TriggerAll = var(47) > 2 || var(49) > 2 ;时间是大于起手时间,也就是>= 3
TriggerAll = RoundState = 2
TriggerAll = StateType != A
TriggerAll = EnemyNear(var(58)),StateType != A
TriggerAll = EnemyNear(var(58)),StateType != L
TriggerAll = EnemyNear(var(58)),MoveType = H
TriggerAll =!InGuardDist || EnemyNear(var(58)),Facing = Facing
TriggerAll = P2BodyDist X = [-10,ifelse(var(47) = 3 || var(49) = 3),30,0)] ;在硬直时间足够的情况下和对手贴脸了再出,如果刚好是最后一帧了就用可以出这招的最大距离出,比如5C最大距离是30,那么就用ifelse写30
Trigger1 = Ctrl || (StateNo = [20,22]) || (StateNo = [100,101]) || (StateNo = [120,149])

还有一些其他中段,上段,下段就不一一描述了,在硬直够的情况下可以连续小跳压制,尽量使用下段技或者中段技来干扰对面防御,最快的技能留着保险比较小的硬直时间

好了,今天的课就先到这,如果您有什么问题的话可以私信我(只要是我会的,不管什么问题),我会第一时间给您答复,或者把问题发到我的邮箱

mizore@kotori.moe, 谢谢大家!
2016.04.2415:24

AI HELPER-4 重力加速度计算(加强版)

Episode 4 重力加速度计算(加强版)

找到一个比较空闲的Helper,确定这个helper是常时存在的,并且至少有3个fvar可以使用

加入下面的代码(加在helper里面),如果变量有冲突那就换,下面的也一样

;-----------------------------------------------------------------------
;重力加速度 常時読み取り
;-----------------------------------------------------------------------
[State -3, 重力加速度]
Type = Null
Trigger1 = fvar(3):= 0 || 1
Trigger1 = fvar(3):=(((EnemyNear(Root,var(58)),Anim != [5051,5059])&&(EnemyNear(Root,var(58)),Anim != [5061,5069]))&&(EnemyNear(Root,var(58)),StateNo = 5050))*25 || 1 ;这个参考Statedef 5050里面的数据(被打下落,hitfall)
Trigger1 = fvar(0):= Ceil((EnemyNear(Root,var(58)),Pos Y - fvar(2) - fvar(1))*1000.0)*(EnemyNear(Root,var(58)),Pos Y < fvar(3))/1000.0 || 1 ;fvar(0)为第一次pos y记录,fvar(1)为第二次,fvar(2)为第三次
Trigger1 = fvar(1):= EnemyNear(Root,var(58)),Pos Y - fvar(2) || 1
Trigger1 = fvar(2):= EnemyNear(Root,var(58)),Pos Y || 1
ignorehitpause = 1

原理的话是这样,因为敌方pos y为变化值,fvar(0)先记下来第一次pos y,fvar(1)记下来第二次,fvar(2)记下来第三次

第一次的值减去第三次的值在减去第二次和第三次这两次的变化的值即为最终答案

下面给出用法,这个写在Statedef -2里面

;-----------------------------------------------------------------------------
; AI用重力加速度計測
;-----------------------------------------------------------------------------
[State -2, yaccel]
Type = VarSet
TriggerAll = NumHelper(AAA) ;AAA为helper的ID
TriggerAll = EnemyNear(var(58)),Vel Y != 0
TriggerAll = EnemyNear(var(58)),Pos Y < (((EnemyNear(var(58)),Anim != [5051,5059]) && (EnemyNear(var(58)),Anim != [5061,5069])) && (EnemyNear(var(58)),StateNo = 5050))*25 ;参考Statedef 5050
TriggerAll = fvar(20) != Helper(AAA),fvar(0)
Trigger1 = EnemyNear(var(58)),StateNo != [5000,5210]
Trigger2 = EnemyNear(var(58)),MoveType != H
FV = 20
Value = Helper(AAA),fvar(0);(通常時のyaccel値) ;通常的yaccel由helper内计算值取代
IgnoreHitPause = 1

[State -2, yaccel]
Type = VarSet
TriggerAll = EnemyNear(var(58)),Vel Y != 0
TriggerAll = EnemyNear(var(58)),MoveType = H
TriggerAll = EnemyNear(var(58)),Pos Y < (((EnemyNear(var(58)),Anim != [5051,5059]) && (EnemyNear(var(58)),Anim != [5061,5069])) && (EnemyNear(var(58)),StateNo = 5050))*25 ;参考Statedef 5050
TriggerAll = fvar(20) != EnemyNear(var(58)),GetHitVar(yaccel)
Trigger1 = EnemyNear(var(58)),StateNo = [5000,5210]
FV = 20
Value = EnemyNear(var(58)),GetHitVar(yaccel);(打撃当てた時のyaccel値) ;敌方被打的yaccel
IgnoreHitPause = 1

;敵が空中じゃない時
[State -2, yaccel]
Type = VarSet
Trigger1 = fvar(20) != 0 && EnemyNear(var(58)),Vel Y = 0
FV = 20
Value = 0;(打撃当てた時のyaccel値)
IgnoreHitPause = 1

然后用DisplayToClipBoard查看fvar(20)的变化即可,大家不妨去试试看,然后理解下

好了,今天的课就先到这,如果您有什么问题的话可以私信我,我会第一时间给您答复,或者把问题发到我的邮箱

mizore@kotori.moe, 谢谢大家!
2016.03.3123:08

AI 辅助器 记录对手滞空时间

Episode 7 记录对手滞空时间

今天的内容可能会略复杂,嗯,所以没看懂的也不太要紧,会用就行了

于是,不谈其他的闲话了,直接进入正题,需要用到的有yaccel计算器,TAG计算器,这两个前面都有讲过这里就不谈了

那么给出辅助器,(不知道的看前面,fvar(20)是记录yaccel的变量,var(58)为TAG变量)

;--------------------------------------------------------------------
; 相手の滞空時間、超絶やっつけ 对手滞空时间
;--------------------------------------------------------------------
[State -3, VarSet]
Type = VarSet
Trigger1 = 1
fvar(1) = 0
IgnoreHitPause = 1 ;还原

[State -3, VarSet]
Type = VarSet
Trigger1 = EnemyNear(var(58)),StateType = A && fvar(20) != 0
Trigger1 = ((floor(EnemyNear(var(58)),Vel Y))**2-2*(fvar(20))*(floor(EnemyNear(var(58)),Pos Y))) >= 0
fvar(1) = floor(((-EnemyNear(var(58)),Vel Y)+(((floor(EnemyNear(var(58)),Vel Y))**2-2*(fvar(20))*(floor(EnemyNear(var(58)),Pos Y)))**0.5))/(fvar(20)))+1
IgnoreHitPause = 1 ;记录

条件略复杂,我们假设一下元,计算的时候把floor忽略

令EnemyNear(var(58)),Vel Y = v, fvar(20) = a, EnemyNear(var(58)),Pos Y = h

trigger1等价代换一下,v**2(y方向v的平方) - 2ah >= 0,也就是v**2 >= 2ah

我们知道,h = 1/2*a*t**2 ,v = at 两式子合并,消去t,得到 v**2 = 2ah,而v**2 = 2ah只是临界条件,v**2 - 2ah >= 0就是说在临界条件之上,这是第一个公式的来源

我们要得到的数据是时间,令fvar(1) = t,那么把公式代换一下,同样的,忽略掉floor,((xxx**0.5)代表对xxx开平方)

((-v)+(v**2-2ah)**0.5)/a + 1 = t, (t-1)*a = -v+(v**2-2ah)**0.5, 令(t-1) = T

aT+v = (v**2-2ah)**0.5, v**2 + 2avT + (a**2)*(T**2) = v**2 - 2ah

舍去两边v**2,舍掉一个a, 2vT + 2ah + aT**2 = 0,这是最终结果

证明结论,令h = 0,也就是说对手在地面被击飞,刚刚pausetime结束的时候,此时pos y = 0

2vT = -aT**2, 2v = -a*T , v = -(1/2)*a*T = -(1/2)*a*(t+1),+1为起始值

那么来图证明一下结论吧,这招的打击速度为 -2,-10,yacce = 0.5
LR~(S)8FQ5P4FAD[)4_$IUX

可以看到下面的打击时间,因为是1起始,所以是40+1 = 41,所以刚才的公式成立
GPDVR802S`JG2VTYET2{2T3

对手在此过程中,如果不受外力,那么对手做匀加速曲线运动,a一定,y方向v随着T变化,x方向的v不变,那么对手做的是抛物线运动,可以看到下图,对手的滞空时间在减少A3EET3X9`{1_NC~HI9SW{P

好的,对手现在着地了,我们也能看到fvar(1)的值变为0了,说明对手不再浮空
_7(H$V~(9Q[68ICA}2NR927

此变量因为有floor的限制,所以会有一定的小误差,但不会超过4,那么,记录对手这个数据有什么用呢?这个变量,在对手Pausetime未消失的时候,虽然有ignorehitpause,但对手没有vel和yaccel,那么我们只能记录下对手pausetime以外的滞空时间

这个变量,给弹幕起手的角色比较好用,能计算对手滞空还有多少时间,来确认进行接下来的连招,如果是比较朴素的角色,还是建议不要用这个了,还省了你一个变量,但是给弹幕起手角色的再合适不过了,当然,如果有援护招式的话,也是很合适的,来判断对手还剩下多少滞空时间进行出招判断

好了,今天的课就先到这,如果您有什么问题的话可以私信我(只要是我会的,不管什么问题),我会第一时间给您答复,或者把问题发到我的邮箱

mizore@kotori.moe, 谢谢大家!

アクセス

オンライン