【ゼロから始めるPython】Pythonでもぐら叩きゲームを作ってみよう!

Python
この記事を書いた人
柊あい

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

公式SNSをフォローする

はじめに

今回はPythonのPygameを使用して、簡単な「もぐら叩きゲーム」を作成します。もぐらがランダムに顔を出し、対応するキーを押すことで得点を競うゲームです。

このゲームでは、リアルタイムに変化するもぐらを狙い、適切なタイミングでキーを押すというシンプルながらも楽しい要素を実装しています。Pygameを使うことで、ゲームの描画やイベント処理が簡単にできるので、初心者でも楽しく作れます。

それでは、ステップバイステップで開発していきましょう!

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


必要な機能

このゲームでは、以下の機能を実装します。

  1. スタート画面の表示(ENTERキーでゲーム開始)
  2. 5匹のもぐらがランダムに顔を出す
  3. F, G, H, J, Kキーを押して、対応するもぐらを叩く
  4. 正しく叩くとスコア+1、失敗するとスコア-1
  5. もぐらを叩くと即座に引っ込む
  6. 30秒経過でゲーム終了し、結果画面を表示
  7. 結果画面でスコアを表示し、ENTERキーでリスタート可能

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

Pygameを使用するため、Python環境にインストールされていない場合は、以下のコマンドでインストールしてください。

pip install pygame

インストールが完了したら、Pygameが正しく動作するか確認するために、以下のコードを試してみましょう。

import pygame
pygame.init()
print("Pygame is ready!")

エラーが出ずに”Pygame is ready!”と表示されれば準備完了です。


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

まず、ゲームのウィンドウサイズやPygameの初期化処理を設定します。

import pygame
pygame.init()

# 画面サイズの設定
WIDTH, HEIGHT = 800, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Whack-a-Mole Game")

このコードでは、ウィンドウサイズを 800×600 に設定し、タイトルを “Whack-a-Mole Game” にしました。


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

次に、ゲームで使用する色やフォント、キー入力を設定します。

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

# フォント設定
font = pygame.font.Font(None, 48)
small_font = pygame.font.Font(None, 36)

# もぐらの位置とキー設定
MOLE_COUNT = 5
MOLE_RADIUS = 40
keys = [pygame.K_f, pygame.K_g, pygame.K_h, pygame.K_j, pygame.K_k]
key_labels = ["F", "G", "H", "J", "K"]

ここでは、

  • もぐらの数を5匹 に設定
  • 対応するキー(F, G, H, J, K) をリスト化
  • 白と黒のカラーを定義
  • フォントを設定

を行っています。


ステップ3: もぐらの動作の設定

次に、もぐらの挙動を管理するクラスを作成します。

class Mole:
    def __init__(self, x, y, key_label):
        self.x = x
        self.y = y
        self.is_up = False
        self.next_change_time = time.time() + random.uniform(1.0, 2.5)
        self.key_label = key_label
    
    def update(self):
        if time.time() > self.next_change_time:
            self.is_up = not self.is_up
            self.next_change_time = time.time() + random.uniform(1.0, 2.5)
    
    def whack(self):
        if self.is_up:
            self.is_up = False
            self.next_change_time = time.time() + random.uniform(1.0, 2.5)
            return True
        return False
    
    def draw(self, screen):
        pygame.draw.circle(screen, WHITE if self.is_up else BLACK, (self.x, self.y), MOLE_RADIUS)
        if self.is_up:
            label = font.render(self.key_label, True, BLACK)
            screen.blit(label, (self.x - 15, self.y - 15))

このクラスでは、

  • もぐらの位置・表示状態を管理
  • 1秒以上の間隔でランダムに顔を出す
  • 叩かれたら即座に隠れる

といった処理を実装しています。


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

ゲームのメインループを作成し、スタート画面 → ゲーム → 結果画面 の流れを制御します。

state = GameState.START
running = True
while running:
    screen.fill(BLACK)
    
    if state == GameState.START:
        title_text = font.render("Whack-a-Mole Game", True, WHITE)
        instruction_text = small_font.render("Press ENTER to Start", True, WHITE)
        screen.blit(title_text, (WIDTH//2 - 200, HEIGHT//3))
        screen.blit(instruction_text, (WIDTH//2 - 150, HEIGHT//2))

ゲームの進行状態を GameState で管理し、ENTERキーでゲームが始まるようにしました。


コード全体

import pygame
import random
import time

# Pygame initialization
pygame.init()

# Screen settings
WIDTH, HEIGHT = 800, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Whack-a-Mole Game")

# Colors
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)

# Font settings
font = pygame.font.Font(None, 48)
small_font = pygame.font.Font(None, 36)

# Game settings
MOLE_COUNT = 5
MOLE_RADIUS = 40
GAP = 50  # Spacing between moles
MOLE_Y = HEIGHT // 2
keys = [pygame.K_f, pygame.K_g, pygame.K_h, pygame.K_j, pygame.K_k]
key_labels = ["F", "G", "H", "J", "K"]

# Mole positions
mole_positions = [(i * (MOLE_RADIUS * 2 + GAP) + 150, MOLE_Y) for i in range(MOLE_COUNT)]

# Game states
class GameState:
    START = 0
    PLAYING = 1
    RESULT = 2

# Mole class
class Mole:
    def __init__(self, x, y, key_label):
        self.x = x
        self.y = y
        self.is_up = False
        self.next_change_time = time.time() + random.uniform(1.0, 2.5)  # At least 1 sec interval
        self.key_label = key_label

    def update(self):
        if time.time() > self.next_change_time:
            self.is_up = not self.is_up
            self.next_change_time = time.time() + random.uniform(1.0, 2.5)  # 1+ sec interval

    def whack(self):
        """Make the mole immediately hide when hit correctly."""
        if self.is_up:
            self.is_up = False
            self.next_change_time = time.time() + random.uniform(1.0, 2.5)  # Reset next appearance time
            return True  # Successful hit
        return False  # Miss

    def draw(self, screen):
        pygame.draw.circle(screen, WHITE if self.is_up else BLACK, (self.x, self.y), MOLE_RADIUS)
        if self.is_up:
            label = font.render(self.key_label, True, BLACK)
            screen.blit(label, (self.x - 15, self.y - 15))  # Show key label in the center

# Main game loop
def main():
    clock = pygame.time.Clock()
    state = GameState.START
    moles = [Mole(x, y, key_labels[i]) for i, (x, y) in enumerate(mole_positions)]
    score = 0
    start_time = 0

    running = True
    while running:
        screen.fill(BLACK)

        if state == GameState.START:
            title_text = font.render("Whack-a-Mole Game", True, WHITE)
            instruction_text = small_font.render("Press ENTER to Start", True, WHITE)
            screen.blit(title_text, (WIDTH//2 - 200, HEIGHT//3))
            screen.blit(instruction_text, (WIDTH//2 - 150, HEIGHT//2))

        elif state == GameState.PLAYING:
            # Update mole state
            for mole in moles:
                mole.update()

            # Draw moles
            for mole in moles:
                mole.draw(screen)

            # Score display
            score_text = small_font.render(f"Score: {score}", True, WHITE)
            screen.blit(score_text, (WIDTH - 200, 50))

            # Check game time
            elapsed_time = time.time() - start_time
            if elapsed_time >= 30:
                state = GameState.RESULT

        elif state == GameState.RESULT:
            result_text = font.render(f"Score: {score}", True, WHITE)
            restart_text = small_font.render("Press ENTER to Restart", True, WHITE)
            screen.blit(result_text, (WIDTH//2 - 100, HEIGHT//3))
            screen.blit(restart_text, (WIDTH//2 - 140, HEIGHT//2))

        # Event handling
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False

            elif event.type == pygame.KEYDOWN:
                if state == GameState.START and event.key == pygame.K_RETURN:
                    state = GameState.PLAYING
                    score = 0
                    start_time = time.time()
                    moles = [Mole(x, y, key_labels[i]) for i, (x, y) in enumerate(mole_positions)]

                elif state == GameState.PLAYING:
                    if event.key in keys:
                        index = keys.index(event.key)
                        if moles[index].whack():
                            score += 1  # Hit successful
                        else:
                            score -= 1  # Wrong timing

                elif state == GameState.RESULT and event.key == pygame.K_RETURN:
                    state = GameState.START

        pygame.display.flip()
        clock.tick(30)

    pygame.quit()

if __name__ == "__main__":
    main()

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

Amazon.co.jp

プレイ画面

実際にプレイした様子を動画に撮りましたのでご覧ください。

音がないので少し寂しいかもしれませんが、きちんとキーボードのタイプを判定して得点を計算できています!


まとめ

さて、このチュートリアルでは、pygameを使ったシンプルな「もぐら叩きゲーム」を作成する方法を学びました。このコードを改良することで、さらに複雑なゲームに挑戦できます。

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

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

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

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

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

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

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

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

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

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

招待コード:STAIT2025