前回は変数と関数について説明しました。今回は色々な記述を見て、復習がてらさらに知識を深めていきます。また、記述を見る、書く為に必要な「条件分岐」についても説明します。
~Shot関数とframe その1~
前回の最後、blt2(星型の威力弾)のShot関数を解説したと思います。その際、3連弾は少し難しいパターンなのでblt1を飛ばしました。
今回はそのblt1のShot関数を見ていきたいと思います。
Shot = function(self,chr_obj_no,chr_id,blt_type,px,py,vx,vy,vec_angle,power,frame)
if frame==0 then
C_CreateBullet(引数略)
C_PlaySoundSE(引数略)
elseif frame == 4 then
C_CreateBullet(引数略)
C_PlaySoundSE(引数略)
elseif frame == 8 then
C_CreateBullet(引数略)
C_PlaySoundSE(引数略)
return true
end
return false
end,
色々説明しないといけないものが多いですね。並行して説明していかないといけないので、大変ですが頑張ってください。
さて、まずはframeというものを説明します。
frame(フレーム)というのは……まあ詳しい話はグーグル先生にでも聞いてください。
とにかく、東方流星群と言うゲームは「30FPS」で、これは「30フレームで1秒」という感じの意味です。
60秒で1分、24時間で1日とかありますよね?あんな感じで、30フレームで1秒と思っておけば大体OKです。
ところで、前回の講座の最後にやったことを覚えているでしょうか。
「return true」を「return false」に変えて弾2を撃ってみましょう、というアレです。弾が大量に出て大変な事になりましたね。
その時に、Shot関数はtrueを返さないと呼び出され続ける、と言いました。これをより正確に言えば、Shot関数はtrueを返さないと毎フレーム(1フレームごとに)呼び出される、となります。
30フレームで1秒と言いましたね。つまり、Shot関数は1秒間に30回呼び出されます。
~Shot関数とframe その2~
実はShot関数には、撃ち始めてから何フレーム目かという引数が渡されています。改めてShot関数を見てみましょう。
Shot = function(self,chr_obj_no,chr_id,blt_type,px,py,vx,vy,vec_angle,power,frame)
一番最後に「frame」という引数がありますね。
最初にShot関数が呼び出された時、frameには0が渡されています。そして、0フレーム目のShot関数でtrueが返らなかった場合は、今度はframeに1が渡されて再びShot関数が呼び出されます。
このような感じで、frameに渡す数を1ずつ増やしながらShot関数が呼び出されるわけですね。
さて、そうなってくると、何となくこの部分が想像が付きませんか?
if frame==0 then
C_CreateBullet(引数略)
C_PlaySoundSE(引数略)
elseif frame == 4 then
C_CreateBullet(引数略)
C_PlaySoundSE(引数略)
elseif frame == 8 then
C_CreateBullet(引数略)
C_PlaySoundSE(引数略)
return true
end
if~endは、ある条件を満たした時だけ処理をさせたい時に使います。条件によって処理を分岐させるので「条件分岐」と呼ばれます。
if A == B then
処理1
end
というのは、
もし(if)
AとBが等しい(A == B)
なら(then)
処理1を実行、という意味です。
if A == B then
処理1
elseif A == C then
処理2
end
というのは、
もし(if)
AとBが等しい(A == B)
なら(then)
処理1を実行し、
そうではなく(elseif)、
AとCが等しい(A == C)
なら(then)
処理2を実行する、という意味です。
elseifはいくらでも繋げることが出来ます。
※一応上限は確かあります。
どうでしょう、これまでの説明でこの部分は分かるようになったでしょうか。
Shot = function(self,chr_obj_no,chr_id,blt_type,px,py,vx,vy,vec_angle,power,frame)
if frame==0 then
C_CreateBullet(引数略)
C_PlaySoundSE(引数略)
elseif frame == 4 then
C_CreateBullet(引数略)
C_PlaySoundSE(引数略)
elseif frame == 8 then
C_CreateBullet(引数略)
C_PlaySoundSE(引数略)
return true
end
return false
end,
- もしframeと0が等しいなら、弾を作成して効果音を鳴らす
- そうではなく、frameと4が等しいなら、弾を作成して効果音を鳴らす
- そうではなく、frameと8が等しいなら、弾を作成して効果音を鳴らし、trueを返す
- 毎回最後にfalseを返す
ちなみに、「return」で何かを返した時点でそこで関数の処理は終了し、それより後ろの行は実行されません。
8フレーム目はreturn trueでtrueを返した時点で、後ろのreturn falseは処理されません。
★練習★
- 今は発射間隔が4フレーム刻みですが、発射間隔を10フレーム刻みにしてみよう。
- 弾をもう一発増やし、4発発射するようにしてみよう。15フレーム目に発射されるようにしよう。
- 弾をもう一発増やし、5発発射するようにしてみよう。30フレーム目に発射されるようにしよう。return trueに気を付けよう。
~条件分岐 補足~
if 条件 then
処理1
else
処理2
end
条件を満たす場合 =>処理1が実行される
条件を満たさない場合 =>処理2が実行される
elseifは分岐の条件を追加する記述でしたが、elseは今までの条件を満たさない全ての場合を拾う事が出来ます。elseにはthenは必要ありません。
※注意
elseは分岐の一番最後に書くこと。下記のような書き方をするとエラーが起きます。
~駄目な例~
if 条件1 then
処理
else
処理
elseif 条件2 then
処理
end
~良い例~
if 条件1 then
処理
elseif 条件2 then
処理
else
処理
end
関係演算子(比較演算子)とは、「if frame == 0 then」の「==」のような部分で、左と右を比較する記号です。条件分岐を作るうえで欠かせません。
if a == b then |
もしaがbと等しいなら |
if a >= b then |
もしaがb以上なら |
if a <= b then |
もしaがb以下なら |
if a > b then |
もしaがbより上(超)なら |
if a < b then |
もしaがbより下(未満)なら |
if a ~= b then |
もしaとbが等しくないなら |
例えばこんな記述があったとします。
if frame==0 then
C_CreateBullet(引数略)
C_PlaySoundSE(引数略)
elseif frame >= 4 then
C_CreateBullet(引数略)
C_PlaySoundSE(引数略)
elseif frame == 8 then
C_CreateBullet(引数略)
C_PlaySoundSE(引数略)
return true
end
return false
これは、魔理沙の3連弾の「elseif frame == 4 then」を、「elseif frame >= 4 then」に書き換えたものです。こうすると、frameが4以上の時は2番目の分岐のelseifの処理が実行されます。つまり、frameが4の時だけでなく、5、6、7の時も弾が発射され、効果音が鳴ります。
では、frameが8の時はどうなるでしょう?
実は、3番目の分岐(elseif frame == 8 then)ではなく、2番目の分岐(elseif frame >= 4 then)が実行されます。
プログラムは基本的に上から実行され、条件分岐は「条件を満たした時点でそれより下の分岐は確認しない」という性質があります。
つまり、「elseif frame >= 4 then」を満たした時点で、もう「elseif frame == 8 then」は確認すらされないのです。そして、trueを返す処理は3つ目の分岐にしか入っていません。と言う事は……
ぐあああああああああああああああああああああああああああああああああああああ
条件分岐の順番には気を付けましょう。
中級編その2はここまでとします。エフェクトの追加方法まで説明しようかと思っていましたが、Shot関数の説明と条件分岐の説明が思ったより長くなってしまったので、中級編その3を作ろうかと思います。ここまでお付き合いいただきありがとうございました。
最終更新:2020年03月23日 17:15