🛸

【Python】プログラミング初心者がChatGPT を使ってシューティングゲームを開発してみた話

2024/11/19に公開

1. はじめに

いきなりですが、プログラミングを学んで「~を作ってみたい」など開発のアイデアはぱっと思い浮かびますか?

私自身、プログラミング基礎を勉強したので実際に成果物と呼べるレベルのものを開発してみたい!!とは思うものの、実際に何なら初心者でも作れるのか分からず悩んでいました。。。

色々調べていたところChat GPT を活用すればコードや画像を生成してゲームを作ることができる!!といった内容の記事を見つけました。
https://zenn.dev/mistletoe/articles/4a69c46e2c6127

そこで、Chat GPT に基本的なコードを作ってもらい自身でコードを書き加えることで、Pythonを使って実際に動くゲームを作ることができました!!
先に完成品をお見せすると、こんな感じです!結構本格的ではありませんか?
https://youtu.be/3TeQHQ6T6Ic?si=mLr__DUCeHqvSgS8

改良前後の比較はこちら
https://youtube.com/shorts/2eEW6iG5kYY?si=dars3REB2vM0nuyc

今回はpygameライブラリを使ってPythonで簡単にシューティングゲームを作成する方法と実際のコードを紹介します。

Chat GPTを活用すれば、初心者でも本格的なゲームを作ることができました。
Python学習中の方の参考になれば幸いです。

この記事は以下に当てはまる方を対象としています。それではいってみましょう。

・Pythonでプログラミングを始めたばかりの人
・自作ゲーム開発に興味がある人
・学んだ知識を使って、簡単なプログラムを書いてみたい人
・実際に何を作ればよいか迷っている方

2. 目次

  1. 実行環境
  2. 事前準備
  3. ゲームの概要と基本構成要素
  4. 基本ソースコードの生成
  5. ソースコードの改修
  6. 実行結果

3. 開発してみた

1. 実行環境

使ったものは以下のとおりです。

  • Windows 10 Pro
  • Python 3.13.0
  • ChatGPT
  • Pygame※
    ※PygameはPythonでのゲーム作成に広く使われているライブラリです。このライブラリを使うと、グラフィック、サウンド、イベント処理が簡単にできるのでゲーム制作にはおすすめです。

2. 事前準備

PygameライブラリをPCにインストールします。
(Pythonのインストール方法については省略しています。)

一例として、コマンドでインストールする方法をご紹介します。
<手順>
コマンドプロンプトで以下のコマンドを実行しインストールします。

pip install pygame

実行後、Successfully installed pygame -version ~と表示されればOKです。

3. ゲームの概要と基本構成要素

今回はプレイヤーが上から降ってくる敵を撃ち落とすシンプルなシューティングゲームを作成します。
プレイヤーが敵に当たってしまうとゲームオーバーです。

主な操作は以下のとおりです。

  • プレイヤーを矢印キーで操作
  • スペースキーで弾を発射
  • 上から敵が降ってくる
  • プレイヤーの弾が敵に当たると、敵が消える

4. 基本ソースコードの生成

はじめにChatGPTで基本的なコードを生成してもらって、Visual Studio Codeで実行してみます。
以下のコードが生成されたコードです。

sample.py
import pygame
import random

# Pygameの初期化
pygame.init()

# 画面サイズと基本設定
WIDTH, HEIGHT = 800, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("シューティングゲーム")

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

# プレイヤー設定
player_size = 50
player_x = WIDTH // 2
player_y = HEIGHT - 2 * player_size
player_speed = 5

# 敵設定
enemy_size = 50
enemy_speed = 5
enemies = []

# 弾の設定
bullet_size = 10
bullet_speed = 10
bullets = []

# ゲームのループを制御する変数
running = True
clock = pygame.time.Clock()

# 敵を生成する関数
def create_enemy():
    x = random.randint(0, WIDTH - enemy_size)
    y = 0
    enemies.append(pygame.Rect(x, y, enemy_size, enemy_size))

# メインループ
while running:
    screen.fill(BLACK)

    # イベント処理
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_SPACE:
                # スペースキーで弾を発射
                bullet = pygame.Rect(player_x + player_size // 2 - bullet_size // 2, player_y, bullet_size, bullet_size)
                bullets.append(bullet)

    # プレイヤーの移動
    keys = pygame.key.get_pressed()
    if keys[pygame.K_LEFT] and player_x > 0:
        player_x -= player_speed
    if keys[pygame.K_RIGHT] and player_x < WIDTH - player_size:
        player_x += player_speed

    # 敵の生成
    if random.randint(1, 30) == 1:  # 一定確率で敵を生成
        create_enemy()

    # 敵の移動
    for enemy in enemies[:]:
        enemy.y += enemy_speed
        if enemy.y > HEIGHT:  # 画面下に到達したら削除
            enemies.remove(enemy)

    # 弾の移動
    for bullet in bullets[:]:
        bullet.y -= bullet_speed
        if bullet.y < 0:  # 画面上に到達したら削除
            bullets.remove(bullet)

    # 衝突判定(弾と敵)
    for bullet in bullets[:]:
        for enemy in enemies[:]:
            if bullet.colliderect(enemy):
                bullets.remove(bullet)
                enemies.remove(enemy)
                break

    # 描画
    player = pygame.Rect(player_x, player_y, player_size, player_size)
    pygame.draw.rect(screen, GREEN, player)

    for enemy in enemies:
        pygame.draw.rect(screen, RED, enemy)

    for bullet in bullets:
        pygame.draw.rect(screen, WHITE, bullet)

    # 画面更新
    pygame.display.flip()
    clock.tick(30)

# ゲーム終了
pygame.quit()

実行結果です。
https://youtu.be/3a2l2KJGJwE?si=ZHOJWBolBahEOciv

緑色がプレイヤー、赤色が敵を表しています。
スペースキーを押すと弾が発射され、敵に弾があたると敵が消える動作のようです。

まず動くものが作られていることに感動してしまいました。。。

ですが、ゲームとしては改善の余地がまだまだありそうです。
そのため、以下の5点を実装することにしました!!

・画面上にスコアを表示する
・プレイヤー、敵、弾に背景に画像を設定する
・プレイヤーが敵に当たるとゲームオーバーとする
・ゲームオーバー画面の表示
・弾を発射時に効果音を出す。

5. ソースコードの改修

調べた情報を参考に各機能を実装します。
*参考にしたサイトは本ページの最後"参考リンク"にまとめています。

画面上にスコアを表示する

<手順>

  1. score変数を初期値0で作成します
# スコアの設定
score = 0
game_over = False
  1. スコアを表示する関数を作成します
# スコアを表示する関数
def display_score():
    score_text = score_font.render("Score: " + str(score), True, WHITE)
    screen.blit(score_text, (10, 10))
  1. 敵と弾衝突判定時に、衝突した場合はスコアを10加算するコードを追加します
# 衝突判定(弾と敵)
        for bullet in bullets[:]:
            for enemy in enemies[:]:
                if bullet.colliderect(enemy):
                    bullets.remove(bullet)
                    enemies.remove(enemy)
                    score += 10  # スコアを10加算
                    break
  1. メインループ内にスコアを表示する関数を追加します
# スコアの表示
        display_score()

プレイヤー、敵、弾に背景に画像を設定する

<手順>

  1. 画像pngファイルをVisual Studio Code上にアップロードします
    使用する画像は以下のフリー素材を利用しました。
    https://dot-illust.net/tag/uchu/
  1. 画像ファイルを読み込むコードを追加します
# プレイヤーと敵と弾の画像を読み込む
player_image_original = pygame.image.load('player.png')
enemy_image_original = pygame.image.load('enemy.png')
bullet_image_original = pygame.image.load('bullet.png')
background_image_original = pygame.image.load("background.png")

▼参考画像

  1. 画像サイズを設定するコードを追加します
# 画像のサイズを設定
player_image = pygame.transform.scale(player_image_original, (player_size, player_size))
enemy_image = pygame.transform.scale(enemy_image_original, (enemy_size, enemy_size))
bullet_image = pygame.transform.scale(bullet_image_original, (bullet_size,bullet_size))
background_image = pygame.transform.scale(background_image_original, (WIDTH, HEIGHT))
  1. メインループ内に画像を描画するコードを追加します
    背景画像の描写は先頭に追加
# メインループ
while running:
    # 背景画像を描画
    screen.blit(background_image, (0, 0))

プレイヤー、敵、弾画像の描写は末尾に追加

# プレイヤーの描画
        screen.blit(player_image, (player_x, player_y))


        # 敵の描画
        for enemy in enemies:
            screen.blit(enemy_image, enemy)


        # 弾の描画
        for bullet in bullets:
            screen.blit(bullet_image, bullet)

プレイヤーが敵に当たるとゲームオーバーとする

<手順>

  1. game_over変数を初期値Falseで作成します
# スコアの設定
score = 0
game_over = False
  1. メインループ内に敵とプレイヤーの位置が同じ場合に、game_over変数をTrueにするコードを追加します
# 敵の移動
        for enemy in enemies[:]:
            enemy.y += enemy_speed
            if enemy.y > HEIGHT:  # 画面下に到達したら削除
                enemies.remove(enemy)
            elif enemy.colliderect(pygame.Rect(player_x, player_y, player_size, player_size)):
                # プレイヤーと敵が衝突したらゲームオーバー
                game_over = True
  1. if-else文を追加します。
if not game_over:
        # プレイヤーの移動
        keys = pygame.key.get_pressed()
        if keys[pygame.K_LEFT] and player_x > 0:
            player_x -= player_speed
        if keys[pygame.K_RIGHT] and player_x < WIDTH - player_size:
            player_x += player_speed

        # 以下省略
            
    else:
        # ゲームオーバー画面の表示
        display_game_over()

ゲームオーバー画面の表示

  1. ゲームオーバーの表示関数を作成します
# ゲームオーバーの表示関数
def display_game_over():
    game_over_text = game_over_font.render("GAME OVER", True, RED)
    final_score_text = score_font.render("Final Score: " + str(score), True, WHITE)
    screen.blit(game_over_text, (WIDTH // 2 - game_over_text.get_width() // 2, HEIGHT // 2 - 50))
    screen.blit(final_score_text, (WIDTH // 2 - final_score_text.get_width() // 2, HEIGHT // 2 + 10))
  1. メインループ内のif-else文でgame_over変数がTrueの場合、display_game_over()を実行するようにコードを追加します
else:
        # ゲームオーバー画面の表示
        display_game_over()

弾を発射時に効果音を出す。

<手順>

  1. 効果音のmp3ファイルをVisual Studio Code上にアップロードします
    使用する効果音は以下の素材をお借りしました。
    効果音:Springin’ Sound Stock, ショット2
    https://www.springin.org/sound-stock/category/machine/page/3/

  2. 弾を発射時にmp3ファイルを再生するコードを追加します

# イベント処理
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_SPACE:
                # スペースキーで弾を発射
                bullet = pygame.Rect(player_x + player_size // 2 - bullet_size // 2, player_y, bullet_size, bullet_size)
                bullets.append(bullet)
                #効果音の設定
                pygame.mixer.Sound('laser.mp3').play()

▼参考画像


上記を修正した最終的なコード全体はこんな感じです。

コード最終形態
game.py
import pygame
import random

# Pygameの初期化
pygame.init()

# 画面サイズと基本設定
WIDTH, HEIGHT = 800, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("シューティングゲーム")

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

# プレイヤーと敵と弾の画像を読み込む
player_image_original = pygame.image.load('player.png')
enemy_image_original = pygame.image.load('enemy.png')
bullet_image_original = pygame.image.load('bullet.png')
background_image_original = pygame.image.load("background.png")

# プレイヤー設定
player_size = 50
player_x = WIDTH // 2
player_y = HEIGHT - 2 * player_size
player_speed = 5

# 敵設定
enemy_size = 50
enemy_speed = 5
enemies = []

# 弾の設定
bullet_size = 10
bullet_speed = 10
bullets = []

# スコアの設定
score = 0
game_over = False

# フォントの設定
game_over_font = pygame.font.Font(None, 72)
score_font = pygame.font.Font(None, 36)

# 画像のサイズを設定
player_image = pygame.transform.scale(player_image_original, (player_size, player_size))
enemy_image = pygame.transform.scale(enemy_image_original, (enemy_size, enemy_size))
bullet_image = pygame.transform.scale(bullet_image_original, (bullet_size,bullet_size))
background_image = pygame.transform.scale(background_image_original, (WIDTH, HEIGHT))


# ゲームのループを制御する変数
running = True
clock = pygame.time.Clock()

# 敵を生成する関数
def create_enemy():
    x = random.randint(0, WIDTH - enemy_size)
    y = 0
    enemies.append(pygame.Rect(x, y, enemy_size, enemy_size))

# スコアを表示する関数
def display_score():
    score_text = score_font.render("Score: " + str(score), True, WHITE)
    screen.blit(score_text, (10, 10))

# ゲームオーバーの表示関数
def display_game_over():
    game_over_text = game_over_font.render("GAME OVER", True, RED)
    final_score_text = score_font.render("Final Score: " + str(score), True, WHITE)
    screen.blit(game_over_text, (WIDTH // 2 - game_over_text.get_width() // 2, HEIGHT // 2 - 50))
    screen.blit(final_score_text, (WIDTH // 2 - final_score_text.get_width() // 2, HEIGHT // 2 + 10))

# メインループ
while running:
    # 背景画像を描画
    screen.blit(background_image, (0, 0))

    # イベント処理
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_SPACE:
                # スペースキーで弾を発射
                bullet = pygame.Rect(player_x + player_size // 2 - bullet_size // 2, player_y, bullet_size, bullet_size)
                bullets.append(bullet)
                #効果音の設定
                pygame.mixer.Sound('laser.mp3').play()

    if not game_over:
        # プレイヤーの移動
        keys = pygame.key.get_pressed()
        if keys[pygame.K_LEFT] and player_x > 0:
            player_x -= player_speed
        if keys[pygame.K_RIGHT] and player_x < WIDTH - player_size:
            player_x += player_speed

        # 敵の生成
        if random.randint(1, 30) == 1:  # 一定確率で敵を生成
            create_enemy()

        # 敵の移動
        for enemy in enemies[:]:
            enemy.y += enemy_speed
            if enemy.y > HEIGHT:  # 画面下に到達したら削除
                enemies.remove(enemy)
            elif enemy.colliderect(pygame.Rect(player_x, player_y, player_size, player_size)):
                # プレイヤーと敵が衝突したらゲームオーバー
                game_over = True

        # 弾の移動
        for bullet in bullets[:]:
            bullet.y -= bullet_speed
            if bullet.y < 0:  # 画面上に到達したら削除
                bullets.remove(bullet)

        # 衝突判定(弾と敵)
        for bullet in bullets[:]:
            for enemy in enemies[:]:
                if bullet.colliderect(enemy):
                    bullets.remove(bullet)
                    enemies.remove(enemy)
                    score += 10  # スコアを10加算
                    break

        # プレイヤーの描画
        screen.blit(player_image, (player_x, player_y))

        # 敵の描画
        for enemy in enemies:
            screen.blit(enemy_image, enemy)

        # 弾の描画
        for bullet in bullets:
            screen.blit(bullet_image, bullet)

        # スコアの表示
        display_score()

    else:
        # ゲームオーバー画面の表示
        display_game_over()

    # 画面更新
    pygame.display.flip()
    clock.tick(30)

# ゲーム終了
pygame.quit()

6. 実行結果

ゲームプレイ画面

ゲームオーバー画面

すべてを実装すると、冒頭でお見せした通り本格的なシューティングゲームになりました。

ただし、現段階では敵もプレイヤーも動くスピードが一定なので、スコアによって敵の落ちるスピードを変えたり、敵も攻撃してくるといった仕掛けを加えると、もっとゲーム性が増して面白くなると思います。要改善デス!

4. まとめ

ChatGPTを使って実際に一日でゲームを開発することができました!
思ったより簡単に作ることができて、しかも本格的なゲームになって自分でも驚いています。
AIを上手く活用できるとできることが広がりますね。
今後は他のゲーム製作に挑戦してみようと思います。

最後まで読んでくださりありがとうございました。
少しでも参考になる情報となっていれば幸いです。

また、改善点やご意見などあればコメントお願いいたします!

5. 参考リンク

参考にした記事
・Pythonでガイコツを撃ち落とすゲームを作ってみる #pygame - Qiita
https://qiita.com/yam_dev/items/4b4d387bdfeb4a8bff25
・PythonをインストールしてPygameを動かすまで - Qiita
https://qiita.com/i-tanaka730/items/ad56461a4f223fdbb4e5

参考動画
・ 【Pygame超入門】50分でゲーム開発(Python)の基礎をマスター
https://www.youtube.com/watch?v=fAJ_BjLd3Ro

素材サイト
・無料 BGM・効果音のフリー音源素材 | Springin’ Sound Stock
https://www.springin.org/sound-stock/
・宇宙 ▪︎ DOT ILLUST
https://dot-illust.net/tag/uchu/

Discussion