Differential D1497 Diff 6567 binaries/data/mods/public/maps/random/rmgen-common/mountain_range_builder.js
Changeset View
Changeset View
Standalone View
Standalone View
binaries/data/mods/public/maps/random/rmgen-common/mountain_range_builder.js
Engine.LoadLibrary("rmgen"); | |||||
elexis: I had put the prottoype into the mapfile rather than the library because maps should be unique… | |||||
Not Done Inline ActionsI put it into a library because I fully intend to use it elsewhere, albeit with very different settings. aeonios: I put it into a library because I fully intend to use it elsewhere, albeit with very different… | |||||
/** | |||||
* @file This class creates random mountainranges ensuring that there are enough breaks to pass between them. | |||||
* | |||||
* To determine their location, random points are connected in shortest-cycle order and then trimmed to max length. | |||||
* | |||||
* Constructor arguments: | |||||
* @param {number} "height": how tall the mountains should be, in absolute height (ie set not modify). | |||||
* @param {number} "width": How wide the mountains will be. | |||||
* @param {number} "count": How many mountain ranges to create. | |||||
* @param {number} "maxLength": The longest that any connected mountain strip is allowed to be. Use to ensure that passable gaps are created. | |||||
* @param {number} "bumpiness": (0..1) How much the height of each peak should vary. | |||||
* @param {number} "waviness": (0..1) How much the mountain ranges should deviate from a straight line. | |||||
* @param {array strings} "terrain": String or array of two or more strings specifying terrain textures to paint. | |||||
* @param {number} "tileclass": The tileclass that the mountains should be assigned. | |||||
* @param {array constraints} "constraint": List of tileclasses to avoid painting over. | |||||
*/ | |||||
function MountainRangeBuilder(args) | |||||
{ | |||||
/** | |||||
* These parameters paint the mountainranges after their location was determined. | |||||
*/ | |||||
var height = args.height || scaleByMapSize(60, 120); | |||||
this.mountainWidth = args.width || height/4; | |||||
this.pathplacer = new PathPlacer(undefined, undefined, undefined, args.bumpiness || 0.4, scaleByMapSize(10, 25), args.waviness || 0.75, 0.2, 0.1); | |||||
this.painters = [ | |||||
new TerrainPainter(args.terrain), | |||||
new SmoothElevationPainter(ELEVATION_SET, height, 4 * height/this.mountainWidth, 3), | |||||
new TileClassPainter(args.tileclass) | |||||
]; | |||||
this.constraint = args.constraint; | |||||
/** | |||||
* Array of Vector2D locations where a mountainrange can start or end. | |||||
*/ | |||||
this.vertices = g_Map.randomCoordinates(2 * (args.count || 16), false); | |||||
/** | |||||
* Maximum length that a mountain path can have. | |||||
*/ | |||||
this.maxLength = args.maxLength || fractionToTiles(0.6); | |||||
/** | |||||
* Number of mountainranges starting or ending at the given point. | |||||
*/ | |||||
this.vertexDegree = this.vertices.map(p => 0); | |||||
/** | |||||
* Each possible edge is an array containing two vertex indices. | |||||
* The algorithm adds possible edges consecutively and removes subsequently invalid edges. | |||||
*/ | |||||
this.possibleEdges = []; | |||||
this.InitPossibleEdges(); | |||||
/** | |||||
* Currently iterated item of possibleEdges that is either used as a mountainrange or removed from the possibleEdges. | |||||
*/ | |||||
this.index = undefined; | |||||
/** | |||||
* These variables hold the indices of the two points of that edge and the location of them as a Vector2D. | |||||
*/ | |||||
this.currentEdge = undefined; | |||||
this.currentEdgeStart = undefined; | |||||
this.currentEdgeEnd = undefined; | |||||
} | |||||
MountainRangeBuilder.prototype.InitPossibleEdges = function() | |||||
{ | |||||
var order = sortPointsShortestCycle(this.vertices); | |||||
var length = 0; | |||||
for (let i = 0; i < order.length - 1; ++i) | |||||
{ | |||||
length += this.vertices[order[i]].distanceTo(this.vertices[order[i+1]]); | |||||
if (length <= this.maxLength) | |||||
{ | |||||
this.possibleEdges.push([order[i], order[i+1]]); | |||||
}else | |||||
{ | |||||
length = 0; | |||||
} | |||||
} | |||||
}; | |||||
MountainRangeBuilder.prototype.UpdateCurrentEdge = function() | |||||
{ | |||||
this.currentEdge = this.possibleEdges[this.index]; | |||||
this.currentEdgeStart = this.vertices[this.currentEdge[0]]; | |||||
this.currentEdgeEnd = this.vertices[this.currentEdge[1]]; | |||||
}; | |||||
MountainRangeBuilder.prototype.PaintCurrentEdge = function() | |||||
{ | |||||
this.pathplacer.start = this.currentEdgeStart; | |||||
this.pathplacer.end = this.currentEdgeEnd; | |||||
this.pathplacer.width = this.mountainWidth; | |||||
// Creating mountainrange | |||||
if (!createArea(this.pathplacer, this.painters, this.constraint)) | |||||
return false; | |||||
return true; | |||||
}; | |||||
/** | |||||
* This is the only function meant to be publicly accessible. | |||||
*/ | |||||
MountainRangeBuilder.prototype.CreateMountainRanges = function() | |||||
{ | |||||
g_Map.log("Creating mountain ranges with " + this.possibleEdges.length + " possible edges"); | |||||
for (let i = 0; i < this.possibleEdges.length; ++i) | |||||
{ | |||||
this.index = i; | |||||
this.UpdateCurrentEdge(); | |||||
if (this.PaintCurrentEdge()) | |||||
{ | |||||
++this.vertexDegree[this.currentEdge[0]]; | |||||
++this.vertexDegree[this.currentEdge[1]]; | |||||
} | |||||
} | |||||
// Create circular mountains to connect ranges that share vertices. | |||||
for (let i = 0; i < this.vertexDegree.length; ++i) | |||||
{ | |||||
if (this.vertexDegree[i] > 1) | |||||
{ | |||||
createArea( | |||||
new ClumpPlacer(diskArea(this.mountainWidth / 2), 0.95, 0.6, Infinity, this.vertices[i]), | |||||
this.painters, | |||||
this.constraint); | |||||
} | |||||
} | |||||
}; | |||||
No newline at end of file |
Wildfire Games · Phabricator
I had put the prottoype into the mapfile rather than the library because maps should be unique and I don't think a second map will use the exact same concept anytime soon.