Created
March 14, 2013 07:36
-
-
Save hyakugei/5159534 to your computer and use it in GitHub Desktop.
Following the rules (more or less) for the original Rogue map-generation algorithm, i made this addition to the rot.js lib. Please note, this is a early, ugly, bit of code. But it works. And makes cool dungeons!
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
ROT.Map.Classic = function(width, height, options) { | |
ROT.Map.call(this, width, height); | |
var getRoomSizes = function(size, cells) | |
{ | |
var max = Math.floor((size/cells) * 0.8); | |
var min = Math.floor((size/cells) * 0.25); | |
if(min < 2) min = 2; | |
if(max < 2) min = 2; | |
return [min, max]; | |
} | |
this._options = { | |
cellWidth: 3, | |
cellHeight: 3 | |
} | |
for (var p in options) { this._options[p] = options[p]; } | |
/* | |
Set the room sizes according to the over-all width of the map, | |
and the cell sizes. | |
*/ | |
if(!this._options.hasOwnProperty("roomWidth")) | |
{ | |
this._options["roomWidth"] = getRoomSizes(width, this._options["cellWidth"]); | |
} | |
if(!this._options.hasOwnProperty["roomHeight"]) | |
{ | |
this._options["roomHeight"] = getRoomSizes(height, this._options["cellHeight"]); | |
} | |
this._map = this._fillMap(0); | |
console.log("Classic create. "); | |
} | |
ROT.Map.Classic.extend(ROT.Map); | |
ROT.Map.Classic.prototype.create = function(callback) { | |
var w = this._width; | |
var h = this._height; | |
var cw = this._options["cellWidth"]; | |
var ch = this._options["cellHeight"]; | |
var cwp = Math.floor(w/cw); // number of units/pixels in each cell width | |
var chp = Math.floor(h/ch); // number of units/pixels in each cell height | |
var cgx = 0; | |
var cgy = 0; | |
var connectedCells = []; | |
var map = []; | |
var roomSizes = []; | |
var rooms = []; | |
var room; | |
var connection; | |
var xOffset; | |
var yOffset; | |
var wall; | |
var connectingRoom; | |
var otherRoom; | |
var otherWall; | |
var wallx; | |
var wally; | |
// room.x | |
// room.y | |
// room.width | |
// room.heigh | |
// room.connections = [ [x,y], [x,y] ] | |
var dir = {}; | |
dir[0] = [0,1]; | |
dir[1] = [1,1]; | |
dir[2] = [1,0]; | |
dir[3] = [1,-1]; | |
dir[4] = [0, -1]; | |
dir[5] = [-1,-1]; | |
dir[6] = [-1,0]; | |
dir[7] = [-1,-1]; | |
// create map | |
for(var i = 0; i < w; i++) | |
{ | |
map.push([]); | |
for(var j = 0; j < h; j++) | |
{ | |
map[i].push(1); | |
} | |
} | |
// create "grid" | |
var grid = []; | |
for(var i = 0; i < cw; i++) | |
{ | |
//grid.push([]); | |
//roomSizes.push([]); | |
rooms.push([]); | |
for(var j = 0; j < ch; j++) | |
{ | |
//grid[i].push(false); | |
//roomSizes[i].push([0,0]); | |
rooms[i].push({"x":0, "y":0, "width":0, "height":0, "connections":[], "cellx":i, "celly":j}); | |
} | |
} | |
console.log(rooms); | |
//pick random starting grid | |
//var currentGrid = ROT.RNG.getRandomInt(1, (cw * ch)) - 1; | |
//console.log("First grid: " + currentGrid); | |
cgx = ROT.RNG.getRandomInt(0, cw-1); | |
cgy = ROT.RNG.getRandomInt(0, ch-1); | |
//grid[cgx][cgy] = false; // mark as connected; | |
//connectedCells.push([cgx,cgy]); | |
var idx; | |
var ncgx; | |
var ncgy; | |
// find unconnected neighbour cells | |
do | |
{ | |
//var dirToCheck = [0,1,2,3,4,5,6,7]; | |
var dirToCheck = [0,2,4,6]; | |
dirToCheck = dirToCheck.randomize(); | |
do | |
{ | |
var found = false; | |
idx = dirToCheck.pop(); | |
ncgx = cgx + dir[idx][0]; | |
ncgy = cgy + dir[idx][1]; | |
if(ncgx < 0 || ncgx >= cw) continue; | |
if(ncgy < 0 || ncgy >= ch) continue; | |
room = rooms[cgx][cgy]; | |
if(room["connections"].length > 0) | |
{ | |
if(room["connections"][0][0] == ncgx && | |
room["connections"][0][1] == ncgy) | |
{ | |
break; | |
} | |
} | |
otherRoom = rooms[ncgx][ncgy]; | |
if(otherRoom["connections"].length == 0) | |
{ | |
// console.log("Connecting cell:" + cgx + "," + cgy + " to " + ncgx + "," + ncgy); | |
// set this as the current cell. | |
//grid[ncgx][ncgy] = [cgx, cgy]; | |
otherRoom["connections"].push([cgx,cgy]); | |
connectedCells.push([ncgx, ncgy]); | |
cgx = ncgx; | |
cgy = ncgy; | |
found = true; | |
} | |
}while(dirToCheck.length > 0 && found == false) | |
}while(dirToCheck.length > 0) | |
// console.log("Now checking for unconnected cells"); | |
//While there are unconnected rooms, try to connect them to a random connected neighbor (if a room has no connected neighbors yet, just keep cycling, you'll fill out to it eventually). | |
var randomConnectedCell; | |
connectedCells = connectedCells.randomize(); | |
for(var i = 0; i < cw; i++) | |
{ | |
for(var j = 0; j < ch; j++) | |
{ | |
room = rooms[i][j]; | |
if(room["connections"].length == 0) | |
{ | |
var directions = [0,2,4,6]; | |
directions = directions.randomize(); | |
var validRoom = false; | |
do | |
{ | |
var dirIdx = directions.pop(); | |
var newI = i + dir[dirIdx][0]; | |
var newJ = j + dir[dirIdx][1]; | |
if(newI < 0 || newI >= cw || | |
newJ < 0 || newJ >= ch) | |
{ | |
continue; | |
} | |
otherRoom = rooms[newI][newJ]; | |
validRoom = true; | |
if(otherRoom["connections"].length == 0) | |
{ | |
break; | |
} | |
for(var k = 0; k < otherRoom["connections"].length; k++) | |
{ | |
if(otherRoom["connections"][k][0] == i && | |
otherRoom["connections"][k][1] == j) | |
{ | |
validRoom = false; | |
break; | |
} | |
} | |
if(validRoom) break; | |
}while(directions.length) | |
if(validRoom) | |
{ | |
room["connections"].push( [otherRoom["cellx"], otherRoom["celly"]] ); | |
} | |
else | |
{ | |
console.log("-- Unable to connect room."); | |
} | |
} | |
} | |
} | |
//Make 0 or more random connections to taste; I find rnd(grid_width) random connections looks good. | |
// later | |
// Create Rooms | |
var roomw; | |
var roomh; | |
var roomWidth = this._options["roomWidth"]; | |
var roomHeight = this._options["roomHeight"]; | |
var sx; | |
var sy; | |
var tx; | |
var ty; | |
for(var i = 0; i < cw; i++) | |
{ | |
for(var j = 0; j < ch; j++) | |
{ | |
sx = cwp * i; | |
sy = chp * j; | |
if(sx == 0) sx = 1; | |
if(sy == 0) sy = 1; | |
roomw = ROT.RNG.getRandomInt(roomWidth[0], roomWidth[1]); | |
roomh = ROT.RNG.getRandomInt(roomHeight[0], roomHeight[1]); | |
if(j > 0) | |
{ | |
otherRoom = rooms[i][j-1]; | |
while(sy - (otherRoom["y"] + otherRoom["height"] ) < 3) | |
{ | |
sy++; | |
} | |
} | |
if(i > 0) | |
{ | |
otherRoom = rooms[i-1][j]; | |
while(sx - (otherRoom["x"] + otherRoom["width"]) < 3) | |
{ | |
sx++; | |
} | |
} | |
var sxOffset = Math.round(ROT.RNG.getRandomInt(0, cwp-roomw)/2); | |
var syOffset = Math.round(ROT.RNG.getRandomInt(0, chp-roomh)/2); | |
while(sx + sxOffset + roomw >= w) { | |
if(sxOffset) | |
{ | |
sxOffset--; | |
} | |
else | |
{ | |
roomw--; | |
} | |
} | |
while(sy + syOffset + roomh >= h) { | |
if(syOffset) | |
{ | |
syOffset--; | |
} | |
else | |
{ | |
roomh--; | |
} | |
} | |
sx = sx + sxOffset; | |
sy = sy + syOffset; | |
rooms[i][j]["x"] = sx; | |
rooms[i][j]["y"] = sy; | |
rooms[i][j]["width"] = roomw; | |
rooms[i][j]["height"] = roomh; | |
for(var ii = sx; ii < sx + roomw; ii++) | |
{ | |
for(var jj = sy; jj < sy + roomh; jj++) | |
{ | |
map[ii][jj] = 0; | |
} | |
} | |
} | |
} | |
// Draw Corridors between connected rooms | |
for(var i = 0; i < cw; i++) | |
{ | |
for(var j = 0; j < ch; j++) | |
{ | |
room = rooms[i][j]; | |
//console.log(room); | |
for(var k = 0; k < room["connections"].length; k++) | |
{ | |
connection = room["connections"][k]; // this is a 2 item array. | |
// console.log(connection); | |
otherRoom = rooms[connection[0]][connection[1]]; | |
// figure out what wall our corridor will start one. | |
// figure out what wall our corridor will end on. | |
if(otherRoom["cellx"] > room["cellx"] ) | |
{ | |
wall = 2; | |
otherWall = 4; | |
} | |
else if(otherRoom["cellx"] < room["cellx"] ) | |
{ | |
wall = 4; | |
otherWall = 2; | |
} | |
else if(otherRoom["celly"] > room["celly"]) | |
{ | |
wall = 3; | |
otherWall = 1; | |
} | |
else if(otherRoom["celly"] < room["celly"]) | |
{ | |
wall = 1; | |
otherWall = 3; | |
} | |
var getWallPosition = function(aRoom, aDirection) | |
{ | |
var rx; | |
var ry; | |
var door; | |
if(aDirection == 1 || aDirection == 3) | |
{ | |
rx = ROT.RNG.getRandomInt(aRoom["x"] + 1, aRoom["x"] + aRoom["width"] - 2); | |
if(aDirection == 1) | |
{ | |
ry = aRoom["y"] - 2; | |
door = ry + 1; | |
} | |
else | |
{ | |
ry = aRoom["y"] + aRoom["height"] + 1; | |
door = ry -1; | |
} | |
map[rx][door] = 0; | |
} | |
else if(aDirection == 2 || aDirection == 4) | |
{ | |
ry = ROT.RNG.getRandomInt(aRoom["y"] + 1, aRoom["y"] + aRoom["height"] - 2); | |
if(aDirection == 2) | |
{ | |
rx = aRoom["x"] + aRoom["width"] + 1; | |
door = rx - 1; | |
} | |
else | |
{ | |
rx = aRoom["x"] - 2; | |
door = rx + 1; | |
} | |
map[door][ry] = 0; | |
} | |
return [rx, ry]; | |
} | |
var drawCorridore = function(startPosition, endPosition) | |
{ | |
//console.log("drawCorridore " ); | |
//console.log(startPosition[0] + "," + startPosition[1]); | |
//console.log(endPosition[0] + "," + endPosition[1]); | |
xOffset = endPosition[0] - startPosition[0]; | |
yOffset = endPosition[1] - startPosition[1]; | |
var xCount = 0; | |
var yCount = 0; | |
var counter = 0; | |
var tx; | |
var ty; | |
var path = []; | |
if(xOffset != 0) | |
xCount = xOffset > 0 ? 1 : -1; | |
if(yOffset != 0) | |
yCount = yOffset > 0 ? 1 : -1; | |
map[startPosition[0]][startPosition[1]] = 0; | |
map[endPosition[0]][endPosition[1]] = 0; | |
while(xOffset != 0 || yOffset != 0) | |
{ | |
if(xOffset != 0 && counter == 0) | |
{ | |
counter = 1; | |
xOffset -= xCount; | |
} | |
else if(yOffset != 0 && counter == 1) | |
{ | |
counter = 0; | |
yOffset -= yCount; | |
} | |
if(xOffset == 0) | |
{ | |
counter = 1; | |
} | |
if(yOffset == 0) | |
{ | |
counter = 0; | |
} | |
tx = endPosition[0] - xOffset; | |
ty = endPosition[1] - yOffset; | |
map[tx][ty] = 0; | |
//map[tx-xCount][ty] = 0; | |
} | |
} | |
//console.log("dir: " + wall + " wall 1: " + getWallPosition(room, wall) + " dir " + otherWall + " wall 2: " + getWallPosition( otherRoom, otherWall)); | |
drawCorridore(getWallPosition(room, wall), getWallPosition(otherRoom, otherWall)); | |
} | |
} | |
} | |
if(callback) | |
{ | |
for(var i = 0; i < w; i++) | |
{ | |
for(var j = 0; j < h; j++) | |
{ | |
callback(i, j, map[i][j]); | |
} | |
} | |
} | |
return this; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment