Spaces:
Running
Running
/** | |
* @class | |
* Dungeon feature; has own .create() method | |
*/ | |
ROT.Map.Feature = function() {} | |
ROT.Map.Feature.prototype.isValid = function(canBeDugCallback) {} | |
ROT.Map.Feature.prototype.create = function(digCallback) {} | |
ROT.Map.Feature.prototype.debug = function() {} | |
ROT.Map.Feature.createRandomAt = function(x, y, dx, dy, options) {} | |
/** | |
* @class Room | |
* @augments ROT.Map.Feature | |
* @param {int} x1 | |
* @param {int} y1 | |
* @param {int} x2 | |
* @param {int} y2 | |
* @param {int} [doorX] | |
* @param {int} [doorY] | |
*/ | |
ROT.Map.Feature.Room = function(x1, y1, x2, y2, doorX, doorY) { | |
this._x1 = x1; | |
this._y1 = y1; | |
this._x2 = x2; | |
this._y2 = y2; | |
this._doors = {}; | |
if (arguments.length > 4) { this.addDoor(doorX, doorY); } | |
} | |
ROT.Map.Feature.Room.extend(ROT.Map.Feature); | |
/** | |
* Room of random size, with a given doors and direction | |
*/ | |
ROT.Map.Feature.Room.createRandomAt = function(x, y, dx, dy, options) { | |
var min = options.roomWidth[0]; | |
var max = options.roomWidth[1]; | |
var width = min + Math.floor(ROT.RNG.getUniform()*(max-min+1)); | |
var min = options.roomHeight[0]; | |
var max = options.roomHeight[1]; | |
var height = min + Math.floor(ROT.RNG.getUniform()*(max-min+1)); | |
if (dx == 1) { /* to the right */ | |
var y2 = y - Math.floor(ROT.RNG.getUniform() * height); | |
return new this(x+1, y2, x+width, y2+height-1, x, y); | |
} | |
if (dx == -1) { /* to the left */ | |
var y2 = y - Math.floor(ROT.RNG.getUniform() * height); | |
return new this(x-width, y2, x-1, y2+height-1, x, y); | |
} | |
if (dy == 1) { /* to the bottom */ | |
var x2 = x - Math.floor(ROT.RNG.getUniform() * width); | |
return new this(x2, y+1, x2+width-1, y+height, x, y); | |
} | |
if (dy == -1) { /* to the top */ | |
var x2 = x - Math.floor(ROT.RNG.getUniform() * width); | |
return new this(x2, y-height, x2+width-1, y-1, x, y); | |
} | |
} | |
/** | |
* Room of random size, positioned around center coords | |
*/ | |
ROT.Map.Feature.Room.createRandomCenter = function(cx, cy, options) { | |
var min = options.roomWidth[0]; | |
var max = options.roomWidth[1]; | |
var width = min + Math.floor(ROT.RNG.getUniform()*(max-min+1)); | |
var min = options.roomHeight[0]; | |
var max = options.roomHeight[1]; | |
var height = min + Math.floor(ROT.RNG.getUniform()*(max-min+1)); | |
var x1 = cx - Math.floor(ROT.RNG.getUniform()*width); | |
var y1 = cy - Math.floor(ROT.RNG.getUniform()*height); | |
var x2 = x1 + width - 1; | |
var y2 = y1 + height - 1; | |
return new this(x1, y1, x2, y2); | |
} | |
/** | |
* Room of random size within a given dimensions | |
*/ | |
ROT.Map.Feature.Room.createRandom = function(availWidth, availHeight, options) { | |
var min = options.roomWidth[0]; | |
var max = options.roomWidth[1]; | |
var width = min + Math.floor(ROT.RNG.getUniform()*(max-min+1)); | |
var min = options.roomHeight[0]; | |
var max = options.roomHeight[1]; | |
var height = min + Math.floor(ROT.RNG.getUniform()*(max-min+1)); | |
var left = availWidth - width - 1; | |
var top = availHeight - height - 1; | |
var x1 = 1 + Math.floor(ROT.RNG.getUniform()*left); | |
var y1 = 1 + Math.floor(ROT.RNG.getUniform()*top); | |
var x2 = x1 + width - 1; | |
var y2 = y1 + height - 1; | |
return new this(x1, y1, x2, y2); | |
} | |
ROT.Map.Feature.Room.prototype.addDoor = function(x, y) { | |
this._doors[x+","+y] = 1; | |
} | |
/** | |
* @param {function} | |
*/ | |
ROT.Map.Feature.Room.prototype.getDoors = function(callback) { | |
for (var key in this._doors) { | |
var parts = key.split(","); | |
callback(parseInt(parts[0]), parseInt(parts[1])); | |
} | |
} | |
ROT.Map.Feature.Room.prototype.clearDoors = function() { | |
this._doors = {}; | |
return this; | |
} | |
ROT.Map.Feature.Room.prototype.debug = function() { | |
console.log("room", this._x1, this._y1, this._x2, this._y2); | |
} | |
ROT.Map.Feature.Room.prototype.isValid = function(isWallCallback, canBeDugCallback) { | |
var left = this._x1-1; | |
var right = this._x2+1; | |
var top = this._y1-1; | |
var bottom = this._y2+1; | |
for (var x=left; x<=right; x++) { | |
for (var y=top; y<=bottom; y++) { | |
if (x == left || x == right || y == top || y == bottom) { | |
if (!isWallCallback(x, y)) { return false; } | |
} else { | |
if (!canBeDugCallback(x, y)) { return false; } | |
} | |
} | |
} | |
return true; | |
} | |
/** | |
* @param {function} digCallback Dig callback with a signature (x, y, value). Values: 0 = empty, 1 = wall, 2 = door. Multiple doors are allowed. | |
*/ | |
ROT.Map.Feature.Room.prototype.create = function(digCallback) { | |
var left = this._x1-1; | |
var right = this._x2+1; | |
var top = this._y1-1; | |
var bottom = this._y2+1; | |
var value = 0; | |
for (var x=left; x<=right; x++) { | |
for (var y=top; y<=bottom; y++) { | |
if (x+","+y in this._doors) { | |
value = 2; | |
} else if (x == left || x == right || y == top || y == bottom) { | |
value = 1; | |
} else { | |
value = 0; | |
} | |
digCallback(x, y, value); | |
} | |
} | |
} | |
ROT.Map.Feature.Room.prototype.getCenter = function() { | |
return [Math.round((this._x1 + this._x2)/2), Math.round((this._y1 + this._y2)/2)]; | |
} | |
ROT.Map.Feature.Room.prototype.getLeft = function() { | |
return this._x1; | |
} | |
ROT.Map.Feature.Room.prototype.getRight = function() { | |
return this._x2; | |
} | |
ROT.Map.Feature.Room.prototype.getTop = function() { | |
return this._y1; | |
} | |
ROT.Map.Feature.Room.prototype.getBottom = function() { | |
return this._y2; | |
} | |
/** | |
* @class Corridor | |
* @augments ROT.Map.Feature | |
* @param {int} startX | |
* @param {int} startY | |
* @param {int} endX | |
* @param {int} endY | |
*/ | |
ROT.Map.Feature.Corridor = function(startX, startY, endX, endY) { | |
this._startX = startX; | |
this._startY = startY; | |
this._endX = endX; | |
this._endY = endY; | |
this._endsWithAWall = true; | |
} | |
ROT.Map.Feature.Corridor.extend(ROT.Map.Feature); | |
ROT.Map.Feature.Corridor.createRandomAt = function(x, y, dx, dy, options) { | |
var min = options.corridorLength[0]; | |
var max = options.corridorLength[1]; | |
var length = min + Math.floor(ROT.RNG.getUniform()*(max-min+1)); | |
return new this(x, y, x + dx*length, y + dy*length); | |
} | |
ROT.Map.Feature.Corridor.prototype.debug = function() { | |
console.log("corridor", this._startX, this._startY, this._endX, this._endY); | |
} | |
ROT.Map.Feature.Corridor.prototype.isValid = function(isWallCallback, canBeDugCallback){ | |
var sx = this._startX; | |
var sy = this._startY; | |
var dx = this._endX-sx; | |
var dy = this._endY-sy; | |
var length = 1 + Math.max(Math.abs(dx), Math.abs(dy)); | |
if (dx) { dx = dx/Math.abs(dx); } | |
if (dy) { dy = dy/Math.abs(dy); } | |
var nx = dy; | |
var ny = -dx; | |
var ok = true; | |
for (var i=0; i<length; i++) { | |
var x = sx + i*dx; | |
var y = sy + i*dy; | |
if (!canBeDugCallback( x, y)) { ok = false; } | |
if (!isWallCallback (x + nx, y + ny)) { ok = false; } | |
if (!isWallCallback (x - nx, y - ny)) { ok = false; } | |
if (!ok) { | |
length = i; | |
this._endX = x-dx; | |
this._endY = y-dy; | |
break; | |
} | |
} | |
/** | |
* If the length degenerated, this corridor might be invalid | |
*/ | |
/* not supported */ | |
if (length == 0) { return false; } | |
/* length 1 allowed only if the next space is empty */ | |
if (length == 1 && isWallCallback(this._endX + dx, this._endY + dy)) { return false; } | |
/** | |
* We do not want the corridor to crash into a corner of a room; | |
* if any of the ending corners is empty, the N+1th cell of this corridor must be empty too. | |
* | |
* Situation: | |
* #######1 | |
* .......? | |
* #######2 | |
* | |
* The corridor was dug from left to right. | |
* 1, 2 - problematic corners, ? = N+1th cell (not dug) | |
*/ | |
var firstCornerBad = !isWallCallback(this._endX + dx + nx, this._endY + dy + ny); | |
var secondCornerBad = !isWallCallback(this._endX + dx - nx, this._endY + dy - ny); | |
this._endsWithAWall = isWallCallback(this._endX + dx, this._endY + dy); | |
if ((firstCornerBad || secondCornerBad) && this._endsWithAWall) { return false; } | |
return true; | |
} | |
/** | |
* @param {function} digCallback Dig callback with a signature (x, y, value). Values: 0 = empty. | |
*/ | |
ROT.Map.Feature.Corridor.prototype.create = function(digCallback) { | |
var sx = this._startX; | |
var sy = this._startY; | |
var dx = this._endX-sx; | |
var dy = this._endY-sy; | |
var length = 1+Math.max(Math.abs(dx), Math.abs(dy)); | |
if (dx) { dx = dx/Math.abs(dx); } | |
if (dy) { dy = dy/Math.abs(dy); } | |
var nx = dy; | |
var ny = -dx; | |
for (var i=0; i<length; i++) { | |
var x = sx + i*dx; | |
var y = sy + i*dy; | |
digCallback(x, y, 0); | |
} | |
return true; | |
} | |
ROT.Map.Feature.Corridor.prototype.createPriorityWalls = function(priorityWallCallback) { | |
if (!this._endsWithAWall) { return; } | |
var sx = this._startX; | |
var sy = this._startY; | |
var dx = this._endX-sx; | |
var dy = this._endY-sy; | |
if (dx) { dx = dx/Math.abs(dx); } | |
if (dy) { dy = dy/Math.abs(dy); } | |
var nx = dy; | |
var ny = -dx; | |
priorityWallCallback(this._endX + dx, this._endY + dy); | |
priorityWallCallback(this._endX + nx, this._endY + ny); | |
priorityWallCallback(this._endX - nx, this._endY - ny); | |
} |