Implement a DiskPlacer to enable random map scripts chosing all points inside a circle without using a special case of the other placers.

Especially useful if the center position doesn't meet the constraint or
is outside of the map boundary.
Removing the preliminary boundary check from the centered placers seems
to come with a too high performance penalty, for instance when creating
forests.

This was SVN commit r21225.
This commit is contained in:
elexis
2018-02-16 18:49:54 +00:00
parent a30ab829f4
commit dc18ea1973
11 changed files with 50 additions and 18 deletions
@@ -101,7 +101,7 @@ while (true)
g_Map.log("Mark valid heightrange for player starting positions");
let tHeightRange = g_Map.createTileClass();
let area = createArea(
new ClumpPlacer(diskArea(fractionToTiles(0.5) - MAP_BORDER_WIDTH), 1, 1, Infinity, mapCenter),
new DiskPlacer(fractionToTiles(0.5) - MAP_BORDER_WIDTH, mapCenter),
new TileClassPainter(tHeightRange),
new HeightConstraint(lowerHeightLimit, upperHeightLimit));
@@ -297,7 +297,7 @@ Engine.SetProgress(30);
g_Map.log("Smoothing player locations");
for (let position of playerPosition)
createArea(
new ClumpPlacer(diskArea(35), 1, 1, Infinity, position),
new DiskPlacer(35, position),
new SmoothElevationPainter(ELEVATION_SET, g_Map.getHeight(position), 35));
g_Map.log("Creating paths between players");
@@ -116,7 +116,7 @@ else if (mapSize == 448)
g_Map.log("Creating big circular lake");
createArea(
new ClumpPlacer(diskArea(radiusCentralLake), 1, 1, Infinity, mapCenter),
new DiskPlacer(radiusCentralLake, mapCenter),
new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 4));
g_Map.log("Creating rivers between players");
@@ -144,22 +144,22 @@ for (let m = 0; m < numPlayers * split; ++m)
g_Map.log("Creating ring of land connecting players");
createArea(
new ClumpPlacer(diskArea(radiusCentralRingLand), 1, 1, Infinity, mapCenter),
new DiskPlacer(radiusCentralRingLand, mapCenter),
new SmoothElevationPainter(ELEVATION_SET, heightRing, 4));
g_Map.log("Creating inner ring of water");
createArea(
new ClumpPlacer(diskArea(radiusCentralWaterRing), 1, 1, Infinity, mapCenter),
new DiskPlacer(radiusCentralWaterRing, mapCenter),
new SmoothElevationPainter(ELEVATION_SET, heightShallow, 3));
g_Map.log("Creating central island");
createArea(
new ClumpPlacer(diskArea(radiusCentralIsland), 1, 1, Infinity, mapCenter),
new DiskPlacer(radiusCentralIsland, mapCenter),
new SmoothElevationPainter(ELEVATION_SET, heightRing, 3));
g_Map.log("Creating hill on the central island");
createArea(
new ClumpPlacer(diskArea(radiusCentralHill), 1, 1, Infinity, mapCenter),
new DiskPlacer(radiusCentralHill, mapCenter),
new SmoothElevationPainter(ELEVATION_SET, heightHill, 8));
paintTerrainBasedOnHeight(-6, 1, 1, tWater);
@@ -482,7 +482,7 @@ function createSunkenTerrain()
g_Map.log("Creating central valley");
createArea(
new ClumpPlacer(diskArea(fractionToTiles(0.29)), 1, 1, Infinity, mapCenter),
new DiskPlacer(fractionToTiles(0.29), mapCenter),
[
new LayeredPainter([g_Terrains.cliff, lower], [3]),
new SmoothElevationPainter(ELEVATION_SET, heightValley, 3),
@@ -491,7 +491,7 @@ function createSunkenTerrain()
g_Map.log("Creating central hill");
createArea(
new ClumpPlacer(diskArea(fractionToTiles(0.21)), 1, 1, Infinity, mapCenter),
new DiskPlacer(fractionToTiles(0.21), mapCenter),
[
new LayeredPainter([g_Terrains.cliff, topTerrain], [3]),
new SmoothElevationPainter(ELEVATION_SET, heightHill, 3),
@@ -107,7 +107,7 @@ Engine.SetProgress(30);
g_Map.log("Marking land");
createArea(
new ClumpPlacer(diskArea(fractionToTiles(0.5)), 1, 1, Infinity, mapCenter),
new DiskPlacer(fractionToTiles(0.5), mapCenter),
new TileClassPainter(g_TileClasses.land),
avoidClasses(g_TileClasses.water, 0));
Engine.SetProgress(35);
@@ -106,7 +106,7 @@ Engine.SetProgress(40);
g_Map.log("Marking eden");
createArea(
new ClumpPlacer(diskArea(fractionToTiles(0.14)), 1, 1, Infinity, mapCenter),
new DiskPlacer(fractionToTiles(0.14), mapCenter),
new TileClassPainter(g_TileClasses.eden),
new HeightConstraint(-Infinity, heightEden));
Engine.SetProgress(45);
@@ -132,7 +132,7 @@ Engine.SetProgress(40);
g_Map.log("Marking dock search location");
var areaDockStart = createArea(
new ClumpPlacer(diskArea(fractionToTiles(0.5)) - 10, 1, 1, Infinity, mapCenter),
new DiskPlacer(fractionToTiles(0.5) - 10, mapCenter),
undefined,
stayClasses(g_TileClasses.land, 6));
@@ -88,7 +88,7 @@ Engine.SetProgress(30);
g_Map.log("Marking land");
createArea(
new ClumpPlacer(diskArea(fractionToTiles(0.5)), 1, 1, Infinity, mapCenter),
new DiskPlacer(fractionToTiles(0.5), mapCenter),
new TileClassPainter(g_TileClasses.land),
avoidClasses(g_TileClasses.water, 0));
Engine.SetProgress(35);
@@ -3,6 +3,38 @@
* The center can be modified externally using setCenterPosition, typically called by createAreas.
*/
/**
* Returns all points on a disk at the given location that meet the constraint.
*/
function DiskPlacer(radius, centerPosition = undefined)
{
this.radius = radius;
this.centerPosition = undefined;
if (centerPosition)
this.setCenterPosition(centerPosition);
}
DiskPlacer.prototype.setCenterPosition = function(position)
{
this.centerPosition = deepfreeze(position.clone().round());
};
DiskPlacer.prototype.place = function(constraint)
{
let points = [];
for (let x = 0; x < g_Map.getSize(); ++x)
for (let y = 0; y < g_Map.getSize(); ++y)
{
let point = new Vector2D(x, y);
if (this.centerPosition.distanceTo(point) <= this.radius && constraint.allows(point))
points.push(point);
}
return points;
};
/**
* Generates a roughly circular clump of points.
*
@@ -186,7 +186,7 @@ function RandomPathPlacer(pathStart, pathEnd, pathWidth, offset, blended)
this.pathEnd = pathEnd;
this.offset = offset;
this.blended = blended;
this.clumpPlacer = new ClumpPlacer(diskArea(pathWidth), 1, 1, Infinity);
this.diskPlacer = new DiskPlacer(pathWidth);
this.maxPathLength = fractionToTiles(2);
}
@@ -203,10 +203,10 @@ RandomPathPlacer.prototype.place = function(constraint)
-getAngle(this.pathStart.x, this.pathStart.y, this.pathEnd.x, this.pathEnd.y) +
-Math.PI / 2 * (randFloat(-1, 1) + (this.blended ? 0.5 : 0)))).round();
this.clumpPlacer.setCenterPosition(position);
this.diskPlacer.setCenterPosition(position);
for (let point of this.clumpPlacer.place(constraint) || [])
if (points.every(p => p.x != point.x || p.y != point.y))
for (let point of this.diskPlacer.place(constraint))
if (points.every(p => !Vector2D.isEqualTo(p, point)))
points.push(point);
}
@@ -635,7 +635,7 @@ for (let i = 0; i < resourceSpots.length; ++i)
if (radius)
createArea(
new ClumpPlacer(diskArea(radius), 1, 1, Infinity, resourceSpots[i]),
new DiskPlacer(radius, resourceSpots[i]),
new SmoothElevationPainter(ELEVATION_SET, g_Map.getHeight(resourceSpots[i]), radius / 3));
}