SCRATCHでゲームを作ろう(ブロック崩し編④)

ゲーム開発

ちょっと更新が滞ってしまいすみません。仕事が大忙しになってしばらく忙殺されておりました。今日はSCRATCHブロック崩しを作る企画の4回目です。前回の記事で作成したRev1.0をベースに、いくつか機能の拡張と変更を行いRev2.0にしてみましょう。

先に遊んでみましょう

今回も解説がなが~くなりそうなので、先にRev2.0のSCRATCHプロジェクトを公開しておきますね。操作方法はRev1.0と同じ+追加でマウス操作も行えるようになっています。そしてどうやらマウス操作できるようにすることでスマホでも指でパドル操作ができるようになったようです。是非スマホでも遊んでみてくださいね。そして是非遊んだ感想などコメントで教えてください。改善要望などもお聞かせください。

  • 「←」キー or 「a」キー:左移動
  • 「→」キー or 「d」キー:右移動
  • マウスに追従した左右移動

Rev2.0の機能拡張、変更内容

Rev2.0ではRev1.0から以下のような機能の拡張と変更を実施しました。

  • マウスでパドルを操作する機能を追加する
  • ブロックボールの衝突判定を高度化し、ブロックの上下辺に当たったのか左右辺に当たったのかによってボールの跳ね返り方向を変える
  • ボールの速度上昇に上限を設けた。またミス後のゲーム再開時に急激にボール速度が上昇するのを抑えた
  • ボールの突入角度が浅い時、パドルの外側から中央までにボールが当たったら跳ね返り角度を深くする変更を行う。また少しだけ跳ね返り角度にランダム性を持たせる
  • その他細かい修正

結構盛りだくさんです。特に二つ目の機能(ブロックボールの衝突判定を高度化)はなかなか思い通りに実装できず、かなーり苦労しました。(何ならまだ納得がいってません。)
では順番に見ていきましょう。

マウス操作の追加

下記はパドルのコードです。主にコード右下の部分がRev2.0で追加されました。変数「mouseX」にマウスのX座標を代入している理由は、マウスが移動したかどうかを判定するためです。もしマウスが移動していたら、パドルのX座標をマウスのX座標と一致させます(ただし横の壁を突き抜けないように考慮する必要はあります)。マウスが動いた時だけマウスに追従させそれ以外は何もしないので、Rev1.0の際のキー操作によるパドル移動もできるようにしています。

ブロックとボールの衝突判定を高度化

次はボール部分のコードの一部を下記に貼っています。ちょっとコードが長くなり過ぎたので全部を見たい人はプロジェクトの中身を見てください。この中ではボールの向きによって以下の6種類の場合分けをしています。

  • 0度 [真上に向かっている]
  • 180度 [真下に向かっている]
  • 0度より大きく90度より小さい [右上に向かっている]
  • 90度より大きい(そして180度より小さい) [右下に向かっている]
  • 0度より小さく-90度より大きい [左上に向かっている]
  • -90度より小さい(そして-180度より大きい) [左下に向かっている]

計算式の中で「向きのtan(タンジェント)」が何度も出てきますが、向きが0度や180度はtanが0になります。割り算の分母が0になるのは好ましくないので、0度や180度を最初に例外処理として書いています。なお向きが90度や-90度の時のtanは∞となるのでこちらも例外処理した方がいいんじゃないの?という疑問を持たれる方もおられるかもしれませんが、ゲームの性質上ボールの向きが90度やー90度になる(=ボールが永久に落ちてこなくなる)ことはないようにしてますので、この場合の例外処理は省略しています。

ここでやっていることを細かく説明しだすとそれだけで記事がひとつできてしまうので、一旦はサラっと解説しておきます。もし分からないことなどあればコメントに書いてもらえればもうちょっと内容を充実させるなど考えます。
まずblock Xとblock Yはボールと衝突があったブロックのX, Y座標です。ブロックは中心座標をX, Yとしていますので、そこから左右(X方向)に±BLK_X_HFSIZE、上下(Y方向)に±BLK_Y_HFSIZEの領域にブロックがあると定義しています。(BLK_X_HFSIZE, BLK_Y_HFSIZEは変数として定義していますが実態は定数です。)

定数というのは一度決めたら変わらない値のことです。そんなものを何故わざわざ変数として書いているかというと、一度に複数個所の値を変更することができて便利だからという理由と、数字をそのまま式の中に書いているとその数字の持つ意味が分からなくなることが多いから数字では書きたくないというのが理由です。定数を定義する方法が規定されている言語も多いですがSCRATCHでは用意されていないようですので変数を使って表現しました。なお、一般的に定数は全部大文字で書くことが多いのでわざと大文字の変数名にしてみました。

まずcollision Xを求めます。これはボールブロック下辺 or 上辺を延ばした線上のどこを通過したかを計算するものです。そしてこのcollision Xがblock X±BLK_X_HFSIZEの範囲内であればボールブロックの上下辺に最初に衝突したことが分かりますし、そうでなければボールブロックの左右辺に最初に衝突したことになります。上下辺に当たったか左右辺に当たったかを判定した後、ボールの向きをそれに合わせて変更しています。なお、ボールのスピードが速いためボールブロックが衝突したと判定された時には上図のようにすでにボールがかなりブロックにめり込んでいることがよくあります。そのため、一旦ブロックへの突入地点までボールのX, Y座標を戻してからボールの向きを変更しています。

ボールの速度調整

あまり細かい説明は省略しますが、Rev1.0ではボールの速度がかなり早くなることがあったのと、ボールを落としてしまった後にゲームが再開した際、最初のブロックに当たった瞬間急にボールがスピードアップするのに違和感があったので、そのあたりを調整してスピードアップがマイルドになるように修正しています。

パドル衝突時のボール跳ね返り角度調整

これはRev1.0とRev2.0でどう挙動を変えたかを下図で見ていただくのが分かりやすいかと思います。下の青いバーがパドルだと思ってください(パドルの右半分を拡大して表示している感じ)。パドル右側の挙動しか書いてませんが左側も左右対称の挙動になっています。
Rev2.0で変わったのは、オレンジの部分でボールの進入角度が浅い時(二段に分かれている矢印の上段側)にボールが外側から中央に向かって飛んできたら少し深めの角度でボールを跳ね返らせるというものです。これまでは一旦ボールの進入角度が浅くなってしまうとそれを深くする方法がありませんでしたが、この修正によりボールが当たるパドル位置をうまく調整することでボールの角度をある程度自由にコントロールできるようになりました。
また、Rev2.0側の図で「±乱」と書かれた部分は乱数で±2度までランダムにボールの跳ね返り角度を変える機能も追加しました。最後の1ブロックボールを当てるのが難しい時にこの乱数があることで当てやすくなりました。

その他細かい調整

その他の細かい調整としては以下のようなものが挙げられます。これ以外にもごく簡単な手直しは入れたかもしれませんがあまりにも変更量が多くてちょっと全部書き出せてないかもしれません。

  • パドルをやや太くしてボールが高速の際にもすり抜けしにくくする(特にゲーム終了画面の時)
  • 壁についてもボールがすり抜けしにくくした(ボールの向きを判定し、壁の外から内へ向かっている時は衝突判定しないようにした)
  • ブロックの色順を変え、下から順にとした(オリジナルのBreakOutの色順に合わせた)
  • 面をクリアしたら残機を1機追加するようにした
  • スコアと残機の表示を画面右側から左側に移動させた(スマホで遊んだ時、画面の左右が見切れることがあり、画面左側にあった方が表示が見える可能性が増えると考えたため)

最後に

今回のRev2.0で一旦はBreakOutの回を終わりにしようと思いますが、正直言ってまだブロックの壊れ方には納得がいってません。この形式に落ち着くまでに色々と試行錯誤をしました(★)が、現状の実装が今のところ一番エレガントで、そこそこ挙動も安定しているとの判断です。ちょうど仕事の方がバタバタしだしたタイミングだったということもあり、ちょっと根が尽きてしまいました。少し仕事が落ち着いたらもう一回ブロックの衝突判定については見直したいとは思ってます。

★ブロックを二つに分けて色をちょっとだけ変え、上下辺に当たったのか左右辺に当たったのかを判別できるようにするアイディアをかなり長く考えていました(極端に書くと下記ような砂時計形状を二つ組み合わせたブロックを作った)が、ボールがブロックにかなりめり込んでから衝突判定が行われることがあることと、分かれたもう一方のブロックをうまく消せないことがあって断念しました。

コメント

タイトルとURLをコピーしました