ChatGPTのみでゲームは作れるのか？

## はじめに
こんにちは!普段はレポートに追われるS高生(3期生)です。
今回は<B>Chat GPT3.5</b>でゲームを作れるのか気になったのでまとめてみました。
ちなみに今回は3つほどゲームを作成してもらいました。
エラーが出た場合や実行されない場合のときはスキップすることがあります。
## ChatGPTが好む言語
ChatGPTに言語の指定もせずにプログラムを書いてって言うとPythonに侵されているChatGPTはPythonというとても遅いスクリプト言語を進めてきます。(まぁ私のメインで書いてる言語はPythonが多いけど...)
## ChatGPTに言語を書いてもらう方法
今までに何度か興味があってプログラムを書かせてみましたが、「〇〇を作って」と言っても、使用技術などしか教えてくれなくてコードを書いてくれませんでした。なので頼むときは「コードを出力してください」という文を追加すると、コードを出力してくれます。あと先ChatGPTが好む言語がPythonなので、なにも言語を指定せずにコードを出力してと、言うと、Pythonでコードが出力されるので注意を！！
## Mincraft
まず超大人気ゲームMincraftを作って欲しいとお願いしました。

> Minecraft風のシンプルなゲームを作ってソースコードを出力してください
```py
''' 
ChatGPT
Minecraft風のシンプルなゲームを作るには、
言語やプラットフォームによって異なるアプローチがあります。
ここでは、PythonとPygameを使用して、
シンプルなブロックビルディングゲームの例を示します。
以下は、Pythonのコード例です。
'''
import pygame
import sys

# 初期化
pygame.init()

# 画面の設定
width, height = 800, 600
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption("Simple Block Game")

# 色の設定
white = (255, 255, 255)
blue = (0, 0, 255)

# プレイヤーの初期位置
player_x, player_y = width // 2, height // 2
player_size = 50

# ブロックの初期位置
block_size = 50
blocks = [(100, 100), (200, 200), (300, 300)]

# ゲームループ
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

    # キー入力の処理
    keys = pygame.key.get_pressed()
    if keys[pygame.K_LEFT]:
        player_x -= 5
    if keys[pygame.K_RIGHT]:
        player_x += 5
    if keys[pygame.K_UP]:
        player_y -= 5
    if keys[pygame.K_DOWN]:
        player_y += 5

    # 描画
    screen.fill(white)
    pygame.draw.rect(screen, blue, (player_x, player_y, player_size, player_size))

    for block in blocks:
        pygame.draw.rect(screen, blue, (block[0], block[1], block_size, block_size))

    pygame.display.flip()
'''
このコードはPygameを使用しています。
PygameはPythonのゲーム開発ライブラリであり、
簡単な2Dゲームを作成するのに適しています。
上記のコードでは、プレイヤーが矢印キーを使用して移動し、
青いブロックを配置できるシンプルなゲームが作成されます。

ゲームのループ内でキー入力を処理し、
描画を行っています。このコードは基本的な概念を示しているため、
さらに機能を追加したり、改良したりすることができます。
'''
```
その出力結果が、![スクリーンショット 2023-12-04 16.50.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3627451/73a32018-85ea-73a8-2304-034406f0da90.png)
 青のブロックが←↓↑→キーを押すと動くというMinecraftとは程遠いゲームができました。

皆さんがご存知のMincraftは3Dゲームだと思うので
> 3dで制作してください

```py
'''
ChatGPT
3Dゲームを制作するには、
通常は専門的な3Dグラフィックスライブラリやエンジンが必要です。
PythonにはPygameやPyOpenGLなどのライブラリがありますが、
これらは2Dグラフィックスに特化しており、
簡単には3Dゲームを構築するのが難しいです。

以下に、PythonとPygameを使用して簡単な3Dブロックワールドの例を示します。
ただし、注意が必要で、これは非常に基本的なものであり、
実際の3Dゲーム制作に必要な機能や技術には程遠いものです。
本格的な3Dゲーム開発には、
通常は専用のゲームエンジンやフレームワークが使用されます。
'''import pygame
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *

vertices = (
    (1, -1, -1),
    (1, 1, -1),
    (-1, 1, -1),
    (-1, -1, -1),
    (1, -1, 1),
    (1, 1, 1),
    (-1, -1, 1),
    (-1, 1, 1)
)

edges = (
    (0, 1),
    (1, 2),
    (2, 3),
    (3, 0),
    (4, 5),
    (5, 6),
    (6, 7),
    (7, 4),
    (0, 4),
    (1, 5),
    (2, 6),
    (3, 7)
)

def draw_cube():
    glBegin(GL_LINES)
    for edge in edges:
        for vertex in edge:
            glVertex3fv(vertices[vertex])
    glEnd()

def main():
    pygame.init()
    display = (800, 600)
    pygame.display.set_mode(display, DOUBLEBUF | OPENGL)
    gluPerspective(45, (display[0] / display[1]), 0.1, 50.0)
    glTranslatef(0.0, 0.0, -5)

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

        glRotatef(1, 3, 1, 1)
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        draw_cube()
        pygame.display.flip()
        pygame.time.wait(10)

if __name__ == "__main__":
    main()
```

![スクリーンショット 2023-12-04 16.56.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3627451/2ce5cf61-efc2-cc73-302c-021594e6e35f.png)

🤔これがMinecraftですか...
これ以上Minecraftは難しいから無理だと思い <b>次！！</b>

## スーパーマ⚪︎オブラザーズ
Mincraft並に有名な世界的なゲーム<b>スーパーマリオブラザーズ</b>(隠すき0)を作成させてみます
> 2dでスーパーマリオブラザーズ風なゲームを作成してください
```py
'''
ゲームの作成には、プログラミングの知識や開発環境が必要です。
以下に、PythonとPygameというライブラリを使用して2Dのスーパーマリオ風のゲームを作成する基本的な手順を示します。
なお、PythonやPygameのバージョンによっては、
コードの一部が変更される可能性があります。

Pythonのインストール:
最初にPythonをインストールしてください。公式ウェブサイト（https://www.python.org/）から最新のバージョンをダウンロードしてインストールします。

Pygameのインストール:
コマンドライン（ターミナルやコマンドプロンプト）を開き、以下のコマンドを実行してPygameをインストールします。
以下は、基本的なスーパーマリオ風のゲームの例です。ファイル名をsuper_mario.pyなどに保存してください。
'''

import pygame
from pygame.locals import *

pygame.init()

# ゲーム画面の設定
screen_width, screen_height = 800, 600
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("Super Mario Clone")

# キャラクターの初期位置
player_x, player_y = 50, 500

# ゲームループ
running = True
while running:
    for event in pygame.event.get():
        if event.type == QUIT:
            running = False

    # ゲームロジック

    # 描画
    screen.fill((255, 255, 255))  # 背景色
    pygame.draw.rect(screen, (255, 0, 0), (player_x, player_y, 50, 50))  # プレイヤーの描画

    pygame.display.flip()

pygame.quit()
```
![スクリーンショット 2023-12-04 22.46.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3627451/f7ede05c-47c6-4f0c-9ee2-2c473e223409.png)

なにも操作できない赤いboxが出来上がりました。
そして完成？系が

```py
import pygame
from pygame.locals import *

pygame.init()

# ゲーム画面の設定
screen_width, screen_height = 800, 600
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("Super Mario Clone")

# プレイヤーの設定
player_width, player_height = 50, 50
player_x, player_y = 50, 500
player_velocity_x, player_velocity_y = 0, 0
player_speed = 5
is_jumping = False
jump_count = 10

# 床の設定
floor_height = 100
floor_color = (0, 255, 0)

# 敵キャラクターの設定
enemy_width, enemy_height = 50, 50
enemy_x, enemy_y = screen_width - enemy_width, screen_height - floor_height - enemy_height
enemy_speed = 3

# ゲームループ
running = True
while running:
    for event in pygame.event.get():
        if event.type == QUIT:
            running = False

    # キー入力の処理
    keys = pygame.key.get_pressed()
    if keys[K_LEFT]:
        player_velocity_x = -player_speed
    elif keys[K_RIGHT]:
        player_velocity_x = player_speed
    else:
        player_velocity_x = 0

    # ジャンプ処理
    if not is_jumping:
        if keys[K_SPACE]:
            is_jumping = True
    else:
        if jump_count >= -10:
            neg = 1
            if jump_count < 0:
                neg = -1
            player_velocity_y = (jump_count ** 2) * 0.5 * neg
            jump_count -= 1
        else:
            is_jumping = False
            jump_count = 10

    # プレイヤーの移動
    player_x += player_velocity_x
    player_y -= player_velocity_y  # y座標を減算することで上方向に移動

    # 画面端の処理
    if player_x < 0:
        player_x = 0
    elif player_x > screen_width - player_width:
        player_x = screen_width - player_width

    # 床との衝突判定
    if player_y > screen_height - floor_height - player_height:
        player_y = screen_height - floor_height - player_height
        is_jumping = False
        jump_count = 10

    # 敵キャラクターの移動
    enemy_x -= enemy_speed
    if enemy_x < 0:
        enemy_x = screen_width - enemy_width

    # プレイヤーと敵キャラクターの接触判定
    if (
        player_x < enemy_x + enemy_width
        and player_x + player_width > enemy_x
        and player_y < enemy_y + enemy_height
        and player_y + player_height > enemy_y
    ):
        print("Game Over!")
        running = False

    # 描画
    screen.fill((255, 255, 255))  # 背景色

    # 床の描画
    pygame.draw.rect(screen, floor_color, (0, screen_height - floor_height, screen_width, floor_height))

    # プレイヤーの描画
    pygame.draw.rect(screen, (255, 0, 0), (player_x, player_y, player_width, player_height))

    # 敵キャラクターの描画
    pygame.draw.rect(screen, (0, 0, 255), (enemy_x, enemy_y, enemy_width, enemy_height))

    pygame.display.flip()

pygame.quit()
```
![スクリーンショット 2023-12-04 22.52.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3627451/10f01f81-a2cf-3d46-263a-3e427a1a91df.png)

一応地形や敵キャラが出てきましたが、実際に遊んでみたところプレイヤーの操作もくそだし、敵キャラの動きがとても速くて私には１回も避けれませんでした。
(ちなみに友達は3回もできてました）

この後調整を任せようとしましたが、まったくと言うほど改善してくれなかったようなので、諦めました。

## ブロック崩し
流石にブロック崩しくらいできるであろうと思いブロック崩しをさせてみることに
>ブロック崩しのソースコードを教えてください

```py
'''
もちろんです！ブロック崩しゲームのソースコードは、
プログラミング言語やゲームエンジンに依存します。
以下は、PythonとPygameを使用した基本的なブロック崩しゲームの例です。
PygameはPythonのゲーム開発用ライブラリで、インストールする必要があります。
'''
import pygame
import sys
from pygame.locals import *

# 初期化
pygame.init()

# 画面サイズ
WIDTH, HEIGHT = 640, 480

# 色
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)

# パドルのサイズと速度
PADDLE_WIDTH, PADDLE_HEIGHT = 100, 10
PADDLE_SPEED = 10

# ボールのサイズと速度
BALL_SIZE = 20
BALL_SPEED = 5

# 画面の作成
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("ブロック崩し")

# パドルの初期位置
paddle_x = (WIDTH - PADDLE_WIDTH) // 2
paddle_y = HEIGHT - PADDLE_HEIGHT - 10

# ボールの初期位置と速度
ball_x = WIDTH // 2
ball_y = HEIGHT // 2
ball_dx = BALL_SPEED
ball_dy = BALL_SPEED

# メインループ
while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()

    keys = pygame.key.get_pressed()
    if keys[K_LEFT] and paddle_x > 0:
        paddle_x -= PADDLE_SPEED
    if keys[K_RIGHT] and paddle_x < WIDTH - PADDLE_WIDTH:
        paddle_x += PADDLE_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 or ball_y >= HEIGHT - BALL_SIZE:
        ball_dy = -ball_dy

    # パドルとの衝突判定
    if (
        ball_y + BALL_SIZE >= paddle_y
        and paddle_x <= ball_x <= paddle_x + PADDLE_WIDTH
    ):
        ball_dy = -ball_dy

    # 画面の描画
    screen.fill(BLACK)
    pygame.draw.rect(screen, WHITE, (paddle_x, paddle_y, PADDLE_WIDTH, PADDLE_HEIGHT))
    pygame.draw.ellipse(screen, RED, (ball_x, ball_y, BALL_SIZE, BALL_SIZE))

    pygame.display.flip()
    pygame.time.Clock().tick(30)
```
![スクリーンショット 2023-12-04 23.04.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3627451/65654987-cdc0-cec7-c543-1046fecf487f.png)
とても楽しそうなゲームですね...
流石にこれではブロック崩しとは言えないので(まずブロックがない)ゲーム性を加えていきたいと思います
> ゲーム性を持たせてください
ChatGPT
```py
'''
ChatGPT
ゲーム性を追加するために、以下のような要素を導入できます：

ブロックの追加:
ブロックを画面上にランダムまたは固定の配置で追加し、ボールがブロックに当たったときにブロックを削除します。ブロックをすべて削除したら、新しいレベルに進むなどの概念を導入できます。

得点の計算:
ブロックを破壊したときに得点を加算し、プレイヤーのスコアを表示します。スコアに基づいて難易度を調整することもできます。

レベルの進行:
一定のスコアに達すると、新しいレベルに進むようにします。新しいレベルでは、ブロックの配置やボールの速度などが変化します。

パワーアップ:
特定の条件で出現するアイテムやパワーアップを導入し、それを取得すると一時的な強化が得られるようにします。例えば、ボールが2つになる、パドルが広がるなどです。

ゲームオーバーとリスタート:
プレイヤーがボールを落としてしまった場合、ライフを減らしてゲームオーバーにすることができます。その後、リスタートオプションを提供することで、プレイヤーが再挑戦できます。

以下に、ブロック崩しゲームにこれらの概念を追加したサンプルコードを示します。このコードはさらに拡張できますが、基本的なアイデアはここにあります：
'''
import pygame
import sys
import random
from pygame.locals import *

# 初期化
pygame.init()

# 画面サイズ
WIDTH, HEIGHT = 640, 480

# 色
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)

# パドルのサイズと速度
PADDLE_WIDTH, PADDLE_HEIGHT = 100, 10
PADDLE_SPEED = 10

# ボールのサイズと速度
BALL_SIZE = 20
BALL_SPEED = 5

# ブロックのサイズ
BLOCK_WIDTH, BLOCK_HEIGHT = 60, 20

# レベルごとのブロックの行数と列数
LEVEL_ROWS, LEVEL_COLS = 5, 10

# 画面の作成
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("ブロック崩し")

# パドルの初期位置
paddle_x = (WIDTH - PADDLE_WIDTH) // 2
paddle_y = HEIGHT - PADDLE_HEIGHT - 10

# ボールの初期位置と速度
ball_x = WIDTH // 2
ball_y = HEIGHT // 2
ball_dx = BALL_SPEED * random.choice([1, -1])
ball_dy = BALL_SPEED

# ブロックの初期化
def initialize_blocks():
    blocks = []
    for row in range(LEVEL_ROWS):
        for col in range(LEVEL_COLS):
            block_x = col * (BLOCK_WIDTH + 5)
            block_y = row * (BLOCK_HEIGHT + 5) + 50
            blocks.append(pygame.Rect(block_x, block_y, BLOCK_WIDTH, BLOCK_HEIGHT))
    return blocks

blocks = initialize_blocks()

# スコアとライフの初期化
score = 0
lives = 3

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

# メインループ
while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()

    keys = pygame.key.get_pressed()
    if keys[K_LEFT] and paddle_x > 0:
        paddle_x -= PADDLE_SPEED
    if keys[K_RIGHT] and paddle_x < WIDTH - PADDLE_WIDTH:
        paddle_x += PADDLE_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 >= paddle_y
        and paddle_x <= ball_x <= paddle_x + PADDLE_WIDTH
    ):
        ball_dy = -ball_dy

    # ブロックとの衝突判定
    for block in blocks:
        if block.colliderect(pygame.Rect(ball_x, ball_y, BALL_SIZE, BALL_SIZE)):
            blocks.remove(block)
            ball_dy = -ball_dy
            score += 10

    # レベルクリア判定
    if not blocks:
        # 次のレベルへ進む
        blocks = initialize_blocks()
        ball_dy = -ball_dy

    # ボールが底に到達した場合
    if ball_y >= HEIGHT:
        lives -= 1
        ball_x = WIDTH // 2
        ball_y = HEIGHT // 2
        ball_dy = BALL_SPEED
        if lives == 0:
            # ゲームオーバー処理
            print("Game Over")
            pygame.quit()
            sys.exit()

    # 画面の描画
    screen.fill(BLACK)
    pygame.draw.rect(screen, WHITE, (paddle_x, paddle_y, PADDLE_WIDTH, PADDLE_HEIGHT))
    pygame.draw.ellipse(screen, RED, (ball_x, ball_y, BALL_SIZE, BALL_SIZE))

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

    # スコアとライフの表示
    score_text = font.render("Score: {}".format(score), True, WHITE)
    screen.blit(score_text, (10, 10))

    lives_text = font.render("Lives: {}".format(lives), True, WHITE)
    screen.blit(lives_text, (WIDTH - 100, 10))

    pygame.display.flip()
    pygame.time.Clock().tick(30)
```
![スクリーンショット 2023-12-04 23.08.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3627451/25c86dde-78ec-7331-f3ac-833c5b16b469.png)
ライフやScoreが表示されていて、多少ボールが下に当たった時にバグっぽいのはあるけれどもこれまで作らせてみたのと比べて一番まともなものができました。

ちなみに新しい機能をつけてと言ってつけてもらったら途中でプレイヤーが消えたのでここで終了です

## 終わり
今回ChatGPTにゲームを作らせてみましたが、多分普通に自分で描くよりも難易度が相当高いと思います。
GPT4ならもっと動くコードを出力してくれるかもしれませんが、現状で無料で使えるGPT3.5では超簡単なものは作れるけど新しい機能を付け加えようとするとバグや、動かなかったりします。
コードの手直しとかで使うならChatGPTを使用するには大いに役立つと思いますが 、GPTのみのゲーム開発はまだ先のようです。

## おまけ
ChatGPTのライバル的存在のMicrosoftの<b>bingAI</b>君やgoogleの<b>Bard</b>君で試してみましたが、
Bingは思った以上にポンコツで、チャットの制限付き
Bardはエラーが出た時にほぼ同じコードしか出さない(ChatGPTより酷い)、エラーをbardに投げると、英語で帰ってきたりするので、結構ムカつくことがありました。
何やかんやGPT3.5君は優秀