ながみえ

一つ前のペチャプターでは反射させるバーを設置しました。

今回は ゲームオーバーの設定 について見ていきましょう。

Chapter1:pygame入門|画面を表示しよう
Chapter2:簡単なノベルゲームを作ろう
Chapter3:簡単なアクションゲームを作ろう
Chapter4:ブロック崩しを作ろう
 ・Chapter4-1:ボールを壁に反射させよう
 ・Chapter4-2:反射させるバーを設置しよう
 ・Chapter4-3:ボールが画面下に落ちたらゲームオーバー ◁今回はここ
 ・Chapter4-4:ぶつかると消えるブロックを配置しよう
Chapter5:シューティングゲームを作ろう
Chapter6:pygameのお役立ち情報

前回のチャプターではボールがバーに当たると跳ね返る処理を追加し、プレイヤーが操作によってボールをコントロールできるようになりました。

これにより、いよいよ「ブロック崩しゲームらしさ」が出てきましたね。

今回はプレイヤーがミスしたときの仕組み、つまり「ゲームオーバー処理」を追加していきます。

具体的には、ボールが画面の一番下まで落ちてしまった場合に、ゲームを終了させて「GAME OVER」と表示する機能を作っていきます。

また、ゲームオーバー後に「リプレイボタン」をクリックすることで、もう一度ゲームを最初から始められるようにもしていきます。

それではボールの動きをもとに、ゲームオーバーの条件を判定する方法から見ていきましょう。

本記事は会員向けの有料記事ですが、現在は期間限定で無料公開中です。

注意点

チャプター4を通してブロック崩しゲームを制作するにあたり、ベースとなるコードや使用する画像をまとめた「Chapter4_set.zip」を 無料配布 しています。

まだ入手していない人は、まずは pygameのトップページ に移動し、チャプター4の章から ダウンロード してください。

<<前のページ

pygameの記事一覧

Pythonのゲームライブラリ pygame を使ってゲームアプリを制作するページのアイキャッチ画像

次のページ>>

ゲームオーバーとは?

ゲームを作る上で、「ゲームオーバー」という仕組みはとても大切です。

プレイヤーが何らかの条件でゲームに失敗したときに、それを明確に伝え、ゲームを終了させる演出を加えることで、ゲームに緊張感や目的意識が生まれます。

今回のブロック崩しゲームでは、「ボールが画面下まで落ちてしまったら失敗」とします。

【Python】勉強猫がノートパソコンを前にして学習を始める様子。記事内の学習スタート用イラスト

画面下に落ちたかどうかの判定を追加しよう

それでは、ゲームオーバーの条件をコードに追加していきましょう。

今回のゲームは画面サイズが「800×600ピクセル」となっており、ボールの縦方向の位置は「ball_rect.y」で管理されています。

ボールが画面下に落ちたかどうかを判定するには、ボールのy座標が600よりも大きくなったかを調べれば良いということになります。

また、ボールが落ちたときに画面を「ゲームオーバー状態」に切り替えるために、「page」という変数を使います。

この変数は現在の画面の状態(プレイ中・ゲームオーバー・ゲームクリアなど)を切り替えるために使用されています。

コードを書いてみよう

まず、現状の「brick_breaker.py」は画面下にボールが到達したときも跳ね返るようになっています。

「## ゲームステージ関数 」の中の「# ボールの処理」の部分を修正して、画面下では跳ね返る処理を削除しましょう。

その後、同じく「# ボールの処理」の部分に以下のコードを書き足しましょう。

if ball_rect.y > 600:  # もしボールが画面下に到達したら
    page = 2           # ゲームオーバー画面に切り替える

この処理を入れることでボールが下に落ちたときに page の値が「2」に変わり、ゲームオーバー用の画面を表示できるようになります。

ゲームオーバー関数を作ろう

ボールが画面の下に落ちたときに page を「2」に切り替える処理を追加しました。

次はその page == 2 のときに表示される「ゲームオーバー画面」を作っていきましょう。

ゲームオーバー画面の役割

ゲームオーバー画面では、次のような要素を表示します。

  • 「GAMEOVER」の文字
  • ゲームをリセットして再挑戦できる「リプレイボタン」

これにより、プレイヤーが失敗してもすぐにやり直せるようになります。

コードを書いてみよう

「brick_breaker.py」の「## ゲームステージ関数 」の下に以下のコードを書き足しましょう。

## ゲームオーバー関数
def gameover():
    reset()  # リセット関数の呼び出し
    screen.fill(pygame.Color("YELLOW"))  # 画面を黄色で塗りつぶす
    font = pygame.font.Font(None, 150)  # フォントを設定
    text = font.render("GAMEOVER", True, pygame.Color("RED"))  # GAMEOVERの文字を赤色で描画
    screen.blit(text, (100, 200))  # 画面に文字を表示
    btn1 = screen.blit(replay_img, (320, 480))  # リプレイボタンを表示
    button_to_jump(btn1, 1)  # ジャンプ関数の呼び出し

この関数では、後で定義するreset()関数を呼び出してボールやスコアなどを初期状態に戻しています。

その後GAMEOVERの文字を画面に大きく表示し、リプレイ用のボタンを表示しています。

【Python】勉強猫がノートパソコンを見ながら考え込む様子。記事内の休憩用イラスト

ジャンプ関数を作ろう

ゲームオーバー画面が表示されたら、次に必要なのは「再挑戦できる仕組み」です。

プレイヤーが「リプレイボタン」をクリックしたときに、ゲームがリセットされて再びスタートできるようにする必要があります。

そのために使うのが、マウスクリックを検出してページを切り替える補助関数 button_to_jump() です。

実装する関数:button_to_jump()

この関数は指定されたボタンの範囲内でマウスの左クリックが押されたときに、ゲームのページ(状態)を切り替える役割を持ちます。

コードを書いてみよう

「brick_breaker.py」の「## ゲームステージ関数 」の下に以下のコードを書き足しましょう。

## ジャンプ関数(ボタンが押されたらnewpageへジャンプする)
def button_to_jump(btn, newpage):
    global page, pushFlag
    mdown = pygame.mouse.get_pressed()  # マウスボタンの状態を取得
    (mx, my) = pygame.mouse.get_pos()   # マウスカーソルの位置を取得
    if mdown[0]:  # 左クリックが押されているかを判定
        if btn.collidepoint(mx, my) and pushFlag == False:  # ボタンの範囲内かつ1回だけ反応させる
            page = newpage  # 指定されたページに切り替える
            pushFlag = True
    else:
        pushFlag = False  # マウスを離したらフラグを戻す

この関数の引数 btn は、ボタン画像を描画したときに返される矩形(Rect型)です。

newpage にはクリック後に切り替えたいページ番号を渡します。今回の場合、再スタートのために 1 を指定しています。

  • page = 1 :ゲーム画面
  • page = 2 :ゲームオーバー画面
  • page = 3 :ゲームクリア画面

リセット関数を作ろう

ゲームに「再挑戦」の機能を加えるときに欠かせないのが、ゲームの状態を元に戻す処理です。

前の章で紹介した「リプレイボタン」を押したときに、次のゲームが前回の続きになってしまっては正しい動作とは言えません。

そこで必要になるのが、reset() 関数です。

この関数は、ボールの位置やスピードなどを最初の状態に戻す働きを持っています。

コードを書いてみよう

「brick_breaker.py」の「## ゲームステージ関数 」の下に以下のコードを書き足しましょう。

## リセット関数(ゲームをリセットする)
def reset():
    global vx, vy, score, blocks
    vx = random.randint(-10, 10)  # 横方向のスピードをランダムに
    vy = -5                       # 縦方向のスピードは一定(上方向)
    ball_rect.x = 400 # ボールの位置を初期位置に戻す
    ball_rect.y = 450
    # ブロックの初期化(Chapter4-4で追加)
【Python】勉強猫がコーヒーを片手にリラックスしている様子。記事内の休憩用イラスト

メインループを更新しよう

これまでの章で、ゲームオーバーの処理と、ゲームのリスタート機能を追加しました。

これらを正しく動かすためには、「現在どの画面を表示するか」を制御する仕組みが必要です。

この制御を行っているのが、変数 page です。

page の値に応じて、プレイ画面・ゲームオーバー画面などを切り替えられるように、メインループ内で条件分岐を設定しておきます。

コードを書いてみよう

「# メインループ」の中に以下のコードを書き足し(書き換え)ましょう。

# メインループ
while True:
    if page == 1:
        gamestage()  # 通常のプレイ画面
    elif page == 2:
        gameover()   # ゲームオーバー画面

まとめ

今回はブロック崩しゲームに「ゲームオーバー」の機能を追加しました。

ボールが画面の下まで落ちてしまったときにゲームオーバーとし、「GAMEOVER」と表示される専用の画面を表示するようにしました。

「失敗があるからこそ成功が嬉しい」——そんなゲームらしさが、この章でしっかりと形になったのではないでしょうか。

次のチャプターでは、いよいよ画面内にブロックを配置し、ボールが当たると壊れる処理を追加していきます。

ここまで読み進めてくださった皆さん、本当にお疲れさまでした。

次のステップへ進む準備は万端です。それでは、次回もがんばっていきましょう!

Q
Chapter4-3の完成コード

今回の記事での完成するコード全体は↓↓の通りです。

必要な方は開いて確認しましょう。

# 初期化(ゲームの準備をする)
import pygame, sys, random
pygame.init()
screen = pygame.display.set_mode((800, 600))
## 背景の設定
haikei_img = pygame.image.load("images/hoshizora.png")
haikei_img = pygame.transform.scale(haikei_img, (800, 600))
# ボールの設定
ball_rect = pygame.Rect(400, 450, 30, 30)  # x=400, y=450 の位置に、30x30の正方形を配置
vx = random.randint(-10, 10)  # x方向の初期速度(ランダムに設定)
vy = -5                       # y方向の初期速度(上に向かって移動)
## バーの設定
bar_rect = pygame.Rect(400, 550, 100, 10)
## ブロックの設定

## リプレイボタンの設定
replay_img = pygame.image.load("images/replaybtn.png")
## メインループ内で使う変数
pushFlag = False
page = 1
score = 0

# ここから各関数の定義
## ゲームステージ関数
def gamestage():
    # 画面の初期化
    global vx, vy, page, score
    screen.blit(haikei_img, (0,0))
    # ユーザー入力
    (mx, my) = pygame.mouse.get_pos()
    # ボールの処理
    if ball_rect.y < 0:  # 画面の上下端に到達したら
        vy = -vy  # 縦方向の速度を反転
    if ball_rect.x < 0 or ball_rect.x > 800 - 30:  # 画面の左右端に到達したら
        vx = -vx  # 横方向の速度を反転
    if ball_rect.y > 600:  # もしボールが画面下に到達したら
        page = 2           # ゲームオーバー画面に切り替える
    if bar_rect.colliderect(ball_rect): # もしバーがボールと衝突したら
        vx = ((ball_rect.x + 15) - (bar_rect.x + 50)) / 4
        vy = random.randint(-10, -5)
    ball_rect.x += vx  # x方向に移動
    ball_rect.y += vy  # y方向に移動
    pygame.draw.circle(
        screen,                # 描画先の画面
        pygame.Color("GOLD"),  # ボールの色(GOLDに設定)
        ball_rect.center,      # 円の中心座標(Rectの中心)
        ball_rect.width // 2   # 円の半径(Rectの幅の半分)
    )

    # バーの処理
    bar_rect.x = mx - 50
    pygame.draw.rect(screen, pygame.Color("BLUE"), bar_rect)

    # ブロックの処理


## ジャンプ関数(ボタンが押されたらnewpageへジャンプする)
def button_to_jump(btn, newpage):
    global page, pushFlag
    mdown = pygame.mouse.get_pressed()  # マウスボタンの状態を取得
    (mx, my) = pygame.mouse.get_pos()   # マウスカーソルの位置を取得
    if mdown[0]:  # 左クリックが押されているかを判定
        if btn.collidepoint(mx, my) and pushFlag == False:  # ボタンの範囲内かつ1回だけ反応させる
            page = newpage  # 指定されたページに切り替える
            pushFlag = True
    else:
        pushFlag = False  # マウスを離したらフラグを戻す

## リセット関数(ゲームをリセットする)
def reset():
    global vx, vy, score, blocks
    vx = random.randint(-10, 10)  # 横方向のスピードをランダムに
    vy = -5                       # 縦方向のスピードは一定(上方向)
    ball_rect.x = 400 # ボールの位置を初期位置に戻す
    ball_rect.y = 450
    # ブロックの初期化(Chapter4-4で追加)

## ゲームオーバー関数
def gameover():
    reset()  # リセット関数の呼び出し
    screen.fill(pygame.Color("YELLOW"))  # 画面を黄色で塗りつぶす
    font = pygame.font.Font(None, 150)  # フォントを設定
    text = font.render("GAMEOVER", True, pygame.Color("RED"))  # GAMEOVERの文字を赤色で描画
    screen.blit(text, (100, 200))  # 画面に文字を表示
    btn1 = screen.blit(replay_img, (320, 480))  # リプレイボタンを表示
    button_to_jump(btn1, 1)  # ジャンプ関数の呼び出し

## ゲームクリア関数


# メインループ
while True:
    if page == 1:
        gamestage()  # 通常のプレイ画面
    elif page == 2:
        gameover()   # ゲームオーバー画面

    # 画面表示
    pygame.display.update()
    pygame.time.Clock().tick(60)
    # 終了処理
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

<<前のページ

pygameの記事一覧

Pythonのゲームライブラリ pygame を使ってゲームアプリを制作するページのアイキャッチ画像

次のページ>>

質問用コンタクトフォーム

この記事を書くにあたりAIを活用しています。

人間の目による確認も行っていますが、もし間違い等ありましたらご指摘頂けると大変助かります。

pygame記事一覧へ戻る
Python記事一覧へ戻る

記事URLをコピーしました