【ChatGPT】プロンプトでPythonコードのゲームを生成してみた

【ChatGPT】プロンプトでPythonコードのゲームを生成してみた

記事の文字数:1535

ChatGPTでPythonで動作するシューティングゲームを作成しました。1回のメッセージでは仕様通りとなりませんでしたが、2回目のメッセージによる修正依頼で、想定通りのシューティングゲームを簡単に作成することができました。


スポンサーリンク

ChatGPTを利用して、Pythonで動作するシューティングゲームを作成させてみました。
1回のプロンプトでは要求を満たさない結果となったので、2回目で修正依頼をすることで、想定通りのシューティングゲームを作成することができました。

プロンプト1

まず以下仕様で、ChatGPTにソースコード作成依頼をしてみました。

送信メッセージ1

Pythonでシューティングゲームを作成してください。
#前提
・Python3で動作すること。
・ソースコードをコピーしてそのまま使えること。
・起動時にエラーが発生しないこと。
#仕様
・矢印キーで上下左右に実機を操作できる。
・スペースキーで弾を発射し、長押しで連射できる。
・敵に当たるか敵の弾に当たるとライフが1つ減る。
・実機のライフは3つで、0になったらゲームオーバーになる。
・実機の色は白色とする。
・敵は上から出て来て、上から下に弾を発射する。
・敵のライフは1つ。
・敵の色は赤色とする。
・敵を倒すとスコアが100増える。
・スコアは左側にSCOREと表示する。
・ライフは右側にLIFEと表示する。
・ゲームオーバー後は、Enterキーでゲームを再開できる。
#アウトプット
・上記仕様をすべて満たすソースコード
・ソースコードのファイル名
・Pythonの必要なライブラリがあれば、インストールコマンド
・作成ソースコードの起動方法
・操作方法・仕様の説明書

ChatGPT回答1

Pythonでシューティングゲームを作成するためには、Pygameライブラリを使用します。
以下に、仕様を満たすソースコードを提供します。

必要なライブラリ

まず、Pygameをインストールする必要があります。以下のコマンドを使用してインストールしてください。

コマンド
pip install pygame

ソースコード

次に、以下のソースコードを shooting_game.py というファイル名で保存してください。

shooting_game.py
import pygame
import random
# ゲームの初期化
pygame.init()
# 画面サイズの設定
screen_width = 800
screen_height = 600
screen = pygame.display.set_mode((screen_width, screen_height))
# フォントの設定
font = pygame.font.SysFont(None, 36)
# 色の設定
white = (255, 255, 255)
red = (255, 0, 0)
black = (0, 0, 0)
# 実機クラス
class Player(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.Surface((50, 50))
self.image.fill(white)
self.rect = self.image.get_rect()
self.rect.center = (screen_width // 2, screen_height - 50)
self.speed = 5
self.lives = 3
def update(self):
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT] and self.rect.left > 0:
self.rect.x -= self.speed
if keys[pygame.K_RIGHT] and self.rect.right < screen_width:
self.rect.x += self.speed
if keys[pygame.K_UP] and self.rect.top > 0:
self.rect.y -= self.speed
if keys[pygame.K_DOWN] and self.rect.bottom < screen_height:
self.rect.y += self.speed
def shoot(self):
bullet = Bullet(self.rect.centerx, self.rect.top)
all_sprites.add(bullet)
player_bullets.add(bullet)
# 弾クラス
class Bullet(pygame.sprite.Sprite):
def __init__(self, x, y):
super().__init__()
self.image = pygame.Surface((5, 10))
self.image.fill(white)
self.rect = self.image.get_rect()
self.rect.centerx = x
self.rect.bottom = y
self.speed = -10
def update(self):
self.rect.y += self.speed
if self.rect.bottom < 0:
self.kill()
# 敵クラス
class Enemy(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.Surface((50, 50))
self.image.fill(red)
self.rect = self.image.get_rect()
self.rect.x = random.randint(0, screen_width - self.rect.width)
self.rect.y = random.randint(-100, -40)
self.speed = random.randint(1, 3)
self.shoot_delay = random.randint(500, 1500)
self.last_shot = pygame.time.get_ticks()
def update(self):
self.rect.y += self.speed
if self.rect.top > screen_height:
self.rect.x = random.randint(0, screen_width - self.rect.width)
self.rect.y = random.randint(-100, -40)
self.speed = random.randint(1, 3)
now = pygame.time.get_ticks()
if now - self.last_shot > self.shoot_delay:
self.shoot()
self.last_shot = now
def shoot(self):
bullet = EnemyBullet(self.rect.centerx, self.rect.bottom)
all_sprites.add(bullet)
enemy_bullets.add(bullet)
# 敵の弾クラス
class EnemyBullet(pygame.sprite.Sprite):
def __init__(self, x, y):
super().__init__()
self.image = pygame.Surface((5, 10))
self.image.fill(red)
self.rect = self.image.get_rect()
self.rect.centerx = x
self.rect.top = y
self.speed = 5
def update(self):
self.rect.y += self.speed
if self.rect.top > screen_height:
self.kill()
# スプライトグループの設定
all_sprites = pygame.sprite.Group()
player_bullets = pygame.sprite.Group()
enemy_bullets = pygame.sprite.Group()
enemies = pygame.sprite.Group()
# プレイヤーの生成
player = Player()
all_sprites.add(player)
# 敵の生成
for _ in range(5):
enemy = Enemy()
all_sprites.add(enemy)
enemies.add(enemy)
# スコアとゲームオーバーフラグ
score = 0
game_over = False
# ゲームループ
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE and not game_over:
player.shoot()
if event.key == pygame.K_RETURN and game_over:
# リスタート
player.lives = 3
score = 0
game_over = False
for bullet in enemy_bullets:
bullet.kill()
for enemy in enemies:
enemy.kill()
for _ in range(5):
enemy = Enemy()
all_sprites.add(enemy)
enemies.add(enemy)
# ゲームがオーバーでない場合の処理
if not game_over:
all_sprites.update()
# プレイヤーの弾と敵の衝突判定
hits = pygame.sprite.groupcollide(enemies, player_bullets, True, True)
for hit in hits:
score += 100
enemy = Enemy()
all_sprites.add(enemy)
enemies.add(enemy)
# プレイヤーと敵の弾の衝突判定
hits = pygame.sprite.spritecollide(player, enemy_bullets, True)
for hit in hits:
player.lives -= 1
if player.lives <= 0:
game_over = True
# プレイヤーと敵の衝突判定
hits = pygame.sprite.spritecollide(player, enemies, False)
for hit in hits:
player.lives -= 1
hit.kill()
enemy = Enemy()
all_sprites.add(enemy)
enemies.add(enemy)
if player.lives <= 0:
game_over = True
# 画面の描画
screen.fill(black)
all_sprites.draw(screen)
# スコアとライフの表示
score_text = font.render(f"SCORE: {score}", True, white)
screen.blit(score_text, (10, 10))
lives_text = font.render(f"LIFE: {player.lives}", True, white)
screen.blit(lives_text, (screen_width - 150, 10))
# ゲームオーバーの表示
if game_over:
game_over_text = font.render("GAME OVER - Press Enter to Restart", True, red)
screen.blit(game_over_text, (screen_width // 4, screen_height // 2))
pygame.display.flip()
pygame.time.delay(30)
pygame.quit()

起動方法

上記のソースコードを shooting_game.py というファイル名で保存します。
コマンドラインまたはターミナルで以下のコマンドを実行してゲームを起動します。

コマンド
python shooting_game.py

操作方法・仕様の説明

  • 矢印キーで実機を上下左右に移動できます。
  • スペースキーで弾を発射できます(長押しで連射可能)。
  • 敵や敵の弾に当たるとライフが1つ減り、ライフが0になるとゲームオーバーです。
  • 敵を倒すとスコアが100増えます。
  • スコアは画面左上に SCORE として表示されます。
  • ライフは画面右上に LIFE として表示されます。
  • ゲームオーバー後はEnterキーでゲームを再開できます。
  • このコードをコピーして実行すれば、指定された仕様を満たすシューティングゲームが動作します。

動作テスト1

まず回答の指定通り、pygameをインストールしました。

$ pip install pygame
Defaulting to user installation because normal site-packages is not writeable
Collecting pygame
Downloading pygame-2.6.0-cp312-cp312-win_amd64.whl.metadata (13 kB)
Downloading pygame-2.6.0-cp312-cp312-win_amd64.whl (10.8 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 10.8/10.8 MB 12.6 MB/s eta 0:00:00
Installing collected packages: pygame
Successfully installed pygame-2.6.0
[notice] A new release of pip is available: 24.0 -> 24.1.2
[notice] To update, run: C:\Users\dorae\AppData\Local\Microsoft\WindowsApps\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\python.exe -m pip install --upgrade pip

shooting_game.pyファイルを保存し、以下コマンドで起動します。

コマンド
python shooting_game.py

実行中画面1

ゲームが起動しましたが、動きがもっさりとしていました。
また、弾の発射はできましたが、連射ができませんでした。

alt text

ゲームオーバー画面1

ライフが0になるとゲームオーバーになり、Enterキーでリスタートできました。
こちらは想定通りの動きです。
alt text

プロンプト2

弾の連射ができないことと、動きがもっさりしていたので、以下の通り修正依頼をすることにしました。

送信メッセージ2

生成ありがとうございます。確認しました。
長押しで連射できず、以下使用が満たされていませんでした。
・スペースキーで弾を発射し、長押しで連射できる。
また動きがもっさりしているので、スムーズに動作するように改善お願いします。

ChatGPT回答2

連射機能と動作のスムーズさを改善するために、次のようにコードを更新します。

  • 連射機能のために、弾の発射にクールダウン(発射間隔)を設定します。
  • 動作をスムーズにするために、フレームレートを管理し、更新を高速化します。

以下の修正されたソースコードを shooting_game.py にコピーして実行してください。

shooting_game.py
import pygame
import random
# ゲームの初期化
pygame.init()
# 画面サイズの設定
screen_width = 800
screen_height = 600
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("Shooting Game")
# フォントの設定
font = pygame.font.SysFont(None, 36)
# 色の設定
white = (255, 255, 255)
red = (255, 0, 0)
black = (0, 0, 0)
# 実機クラス
class Player(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.Surface((50, 50))
self.image.fill(white)
self.rect = self.image.get_rect()
self.rect.center = (screen_width // 2, screen_height - 50)
self.speed = 5
self.lives = 3
self.shoot_delay = 250 # ミリ秒
self.last_shot = pygame.time.get_ticks()
def update(self):
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT] and self.rect.left > 0:
self.rect.x -= self.speed
if keys[pygame.K_RIGHT] and self.rect.right < screen_width:
self.rect.x += self.speed
if keys[pygame.K_UP] and self.rect.top > 0:
self.rect.y -= self.speed
if keys[pygame.K_DOWN] and self.rect.bottom < screen_height:
self.rect.y += self.speed
if keys[pygame.K_SPACE]:
self.shoot()
def shoot(self):
now = pygame.time.get_ticks()
if now - self.last_shot > self.shoot_delay:
self.last_shot = now
bullet = Bullet(self.rect.centerx, self.rect.top)
all_sprites.add(bullet)
player_bullets.add(bullet)
# 弾クラス
class Bullet(pygame.sprite.Sprite):
def __init__(self, x, y):
super().__init__()
self.image = pygame.Surface((5, 10))
self.image.fill(white)
self.rect = self.image.get_rect()
self.rect.centerx = x
self.rect.bottom = y
self.speed = -10
def update(self):
self.rect.y += self.speed
if self.rect.bottom < 0:
self.kill()
# 敵クラス
class Enemy(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.Surface((50, 50))
self.image.fill(red)
self.rect = self.image.get_rect()
self.rect.x = random.randint(0, screen_width - self.rect.width)
self.rect.y = random.randint(-100, -40)
self.speed = random.randint(1, 3)
self.shoot_delay = random.randint(1000, 2000)
self.last_shot = pygame.time.get_ticks()
def update(self):
self.rect.y += self.speed
if self.rect.top > screen_height:
self.rect.x = random.randint(0, screen_width - self.rect.width)
self.rect.y = random.randint(-100, -40)
self.speed = random.randint(1, 3)
now = pygame.time.get_ticks()
if now - self.last_shot > self.shoot_delay:
self.shoot()
self.last_shot = now
def shoot(self):
bullet = EnemyBullet(self.rect.centerx, self.rect.bottom)
all_sprites.add(bullet)
enemy_bullets.add(bullet)
# 敵の弾クラス
class EnemyBullet(pygame.sprite.Sprite):
def __init__(self, x, y):
super().__init__()
self.image = pygame.Surface((5, 10))
self.image.fill(red)
self.rect = self.image.get_rect()
self.rect.centerx = x
self.rect.top = y
self.speed = 5
def update(self):
self.rect.y += self.speed
if self.rect.top > screen_height:
self.kill()
# スプライトグループの設定
all_sprites = pygame.sprite.Group()
player_bullets = pygame.sprite.Group()
enemy_bullets = pygame.sprite.Group()
enemies = pygame.sprite.Group()
# プレイヤーの生成
player = Player()
all_sprites.add(player)
# 敵の生成
for _ in range(5):
enemy = Enemy()
all_sprites.add(enemy)
enemies.add(enemy)
# スコアとゲームオーバーフラグ
score = 0
game_over = False
# クロックオブジェクトの生成
clock = pygame.time.Clock()
# ゲームループ
running = True
while running:
clock.tick(60) # フレームレートを60FPSに設定
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_RETURN and game_over:
# リスタート
player.lives = 3
score = 0
game_over = False
for bullet in enemy_bullets:
bullet.kill()
for enemy in enemies:
enemy.kill()
for _ in range(5):
enemy = Enemy()
all_sprites.add(enemy)
enemies.add(enemy)
# ゲームがオーバーでない場合の処理
if not game_over:
all_sprites.update()
# プレイヤーの弾と敵の衝突判定
hits = pygame.sprite.groupcollide(enemies, player_bullets, True, True)
for hit in hits:
score += 100
enemy = Enemy()
all_sprites.add(enemy)
enemies.add(enemy)
# プレイヤーと敵の弾の衝突判定
hits = pygame.sprite.spritecollide(player, enemy_bullets, True)
for hit in hits:
player.lives -= 1
if player.lives <= 0:
game_over = True
# プレイヤーと敵の衝突判定
hits = pygame.sprite.spritecollide(player, enemies, False)
for hit in hits:
player.lives -= 1
hit.kill()
enemy = Enemy()
all_sprites.add(enemy)
enemies.add(enemy)
if player.lives <= 0:
game_over = True
# 画面の描画
screen.fill(black)
all_sprites.draw(screen)
# スコアとライフの表示
score_text = font.render(f"SCORE: {score}", True, white)
screen.blit(score_text, (10, 10))
lives_text = font.render(f"LIFE: {player.lives}", True, white)
screen.blit(lives_text, (screen_width - 150, 10))
# ゲームオーバーの表示
if game_over:
game_over_text = font.render("GAME OVER - Press Enter to Restart", True, red)
screen.blit(game_over_text, (screen_width // 4, screen_height // 2))
pygame.display.flip()
pygame.quit()

この修正後のコードは、以下の改善点があります:

  • スペースキーを長押しで連射ができるようにしました。
  • クロックオブジェクトを使ってフレームレートを60FPSに設定し、動作をスムーズにしました。

これで、よりスムーズな動作と連射機能を備えたシューティングゲームを楽しむことができます。

動作テスト2

ChatGPTの回答通り、連射ができるようになり、動きもスムーズになりました!

実行中画面2

alt text

ゲームオーバー画面2

alt text

まとめ

  • ChatGTPでソースコードを作成する際は、具体的な仕様を記載する。
  • 記載した仕様が満たされていない場合は、修正依頼をする必要がある。

以上で本記事の解説を終わります。
よいITライフを!
スポンサーリンク
Scroll to Top