第7回

prev slash top slash next

第7回:ループと関数

今回は似た処理をまとめてみましょう。

ループ

前回までに作ったスクリプトをもっと弾幕らしくしていくために、全方位弾を作ってみましょう。
全方位弾と言うのは全ての方向に等間隔で発射された弾のことです。
今回は10way全方位弾を作ってみましょう。

script_enemy_main{
 let angle = 90;
 let count = 0;
 @Initialize{〜}
 @MainLoop{
 〜
  if(count%20==0)
  {
   CreateShot01(GetX, GetY, 2, angle, BLUE01, 10);
   CreateShot01(GetX, GetY, 2, angle+36, BLUE01, 10);
   CreateShot01(GetX, GetY, 2, angle+72, BLUE01, 10);
   CreateShot01(GetX, GetY, 2, angle+108, BLUE01, 10);
   CreateShot01(GetX, GetY, 2, angle+144, BLUE01, 10);
   CreateShot01(GetX, GetY, 2, angle+180, BLUE01, 10);
   CreateShot01(GetX, GetY, 2, angle+216, BLUE01, 10);
   CreateShot01(GetX, GetY, 2, angle+252, BLUE01, 10);
   CreateShot01(GetX, GetY, 2, angle+288, BLUE01, 10);
   CreateShot01(GetX, GetY, 2, angle+324, BLUE01, 10);
  }
  count++;
 }
}

ごちゃごちゃしてますが、単に発射角をずらして同時に発射しているだけです。
一応これで10wayの全方位弾になります。

ですがこれでは無駄が多いです。
殆ど同じ処理を10個並べて書いてありますが、1つにまとめて書けたらよさそうです。
これは[loop]を使えば解決します。

if(count%20==0)
{
 loop(10)
 {
  CreateShot01(GetX, GetY, 2, angle, BLUE01, 10);
  angle+=36;
 }

}

ここで重要なのは、[loop]です。
loopは後ろの()の中に書いてあるだけ{}の中の処理を繰り返します。
上の例では、36度ずつ発射角を増やして10回弾を発射します。

ループ処理を使っていると、ループ処理から抜けたくなるときがあるかもしれません。
そういうときには[break]を使います。
しかし、{}の中に直接[break]を書いたのでは、すぐにループから抜けてしまうので、
前回説明した条件分岐と組み合わせて使うことになります。

関数

関数を使えば、同じような処理をまとめて使いまわすことが出来ます。
今回は2種類の全方位弾を交互に発射してみましょう。
1つ目は、自機狙いの16way弾(BLUE01)
2つ目は、角度ランダムの32way弾(RED01)
として、20フレームごとに発射するようにしましょう。
交互に発射するには、1つ目を20フレーム後、2つ目を40フレーム後に発射すれば、
うまくいきそうです。

script_enemy_main
{
 let angle = 0;
 let count = 0;
 @Initialize{〜}
 @MainLoop
 {
  if(count==20)
  {
   angle = GetAngleToPlayer;
   loop(16)
   {
    CreateShot01(GetX, GetY, 2, angle, BLUE01, 10);
    angle+=360/16;
   }
  }

  if(count==40)
  {
   angle = rand(0, 360);
   loop(32)
   {
    CreateShot01(GetX, GetY, 2, angle, RED01, 10);
    angle+=360/32;
   }
   count=0;
  }

  count++;
 }
}

まずは、青いほうからみていきましょう。

if(count==20){〜}
countが20になった時のみ{}の中の処理が行われます。
まず最初に[angle = GetAngleToPlayer]でangleの角度が設定されます。
GetAngleToPlayerは、敵から見た自機への角度が取得できます。

loop(16)
{
 CreateShot01(GetX, GetY, 2, angle, BLUE01, 10);
 angle+=360/16;
}
これが全方位弾を撃つ部分です。
初めて出てきた[/]は割り算を表します。[a/b→a÷b]
ちなみに掛け算は[*]を使います。[a*b→a×b]
肝心の処理の内容は、
自機への角度に設定されたangleに[360/16]を16回足していきます。
360/16は22.5と書いてもかまいませんが、今はこう書いてください。

次は赤い方です。

if(count==40){〜}
countが40になった時に{}の中の処理が行われます。
まず最初に[angle = rand(0, 360)]でangleの角度が設定されます。
角度をランダムに設定するには、[rand]を使います。
rand(最小値, 最大値)と設定すると、最小値と最大値の間のランダムな実数を取得します。
この場合、0度以上360度以下のランダムな角度が取得できます。

loop(32)
{
 CreateShot01(GetX, GetY, 2, angle, RED01, 10);
 angle+=360/32;
}
この部分はさっきと殆ど変わっていません。
変更点は、16だった部分が32になり、弾の種類がBLUE01からRED01になったくらいです。

count=0;
ここでcountをいったん0に戻しています。
この処理があることで、繰り返して発射することが出来るようになります。

上のスクリプトを見ると、全方位弾を撃つ部分が2つ出てきました。
この処理は非常に似ています。が、今回はloopでまとめることが出来なさそうです。
そこで関数の出番です。

function AllroundShot(let angle, let color, let way)
{
 loop(way)
 {
  CreateShot01(GetX, GetY, 2, angle, color, 10);
  angle+=360/way;
 }
}

これがユーザー定義関数とか言われているものです。
script_enemy_mainの{}の中に書くと、そのスクリプト全体でそれが使えるようになります。
関数は、関数を定義した{}の外では使えないので注意してください。
マイクロスレッドの所で、似たようなことが説明してあります。
こうして定義しておくと、ifの部分をこうやって書くことが出来ます。

if(count==20)
{
 AllroundShot(GetAngleToPlayer, BLUE01, 16);
}
if(count==40)
{
 AllroundShot(rand(0, 360), RED01, 32);
 count=0;
}

どうでしょう、関数を使わなかったときと比べると、ずいぶんさっぱりしました。
ではどうなっているのか詳しく見ていくことにします。
はじめに関数を使用している部分を見てみましょう。

AllroundShot(GetAngleToPlayer, BLUE01, 16);
AllroundShot(rand(0, 360), RED01, 32);
この部分を見るとCreateShot01と似たようになっています。
こうすれば、AllroundShotで定義された処理が実行されます。
関数を実行することを、「関数を呼ぶ」と言ったりします。
そして、関数に渡されている値(GetAngletoPlayer,BLUE01,rand(0, 360)など)のことを実引数といいます。

次は定義している部分を見てみましょう。

function AllroundShot(let angle, let color, let way){〜}
関数を定義するときには、実引数を入れるところで変数宣言のようなことをしています。
これを、仮引数と言います。
関数が呼ばれたときに、仮引数は関数に渡された実引数で初期化されます。
実引数の値を変えると関数の処理結果も変わる事になります。
仮引数にも変数と同様にスコープと寿命があり、それらはそれぞれ関数が終わるまでです。

次回はその他の関数と三角関数です。


top
prev slash next
inserted by FC2 system