1時間でブロック崩しを作ろうとした(Java)
ゲーム作りは毎回完成せずに挫折しているので、短時間で簡単なゲームを作ろうと思い、1時間を目標にブロック崩しを作った。実際はコーディングだけで2時間半かかったが。タイトル詐欺。あくまで目標だったということで。
作業環境:eclipse
言語:Java (swing)
概観 (vine消滅により消失)
ボールやブロックなどは円・矩形描画で済ませ、効果音はなし。
バー操作を十字キーの左右で行い、ボールに当てるとボールが上に跳ね返る。ボールが下に落ちるとゲームオーバー。
スタート画面やクリア画面もないため少し寂しいが、とりあえずブロック崩しとしてプレイできるようにした。
ソースコード
breakout/Breakout/src/breakout at master · threepipes/breakout · GitHub
クラス設計
- JFrameとスレッドを用いたアニメーション
- ボール等は抽象クラスSpriteを継承する形の、申し訳程度のオブジェクト指向
JPanelを継承したクラスMainFrameで、ゲーム状態・キー受付・オブジェクトの管理といったシステム関連のことはすべて受け持っている。
個別オブジェクトの描画や更新・衝突判定などは、オブジェクト自身に任せている。
考察
キー受付
現在の実装では、1回のキー受付で1つのキーしか取得していないので、キーの同時押しの際にバーの挙動がおかしくなる。
これを回避するためには、現在押されてるキーをすべて取得し、押されている方向にx座標を動かすようにする必要がある。たとえばこの場合には、同時押しを行うと左右方向にx座標の加算が行われ、打ち消しあって止まる、などといった動作を実現できる。
衝突判定
一応の完成に至った際、バーの横からボールにぶつかると、ボールがバーに刺さるバグが残っていた*1。一般的なブロック崩しではどのような対応をしているのだろうと気になって探したところ、対応の種類がいくつかあった。
- ボールがどこからぶつかっても、y座標を強制的にバーの上に変更
- 当たった角度によって反射角度を変える、物理挙動に近い動作
- バーが球
- バーにボールが当たるとくっついて、再発射できる
下2つは別物という感じだが、考え方として面白かった。上2つはだいたい半々の割合で見つかり、実装が楽な1つ目を採用した。
感想
作成直前になって「これ矩形と円の衝突判定いるじゃん!やったことないって!」と慌てて調べたものだから、衝突判定がベクトルを使った大仰な実装になってしまった。よく考えてみれば、矩形の縦横はxy座標に平行なのだから、xy座標の比較だけで済む話だった。
そもそも形にするだけならボールを矩形として扱ってもよかった。
ゲーム作成、特に2Dゲームは数学的・物理的に"厳密な動作"というよりも、"納得できる動作"が求められることが多いので、次回短時間で作るときは、うまくごまかせる簡潔な実装をしたい。
*1:これは衝突判定の順番や衝突後の処理の簡素化に起因していたもので、求めていた挙動(横からぶつかったボールは横に反射する)にするためにはボールが1フレーム前にどこにいたか、という情報が必要だった