【ゼロから始めるPython】Pythonでスカッシュゲーム(壁打ちテニス)を作ってみよう!

AIプログラミング
この記事を書いた人
柊あい

生成AI研究家。新卒で一般企業に就職するも、日々の過酷な残業でメンタルを崩し、退職。
そんな中、生成AIに出会い、当時はまだ珍しかったAI活用フリーランサーとして活動。現在はAI活用を広めるインフルエンサーとして、本サイトの記事の執筆を担当。

公式SNSをフォローする

はじめに

今回は、Pygameを使って簡単なスカッシュ(壁打ちテニス)ゲームを作成する方法を紹介します。本記事では、ゲームの設計から実装までをステップバイステップで解説し、最終的にスコア機能やゲームオーバー処理を実装した完全なゲームを作成します。

Pythonで制作できるゲーム一覧はこちらの記事で確認できます!

必要な機能

今回のスカッシュゲームには、以下の機能を実装します。

  • スタート画面:ゲーム起動時に「ENTERキー」を押すとゲームが始まる。
  • プレイ画面:ボールとバーが表示され、ボールが等速で移動。
  • バーの操作:左右キーでバーを動かせる。
  • ボールの反射:壁やバーに当たるとボールが跳ね返る。
  • スコアの加算:ボールがバーに当たるたびに10点加算。
  • ゲームオーバー処理:ボールが画面下に落ちるとゲームオーバー。
  • リスタート:ゲームオーバー画面でENTERキーを押すと、スタート画面に戻る。

準備: 必要なライブラリのインストール

Pygameを使用するので、以下のコマンドを実行してインストールしてください。

pip install pygame

ステップ1: 基本設定と画面の準備

まず、Pygameを初期化し、ゲームウィンドウを設定します。

import pygame

# 画面のサイズ
WIDTH, HEIGHT = 600, 400

# Pygameの初期化
pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Squash Game")
font = pygame.font.Font(None, 36)
clock = pygame.time.Clock()

ステップ2: 色とキャラクター・ゲーム要素の設定

ボールやバーのサイズ、速度、色を設定します。

# 色の設定
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)

# ゲーム要素のサイズ
BAR_WIDTH, BAR_HEIGHT = 100, 10
BALL_SIZE = 10
BALL_SPEED = 4
BAR_SPEED = 6

ステップ3: スタート画面と状態管理

ゲームには3つの状態(スタート、プレイ中、ゲームオーバー)があります。

START, PLAYING, GAME_OVER = "start", "playing", "game_over"
game_state = START

また、ゲームの初期化関数を作成します。

def reset_game():
    global ball_x, ball_y, ball_dx, ball_dy, bar_x, score
    ball_x, ball_y = WIDTH // 2, HEIGHT // 2
    ball_dx, ball_dy = random.choice([-BALL_SPEED, BALL_SPEED]), -BALL_SPEED
    bar_x = (WIDTH - BAR_WIDTH) // 2
    score = 0

ステップ4: ゲームループの構築

ゲームのメインループを作成し、イベントを処理します。

running = True
while running:
    screen.fill(BLACK)
    
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.KEYDOWN:
            if game_state == START and event.key == pygame.K_RETURN:
                reset_game()
                game_state = PLAYING
            elif game_state == GAME_OVER and event.key == pygame.K_RETURN:
                game_state = START

ステップ5: バーの移動とボールの反射

    keys = pygame.key.get_pressed()
    if game_state == PLAYING:
        if keys[pygame.K_LEFT] and bar_x > 0:
            bar_x -= BAR_SPEED
        if keys[pygame.K_RIGHT] and bar_x < WIDTH - BAR_WIDTH:
            bar_x += BAR_SPEED
        
        # ボールの移動
        ball_x += ball_dx
        ball_y += ball_dy
        
        # 壁の反射
        if ball_x <= 0 or ball_x >= WIDTH - BALL_SIZE:
            ball_dx = -ball_dx
        if ball_y <= 0:
            ball_dy = -ball_dy

ステップ6: ゲームオーバー判定とスコア加算

        # バーとの衝突判定
        if (ball_y + BALL_SIZE >= HEIGHT - BAR_HEIGHT and
            bar_x <= ball_x <= bar_x + BAR_WIDTH):
            ball_dy = -ball_dy
            score += 10
        
        # ボールが下に落ちた場合
        if ball_y >= HEIGHT:
            game_state = GAME_OVER

ステップ7: キャラクターとスコアの描画

    # 画面描画
    if game_state == START:
        text = font.render("Press ENTER to Start", True, WHITE)
        screen.blit(text, (WIDTH // 2 - text.get_width() // 2, HEIGHT // 2))
    elif game_state == PLAYING:
        pygame.draw.rect(screen, WHITE, (bar_x, HEIGHT - BAR_HEIGHT, BAR_WIDTH, BAR_HEIGHT))
        pygame.draw.ellipse(screen, WHITE, (ball_x, ball_y, BALL_SIZE, BALL_SIZE))
        score_text = font.render(f"Score: {score}", True, WHITE)
        screen.blit(score_text, (WIDTH - 150, 10))
    elif game_state == GAME_OVER:
        game_over_text = font.render(f"Game Over! Score: {score}", True, WHITE)
        screen.blit(game_over_text, (WIDTH // 2 - game_over_text.get_width() // 2, HEIGHT // 2))

コード全体

Pythonでのゲーム制作を学びたい人はこちらの書籍がおすすめです!

Amazon.co.jp
import pygame
import random

# ゲームの基本設定
WIDTH, HEIGHT = 600, 400
BAR_WIDTH, BAR_HEIGHT = 100, 10
BALL_SIZE = 10
BALL_SPEED = 4
BAR_SPEED = 6
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)

# Pygameの初期化
pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Squash Game")
font = pygame.font.Font(None, 36)
clock = pygame.time.Clock()

# ゲームの状態
START, PLAYING, GAME_OVER = "start", "playing", "game_over"
game_state = START

# ゲームのリセット関数
def reset_game():
    global ball_x, ball_y, ball_dx, ball_dy, bar_x, score
    ball_x, ball_y = WIDTH // 2, HEIGHT // 2
    ball_dx, ball_dy = random.choice([-BALL_SPEED, BALL_SPEED]), -BALL_SPEED
    bar_x = (WIDTH - BAR_WIDTH) // 2
    score = 0

# ゲームループ
running = True
while running:
    screen.fill(BLACK)
    
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.KEYDOWN:
            if game_state == START and event.key == pygame.K_RETURN:
                reset_game()
                game_state = PLAYING
            elif game_state == GAME_OVER and event.key == pygame.K_RETURN:
                game_state = START

    keys = pygame.key.get_pressed()
    if game_state == PLAYING:
        if keys[pygame.K_LEFT] and bar_x > 0:
            bar_x -= BAR_SPEED
        if keys[pygame.K_RIGHT] and bar_x < WIDTH - BAR_WIDTH:
            bar_x += BAR_SPEED
        
        # ボールの移動
        ball_x += ball_dx
        ball_y += ball_dy
        
        # 壁の反射
        if ball_x <= 0 or ball_x >= WIDTH - BALL_SIZE:
            ball_dx = -ball_dx
        if ball_y <= 0:
            ball_dy = -ball_dy
        
        # バーとの衝突判定
        if (ball_y + BALL_SIZE >= HEIGHT - BAR_HEIGHT and
            bar_x <= ball_x <= bar_x + BAR_WIDTH):
            ball_dy = -ball_dy
            score += 10
        
        # ボールが下に落ちた場合
        if ball_y >= HEIGHT:
            game_state = GAME_OVER
    
    # 描画処理
    if game_state == START:
        text = font.render("Press ENTER to Start", True, WHITE)
        screen.blit(text, (WIDTH // 2 - text.get_width() // 2, HEIGHT // 2))
    elif game_state == PLAYING:
        pygame.draw.rect(screen, WHITE, (bar_x, HEIGHT - BAR_HEIGHT, BAR_WIDTH, BAR_HEIGHT))
        pygame.draw.ellipse(screen, WHITE, (ball_x, ball_y, BALL_SIZE, BALL_SIZE))
        score_text = font.render(f"Score: {score}", True, WHITE)
        screen.blit(score_text, (WIDTH - 150, 10))
    elif game_state == GAME_OVER:
        game_over_text = font.render(f"Game Over! Score: {score}", True, WHITE)
        screen.blit(game_over_text, (WIDTH // 2 - game_over_text.get_width() // 2, HEIGHT // 2))
        restart_text = font.render("Press ENTER to Restart", True, WHITE)
        screen.blit(restart_text, (WIDTH // 2 - restart_text.get_width() // 2, HEIGHT // 2 + 40))
    
    pygame.display.flip()
    clock.tick(60)

pygame.quit()

プレイ画面

実際にプレイしてみた動画がこちらです。リアルなスカッシュみたいに楽しむことができます。

ボールのスピードを調節することで、難易度を変えることもできますね!


まとめ

このチュートリアルでは、pygameを使ったスカッシュゲームを作成しました。このコードを改良することで、さらに複雑なゲームに挑戦できます。

Pythonでのゲーム制作ついて書籍でもっと学習したい方は、Kindleでの購入がおすすめです!

おすすめの書籍についてはこちらの記事で紹介しています!

ところで、ここでここまで記事を読んでいただいた皆さんにお知らせしなければならないことがあります…

実は、このプログラム、ChatGPTに全て書いてもらっているのです。

ChatGPTで特殊なプロンプトを使えば、今までエンジニアが数時間掛けて書いていたコードを、ものの3分で作成してくれます。

これからエンジニアとして活躍したい方、文系からエンジニアを目指したい方は、ぜひChatGPTの活用方法を学んで、高度なIT人材になりましょう!

ChatGPTを使ってPythonでゲームを制作したい方は、こちらのAIスクールがおすすめです!

AIで楽して稼ぐ副業スクール -イナズマ塾-
「副業のやり方がわからない」「時給が低い」そんな方々向けに、生成AIを使った副業の方法を0から学べる業界最安級のスクールです。eラーニング+コーチングで不労所得を実現する副業の方法を徹底解説します。

なお、当サイト限定の特典として、無料面談フォーム入力時に下記の招待コードを入力すると、受講料が20%OFFになります!!!

イナズマ塾に入塾を検討されている方は、ぜひ、こちらの割引をご利用ください!!

招待コード:STAIT2025