この記事は穴掘り法によるマップ(壁)の自動生成を Godot Engine で実装したサンプルを紹介するページです
穴掘り法によるダンジョンの自動生成Roguelike (ローグライクゲーム) や、 Dungeon crawler (3DダンジョンRPG) のお手軽な自動生成ダンジョンとして使用できると思います。
穴掘り法の実装例
以下、穴掘り法を実装したサンプルコードです
extends Node2D
# マップの広さ
const MAP_WIDTH = 16
const MAP_HEIGHT = 9
# tilemap上の値
const TILE_WALL = 0
# _arrayでの値
const ARRAY_OUT_OF_RANGE = -1 # 領域外
const ARRAY_PASSAGE = 0 # 通路
const ARRAY_WALL = 1 # 影
# 2次元配列管理
class Array2D:
var _width = 0
var _height = 0
var _pool = []
func _init(w:int, h:int) -> void:
_width = w
_height = h
for j in range(h):
for i in range(w):
_pool.append(0)
func fill(v:int) -> void:
for j in range(_height):
for i in range(_width):
_pool[i + j * _width] = v
func setv(i:int, j:int, v:int) -> void:
if i < 0 or i >= _width:
return # 領域外
if j < 0 or j >= _height:
return # 領域外
_pool[i + j * _width] = v
func getv(i:int, j:int) -> int:
if i < 0 or i >= _width:
return ARRAY_OUT_OF_RANGE # 領域外
if j < 0 or j >= _height:
return ARRAY_OUT_OF_RANGE # 領域外
return _pool[i + j * _width]
func dump() -> void:
print("[array2d]")
for j in range(_height):
var s = ""
for i in range(_width):
s += "%d, "%getv(i, j)
print(s)
var _array = Array2D.new(MAP_WIDTH, MAP_HEIGHT)
onready var tilemap = $TileMap
func _ready() -> void:
_regenerate()
_redraw()
# ダンジョンを生成する
func _regenerate() -> void:
_array.fill(ARRAY_WALL)
# 開始地点を決める
var xstart = randi()%MAP_WIDTH
var ystart = randi()%MAP_HEIGHT
# 穴掘り開始
_dig(xstart, ystart)
# デバッグ用に作成したリストを出力する
_array.dump()
# 穴を掘る
func _dig(x:int, y:int) -> void:
# 開始地点を掘る
_array.setv(x, y, ARRAY_PASSAGE)
# 掘れるかどうかを判定する方向
var dir_list = [
Vector2(-1, 0),
Vector2(0, -1),
Vector2(1, 0),
Vector2(0, 1)
]
# シャッフル
dir_list.shuffle()
for dir in dir_list:
var dx = dir.x
var dy = dir.y
if _array.getv(x + dx*2, y + dy*2) == ARRAY_WALL:
# 2マス先が壁なので掘れる
_array.setv(x+dx, y+dy, 0)
# 次の穴を掘る
_dig(x + dx*2, y + dy*2)
# タイルマップに反映する
func _redraw() -> void:
tilemap.clear()
for j in range(MAP_HEIGHT):
for i in range(MAP_WIDTH):
if _array.getv(i, j) == ARRAY_WALL:
tilemap.set_cell(i, j, 0)
# 再生性ボタンを押した
func _on_ButtonRedraw_pressed() -> void:
_regenerate()
_redraw()
穴掘り法の考え方については関連ページのコードをそのまま使用しています。
穴掘り法によるダンジョンの自動生成少し気をつけるところとしては、穴掘りで使用する配列を「Array2D」クラスで管理し、内部で使用する値を「ARRAY_*」定数で扱っていることとなります。
完成プロジェクト
今回作成したプロジェクトファイルを添付しておきます。