もどる

この記事は「うずら」とAIが協力して作成しました。
なるべく正確さを心がけていますが、最新の公式ドキュメントなどもあわせて確認してみてね!

python2026.3.19

4-9. 伝説の完結:タイトル画面とエンディング

伝説の完結
ゲーム完成

皆さん、こんにちは!世界最高に親切な技術講師うずらです。

退屈な授業からの脱出!から始まった「目に見える形でPythonを学ぼう!」の旅も、いよいよクライマックスです。これまでたくさんの魔法を学び、宇宙を舞台にしたシューティングゲームを作り上げてきました。

今回は、ゲームの始まり(タイトル)終わり(エンディング)、そして失敗(ゲームオーバー)の場面を実装し、皆さんの作品を一つの完成形に仕上げていきます。

1. 3秒でわかるまとめ

ゲームの状態を「進行中」「ゲームオーバー」「ゲームクリア」の3つに分け、それぞれの状況に応じて表示や処理を切り替えることで、ゲーム全体を一つの作品として完結させます。

+-----------------------+
|  ゲーム起動           |
|  (初期状態)           |
+----------|------------+
           v
+-----------------------+
|  ゲームプレイ中       |
|  (敵出現、移動、攻撃) |
+----------|------------+
     +----+----+
     |         |
     v         v
+----------+  +----------+
| ゲームオーバー |  | ゲームクリア |
|  (自機撃墜) |  | (ボス撃破) |
+----------+  +----------+

2. ゲームの結末を司る「状態変数」

ゲームが複雑になってくると、「今、ゲームはどんな状況にあるのか?」をプログラムに教えてあげる必要があります。これを「ゲームの状態」や「シーン」と呼びます。

今回は、これまでの game_over 変数に加えて、新たに stage_clear という変数を導入します。

# ゲーム進行状況
score = 0
game_over = False
stage_clear = False # 新しく追加
boss_active = False

この stage_clear 変数は、ボスを倒したときに True に設定され、ゲームのクリア状態を表します。

update 関数と draw 関数の冒頭で、これらの状態変数を使って処理を分岐させます。

# --- 1. ゲームオーバー / クリアチェック ---
if game_over or stage_clear:
    return

game_over または stage_clear のどちらかが True であれば、それ以降の update 関数の処理(プレイヤーの操作、敵の移動、当たり判定など)はすべてスキップされます。return は関数の処理をそこで終了させる指示です。

補足だよ

return文は、関数がその時点で処理を終えることを意味します。これにより、ゲームオーバーやゲームクリアの表示中は、プレイヤー操作や敵の動きが停止し、静止画のようになります。

3. 伝説の終幕!ゲームクリア画面の実装

ボスを撃破したときに、stage_clearTrue に切り替える処理を追加しましょう。前回の記事 実践:決戦モード変化 でボスのHP管理を実装しましたね。その部分に手を加えます。

まずは、update 関数内のボス撃破判定の箇所を見てみましょう。

            # ... (中略) ...
                
                if boss['hp'] <= 0:
                    boss = None
                    score += 1000
                    stage_clear = True # ここを追加
                    boss_active = False
                    spawn_particles(player_x, player_y - 20, 100, COL_RED) 
                    break

ボスが倒されたとき (boss['hp'] <= 0) に、stage_clearTrue に変更しています。これで、ゲームがクリア状態になったことをプログラムが認識できるようになりました。

次に、draw 関数でクリア画面を表示する処理を追加します。

    # ゲームオーバー
    if game_over:
        pyxel.text(55, 50, "GAME OVER", COL_RED)
        pyxel.text(45, 60, f"SCORE: {score}", COL_WHITE)
        return
        
    # ゲームクリア (追加する部分)
    if stage_clear:
        pyxel.text(55, 50, "GAME CLEAR!!", COL_YELLOW)
        pyxel.text(45, 60, f"SCORE: {score}", COL_WHITE)
        return

draw 関数では、まず game_overstage_clear のどちらかが True かを確認します。

  • もし game_overTrue なら、「GAME OVER」の文字とスコアを表示して return で描画を終了します。
  • もし stage_clearTrue なら、その後に「GAME CLEAR!!」の文字とスコアを表示して return で描画を終了します。

これにより、ゲームオーバーとゲームクリアのどちらかの状態になった場合、それ以降のゲームオブジェクト(プレイヤー、敵など)の描画は行われず、メッセージだけが表示されるようになります。

補足だよ

if game_over: のブロックの後に if stage_clear: のブロックが来ることで、ゲームオーバーとクリアが同時に発生する状況(通常はありませんが)でも、どちらか一方だけが適切に表示されます。この順番が逆だと、意図しない表示になる可能性があります。

4. 盛り上がるゲーム体験!効果音を追加しよう

ゲームには、音の演出が欠かせません。プレイヤーの操作や敵の爆発に効果音が加わることで、ゲーム体験は格段に向上します。Pyxelには、簡単に音を鳴らす機能が用意されています。

まず、pyxel.init の直後に、ゲーム全体で使う音を定義しましょう。

# --- Pyxelの初期化と音の定義 ---
pyxel.init(SCREEN_WIDTH, SCREEN_HEIGHT, title=GAME_TITLE)

# Sound 0: ヒット音 / 撃破音
pyxel.sound(0).set('c2c1', 'n', '6', 'f', 25)
# Sound 1: 発射音
pyxel.sound(1).set('a2g2', 's', '2', 'f', 4)
# Sound 2: パワーアップ / アイテム取得
pyxel.sound(2).set('c2e2g2c3', 't', '6', 'nn', 30)
# Sound 3: ボス出現音
pyxel.sound(3).set('c1d1e1f1g1a1b1c2', 't', '6', 'nn', 60)
# Sound 4: ボム音
pyxel.sound(4).set('c2c2c2c2', 'n', '7', 'f', 10)

pyxel.sound(番号).set(ノート, タイプ, ボリューム, テンポ, ゲート) という形式で音を定義します。

  • 番号: 0から15までの音源番号です。
  • ノート: 音の高さ。'c2c1' のように音階を文字で指定します。cがド、dがレ、eがミ、fがファ、gがソ、aがラ、bがシ。数字はオクターブを表し、_ は休符です。
  • タイプ: 音の波形。's' は方形波、't' は三角波、'p' はパルス波、'n' はノイズです。
  • ボリューム: 音量。'6' のように1から7までの文字で指定します。
  • テンポ: 音の速さ。'f' は速く、'n' は普通、's' は遅いです。
  • ゲート: 音の持続時間。数値が小さいほど短く、音が途切れて聞こえます。

次に、ゲーム内の各イベントで音を鳴らすために pyxel.play() 関数を使います。

# 弾の発射時
if pyxel.btnp(pyxel.KEY_SPACE):
    # ... (中略) ...
    pyxel.play(1, 1) # Sound 1 をチャンネル 1 で再生

# ボム発動時
if pyxel.btnp(pyxel.KEY_Z) or pyxel.btnp(pyxel.KEY_B):
    trigger_bomb()
    pyxel.play(3, 4) # Sound 4 をチャンネル 3 で再生

# ボス出現時
if score >= 500: # ボス出現条件
    # ... (中略) ...
    pyxel.play(3, 3) # Sound 3 をチャンネル 3 で再生

# ボス被弾時
if boss['hp'] -= 1:
    # ... (中略) ...
    pyxel.play(0, 0) # Sound 0 をチャンネル 0 で再生

# 敵被弾・撃破時
if hit:
    # ... (中略) ...
    pyxel.play(0, 0) # Sound 0 をチャンネル 0 で再生

# アイテム取得時
if check_collision(...): # アイテム取得判定
    # ... (中略) ...
    pyxel.play(2, 2) # Sound 2 をチャンネル 2 で再生

pyxel.play(チャンネル, 音源番号) で、指定した音源を再生できます。チャンネルは0から3まであり、同時に鳴らせる音の数を示します。例えば、弾を撃ちながら敵を倒すときなど、複数の音が同時に鳴るように設定できます。

豆知識

同じ音源を複数のチャンネルで再生することもできます。例えば、Sound 0(ヒット音)を同時に2つのチャンネルで再生すれば、少し厚みのある音にすることも可能です。

これで、皆さんのゲームは視覚だけでなく、聴覚にも訴えかける、より臨場感あふれる作品へと進化しました!

5. 完成!伝説の宇宙シューティングをプレイしよう

おめでとうございます!これで皆さんの「ASTRO SURVIVOR」は、タイトル、ゲームプレイ、エンディング、ゲームオーバーが全てつながった、一つの完全な作品として完成しました。

これまでの道のりで学んだ変数、リスト、辞書、関数、条件分岐、そしてPyxelを使った描画や操作、当たり判定など、Pythonプログラミングの基礎がゲームを通して「目に見える形」で繋がったことを実感できたのではないでしょうか。

このゲームは、皆さんのプログラミングの旅の始まりに過ぎません。これからも新しいアイデアを思いつき、どんどん改造して、自分だけの伝説のゲームを作り続けてくださいね!


これでゲームは完成です。ぜひ、下の完成版を実際に動かして、皆さんの作ったゲームのエンディングまでプレイしてみてください!

実際に動かしてみよう!

矢印キーで自機移動、スペースキーでショット、ZキーまたはBキーでボム発動です。敵を倒してボスを出現させ、撃破してクリアを目指しましょう!

最後まで読んでくれてありがとう!🌱
ノートみたいに、いつでも見返してね。