スクリプト/Rmakeで自由なゲームをつくろう / 第04回 敵キャラクターを登場させる(履歴ID:107)
最終投稿者: aoihikawa
更新:2011/08/11 23:07:26
Rmakeで自由なゲームをつくろう
第04回 敵キャラクターを登場させる
こんにちは。
フリーデザイナープログラマー(自称)の
簸川 葵(ひかわ あおい)と申します。
第03回 ではキャラクターをキー操作で動かすまでのお話でした。
第04回は、これまでつくってきたものに、ちょっとずつ手を加えながら
敵キャラクターを登場させるところまで、やっていきますね。
04-01 背景を動かそう
敵キャラクターを登場させる前に、前回のおさらいも兼ねて、
背景を動かしてみましょう。
背景を動かすためには、縦に長ーい画像を準備する方法もありますが、
今回は、1枚の絵を2枚使用して、これをループさせて表示します。
さて、2枚同じものを表示するには、
背景に関連しているスクリプトを、コピーして増やすこともできますが、
スクリプトがどんどん長くなってしまいます。
そこで、「配列」というものを使います。
配列とは、変数を分割し縦に長い箱にしたものです。
縦方向の場所を区別するときは、番号を使用します。
#変数 pos_bg_x = 0 #変数の配列化 pos_bg_x = createArray() #変数を配列にする関数 #これ以降、「pos_bg_x」は配列になります pos_bg_x[0] = 0 #配列は「変数[番号]」で場所を区別します pos_bg_x[1] = 800 basyo = 2 pos_bg_x[basyo] = 1600 #番号に入れる数値は、変数でも使用できます
配列の各番号の場所を、さらに配列にすることもできます。
これを「2次元配列」と呼びます。
変数が、リバーシゲームの升目のようになった感じですね。
pos_bg = createArray() #変数を配列にします #0番目を1枚目の背景、1番目を2枚目の背景とします。 pos_bg[0] = createArray() #配列の中身をさらに配列にします(2次元配列) pos_bg[1] = createArray() #次の場所も同じように x = 0; y = 1 #分かりやすくするために定数を準備しておきます pos_bg[0][x] = 0 #1枚目の背景のX座標とY座標 pos_bg[0][y] = 0 pos_bg[1][x] = 0 #2枚目の背景のX座標とY座標 pos_bg[1][y] = 0
これを繰り返すことで、3次元配列、とか4次元配列、などという
感じのものも作ることができてしまいます。
ただ、これ以降場合、「多次元配列」という呼び方で
まとめてしまうことが多いです。
それでは、この配列を利用して、
表示する背景を2枚に増やしてみましょう。
#ここから↑は省略 #_/_/_/_/_/_/_/_/_/_/_/_/ 変更分 _/_/_/_/_/_/_/_/_/_/_/_/ #----- 画像の設定 ----- get = createArray() set = createArray() x = 0; y = 1; w = 2; h = 3 #キャラクター画像の設定 img_no = 76793 img_char_name = "img_char" get[x] = 0; get[y] = 0; get[w] = 64; get[h] = 64 set[x] = 0; set[y] = 0; set[w] = 64; set[h] = 64 set_z = 7 pos_char = createArray() pos_char[x] = 368; pos_char[y] = 500 setCreateSprite(img_char_name, img_no, get, set, set_z, pos_char) #背景画像の設定 img_no = 76800 img_bg_name = "img_bg" get[x] = 0; get[y] = 0; get[w] = 800; get[h] = 600 set[x] = 0; set[y] = 0; set[w] = 800; set[h] = 600 set_z = 1 pos_bg = createArray() pos_bg[0] = createArray() pos_bg[0][x] = 0; pos_bg[0][y] = 0 pos_bg[1] = createArray() pos_bg[1][x] = 0; pos_bg[1][y] = -600 setCreateSprite(img_bg_name, img_no, get, set, set_z, pos_bg, 2) #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ #ここから↓は省略
setCreateSpriteの引数に含まれている配列に番号が振られていません。
このように、配列に番号が振られていない場合、
その配列の集合全体を意味します。
つまり、「get」は「get[x]~get[h]」を纏めた状態で
関数に渡しているわけです。
それでは、受け取る方の関数も配列に対応してあげましょう。
#メニュー項目等の表示OFF setMenuItemVisible(getMenuBackLog(), false) setMenuItemVisible(getMenuSave(), false) setMenuItemVisible(getMenuLoad(), false) setHelpVisible(false) #キャンバスの初期化 setCanvasVisible(false) deleteAllSprite() drawCanvas() #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ #----- 関数の設定 ----- #スプライトの表示位置を変更する関数 def setSpritePos(img_name, pos, i) if i setSpritePosition(getVariable(img_name)[i], pos[i][0], pos[i][1]) else setSpritePosition(getVariable(img_name), pos[0], pos[1]) end end #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ #_/_/_/_/_/_/_/_/_/_/_/_/ 変更分 _/_/_/_/_/_/_/_/_/_/_/_/ #画像を設定する関数 def setCreateSprite(img_name, img_no, get, set, set_z, pos, ilen) x = 0; y = 1; w = 2; h = 3 if ilen setVariable(img_name, createArray()) i = 0 while i < ilen getVariable(img_name)[i] = createSprite(img_no) setSpriteRect(getVariable(img_name)[i], get[x], get[y], get[w], get[h], set[x], set[y], set[w], set[h]) setSpriteZOrder(getVariable(img_name)[i], set_z) setSpritePos(img_name, pos, i) i = i + 1 end else setVariable(img_name, createSprite(img_no)) setSpriteRect(getVariable(img_name), get[x], get[y], get[w], get[h], set[x], set[y], set[w], set[h]) setSpriteZOrder(getVariable(img_name), set_z) setSpritePos(img_name, pos) end end #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ #ここから↓は省略
1つめのsetSpritePosという関数はsetSpritePositionを
簡単に利用するために纏めた関数になっています。
引数の「i」は配列の場所を受け取る仕組みになっています。
もし、場所が指定されていない場合、
通常の変数として扱うように処理を分岐させています。
2つめのsetCreateSpriteという関数は先ほどの
「get」、「set」、「pos」という配列に対応するように
変更されています。
また、渡された値が配列だった場合、
配列の長さだけループさせて、画像を設定するように
変更されています。
背景を動かす定数を準備します。
#ここから↑は省略 #定数の設定 char_speed = 10 char_w_max = 800 - 64; char_h_max = 600 - 64 char_anime_change = 3 #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ bg_speed = 3 #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ #変数の設定 char_anime_count = 0 #ここから↓は省略
「bg_speed」には、背景の移動速度が入ります。
準備した配列や関数などを利用して、
キャラクターの移動の変更点と
背景を動かす処理のスクリプトを書きます。
#ここから↑は省略 #----- ゲームのメイン処理を入れる場所 ----- #(ゲームの終了時はmainloopをfalseに) #----- キャラクターの移動 ----- #_/_/_/_/_/_/_/_/_/_/_/_/ 変更分 _/_/_/_/_/_/_/_/_/_/_/_/ if key_flg_left #左 pos_char[x] = pos_char[x] - char_speed if pos_char[x] < 0 pos_char[x] = 0 end setSpritePos(img_char_name, pos_char) elsif key_flg_right #右 pos_char[x] = pos_char[x] + char_speed if pos_char[x] > char_w_max pos_char[x] = char_w_max end setSpritePos(img_char_name, pos_char) end if key_flg_up #上 pos_char[y] = pos_char[y] - char_speed if pos_char[y] < 0 pos_char[y] = 0 end setSpritePos(img_char_name, pos_char) elsif key_flg_down #下 pos_char[y] = pos_char[y] + char_speed if pos_char[y] > char_h_max pos_char[y] = char_h_max end setSpritePos(img_char_name, pos_char) end #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ #----- キャラクターのアニメーション ----- #アニメーション用カウンター char_anime_count = char_anime_count + 1 if char_anime_count == (char_anime_change * 2) char_anime_count = 0 end #キャラクターの表示を切替 if key_flg_left if char_anime_count < char_anime_change setCharSpritePattern(2) else setCharSpritePattern(5) end elsif key_flg_right if char_anime_count < char_anime_change setCharSpritePattern(3) else setCharSpritePattern(6) end else if char_anime_count < char_anime_change setCharSpritePattern(1) else setCharSpritePattern(4) end end #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ #----- 背景のスクロール ----- i = 0 while i < 2 pos_bg[i][y] = pos_bg[i][y] + bg_speed if pos_bg[i][y] > 600 pos_bg[i][y] = (pos_bg[i][y] % 600) - 600 end setSpritePos(img_bg_name, pos_bg, i) i = i + 1 end #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ #----- 画面の更新 ----- drawCanvas() waitTime(30) end endInput() #入力受付の終了 goEnding() #ゲームのクリア
ここまでで、背景がスクロールするようになりました。
完成したら、テストプレーを行ってみましょう。
04-02 敵キャラクターを表示しよう
今回も、お手軽にスクリプトの作成までできるよう、
敵キャラクターのサンプルの素材を準備いたしました。
第02回を参考に、クリップからリソースへの登録まで行い、
すぐにスクリプトで利用できるように、準備してください。
それでは、敵キャラクター用の関数から。
ベースはキャラクター用の関数を利用します。
#ここから↑は省略 #キャラクターの表示内容を変更する関数 def setCharSpritePattern(no) img_char_name = "img_char" get_x = 0; get_y = 0; get_w = 64; get_h = 64 set_x = 0; set_y = 0; set_w = 64; set_h = 64 if no == 1 get_x = 0; get_y = 0 elsif no == 2 get_x = 64; get_y = 0 elsif no == 3 get_x = 128; get_y = 0 elsif no == 4 get_x = 0; get_y = 64 elsif no == 5 get_x = 64; get_y = 64 elsif no == 6 get_x = 128; get_y = 64 else get_w = 0; get_h = 0 set_w = 0; set_h = 0 end setSpriteRect(getVariable(img_char_name), get_x, get_y, get_w, get_h, set_x, set_y, set_w, set_h) end #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ #敵キャラクターの表示内容を変更する関数 def setEnemySpritePattern(no, i) img_enemy_name = "img_enemy" get_x = 0; get_y = 0; get_w = 64; get_h = 64 set_x = 0; set_y = 0; set_w = 64; set_h = 64 if no == 1 get_x = 0; get_y = 0 elsif no == 2 get_x = 64; get_y = 0 elsif no == 3 get_x = 128; get_y = 0 elsif no == 4 get_x = 192; get_y = 0 else get_w = 0; get_h = 0 set_w = 0; set_h = 0 end setSpriteRect(getVariable(img_enemy_name)[i], get_x, get_y, get_w, get_h, set_x, set_y, set_w, set_h) end #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ #ここから↓は省略
作成した関数のすぐ下に、ばらばらな箇所でつくっていた定数を纏めながら
敵キャラクター用の定数も定義します。
定数を一纏めにしておく方が、後でちょっと値を変更したくなった時、
分かりやすいからです。
さらに、どういった意味の定数なのか、コメントも付けておきますね。
#ここから↑は省略 setSpriteRect(getVariable(img_enemy_name)[i], get_x, get_y, get_w, get_h, set_x, set_y, set_w, set_h) end #_/_/_/_/_/_/_/_/_/_/_/_/ 変更分 _/_/_/_/_/_/_/_/_/_/_/_/ #----- 定数の設定 ----- x = 0; y = 1; w = 2; h = 3 #キャラクターの設定 char_speed = 10 char_w_max = 800 - 64; char_h_max = 600 - 64 char_anime_change = 3 #背景の設定 bg_speed = 3 #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ #敵キャラクターの設定 max_enemy = 3 enemy_speed = 5 enemy_baratuki = 20 enemy_w_max = 800 - 64; enemy_h_min = -64 enemy_anime_change = 2 #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/
「max_enemy」は敵キャラクターの数、
「enemy_speed」は敵キャラクターの移動速度、
「enemy_baratuki」は敵キャラクターを出現させるときのばらつき具合、
「enemy_w_max」と「enemy_h_min」は後で使用する
敵キャラクターの出現位置となるX座標の最大値とY座標を設定しています。
続いて、画像の設定です。
こちらも、キャラクターの設定をベースにしながら、
敵キャラクターの数だけ、配列で増やします。
#ここから↑は省略 enemy_anime_change = 2 #----- 画像の設定 ----- get = createArray() set = createArray() #キャラクター画像の設定 img_no = 76793 img_char_name = "img_char" get[x] = 0; get[y] = 0; get[w] = 64; get[h] = 64 set[x] = 0; set[y] = 0; set[w] = 64; set[h] = 64 set_z = 7 pos_char = createArray() pos_char[x] = 368; pos_char[y] = 500 setCreateSprite(img_char_name, img_no, get, set, set_z, pos_char) #背景画像の設定 img_no = 76800 img_bg_name = "img_bg" get[x] = 0; get[y] = 0; get[w] = 800; get[h] = 600 set[x] = 0; set[y] = 0; set[w] = 800; set[h] = 600 set_z = 1 pos_bg = createArray() pos_bg[0] = createArray() pos_bg[0][x] = 0; pos_bg[0][y] = 0 pos_bg[1] = createArray() pos_bg[1][x] = 0; pos_bg[1][y] = -600 setCreateSprite(img_bg_name, img_no, get, set, set_z, pos_bg, 2) #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ #敵キャラクターの画像の設定 img_no = 77127 img_enemy_name = "img_enemy" get[x] = 0; get[y] = 0; get[w] = 64; get[h] = 64 set[x] = 0; set[y] = 0; set[w] = 64; set[h] = 64 set_z = 5 pos_enemy = createArray() i = 0 while i < max_enemy pos_enemy[i] = createArray() pos_enemy[i][x] = 800; pos_enemy[i][y] = 600 i = i + 1 end setCreateSprite(img_enemy_name, img_no, get, set, set_z, pos_enemy, max_enemy) #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ #ここから↓は省略
敵キャラクターの初期座標が画面外になっています。
これは登場するシーンがくるまで、舞台袖で待っていてもらうのと
同じ仕組みになっています。
変数も同様に、キャラクターの設定をベースにしながら、
敵キャラクターの数だけ、配列で増やします。
#ここから↑は省略 setCreateSprite(img_enemy_name, img_no, get, set, set_z, pos_enemy, max_enemy) #----- 変数の設定 ----- #キー入力フラグの設定 key_flg_left = false; key_flg_right = false key_flg_up = false; key_flg_down = false key_flg_z = false #アニメーション用カウンター #キャラクター char_anime_count = 0 #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ #敵キャラクター enemy_anime_count = createArray() i = 0 while i < max_enemy enemy_anime_count[i] = -1 i = i + 1 end enemy_syutugen_count = 0 #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ #画面の更新 drawCanvas() setCanvasVisible(true) #ここから↓は省略
「enemy_syutugen_count」は敵キャラが画面上に何体出現しているか
カウントするために使用します。
後でこれを利用することで、敵キャラクターを出現させる
スクリプトの実行を分岐させます。
最後に、敵キャラクターを登場、アニメーションさせる
スクリプトを書きます。
#ここから↑は省略 #----- 背景のスクロール ----- i = 0 while i < 2 pos_bg[i][y] = pos_bg[i][y] + bg_speed if pos_bg[i][y] > 600 pos_bg[i][y] = (pos_bg[i][y] % 600) - 600 end setSpritePos(img_bg_name, pos_bg, i) i = i + 1 end #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ #----- 敵キャラクターのアニメーション ----- i = 0 while i < max_enemy #敵キャラクターを出現させる if (enemy_syutugen_count < max_enemy) && (enemy_anime_count[i] < 0) if rand(enemy_baratuki) == 0 #出現カウントが最大値より少なく、アニメーションがマイナス(初期値)の場合 enemy_syutugen_count = enemy_syutugen_count + 1 #出現カウント pos_enemy[i][x] = rand(enemy_w_max) pos_enemy[i][y] = enemy_h_min enemy_anime_count[i] = 0 #アニメーションをリセット end end if enemy_anime_count[i] > -1 #アニメーション用カウンター enemy_anime_count[i] = enemy_anime_count[i] + 1 if enemy_anime_count[i] == (enemy_anime_change * 4) enemy_anime_count[i] = 0 #アニメーションをリセット end #敵キャラクターの表示を切替 if enemy_anime_count[i] < enemy_anime_change setEnemySpritePattern(1, i) elsif enemy_anime_count[i] < (enemy_anime_change * 2) setEnemySpritePattern(2, i) elsif enemy_anime_count[i] < (enemy_anime_change * 3) setEnemySpritePattern(3, i) else setEnemySpritePattern(2, i) end #敵キャラクターの移動 pos_enemy[i][y] = pos_enemy[i][y] + enemy_speed if pos_enemy[i][y] > 600 enemy_syutugen_count = enemy_syutugen_count - 1 #出現カウント pos_enemy[i][x] = 800 pos_enemy[i][y] = 600 enemy_anime_count[i] = -1 end setSpritePos(img_enemy_name, pos_enemy, i) end i = i + 1 end #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ #----- 画面の更新 ----- drawCanvas() waitTime(30) end endInput() #入力受付の終了 goEnding() #ゲームのクリア
こちらも、基本的にはキャラクターのスクリプトをベースにしていますが、
いくつか、異なっている箇所があります。
説明用に、先ほどの一部を抜粋します。
i = 0 while i < max_enemy #敵キャラクターを出現させる if (enemy_syutugen_count < max_enemy) && (enemy_anime_count[i] < 0)
まず、while文で敵キャラクターの最大数まで、処理をループさせています。
次にif文が入っていますが、ここで新しい記号が登場しています。
実は、while文やif文の条件式は、ひとつの条件式の中に、
同時に複数の条件を組み合わせることができます。
「(条件1) && (条件2)」はAND関数と呼び、
条件1と条件2の両方が成立したときだけ、成立と判断されます。
「(条件1) || (条件2)」はOR関数と呼び、
条件1と条件2のどちらか片方でも成立したら、成立と判断されます。
なお、while文、if文などの途中で、この条件式を繋ぐ記号が行の最後だった場合
関数の「,」の時のように、次の行もスクリプトでは同じ行として判断されます。
#次の2つは同一 if (enemy_syutugen_count < max_enemy) && (enemy_anime_count[i] < 0) end #-------------------------------------------------- if (enemy_syutugen_count < max_enemy) && (enemy_anime_count[i] < 0) end
また、ちょっと特殊なもので、
「!(条件1) 」はNOT関数と呼び、
条件1が不成立なら成立、成立なら不成立、と判断されるものもあります。
説明用に、先ほどの一部を抜粋します。
if rand(enemy_baratuki) == 0 #出現カウントが最大値より少なく、アニメーションがマイナス(初期値)の場合 enemy_syutugen_count = enemy_syutugen_count + 1 #出現カウント pos_enemy[i][x] = rand(enemy_w_max) pos_enemy[i][y] = enemy_h_min enemy_anime_count[i] = 0 #アニメーションをリセット end
次のif文では、第01回で登場した、rand関数が使用されています。
「0~enemy_baratuki」の間でランダムで値を決定してもらい、
この値が「0」となったときだけ、出現させるスクリプトに移動するようになっています。
if文の中身については、出現数のカウントと
出現させた時の変数の初期値の設定を行っています。
X座標もまた、毎回異なる場所に出現するように、
「0~enemy_w_max」でX座標を決定してもらうように、rand関数が使用されています。
説明用に、先ほどの一部を抜粋します。
if enemy_anime_count[i] > -1 #アニメーション用カウンター enemy_anime_count[i] = enemy_anime_count[i] + 1 if enemy_anime_count[i] == (enemy_anime_change * 4) enemy_anime_count[i] = 0 #アニメーションをリセット end #敵キャラクターの表示を切替 if enemy_anime_count[i] < enemy_anime_change setEnemySpritePattern(1, i) elsif enemy_anime_count[i] < (enemy_anime_change * 2) setEnemySpritePattern(2, i) elsif enemy_anime_count[i] < (enemy_anime_change * 3) setEnemySpritePattern(3, i) else setEnemySpritePattern(2, i) end
続いて、敵キャラクターのアニメーション。
「enemy_anime_count」が初期値になっているかどうか判断することで、
出現している状態のときのみ実行されるようになっています。
また、アニメーションが耳をぱたぱたさせる動きとなる、
1→2→3→2の繰り返しとなるよう変更されています。
説明用に、先ほどの一部を抜粋します。
#敵キャラクターの移動 pos_enemy[i][y] = pos_enemy[i][y] + enemy_speed if pos_enemy[i][y] > 600 enemy_syutugen_count = enemy_syutugen_count - 1 #出現カウント pos_enemy[i][x] = 800 pos_enemy[i][y] = 600 enemy_anime_count[i] = -1 end setSpritePos(img_enemy_name, pos_enemy, i) end
最後に、敵キャラクターの移動と座標の移動。
if文で、画面外まで敵キャラクターが移動したとき、
使用していた変数を初期化する仕組みになっています。
ここまでで、敵キャラクターが表示されるようになりました。
完成したら、テストプレーを行ってみましょう。
04-03 当たり判定を付けよう
さて、敵キャラクターが登場しただけでは少し物足りないですね。
キャラクターが敵キャラクターに当ったとき、ミスになるように
キャラクターと敵キャラクターに当たり判定を付けてみましょう。
まずは当たり判定の設定から。
キャラクターの座標をそのまま利用することも出来ますが、
今回は、それより内側の位置に当たり判定を設定します。
キャラクターの座標から当たり判定までの
差分の値を定数で設定します。
#ここから↑は省略 #----- 定数の設定 ----- x = 0; y = 1; w = 2; h = 3 #キャラクターの設定 char_speed = 10 char_w_max = 800 - 64; char_h_max = 600 - 64 char_anime_change = 3 #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ char_hit = createArray() char_hit[x] = 25; char_hit[y] = 20 char_hit[w] = 14; char_hit[h] = 30 #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ #背景の設定 bg_speed = 3 #敵キャラクターの設定 max_enemy = 3 enemy_speed = 5 enemy_baratuki = 20 enemy_w_max = 800 - 64; enemy_h_min = -64 enemy_anime_change = 2 #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ enemy_hit = createArray() enemy_hit[x] = 20; enemy_hit[y] = 20 enemy_hit[w] = 24; enemy_hit[h] = 35 #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ #ここから↓は省略
差分から、当たり判定を算出して保存しておく変数を準備します。
#ここから↑は省略 #アニメーション用カウンター #キャラクター char_anime_count = 0 #敵キャラクター enemy_anime_count = createArray() i = 0 while i < max_enemy enemy_anime_count[i] = -1 i = i + 1 end enemy_syutugen_count = 0 #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ #キャラクターの非ダメージ char_damage = false #キャラクターの当たり判定範囲 char_atari = createArray() char_atari[x] = pos_char[x] + char_hit[x] char_atari[y] = pos_char[y] + char_hit[y] char_atari[w] = char_atari[x] + char_hit[w] char_atari[h] = char_atari[y] + char_hit[h] #敵キャラクターの当たり判定範囲 enemy_atari = createArray() #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ #画面の更新 drawCanvas() setCanvasVisible(true) #ここから↓は省略
「char_damage」には、敵に当たったかどうかの
スイッチを設定します。
キャラクター、敵キャラクターの移動ごとに、
当たり判定の再計算を行います。
#ここから↑は省略 setCharSpritePattern(4) end end #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ #キャラクターの当たり判定範囲 if key_flg_left || key_flg_right || key_flg_up || key_flg_down char_atari[x] = pos_char[x] + char_hit[x] char_atari[y] = pos_char[y] + char_hit[y] char_atari[w] = char_atari[x] + char_hit[w] char_atari[h] = char_atari[y] + char_hit[h] end #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ #----- 背景のスクロール ----- #ここから↓は省略
#ここから↑は省略 #敵キャラクターの移動 pos_enemy[i][y] = pos_enemy[i][y] + enemy_speed if pos_enemy[i][y] > 600 enemy_syutugen_count = enemy_syutugen_count - 1 #出現カウント pos_enemy[i][x] = 800 pos_enemy[i][y] = 600 enemy_anime_count[i] = -1 end setSpritePos(img_enemy_name, pos_enemy, i) #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ #敵キャラクターの当たり判定範囲 enemy_atari[x] = pos_enemy[i][x] + enemy_hit[x] enemy_atari[y] = pos_enemy[i][y] + enemy_hit[y] enemy_atari[w] = enemy_atari[x] + enemy_hit[w] enemy_atari[h] = enemy_atari[y] + enemy_hit[h] #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ end i = i + 1 end #ここから↓は省略
最後に、実際に当たったかどうかの判定を行い、
当たってしまうとメインループを終了させ、ゲームを終了します。
当たったかどうかの判定は、キャラクターと敵キャラクターの
上下左右、それぞれの位置が超えているかどうか比較することで
判断します。
#ここから↑は省略 #敵キャラクターの移動 pos_enemy[i][y] = pos_enemy[i][y] + enemy_speed if pos_enemy[i][y] > 600 enemy_syutugen_count = enemy_syutugen_count - 1 #出現カウント pos_enemy[i][x] = 800 pos_enemy[i][y] = 600 enemy_anime_count[i] = -1 end setSpritePos(img_enemy_name, pos_enemy, i) #敵キャラクターの当たり判定範囲 enemy_atari[x] = pos_enemy[i][x] + enemy_hit[x] enemy_atari[y] = pos_enemy[i][y] + enemy_hit[y] enemy_atari[w] = enemy_atari[x] + enemy_hit[w] enemy_atari[h] = enemy_atari[y] + enemy_hit[h] #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ #当たり判定のチェック if ((char_atari[w]) > (enemy_atari[x])) && ((char_atari[h]) > (enemy_atari[y])) && ((char_atari[x]) < (enemy_atari[w])) && ((char_atari[y]) < (enemy_atari[h])) char_damage = true mainloop = false end #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ end i = i + 1 end #----- 画面の更新 ----- drawCanvas() waitTime(30) end endInput() #入力受付の終了 #_/_/_/_/_/_/_/_/_/_/_/_/ 変更分 _/_/_/_/_/_/_/_/_/_/_/_/ if char_damage goBadEnding() #ゲームオーバー else goEnding() #ゲームのクリア end #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/
当たってしまったとき、「char_damage」をオンに変更してから、
「mainloop」をオフに変更してゲームのメインループを抜けています。
最後に、「char_damage」を比較することで、
ゲームクリアか、ゲームオーバーか分岐させています。
なお、新しく登場したgoBadEndingは、
ゲームオーバー画面に移動する関数です。
スクリプト全体(一部、少し整理しています)
これで、一通り完成です。
保存、終了をして、テストプレーを行い、
敵キャラクターに当たると、ゲームオーバーになるかどうか、
確認してみましょう。
04-04 おわりに
いかがでしたでしょうか。
大分、シューティングゲームらしくなってきました。
さて、次回は敵キャラクターに反撃する手段、
「弾を発射させる」です。
第01回 スクリプトって何?
第02回 画面にキャラクターを描画する
第03回 キャラクターをキー入力で操作する
第04回 敵キャラクターを登場させる
第05回 弾を発射させる
第06回 より面白くするために
この記事についてご質問等がありましたら
こちらのブログ記事のコメントへご投稿、
よろしくお願いいたします。