第8回 メビウスの輪

今回は、同じ処理を微妙に条件を変えて何度も実行してみたいと思います。

要旨

それではいってみましょう。

n-way 弾

もうちょっと弾幕っぽくするため、n-way 弾を実装して(作って)みましょう。n-way 弾というのは、ある方向に扇状に放たれた n 個の等間隔の弾のことです。例えば、5 度間隔の 5-way 弾を撃つには、次のようにします。

#東方弾幕風
#Title[テストスクリプト]
#Text[テストスクリプト]
#ScriptVersion[2]

script_enemy_main {
    let imgBoss   = "script\img\ExRumia.png";
    let frame     =  0;
    let angleBase = 90;

    @Initialize {
        SetX(GetCenterX);
        SetY(GetClipMinY + 120);
        SetLife(2000);

        LoadGraphic(imgBoss);
        SetTexture(imgBoss);
        SetGraphicRect(0, 0, 63, 63);
    }

    @MainLoop {
        SetCollisionA(GetX, GetY, 24);
        SetCollisionB(GetX, GetY, 24);

        frame++;
        if(frame == 30) {
            CreateShot01(GetX, GetY, 1, angleBase - 10, WHITE01, 0);
            CreateShot01(GetX, GetY, 1, angleBase -  5, WHITE01, 0);
            CreateShot01(GetX, GetY, 1, angleBase     , WHITE01, 0);
            CreateShot01(GetX, GetY, 1, angleBase +  5, WHITE01, 0);
            CreateShot01(GetX, GetY, 1, angleBase + 10, WHITE01, 0);

            angleBase += 8;
            frame = 0;
        }
    }

    @DrawLoop {
        DrawGraphic(GetX, GetY);
    }

    @Finalize {
        DeleteGraphic(imgBoss);
    }
}

単に発射角をずらして 5 発撃っているだけですね。特に大きな問題はないと思います。

しかし、このプログラムを見るとどうも無駄が多いように感じます。殆ど同じ処理が 5 つも並べて書いてありますが、1つにまとめて書けても良さそうではありませんか? つまり、発射角の部分をさらに別の変数にし、これを変化させつつ 5 回同じ処理をする、といったことはできないのでしょうか、ということです。

実は、これは可能です。これには次のようにします。

let angle = angleBase - 6;
loop(5) {
    CreateShot01(GetX, GetY, 1, angle, WHITE01, 0);
    angle += 5;
}

ここで最も重要なのは loop です。loop は、後の ( ) に書いてある回数だけ { } の中身を実行します。上の例では ( ) の中の数が 5 なので、{ } の中身は 5 回実行されます。

以上の処理を要約すると、次のようになります。先ず、発射角として angle という変数を宣言します。そして、発射角 angle を 3 度ずらしつつ、5 回弾を発射します。これで 5-way 弾になるわけです。

このように、何度も同じ処理を実行することをループ処理と言います。このループ処理の流れを詳しく見るために、ループを展開して(ループを使わないで書いて)みましょう。

let angle = angleBase - 6;
CreateShot01(GetX, GetY, 1, angle, WHITE01, 0);
angle += 3;
CreateShot01(GetX, GetY, 1, angle, WHITE01, 0);
angle += 3;
CreateShot01(GetX, GetY, 1, angle, WHITE01, 0);
angle += 3;
CreateShot01(GetX, GetY, 1, angle, WHITE01, 0);
angle += 3;
CreateShot01(GetX, GetY, 1, angle, WHITE01, 0);
angle += 3;

最初、angleangleBase - 6 になっています。この次の CreateShot01 が、最初のプログラムでの一番最初と同じ処理になっていることが分かると思います。

そして、次に angle に 3 を足しています。すると、angle の値は angleBase - 3 になることが分かります。この次の CreateShot01 が、最初のプログラムでの二番目と同じ処理になっていることも分かると思います。

その後も同様に考えると、angleangleBase, angleBase + 3, angleBase + 6 と変わって行く事が分かると思います。最初のプログラムと同様の向きに弾が発射されることが分かりますね。

ループ処理の文法

ループ処理の文法を詳しく書くと次のようになります。

loop[(<ループ回数>)] {
    <何度も実行される処理>
}

ループ回数は省略する事ができます。ループ回数を省略すると、無限ループになります。無限ループになったら永遠に終わらないのではないかと思われますが、無限ループから脱出する処理を組み合わせる事によって、無限ループが有用になる場合があります。

強制的にループから脱出するには、break を使います。

break;

ただ break を使っただけでは常にループから抜けてしまうので、条件分岐と組み合わせて使うことになると思います。

要旨

次回は、特定の処理を使い回せるようにしてみましょう。

第7回 | 第9回 | 目次へ戻る

この講座はロベールが作成しました。
inserted by FC2 system