ChatGPTにゲーム作りのお手伝いをしてもらう
ChatGPTはコーディングが得意だという情報をたくさん目にするようになったので、自分もやってみようと思って、いろいろトライしてみました。
現状では長いコードを書かせようとすると途中で途切れてしまったり(「続けて」とお願いすると続けてくれるんですが少々面倒)、凡ミスが割と多く何度もリテイクをお願いしなくてはいけなかったりするので、本格的なプログラムを作ってもらうにはまだ難しい印象なのですが、いろいろ試行錯誤するうちに、プログラムの一部分のたたき台を作ってもらうのには有用かもな、と思いました。
お題:ローグライクゲームのマップ自動生成をお願いする
たとえば、私はいまローグライクなゲームをPyxel(Pythonで動くレトロゲームエンジン)で作ろうかなと考えているのですが、ローグライクゲームといえば必要不可欠なのは「マップの自動生成」の仕組みです。
ですが私はマップの自動生成アルゴリズムなど全然わかりません。もちろん検索すれば先人たちが十分な情報をネットに上げてくださっているので、それを参考に実装することはできるんですが、それなりに手間はかかります。
そこで、今回はこの部分をChatGPTさんに任せてみました。
次の画像は実際に生成してもらったマップです。(0と1のテキストデータで出力してもらったのを、わかりやすいように□とスペースに置き換えています。)
ちゃんとダンジョンマップができていますね。
以下はこのマップを生成してもらうために、私がChatGPTに依頼したスクリプトです。
別に何の工夫もないんですが、「区域分割法」という言葉は「マップ 自動生成」とかのキーワードでググって知った、自動生成の手法の1つみたいです。
Pythonで、区域分割法を使ってダンジョンのマップを自動生成するサンプルプログラムを作っていただけませんか?
次は、ちょっと長くなりますがChatGPTが書いてくれたコード。
ちなみに1発目はコンパイルエラーが出たので、エラーログをそのまま貼り付けたら修正してくれました。
import random
class Rect:
def __init__(self, x, y, w, h):
self.x1 = x
self.y1 = y
self.x2 = x + w
self.y2 = y + h
def center(self):
center_x = int((self.x1 + self.x2) / 2)
center_y = int((self.y1 + self.y2) / 2)
return (center_x, center_y)
def intersect(self, other):
return (
self.x1 <= other.x2
and self.x2 >= other.x1
and self.y1 <= other.y2
and self.y2 >= other.y1
)
class DungeonGenerator:
def __init__(self, width, height, min_room_size, max_room_size):
self.width = width
self.height = height
self.min_room_size = min_room_size
self.max_room_size = max_room_size
self.dungeon_map = [[1 for y in range(self.height)] for x in range(self.width)]
self.rooms = []
def generate(self):
self._create_rooms()
self._create_corridors()
return self.dungeon_map
def _create_rooms(self):
for i in range(10):
w = random.randint(self.min_room_size, self.max_room_size)
h = random.randint(self.min_room_size, self.max_room_size)
x = random.randint(0, self.width - w - 1)
y = random.randint(0, self.height - h - 1)
new_room = Rect(x, y, w, h)
for other_room in self.rooms:
if new_room.intersect(other_room):
break
else:
self._paint_room(new_room)
self.rooms.append(new_room)
def _paint_room(self, room):
for x in range(room.x1 + 1, room.x2):
for y in range(room.y1 + 1, room.y2):
self.dungeon_map[x][y] = 0
def _create_corridors(self):
rooms = sorted(self.rooms, key=lambda x: x.center())
for i in range(len(rooms) - 1):
x1, y1 = rooms[i].center()
x2, y2 = rooms[i + 1].center()
if random.randint(0, 1) == 1:
self._paint_horizontally(x1, x2, y1)
self._paint_vertically(y1, y2, x2)
else:
self._paint_vertically(y1, y2, x1)
self._paint_horizontally(x1, x2, y2)
def _paint_horizontally(self, x1, x2, y):
for x in range(min(x1, x2), max(x1, x2) + 1):
self.dungeon_map[x][y] = 0
def _paint_vertically(self, y1, y2, x):
for y in range(min(y1, y2), max(y1, y2) + 1):
self.dungeon_map[x][y] = 0
if __name__ == "__main__":
dungeon = DungeonGenerator(50, 80, 4, 10)
dungeon.generate()
for row in dungeon.dungeon_map:
print("".join(str(cell) for cell in row))以下はChatGPTさんによるセルフ解説です。
上記のコードでは、Rectクラスを使用して矩形の座標を管理し、DungeonGeneratorクラスを使用してダンジョンを生成します。
まず、_create_roomsメソッドを使用して、ランダムな位置とサイズの部屋を作成します。このメソッドでは、部屋が他の部屋と重ならないようにするため、作成された各部屋がすでに存在する部屋と交差していないかを確認します。交差がある場合は、新しい部屋は破棄されます。交差がない場合は、_paint_roomメソッドを使用して部屋を描画し、部屋を部屋のリストに追加します。
次に、_create_corridorsメソッドを使用して、部屋を接続する通路を作成します。このメソッドでは、部屋を中心座標でソートし、ランダムに水平または垂直方向に通路を描画します。
最後に、生成されたダンジョンを出力するために、生成されたマップを文字列に変換して表示するようにします。上記のコードでは、50x80のダンジョンを生成しています。部屋のサイズは、最小サイズが4x4、最大サイズが10x10となっています。
まあ、このくらいであればググってソースコードを載せてくれているブログ記事やらを探してコードをコピペするのと大して変わらないのかもしれませんが、ChatGPTさんは修正指示を出せばカスタマイズしてくれたりもするので(私が何回か試した所感だと、思い通りの方針に誘導するのはなかなか難しいのですが)、敷居が低い割にそこそこ実用的なChatGPTの使い方かなーなんて思ってます。
ChatGPTは今後もどんどん進化していくでしょうし、置いていかれないようにしたいですね。


コメント