A dungeon delver roguelike using Pathfinder 2nd edition rules
at godot 3.7 kB view raw
1class_name Dungeon 2 3extends Node 4 5@export var grid: PackedByteArray = [] 6@export var width: int = 6 7@export var height: int = 6 8@export var entrance: int = -1 9@export var init: bool = false 10@export var currentRoom: int = -1 11 12const BitUsedRoom: int = 0x01 13const BitEntrance: int = 0x02 14const BitDoorNorth: int = 0x04 15const BitDoorEast: int = 0x08 16const BitDoorSouth: int = 0x10 17const BitDoorWest: int = 0x20 18const BitStairBelow: int = 0x40 19const BitStairUp: int = 0x80 20 21const Neighbors: int = BitDoorNorth | BitDoorEast | BitDoorSouth | BitDoorWest 22 23var rng: RandomNumberGenerator = RandomNumberGenerator.new() 24 25func _ready() -> void: 26 if init: 27 generate() 28 currentRoom = entrance 29 var nextScene: Node3D = preload("res://dungeonRoom/dungeonRoom.tscn").instantiate() 30 get_node("/root/Main").call_deferred("add_child", nextScene) 31 32func fillArray(r: Array, size: int): 33 for i in range(size): 34 r.append(0) 35 36func fillByteArray(r: PackedByteArray, size: int): 37 for i in range(size): 38 r.append(0) 39 40func generate(): 41 var dungeonArea: int = width * height 42 fillByteArray(grid, dungeonArea) 43 var generatedCellsNum: int = 0 44 var generatedCells: Array[int] 45 fillArray(generatedCells, dungeonArea) 46 var i = 0 47 48 while ((generatedCellsNum < dungeonArea) and ((i == 0) or (i < generatedCellsNum))): 49 if (i == 0) and (generatedCellsNum == 0): 50 entrance = rng.randi_range(0, dungeonArea - 1) 51 generatedCells[0] = entrance 52 grid[entrance] = BitEntrance | BitUsedRoom 53 generatedCellsNum = 1 54 55 var generatedCellsRef: Array[int] = [generatedCellsNum] 56 generateRoom(i, generatedCells, generatedCellsRef) 57 generatedCellsNum = generatedCellsRef[0] 58 59 if !(grid[generatedCells[i]] & BitUsedRoom): 60 grid[generatedCells[i]] |= BitUsedRoom 61 62 if (i == (generatedCellsNum - 1)) and (generatedCellsNum < (dungeonArea * 0.75)): 63 i = -1 64 65 i += 1 66 67func generateRoom(cellIndexQueue: int, cellsQueue: Array[int], queueSize: Array[int]) -> void: 68 var potentialDoors: int = rng.randi_range(0, Neighbors - 1) 69 var cellIndex: int = cellsQueue[cellIndexQueue] 70 71 var door: int = 1 72 var oppositeDoor: int 73 74 while door <= Neighbors: 75 if ((door & Neighbors) != door) or (grid[cellIndex] & door): 76 door <<= 1 77 continue 78 79 var neighborRoom: int = getNeighborRoomIndex(cellIndex, door) 80 81 if (!~neighborRoom) or (grid[neighborRoom] & BitUsedRoom): 82 door <<= 1 83 continue 84 85 oppositeDoor = getOppositeDirectionBit(door) 86 87 if (door & potentialDoors) == door: 88 grid[cellIndex] |= door 89 grid[neighborRoom] |= oppositeDoor 90 91 if grid[neighborRoom] == oppositeDoor: 92 cellsQueue[queueSize[0]] = neighborRoom 93 queueSize[0] += 1 94 95 door <<= 1 96 97func getNeighborRoomIndex(currRoom: int, direction: int) -> int: 98 var neighborRoom: int 99 100 if direction == BitDoorNorth: 101 neighborRoom = currRoom - width 102 elif direction == BitDoorEast: 103 neighborRoom = currRoom + 1 104 elif direction == BitDoorSouth: 105 neighborRoom = currRoom + width 106 elif direction == BitDoorWest: 107 neighborRoom = currRoom - 1 108 109 if ((direction == BitDoorNorth) and (neighborRoom >= 0)) or ((direction == BitDoorSouth) and (neighborRoom < (width * height))) or ((direction == BitDoorEast) and ((neighborRoom % width) > 0)) or ((direction == BitDoorWest) and ((neighborRoom % width) < (width - 1))): 110 return neighborRoom 111 112 return -1 113 114func getOppositeDirectionBit(direction: int) -> int: 115 var oppositeDirection: int = -1 116 117 if direction == BitDoorNorth: 118 oppositeDirection = BitDoorSouth 119 elif direction == BitDoorEast: 120 oppositeDirection = BitDoorWest 121 elif direction == BitDoorSouth: 122 oppositeDirection = BitDoorNorth 123 elif direction == BitDoorWest: 124 oppositeDirection = BitDoorEast 125 126 return oppositeDirection