前提
pythonのpygameでダンジョン自動生成アルゴリズムを開発しています。
タイルは16x16で作っています。
実現したいこと
・Roomから道を伸ばして別のRoomにつなぎたい。
・行き止まりをなくしたい。
・Room同士の間隔を2マス以上開けたい。
・タイルベースのマップに応用するためRectベースで行いたい。
発生している問題・エラーメッセージ
・Roomからの道の伸ばし方はわかるがアルゴリズム的に処理できない。(どんなダンジョンにでも適用できるようにできない。)
該当のソースコード
####### モジュールのインポート ------------------------------------------------------# import pygame from pygame.locals import * import sys import random import time import copy ####### 初期化 ----------------------------------------------------------------------# pygame.init() ####### 変数の定義 ------------------------------------------------------------------# DISPLAY_WIDTH = 1024 DISPLAY_HEIGHT = 576 display = pygame.display.set_mode((1024, 576)) main_canvas = pygame.Surface((1024, 576)) running = True ####### クラスの定義 ----------------------------------------------------------------# class Level: def __init__(self, canvas: pygame.Surface): self.canvas = canvas self.WIDTH = 64 self.HEIGHT = 32 self.tiles = [] self.areas = [] self.off_set_areas = [] self.rooms = [] self.MIN_ROOM_SIZE = 4 self.MAX_ROOM_NUM = 25 for y in range(self.HEIGHT): self.tiles.append([1] * self.WIDTH) def draw(self): # タイルの表示 for y in range(self.HEIGHT): for x in range(self.WIDTH): X = x * 16 Y = (y + 1) * 16 if self.tiles[y][x] == 0: pygame.draw.rect(self.canvas, (255, 255, 255), (X, Y, 16, 16)) if self.tiles[y][x] == 1: pygame.draw.rect(self.canvas, (0, 0, 0), (X, Y, 16, 16)) # グリッドの表示 for y in range(self.HEIGHT): for x in range(self.WIDTH): X = x * 16 Y = (y + 1) * 16 pygame.draw.rect(self.canvas, (0, 0, 0), (X, Y, 16, 16), width=1) # エリアの表示 for area in self.areas: pygame.draw.rect(self.canvas, (0, 0, 255), area, width=1) # オフセットエリアの表示 for area in self.off_set_areas: pygame.draw.rect(self.canvas, (255, 0, 0), area, width=2) # 部屋の表示 for room in self.rooms: pygame.draw.rect(self.canvas, (0, 255, 0), room, width=2) def put_areas(self): for y in range(0, self.HEIGHT, 8): for x in range(0, self.WIDTH, 8): X = x * 16 Y = (y + 1) * 16 self.areas.append(Rect(X, Y, 8 * 16, 8 * 16)) self.off_set_areas.append(Rect(X + 16, Y + 16, 6 * 16, 6 * 16)) def put_rooms(self): # エリアをシャッフル copy_off_set_areas = copy.copy(self.off_set_areas) random.shuffle(copy_off_set_areas) for area in copy_off_set_areas: if len(self.rooms) < self.MAX_ROOM_NUM: c_rect = self.create_room(area) self.rooms.append(Room(c_rect)) else: rect = self.create_relay(area) self.rooms.append(Room(rect)) def apply_rect_to_rooms(self): for room in self.rooms: for y in range(room.rect.top, room.rect.bottom, 16): for x in range(room.rect.left, room.rect.right, 16): dx = x // 16 dy = y // 16 - 1 self.tiles[dy][dx] = 0 def create_room(self, area): room_x = random.randrange(area.x, area.x + area.width, 16) room_y = random.randrange(area.y, area.y + area.width, 16) room_width = random.randint(self.MIN_ROOM_SIZE, area.width // 16) * 16 room_height = random.randint(self.MIN_ROOM_SIZE, area.height // 16) * 16 rect = Rect(room_x, room_y, room_width, room_height) c_rect = area.clip(rect) if c_rect.width // 16 < self.MIN_ROOM_SIZE or c_rect.height // 16 < self.MIN_ROOM_SIZE: return self.create_room(area) return c_rect def create_relay(self, area): relay_x = random.randrange(area.x, area.x + area.width, 16) relay_y = random.randrange(area.y, area.y + area.width, 16) relay_width = 16 relay_height = 16 rect = Rect(relay_x, relay_y, relay_width, relay_height) return rect class Room: def __init__(self, rect): self.rect = rect ####### メイン処理 ------------------------------------------------------------------# if __name__ == '__main__': level = Level(main_canvas) level.put_areas() level.put_rooms() level.apply_rect_to_rooms() while running: for event in pygame.event.get(): if event.type == QUIT: pygame.quit() sys.exit() if event.type == KEYDOWN and event.key == K_a: level = Level(main_canvas) level.put_areas() level.put_rooms() level.apply_rect_to_rooms() # ループ処理 display.fill("black") main_canvas.fill("black") level.draw() display.blit(pygame.transform.scale(main_canvas, (DISPLAY_WIDTH, DISPLAY_HEIGHT)), (0, 0)) # アップデート pygame.display.update()
試したこと
・Roomから手動で道を引く
補足情報(FW/ツールのバージョンなど)
・参考にしたサイト https://qiita.com/kyooooooooma/items/a8ee1157b89b7f744098#%E4%BD%9C%E4%BE%8B
・pygameについての知識はある程度あります。(小規模なゲームなら作れる。pygameの使い方についての理解はある。)
あなたの回答
tips
プレビュー