コンテンツへスキップ

STG その4

キャラの移動について。

モーションってのは要するに時間の関数なわけで。現在の時間を与えるとその位置を返す。そう考えると、そういう関数を返すファクトリ関数をいっぱい用意して組み合わせてやればモーションは完成するはず。

[cc lang=”python”]
#stからetの間で時間を正規化
def timeL(st, et):
_st = st
_dt = float(et – st)
def _timeL(t):
t -= _st
val = t / _dt
if val < 0.0: return 0.0 elif val > 1.0:
return 1.0
else:
return val
return _timeL

#spからepまで直線移動
def posL(sp, ep, tfnc):
_d = ep – sp
_sp = sp
_tfnc = tfnc
def _posL(t):
return _sp + _d * _tfnc(t)
return _posL

#モーション関数
pf = posL(v(0,0,0), v(100,100,0), timeL(10, 30))
obj.pos = pf(t)
[/cc]

あとは時間を変形したりベジェやら円で動かしたりあれこれしてやる感じ。

でまあ、ぶっちゃけこれでもいいんですが、いささかお上品すぎてやりづらい。まずフレーム固定なので時間の関数って形は気にする必要がない。要するに次々と現在の座標を返す仕組みだけがあればいいので、ジェネレータを使ってもいいよね。

[cc lang=”python”]
def timeL(st, et):
dt = et – st
return chain(repeat(0.0, st), (t / float(dt) for t in xrange(dt)), repeat(1.0, et))

def posL(sp, ep, tbl):
ep -= sp
return (sp + ep * t for t in tbl)

pg = posLiner(v(0,0,0), v(100,100,0), timeTbl(10, 30))
obj.pos = pg.next()
[/cc]

これだけ見てるとあんまり変わらないし、速度的にも変わらないっぽいんだけど、どっちが楽だろうね。pythonは関数の呼び出しがちょー遅いので、上のクロージャーばりばりな方だと複雑になると辛いかも知れない。ジェネレーターの方がyield使った書き方もできるしitertoolsとかも使えるし融通が効くかも知れない。あと中身をただの座標のベタリストにするのも楽だよなあ。

決め打ちのモーションを作りたい場合、3Dソフトで全部作ってから持ってくるわけですが、この場合60fpsで全部ベイクして持ってきても容量的にもたいしたことないわけで、そういうデータの扱いも一緒にできる必要があるのよね。

ただまあ、フラグとif文ずらずらと並べるのが一番良かったりするのかも知れない。ゲームのロジック部分の抽象化を高めると、アイデアが枯れていく気がしないでもない。どうだろ。

そもそもeffにはモーション用に特化した機構があってpawnっていう組み込み言語でコルーチン的に処理を記述しておけば描画オブジェクト単位で勝手に動いてくれるんですが、pawnはc風で正直あんまり使いたくないので弾やパーティクルなどシンプルなものに限定して使ってたり。

というわけで悩んでます。システム面でできてないのは、あとはもうこの辺ぐらいなのよね。しょうが無いので適当に組みながら組みやすい方向でやるしか無いかな。