micro:bit 判断力ゲームのプログラム実装 — スプライト・関数・フロー設計の詳細
前回の記事で定義した判断力ゲームの仕様をもとに、MakeCode でプログラムを実装します。スプライト機能を活用して自機・弾・ライフを管理し、関数に処理を分割することで見通しのよいコードを作成します。
目次
実装ステップの全体設計
複雑なゲームをいきなり実装しようとすると難しく感じますが、処理を小さなステップに分けて順番に実装することで確実に進められます。以下の順序でプログラムを作成します。

- 壁エリアの設置
- ライフエリアの設置
- ゲームエリア:自機の設置
- ボタン動作の設計
- メインフロー設計
- ゲームエリア:弾の生成・削除処理
- ゲームエリア:弾の移動処理
- ゲームエリア:弾と自機の接触判定処理
- ライフエリア・ライフ処理
- ゲームオーバー処理
- スコア処理
- 難易度調整
スプライト機能と LED 座標の理解
このゲームのプログラミングでは「ゲーム」パーツリストの中のスプライト機能を使います。スプライトは LED 上のコマのようなもので、壁の作成・ボタンによる制御・接触判定・削除などさまざまな動作を実現できます。
micro:bit の LED は以下の座標で管理されています。スプライトを配置する際の参考にしてください。

① 壁エリア・② ライフエリア・③ 自機の設置
スプライト機能を使って壁エリアを設計します。純粋な壁としての利用なので特別な制御は不要です。「最初だけ」ブロックに以下のようにプログラムしてください。

この時点でシミュレータ画面は以下のようになります。

同様の方法でライフ・自機も設置します。変数名は後から見返してもわかりやすい名前にすることをお勧めします。ライフは初期値 5 でスプライトと変数の両方を用意し、弾の存在有無を示す flag 変数もここで用意します。

④ ボタン動作の設計
A ボタンで自機を左に、B ボタンで自機を右に移動するようプログラムします。B ボタンは壁を超えないよう、自機の現在位置を確認してから移動するかどうかを判定してください。A+B ボタン同時押しはリセット(「制御」パーツリストから選択)です。

ここまで作成すると A・B ボタンで自機が動かせるようになります。一度バイナリをダウンロードして実機で動作を確認してみてください。
⑤ メインフロー設計(弾の4フェーズ処理)
弾の生成・移動は以下の4フェーズで実行されます。各フェーズ間には wait(1秒の待ち時間)を入れます。太字は関数名です。
- フェーズ1:弾を1つ下に移動(atk_move)→ 接触判定(atk_check)→ ATK1/2 削除(atk_delete_12)→ ATK1/2 生成(atk_create_12)
- フェーズ2:弾を1つ下に移動(atk_move)
- フェーズ3:弾を1つ下に移動(atk_move)→ 接触判定(atk_check)→ ATK3/4 削除(atk_delete_34)→ ATK3/4 生成(atk_create_34)
- フェーズ4:弾を1つ下に移動(atk_move)
まず関数の中身を空の状態で仮作成し、「ずっと」ブロックに以下のように配置してください。

⑥ 弾の生成・削除処理(atk_create / atk_delete)
弾を生成する atk_create_12 / atk_create_34 関数を実装します。「計算」パーツリストの乱数パーツを活用してください。

削除関数 atk_delete_12 / atk_delete_34 では、存在しないスプライトを削除するとエラーになるため、atk_flag でスプライトの有無を確認してから削除します。

⑦ 弾の移動処理(atk_move)
弾を下方向に移動させる処理です。存在しないスプライトを移動させるとエラーになるため、flag で有無を確認してから移動します。

⑧ 弾と自機の接触判定処理(atk_check)
弾が自機に接触しているかを判定する atk_check 関数を実装します。ここでも flag でスプライトの有無を確認します。最後に life_update 関数を呼び出すため、中身が空の状態で先に作成しておいてください。

⑨ ライフエリア・ライフ処理(life_update)
life_update 関数では残ライフに応じてライフ表示を更新し、ライフが 0 になったら gameover 関数を呼び出します。gameover 関数も先に空の状態で作成しておいてください。

⑩ ゲームオーバー処理(gameover)
ライフが 0 になった時の gameover 関数を実装します。スコアに応じてアイコン表示を切り替えます。

※2023/8/10 追記:上記画像のスコア毎のアイコン表示方法に誤りがありました。以下のいずれか1つのみが選択されるようコードを修正してください。
- score < 10
- score < 20
- score >= 20
⑪ スコア処理
「最初だけ」ブロックにスコア変数を追加します(初期値 0)。

加点のタイミングはゲームデザインの自由度が高い部分です。「ずっと」ブロックの4フェーズが一巡するごとに +1 点とする実装例を以下に示します。

⑫ 難易度調整(弾の速度を徐々に上げる)
このままでは熟練したプレイヤーがゲームをし続けられてしまいます。speed 変数(初期値 1000)を「最初だけ」ブロックに追加します。

「ずっと」ブロックを以下のように変更して、弾の速度を徐々に上げます。速度変化の具合もゲームデザインとして自由に調整できます。

これでゲームが完成しました。ぜひ実際にプレイして動作を確認してください。関数の中身で不明な点があればお気軽にお問い合わせください。






ディスカッション
コメント一覧
こんにちは。
いつも参考にさせて頂いております。
判断力ゲームの
関数 game over のアイコンを表示する部分が点数によっては2種類表示されてしまいます。
点数判定の「もし 〜 なら」の連続した判断ではなく、「もし 〜 なら 〜 でなければもし 〜 なら 〜 でなければ 〜」で判断するようにした方がよいのではないでしょうか?
よろしくご回答をお願い致します。
尾崎様
確認致しましたが、スコア表示の後のアイコン表示については尾崎様にコメント頂いた通り、現状のコードでは意図した動作になりませんので「もし 〜 なら 〜 でなければもし 〜 なら 〜 でなければ 〜」という、いずれか1つのみを選択するような判定文を用いるべきですね。
私の方では作成した後に十分にテストが出来ておりませんでした。ご指摘頂き有難うございます。
ブログの方には注釈を入れておきたいと思います。
今後とも宜しくお願い致します。