こんな画像ぶっぱして何が楽しいの
※ソースの通り、1つ1つが一定速度で回転しつつ、微振動してます。
※自機がうにょうにょになりました
stage1.lua
module("stage1", package.seeall) local function test_func(self) -- self.imgindex = 2 while true do --local vel = vector2.new(math.random() - 0.5, math.random() - 0.5) --vector2.add(self.pos, vel) self.pos[1] = self.pos[1] + math.random() - 0.5; self.pos[2] = self.pos[2] + math.random() - 0.5; self.rot = self.rot + 0.1 coroutine.yield(true) end end function advance(add_enemy) for i = 1, 1000 do if i % 100 == 0 then trace("Frame", i) end local pos = vector2.new(math.random() * 640, math.random() * 480) add_enemy("ball", pos, test_func) coroutine.yield(true) end return false end
ステージファイルはadvance()関数をエクスポートします。とりあえず敵を出現させる関数だけ渡してみました。他にはボス戦セットとか背景スクロールくらいだからテーブルにまとめなくていいかな、と(どうなっても知らんぞ…)。引数は画像リストの識別文字列・座標・行動コルーチンです。コルーチン中ではEnemyクラスのインスタンスがselfとして渡され、pos(座標)・rot(回転角)・imgindex(画像リスト中のインデックス)などを変更します。
というわけでコルーチンに手を出してみました。コルーチンとは中断可能な関数で、resume(再開)するとyield(中断)するまで実行し、その後再びresumeすると前回yieldしたところから実行されます。というかステージだとか敵や弾の動きだとかを関数内に直列に書けるため、ほとんどこれだけのためにLuaを使ってます。
for i = 1, 60 do x = x - 1 coroutine.yield() end
60フレーム左へ動く、などというコードをこのように書けて非常に便利です。
Frame500
FPS: 60.164730072021
FPS: 60.003959655762
Frame600
FPS: 60.004322052002
Frame700
FPS: 59.784656524658
FPS: 60.215148925781
Frame800
FPS: 58.407234191895
FPS: 54.427101135254
Frame900
FPS: 51.038070678711
Frame1000
FPS: 47.070858001709
1Fに1つずつ追加しているので700〜800個あたりで速度低下が来ていますね。画像サイズを1/2(面積1/4)にしてもあまり変わらず、コメントアウトで書きなおされているガーベジコレクション対策である程度処理落ちラインが移動したのでLua実行のCPU負荷の方に強く来るみたいです。まあ仮に弾幕を作りたいならこういうホットスポット*1はC/C++に移した方がいいと思います。そういうことが比較的楽に行えるのもLuaの利点だと思います。ちなみにこのゲームは弾幕シューティングではなく世紀末シューティングアクションゲームらしいので100〜300発もあれば十分なんじゃないでしょうか。
*1:一番きついところ。JavaVM用語?それとも一般用語?