Created
July 4, 2023 23:12
-
-
Save darrenmason/957b477f75287facad81f147aa4f80bf to your computer and use it in GitHub Desktop.
dungeon generator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class DungeonGenerator { | |
constructor(width, height, maxRooms, minRoomSize, maxRoomSize) { | |
this.width = width; | |
this.height = height; | |
this.maxRooms = maxRooms; | |
this.minRoomSize = minRoomSize; | |
this.maxRoomSize = maxRoomSize; | |
this.dungeon = []; | |
} | |
generateDungeon() { | |
// Initialize the dungeon grid | |
this.dungeon = new Array(this.height); | |
for (let y = 0; y < this.height; y++) { | |
this.dungeon[y] = new Array(this.width).fill('#'); | |
} | |
// Generate rooms | |
const rooms = []; | |
for (let i = 0; i < this.maxRooms; i++) { | |
const roomWidth = Math.floor(Math.random() * (this.maxRoomSize - this.minRoomSize + 1)) + this.minRoomSize; | |
const roomHeight = Math.floor(Math.random() * (this.maxRoomSize - this.minRoomSize + 1)) + this.minRoomSize; | |
const x = Math.floor(Math.random() * (this.width - roomWidth - 1)) + 1; | |
const y = Math.floor(Math.random() * (this.height - roomHeight - 1)) + 1; | |
const room = new Room(x, y, roomWidth, roomHeight); | |
if (this.isRoomOverlap(room, rooms)) { | |
continue; | |
} | |
rooms.push(room); | |
// Carve the room into the dungeon grid | |
for (let row = room.y; row < room.y + room.height; row++) { | |
for (let col = room.x; col < room.x + room.width; col++) { | |
this.dungeon[row][col] = '.'; | |
} | |
} | |
} | |
// Connect rooms with tunnels | |
for (let i = 0; i < rooms.length - 1; i++) { | |
const currentRoom = rooms[i]; | |
const nextRoom = rooms[i + 1]; | |
const startPoint = currentRoom.getCenter(); | |
const endPoint = nextRoom.getCenter(); | |
this.connectRooms(startPoint, endPoint); | |
} | |
return this.dungeon; | |
} | |
isRoomOverlap(room, rooms) { | |
for (const existingRoom of rooms) { | |
if ( | |
room.x < existingRoom.x + existingRoom.width && | |
room.x + room.width > existingRoom.x && | |
room.y < existingRoom.y + existingRoom.height && | |
room.y + room.height > existingRoom.y | |
) { | |
return true; | |
} | |
} | |
return false; | |
} | |
connectRooms(startPoint, endPoint) { | |
let x = startPoint.x; | |
let y = startPoint.y; | |
while (x !== endPoint.x || y !== endPoint.y) { | |
if (x !== endPoint.x) { | |
x += x < endPoint.x ? 1 : -1; | |
} else if (y !== endPoint.y) { | |
y += y < endPoint.y ? 1 : -1; | |
} | |
if (this.dungeon[y][x] === '#') { | |
this.dungeon[y][x] = '.'; | |
} | |
} | |
} | |
} | |
class Room { | |
constructor(x, y, width, height) { | |
this.x = x; | |
this.y = y; | |
this.width = width; | |
this.height = height; | |
} | |
getCenter() { | |
const centerX = Math.floor((this.x + this.x + this.width) / 2); | |
const centerY = Math.floor((this.y + this.y + this.height) / 2); | |
return { x: centerX, y: centerY }; | |
} | |
} | |
// Example usage | |
const dungeonWidth = 40; | |
const dungeonHeight = 20; | |
const maxRooms = 10; | |
const minRoomSize = 3; | |
const maxRoomSize = 6; | |
const generator = new DungeonGenerator(dungeonWidth, dungeonHeight, maxRooms, minRoomSize, maxRoomSize); | |
const dungeon = generator.generateDungeon(); | |
// Print the dungeon to the console | |
for (let y = 0; y < dungeonHeight; y++) { | |
console.log(dungeon[y].join('')); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment