見出し画像

Step82 pygame入門⑩:残り時間を追加して、ゲーム終了処理を作る

さてこれまで

  • キャラクターを動かす

  • ジャンプする

  • アイテムを獲得する

  • スコアをカウントする

という、ゲームの基本要素 を一通り作ってきましたね(*^^*)

今回はいよいよこのシリーズの終了に近づく1歩目、

「制限時間の追加」

に進んでいきます。

ゲームには始まりがあれば「終わりもあります」。
終わりがあるから楽しめるとも言えるかもしれません。


1. 今回やること

今回についてまとめると、次の4つを追加することになります。

  1. 残り時間(60秒)を表示する

  2. 時間が減っていく仕組みを作る

  3. 時間切れでゲームを終了状態にする

  4. 画面中央にスコアを表示し、動きを止める


2. 「時間」をどうやって測るか

pygame では、
現在の時間(ミリ秒) を簡単に取得できるようになっています。

pygame.time.get_ticks()

これは、

  • プログラム開始からの経過時間

  • 単位はミリ秒(1000ミリ秒 = 1秒)

という意味になります。


3. 残り時間の変数を用意する

まず、制限時間を決めます。

TIME_LIMIT = 60  # 制限時間(秒)
start_time = pygame.time.get_ticks()
  • TIME_LIMIT → ゲーム全体の制限時間

  • start_time → ゲーム開始時刻


4. 残り時間を計算する

毎フレーム、次のように計算しましょう。

elapsed_time = (pygame.time.get_ticks() - start_time) // 1000
remaining_time = TIME_LIMIT - elapsed_time
  • get_ticks() で今の時刻を取得

  • 開始時刻との差を取る

  • 1000 で割って「秒」に変換します

  • 制限時間から引く

これで、「残り何秒なのか」が分かるようになります。


5. ゲーム終了フラグを用意する

「ゲームが終わったかどうか」を管理するためにも、次のような変数を用意しておきましょう。

game_over = False
  • False → プレイ中

  • True → ゲーム終了


6. 時間切れでゲーム終了にする

if remaining_time <= 0:
    remaining_time = 0
    game_over = True

やることは単純で、if文を使用します。
つまり次のような理屈によってゲームオーバー状態かどうかを切り替えます。

  • 時間が 0 になったら

  • ゲーム終了状態


7. ゲーム終了中は「動かさない」

とても大事なポイントですが、これはもしかしたら動けるのも面白いかもしれません。好みが分かれそうです(><)
ただ、このステップでは一応「動かさない」方向で進みたいと思います。

ゲームが終わったら、操作を受け付けないようにする

移動やジャンプの処理をgame_over が False のときだけ行えるように制限しておきます。


8. 完成コード

import pygame
import sys

pygame.init()

WIDTH, HEIGHT = 640, 480
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Step82: Timer")

clock = pygame.time.Clock()

# フォント
font = pygame.font.SysFont(None, 32)
big_font = pygame.font.SysFont(None, 48)

# キャラクター
player_image = pygame.image.load("neko.png")
player_rect = player_image.get_rect()
player_rect.topleft = (100, 200)

speed = 5
gravity = 1
jump_power = -15

dx = 0
dy = 0
on_ground = False
facing_right = True

# ステージ
blocks = [
    pygame.Rect(0, 400, 640, 40),
    pygame.Rect(250, 300, 120, 20),
]

# アイテム
item_image = pygame.image.load("catfood.png")
item_rect = item_image.get_rect()
item_rect.topleft = (350, 260)
item_count = 0

# タイマー
TIME_LIMIT = 60
start_time = pygame.time.get_ticks()
game_over = False

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

        if not game_over:
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE and on_ground:
                    dy = jump_power
                    on_ground = False

    keys = pygame.key.get_pressed()

    if not game_over:
        dx = 0
        if keys[pygame.K_RIGHT]:
            dx = speed
            facing_right = True
        if keys[pygame.K_LEFT]:
            dx = -speed
            facing_right = False

        # 横移動
        player_rect.x += dx
        for block in blocks:
            if player_rect.colliderect(block):
                player_rect.x -= dx

        # 重力
        dy += gravity
        player_rect.y += dy

        on_ground = False
        for block in blocks:
            if player_rect.colliderect(block):
                if dy > 0:
                    player_rect.bottom = block.top
                    dy = 0
                    on_ground = True

        # アイテム取得
        if item_rect and player_rect.colliderect(item_rect):
            item_count += 1
            item_rect = None

    # 残り時間計算
    elapsed_time = (pygame.time.get_ticks() - start_time) // 1000
    remaining_time = TIME_LIMIT - elapsed_time

    if remaining_time <= 0:
        remaining_time = 0
        game_over = True

    # 描画
    screen.fill((180, 220, 255))

    for block in blocks:
        pygame.draw.rect(screen, (100, 100, 100), block)

    if item_rect:
        screen.blit(item_image, item_rect.topleft)

    if facing_right:
        screen.blit(player_image, player_rect.topleft)
    else:
        flipped = pygame.transform.flip(player_image, True, False)
        screen.blit(flipped, player_rect.topleft)

    # 表示
    time_text = font.render(f"Time: {remaining_time}", True, (0, 0, 0))
    score_text = font.render(f"Food: {item_count}", True, (0, 0, 0))

    screen.blit(time_text, (10, 10))
    screen.blit(score_text, (10, 40))

    if game_over:
        result = big_font.render(f"Food: {item_count}", True, (0, 0, 0))
        rect = result.get_rect(center=(WIDTH // 2, HEIGHT // 2))
        screen.blit(result, rect)

    pygame.display.update()
    clock.tick(60)

9. ポイントまとめ

  • 時間管理は get_ticks()

  • 秒に直すには 1000 で割る

  • game_over フラグで処理を止める

  • ゲームは「状態管理」が重要である

次の記事


いいなと思ったら応援しよう!

DOI@日々学びの本質を考え続ける探求者 よろしければ応援お願いします! いただいたチップは引き続きプログラミングや学びについて、皆さんの利益になるようなよい記事を書くことで恩返しをさせていただきます!