Xangle/Yangle 04 - エフェクトを組み合わせよう
ここでは立方体を組み立ててみようと思います
こんな感じ。
基本的な考え方としましては、
①"基準Explod"(一個)を記述したステート。time = 0で②へ
↓
②"基準Explod"と一定の角度を保ち、また一定の位置関係を持つ"付属Explod"(複数個)を記述したステート。付属Explodの数だけこのステートをtime = 0でループさせる。ループ後、time = 0で③へ
↓
③何もしないステート。1F経過で①に戻る
これをひたすら繰り返します。立方体を動かしたい場合は①で動作を記述すれば、付属Explodは勝手についてくるわけです
②でループさせる理由は、付属Explodを一つ一つ記述していると変数がいくつあっても足りないからです
では詳しく記述していきます。
;helperを出します
[Statedef 310]
type = S
movetype= A
physics = S
ctrl = 0
anim = 1000;上の画像のKFMのアニメ
[State -2,Helper]
type = Helper
trigger1 = Animelem = 6
trigger1 = numhelper(310) = 0
ID = 310
stateno = 311
postype = P1
pos = 60,-60
OwnPal = 1
[State 821, 4]
type = ChangeState
trigger1 = Animtime = 0
value = 0
ctrl = 1
;このhelperのステートが以下
;まず基準Explodを記述します
[Statedef 311];基準Explod
type = S
movetype= A
physics = N
ctrl = 0
velset = 2.5,0
anim = 8999;透明アニメ
[State -2,Explod];宣言
type = Explod
trigger1 = time = 0
trigger1 = numexplod(311) = 0
anim = 8999;透明アニメ。今回基準Explodは透明です。立方体の中心になります
ID = 311
pos = 0, 0
postype = p1
bindtime = -1
removetime = -1
scale = 1.5, 1.5
vel = 0,0
sprpriority = 10
shadow = 0, 0, 0
ownpal = 1
;----------
;初期値設定
;回転角度は変数に保存します。後々この変数を利用して付属Explodを記述します
;ついでに歪みを消す記述をしています。青文字部分
;→[Xangle/Yangle 01]簡単なエフェクトを作ろう
[State 821, 4]
type = Null
triggerall = time = 0
trigger1 = 1 || fvar(0) := 2*var(0) - atan(((120 - ScreenPos Y + Pos Y)*(ScreenHeight/GameHeight))/500)*180/pi
trigger1 = 1 || fvar(1) := 2*var(0)*2
trigger1 = 1 || var(1) := 2*var(0)
trigger1 = 1 || fvar(24) := fvar(0); こちらは歪み処理
trigger1 = 1 || fvar(25) := fvar(1); を行わない分です。
trigger1 = 1 || var(4) := var(1); あとで使います
fvar(0):Xangle
fvar(1):Yangle
var(1) :angle
です。var(0)はループ数。1F毎にループするので時間を表しています。
2*var(0)とか2*var(0)*2はただぐちゃぐちゃ回転させたかったからこんな記述しているだけです
fvar(24):Xangle
fvar(25):Yangle
var(4) :angle
になりますね。これらの変数はすぐ下の処理を受けません
;----------
;YXYオイラー角に変換
;Y1変換
[State -2, var];式が長くなるので分割
type = varset
trigger1 = time = 0
fvar(4) = ((-sin(fvar(0)*(pi/180))*cos(var(1)*(pi/180)) + cos(fvar(0)*(pi/180))*sin(fvar(1)*(pi/180))*sin(var(1)*(pi/180)))**2 + (cos(fvar(1)*(pi/180))*sin(var(1)*(pi/180)))**2)**.5
[State -2, var];計算
type = varset
trigger1 = time = 0
fvar(5) = -2*atan((cos(fvar(1)*(pi/180))*sin(var(1)*(pi/180)))/(fvar(4) - sin(fvar(0)*(pi/180))*cos(var(1)*(pi/180)) + cos(fvar(0)*(pi/180))*sin(fvar(1)*(pi/180))*sin(var(1)*(pi/180))))*(180/pi)
;X2変換
[State -2, var];計算
type = varset
trigger1 = time = 0
fvar(6) = -acos(cos(fvar(0)*(pi/180))*cos(var(1)*(pi/180)) + sin(fvar(0)*(pi/180))*sin(fvar(1)*(pi/180))*sin(var(1)*(pi/180)))*(180/pi)
;Y3変換
[State -2, var];式が長くなるので分割
type = varset
trigger1 = time = 0
fvar(7) = ((sin(fvar(0)*(pi/180))*cos(fvar(1)*(pi/180)))**2 + (-cos(fvar(0)*(pi/180))*sin(var(1)*(pi/180)) + sin(fvar(0)*(pi/180))*sin(fvar(1)*(pi/180))*cos(var(1)*(pi/180)))**2)**.5
[State -2, var];計算
type = varset
trigger1 = time = 0
fvar(8) = 2*atan((-cos(fvar(0)*(pi/180))*sin(var(1)*(pi/180)) + sin(fvar(0)*(pi/180))*sin(fvar(1)*(pi/180))*cos(var(1)*(pi/180)))/( fvar(7) + sin(fvar(0)*(pi/180))*cos(fvar(1)*(pi/180))))*(180/pi) + 180
[State -2, var]
type = varadd
trigger1 = time = 0
fvar(5) = -facing*atan((Pos X*(ScreenWidth/GameWidth))/500)*(180/pi)
;----------
;XYZオイラー角に変換
;Xangle(X1)変換
[State -2, var];式が長くなるので分割
type = varset
trigger1 = time = 0
fvar(9) = ((cos(fvar(5)*(pi/180))*cos(fvar(6)*(pi/180))*cos(fvar(8)*(pi/180)) - sin(fvar(5)*(pi/180))*sin(fvar(8)*(pi/180)))**2 + (sin(fvar(6)*(pi/180))*cos(fvar(8)*(pi/180)))**2)**.5
[State -2, var];計算
type = varset
trigger1 = time = 0
fvar(0) = 2*atan((sin(fvar(6)*(pi/180))*cos(fvar(8)*(pi/180)))/( fvar(9) + (cos(fvar(5)*(pi/180))*cos(fvar(6)*(pi/180))*cos(fvar(8)*(pi/180)) - sin(fvar(5)*(pi/180))*sin(fvar(8)*(pi/180)))))*(180/pi)
;Yangle(Y2)変換
[State -2, var];計算
type = varset
trigger1 = time = 0
fvar(1) = -asin(-cos(fvar(5)*(pi/180))*sin(fvar(8)*(pi/180)) - sin(fvar(5)*(pi/180))*cos(fvar(6)*(pi/180))*cos(fvar(8)*(pi/180)))*(180/pi)
;angle(Z3)変換
[State -2, var];式が長くなるので分割
type = varset
trigger1 = time = 0
fvar(10) = ((sin(fvar(5)*(pi/180))*sin(fvar(6)*(pi/180)))**2 + (cos(fvar(5)*(pi/180))*cos(fvar(8)*(pi/180)) - sin(fvar(5)*(pi/180))*cos(fvar(6)*(pi/180))*sin(fvar(8)*(pi/180)))**2)**.5
[State -2, var];計算
type = varset
trigger1 = time = 0
var(1) = ceil(2*atan((sin(fvar(5)*(pi/180))*sin(fvar(6)*(pi/180)))/( fvar(10) + cos(fvar(5)*(pi/180))*cos(fvar(8)*(pi/180)) - sin(fvar(5)*(pi/180))*cos(fvar(6)*(pi/180))*sin(fvar(8)*(pi/180))))*(180/pi) - 0.4)
;ここまで
;----------
;最終的な基準Explodの回転角度を記述します
[State -2,Explod]
type = ModifyExplod
trigger1 = numexplod(311) = 1
ID = 311
xangle = fvar(0)
yangle = fvar(1)
angle = var(1)
[State 821, 4]
type = ChangeState
trigger1 = time = 0
value = 312
;time = 0でステート移動。付属Explodを記述していきます。ここからが本番
[Statedef 312];付属Explod
type = S
movetype= A
physics = N
ctrl = 0
velset = 2.5,0
anim = 8999;透明アニメ
[State -2,Explod];宣言
type = Explod
trigger1 = time = 0
trigger1 = numexplod(312+var(3)) = 0;var(3)はこのステートのループ回数
anim = 8001;立方体1面分のアニメ
ID = 312+var(3);var(3)はこのステートのループ回数
pos = 0, 0
postype = p1
bindtime = -1
removetime = -1
scale = 1.5, 1.5
vel = 0,0
sprpriority = 10
shadow = 0, 0, 0
ownpal = 1
;----------
;入力(基準のxangle,yangle,angle値を保存)
;基準Explodの回転角度を変数に保存します。これを弄って付属Explodを作っていきます
[State 821, 4];xangle
type = VarSet
trigger1 = time = 0
fvar(11) = fvar(0)
[State 821, 4];yangle
type = VarSet
trigger1 = time = 0
fvar(12) = fvar(1)
[State 821, 4];angle
type = VarSet
trigger1 = time = 0
var(2) = var(1)
;----------一旦読み飛ばしてください。あとで説明します。
;YXYオイラー角に変換前にずらす
[State -2, var]
type = varset
trigger1 = var(3) = 4
var(2) = var(2) + 90
[State -2, var]
type = varset
trigger1 = var(3) = 5
var(2) = var(2) + 90
;----------
;YXYオイラー角に変換
;Y1変換
[State -2, var];式が長くなるので分割
type = varset
trigger1 = time = 0
fvar(13) = ((-sin(fvar(11)*(pi/180))*cos(var(2)*(pi/180)) + cos(fvar(11)*(pi/180))*sin(fvar(12)*(pi/180))*sin(var(2)*(pi/180)))**2 + (cos(fvar(12)*(pi/180))*sin(var(2)*(pi/180)))**2)**.5
[State -2, var];計算
type = varset
trigger1 = time = 0
fvar(14) = -2*atan((cos(fvar(12)*(pi/180))*sin(var(2)*(pi/180)))/( fvar(13) - sin(fvar(11)*(pi/180))*cos(var(2)*(pi/180)) + cos(fvar(11)*(pi/180))*sin(fvar(12)*(pi/180))*sin(var(2)*(pi/180))))*(180/pi)
;X2変換
[State -2, var];計算
type = varset
trigger1 = time = 0
fvar(15) = -acos(cos(fvar(11)*(pi/180))*cos(var(2)*(pi/180)) + sin(fvar(11)*(pi/180))*sin(fvar(12)*(pi/180))*sin(var(2)*(pi/180)))*(180/pi)
;Y3変換
[State -2, var];式が長くなるので分割
type = varset
trigger1 = time = 0
fvar(16) = ((sin(fvar(11)*(pi/180))*cos(fvar(12)*(pi/180)))**2 + (-cos(fvar(11)*(pi/180))*sin(var(2)*(pi/180)) + sin(fvar(11)*(pi/180))*sin(fvar(12)*(pi/180))*cos(var(2)*(pi/180)))**2)**.5
[State -2, var];計算
type = varset
trigger1 = time = 0
fvar(17) = 2*atan((-cos(fvar(11)*(pi/180))*sin(var(2)*(pi/180)) + sin(fvar(11)*(pi/180))*sin(fvar(12)*(pi/180))*cos(var(2)*(pi/180)))/( fvar(16) + sin(fvar(11)*(pi/180))*cos(fvar(12)*(pi/180))))*(180/pi) + 180
;----------一旦読み飛ばしてください。あとで説明します。
;XYZオイラー角に変換前にずらす
[State -2, var]
type = varset
trigger1 = var(3) = 0
fvar(17) = fvar(17) + 90
[State -2, var]
type = varset
trigger1 = var(3) = 1
fvar(17) = fvar(17) + 90
[State -2, var]
type = varset
trigger1 = var(3) = 4
fvar(17) = fvar(17) + 90
[State -2, var]
type = varset
trigger1 = var(3) = 5
fvar(17) = fvar(17) + 90
;----------
;XYZオイラー角に変換
;Xangle(X1)変換
[State -2, var];式が長くなるので分割
type = varset
trigger1 = time = 0
fvar(18) = ((cos(fvar(14)*(pi/180))*cos(fvar(15)*(pi/180))*cos(fvar(17)*(pi/180)) - sin(fvar(14)*(pi/180))*sin(fvar(17)*(pi/180)))**2 + (sin(fvar(15)*(pi/180))*cos(fvar(17)*(pi/180)))**2)**.5
[State -2, var];計算
type = varset
trigger1 = time = 0
fvar(11) = 2*atan((sin(fvar(15)*(pi/180))*cos(fvar(17)*(pi/180)))/( fvar(18) + (cos(fvar(14)*(pi/180))*cos(fvar(15)*(pi/180))*cos(fvar(17)*(pi/180)) - sin(fvar(14)*(pi/180))*sin(fvar(17)*(pi/180)))))*(180/pi)
;Yangle(Y2)変換
[State -2, var];計算
type = varset
trigger1 = time = 0
fvar(12) = -asin(-cos(fvar(14)*(pi/180))*sin(fvar(17)*(pi/180)) - sin(fvar(14)*(pi/180))*cos(fvar(15)*(pi/180))*cos(fvar(17)*(pi/180)))*(180/pi)
;angle(Z3)変換
[State -2, var];式が長くなるので分割
type = varset
trigger1 = time = 0
fvar(19) = ((sin(fvar(14)*(pi/180))*sin(fvar(15)*(pi/180)))**2 + (cos(fvar(14)*(pi/180))*cos(fvar(17)*(pi/180)) - sin(fvar(14)*(pi/180))*cos(fvar(15)*(pi/180))*sin(fvar(17)*(pi/180)))**2)**.5
[State -2, var];計算
type = varset
trigger1 = time = 0
var(2) = ceil(2*atan((sin(fvar(14)*(pi/180))*sin(fvar(15)*(pi/180)))/( fvar(19) + cos(fvar(14)*(pi/180))*cos(fvar(17)*(pi/180)) - sin(fvar(14)*(pi/180))*cos(fvar(15)*(pi/180))*sin(fvar(17)*(pi/180))))*(180/pi) - 0.4)
;----------一旦読み飛ばしてください。あとで説明します。
;位置関係の設定
[State -2, var];x
type = varset
trigger1 = var(3) = 0
fvar(20) = 15*(cos(fvar(25)*(pi/180))*cos(var(4)*(pi/180)))
[State -2, var];y
type = varset
trigger1 = var(3) = 0
fvar(21) = 15*(sin(fvar(24)*(pi/180))*sin(fvar(25)*(pi/180))*cos(var(4)*(pi/180)) - cos(fvar(24)*(pi/180))*sin(var(4)*(pi/180)))
[State -2, var];z
type = varset
trigger1 = var(3) = 0
fvar(22) = 15*(cos(fvar(24)*(pi/180))*sin(fvar(25)*(pi/180))*cos(var(4)*(pi/180)) + sin(fvar(24)*(pi/180))*sin(var(4)*(pi/180)))
[State -2, var];x
type = varset
trigger1 = var(3) = 1
fvar(20) = -15*(cos(fvar(25)*(pi/180))*cos(var(4)*(pi/180)))
[State -2, var];y
type = varset
trigger1 = var(3) = 1
fvar(21) = -15*(sin(fvar(24)*(pi/180))*sin(fvar(25)*(pi/180))*cos(var(4)*(pi/180)) - cos(fvar(24)*(pi/180))*sin(var(4)*(pi/180)))
[State -2, var];z
type = varset
trigger1 = var(3) = 1
fvar(22) = -15*(cos(fvar(24)*(pi/180))*sin(fvar(25)*(pi/180))*cos(var(4)*(pi/180)) + sin(fvar(24)*(pi/180))*sin(var(4)*(pi/180)))
[State -2, var];x
type = varset
trigger1 = var(3) = 2
fvar(20) = 15*(-sin(fvar(25)*(pi/180)))
[State -2, var];y
type = varset
trigger1 = var(3) = 2
fvar(21) = 15*(sin(fvar(24)*(pi/180))*cos(fvar(25)*(pi/180)))
[State -2, var];z
type = varset
trigger1 = var(3) = 2
fvar(22) = 15*(cos(fvar(24)*(pi/180))*cos(fvar(25)*(pi/180)))
[State -2, var];x
type = varset
trigger1 = var(3) = 3
fvar(20) = -15*(-sin(fvar(25)*(pi/180)))
[State -2, var];y
type = varset
trigger1 = var(3) = 3
fvar(21) = -15*(sin(fvar(24)*(pi/180))*cos(fvar(25)*(pi/180)))
[State -2, var];z
type = varset
trigger1 = var(3) = 3
fvar(22) = -15*(cos(fvar(24)*(pi/180))*cos(fvar(25)*(pi/180)))
[State -2, var];x
type = varset
trigger1 = var(3) = 4
fvar(20) = 15*(cos(fvar(25)*(pi/180))*sin(var(4)*(pi/180)))
[State -2, var];y
type = varset
trigger1 = var(3) = 4
fvar(21) = 15*(sin(fvar(24)*(pi/180))*sin(fvar(25)*(pi/180))*sin(var(4)*(pi/180)) + cos(fvar(24)*(pi/180))*cos(var(4)*(pi/180)))
[State -2, var];z
type = varset
trigger1 = var(3) = 4
fvar(22) = 15*(cos(fvar(24)*(pi/180))*sin(fvar(25)*(pi/180))*sin(var(4)*(pi/180)) - sin(fvar(24)*(pi/180))*cos(var(4)*(pi/180)))
[State -2, var];x
type = varset
trigger1 = var(3) = 5
fvar(20) = -15*(cos(fvar(25)*(pi/180))*sin(var(4)*(pi/180)))
[State -2, var];y
type = varset
trigger1 = var(3) = 5
fvar(21) = -15*(sin(fvar(24)*(pi/180))*sin(fvar(25)*(pi/180))*sin(var(4)*(pi/180)) + cos(fvar(24)*(pi/180))*cos(var(4)*(pi/180)))
[State -2, var];z
type = varset
trigger1 = var(3) = 5
fvar(22) = -15*(cos(fvar(24)*(pi/180))*sin(fvar(25)*(pi/180))*sin(var(4)*(pi/180)) - sin(fvar(24)*(pi/180))*cos(var(4)*(pi/180)))
;----------
;最終的な付属Explodの記述です
;水色は後で説明します
[State -2,Explod]
type = ModifyExplod
trigger1 = numexplod(312) >= 1
ID = 312+var(3);var(3)はこのステートのループ回数
postype = P1
pos = (500*fvar(20))/(500 + fvar(22)),(500*fvar(21))/(500 + fvar(22))
scale = 1.5*(500/(500+fvar(22))), 1.5*(500/(500+fvar(22)))
sprpriority = ceil(-fvar(22)-0.4)
xangle = fvar(11)
yangle = fvar(12)
angle = var(2)
[State -2, varadd];var(3)はこのステートのループ回数
type = varadd
trigger1 = time = 0
var(3) = 1
[State 1,changestate];付属Explodの数(ここでは6個)だけループします
type = ChangeState
trigger1 = time = 0
trigger1 = var(3) != 6;ループ回数(基準以外の数)
value = stateno
[State 1,changestate];処理終了後終了ステート
type = ChangeState
trigger1 = time = 0
trigger1 = var(3) = 6;ループ回数(基準以外の数)
trigger1 = 1 || var(3) := 0;0にリセットします
value = 313
;time = 0で1F経過ステートへ
[Statedef 313];1F待機
type = S
movetype= A
physics = S
ctrl = 0
anim = 8999;透明アニメ
[State -2, varadd];var(0)はこの記述全般のループ回数
type = varadd
trigger1 = time = 0
var(0) = 1
[State 821, 4]
type = DestroySelf
trigger1 = var(0) = 180;180Fで消えます
RemoveExplods = 1;Explodもすべて消します
[State 821, 4];この記述全般のループ記述
type = ChangeState
trigger1 = time = 1
value = 311
ある付属Explodはvar(3)が0の時の[state 312]、またある付属Explodはvar(3)が1の時の[state 312]に記述されます。つまりtrigger1 = var(3) = ???で一つ一つの付属Explodを個別に記述できます
さて、付属Explodの記述をまとめると。。。
1.基準Explodの角度を変数に入力
↓A
2.YXYオイラー角に変換
↓B
3.XYZオイラー角に変換
↓C
4.ModifyExplodで出力
一.基準よりもねじりたい場合(立法体を作る場合は2面必要)
BにおいてY3角(YXYオイラー角)を変更する
二.基準よりも前方を持ち上げたい場合(立法体を作る場合は2面必要)
三.基準よりも左右に回したい場合(立法体を作る場合はいらない)
CにおいてZ3角(XYZオイラー角)を変更する
これで基準Explodと一定の角度を保たせることができました(上の水色参考)
最後に基準との一定の位置関係を持たせます
基準Explodがグルグル回転しているとき、付属ExplodのX,Y座標はどう変化するのでしょうか。答えは割と簡単です
最初の状態(回転角度全て0)での基準Explodとの位置関係を考えましょう。1辺の長さを2Lとすれば、その半分はLですから、
基準からX座標+Lしたもの、-Lしたもの、Y座標+Lしたもの、-Lしたもの、Z座標+Lしたもの、-Lしたもの
の6面で立方体が構成されます。(基準Explodは立方体の中心です)
(
xcosβcosγ + ycosβsinγ - zsinβ
,
x(sinαsinβcosγ - cosαsinγ) + y(sinαsinβsinγ + cosαcosγ) + zsinαcosβ
,
x(cosαsinβcosγ + sinαsinγ) + y(cosαsinβsinγ - sinαcosγ) + zcosαcosβ
)
という位置ベクトルだけ基準Explodからズれているわけです。立方体を作りたいのなら、(x,y,z) = (L,0,0)を代入したもの、(-L,0,0)を代入したもの、(0,L,0)、(0,-L,0)、(0,0,L)、(0,0,-L)を代入したものの計6個が必要ですね
ただし、この計算は歪みを考慮する必要がありません。MUGEN上で画面端に移動させたとき、角度は歪んでも位置は歪まないからです。よってこの計算に使う変数は歪み処理を行っていないものです。上の例ではfvar(24),(25),var(4)になります。
この数値をModifyExplodのpos = に入れたらOKってなれば良かったんですけど、Z座標はModifyExplodでは直接指定できません。そこでscale = でZ座標分小さくします。MUGENではカメラからスクリーンまでの距離(焦点距離)は500です。基準ExplodのZ座標はスクリーンと同じ位置なので500ですから、付属ExplodのZ座標は(500+上の位置ベクトルのZ成分)となります。スクリーン上でscale = 1なら、
scale =
(500/(500+上の位置ベクトルのZ成分)) ,
(500/(500+上の位置ベクトルのZ成分))
とこう記述すればいいわけです。また、奥に行けば行くほど遠近法によってX,Y座標も変化しにくくなります。よって、
pos =
(500*上の位置ベクトルのX成分)/(500 + 上の位置ベクトルのZ成分) ,
(500*上の位置ベクトルのY成分)/(500 + 上の位置ベクトルのZ成分)
こう記述すればいいわけです
以上で上の水色部分も理解できると思います。多分
この記述を搭載したキャラクターを公開しています(XYangle_SankouYou_kfm.zip)
DLはブログ右側の”トップ”から。