tmlib.js
bulletml.js
bulletml.js-tutorial

tmlib.jsとbulletml.jsを使って弾幕STGを作る(2)

More than 3 years have passed since last update.

前回のおさらい

さて、前回は以下のようなDSLで、単発の自機狙い弾を発射しました。

var DANMAKU0 = new bulletml.Root({
    top: action([
        fire(bullet())
    ])
});

今回はもう少し記述を追加して、より複雑なパターンの攻撃を作ってみましょう。

今回作成するソースはこちら

今回のテーマに入る前に

今回のテーマに入る前に、すこしコードの修正を加えましょう。
と言っても1箇所だけ。
アプリケーションのFPS(フレームレート)を60に上げます。

ソースコード17行目付近に以下のコードを追加してください。

...
tm.main(function() {
    app = tm.display.CanvasApp("#app");
    app.fps = 60; // FPSを60にする ←new!!
    app.resize(320, 320).fitWindow();
    app.replaceScene(MainScene());
...

tmlib.jsではFPSのデフォルト値が30となっていますが、この状態のままですとBulletMLとしては少々遅いので2倍にしておきます。

発射方向を変化させる

前回の例では、fire関数にbulletのみを与えていました。
実は、これは発射の方向と速度を省略したかたちとなっています。
この状態ではデフォルトとなる、自機狙い弾を速度1で発射するアクションになります。

もう少し凝った弾を発射するには、例えば以下のように書きます。

var DANMAKU0 = new bulletml.Root({
    top: action([
        repeat(100, [
            fire(direction(23, "sequence"), bullet()),
            wait(1)
        ])
    ])
});

repeatアクション

topアクションの直下階層にrepeatという関数が追加されています。
repeat関数は、あるアクションを複数繰り返すときに使います。
第1引数に繰り返し回数、第2引数にアクションまたはアクションの配列を指定します。
この例では、繰り返し回数100回、繰り返すアクションはfirewaitとなっています。

fire関数にはdirectionが追加されています。
direction関数は発射する方向を生成する関数です。
direction関数にはtypeが指定できます。typeには以下の3種類があります。

  • aim 自機を狙った方向
  • absolute 自機の位置に依存しない絶対方向(真上を0度とします)
  • sequence 直前に撃った方向との相対方向

今回の場合はsequenceですので、直前に撃った方向との相対方向に発射します。
単位は度です。
直前から23度ずれた方向に弾を撃ちます。

waitアクション

waitアクションは一定時間何もせずに待機するアクションです。
単位はフレームです。
今回の場合は1フレーム待機します。

渦巻弾または回転砲台

ここまでの記述で、

  • 直前から23度ずれた方向に弾を撃ち
  • 1フレーム待つ

という動作を100回繰り返す動作が定義できました。

ブラウザで動かしてみましょう。
くるくると回転しながら弾をばらまく攻撃を行うのが確認できるはずです。
ss2.png

このような攻撃を、渦巻弾とか回転砲台と呼ぶようです。
怒首領蜂大往生2面ボス「百虎」等、弾幕STGではよく使われています。

弾にアクションを定義する

これまでの例では攻撃主体(敵キャラ)にアクションを定義してきましたが、弾にもアクションを実行させることが出来ます。

弾幕定義を以下のように変更してみましょう。

var DANMAKU0 = new bulletml.Root({
    top: action([
        repeat(100, [
            fire(bullet(actionRef("explosion"))),
            wait(200)
        ])
    ]),
    explosion: action([
        wait(100),
        changeSpeed(speed(0), 20),
        wait(20),
        repeat(8, [
            fire(direction("$rand * 360"), bullet())
        ]),
        vanish()
    ])
});

actionRefアクション

bullet関数に引数としてactionRefアクションが加わっています。
actionRefアクションは、プロパティ名を指定してアクションを参照する時に使います。
ここではexplosionという名前のアクションを参照しています。

bullet関数の引数にactionまたはactionRefが与えた場合、発射後の弾にアクションを実行させることができます。
explosionプロパティの中では、waitchangeSpeedwaitrepeatvanishという順にアクションを定義しています。

changeSpeedアクション

changeSpeedアクションは弾の速度を、指定したspeedに指定フレームかけて変化させます。
今回の例では、20フレームかけてスピードを0にするよう記述しています。

vanishアクション

vanishアクションは弾を消すアクションです。

パラメータに式を指定

directionの引数に "$rand * 360" という文字列が指定されています。
このように、数値を指定する場所では文字列によって式を記述することも可能です。
$randは0から1までの乱数を発生させる変数です。
ここでは、ランダムな方向に弾を発射するような指定となっています。

炸裂弾

explosionプロパティは、全体として

  • 100フレーム何もしない
  • 20フレームかけて停止する(速度を0にする)
  • 20フレーム(速度が0になるまで)待機
  • 以下を8回繰り返す
    • ランダムな方向へ弾を発射する
  • 弾を消す

というアクションとなります。
ss3.png

このように、弾自身が複数の弾に分裂するような攻撃を、炸裂弾と呼ぶようです。
使用例としては、怒首領蜂真ボス「火蜂」や怒首領蜂最大往生3面ボス「源武」などがあります。

その他のアクション

この他、BulletMLには以下の様なアクションがあります。

  • changeDirection 弾の進行方向を変化させます。
  • accel 弾を加速します
  • bindVar 変数に値を代入します。bulletml.js独自拡張のアクションです。
  • notify 攻撃主体にイベントの発生を通知します。bulletml.js独自拡張のアクションです。

くわしいリファレンスは以下を参照ください。

まとめ

今回は、より複雑な弾幕パターンの定義の仕方と、利用可能なアクションを紹介しました。
これらを組み合わせることで、さらに複雑で奥深い弾幕パターンを構築することが出来ると思います。
みなさんも熱く激しい弾幕をガンガン作ってみてください。

今回作成したソースはこちら