Added a new "placer" function for the rmgen library.

This new placer generates terrain features that are less "predictable".
It also increases the map generation time considerably.

Currently it is only implemented on Persian Highlands random map.

This was SVN commit r14091.
This commit is contained in:
O.Davoodi 2013-11-07 14:50:16 +00:00
parent b7751a277c
commit 6d62b3bf40
2 changed files with 165 additions and 6 deletions

View File

@ -179,7 +179,7 @@ RMS.SetProgress(10);
// create patches
log("Creating rock patches...");
placer = new ClumpPlacer(scaleByMapSize(40, 150), 0.2, 0.1, 0);
placer = new ChainPlacer(1, floor(scaleByMapSize(3, 6)), floor(scaleByMapSize(20, 45)), 0);
painter = new TerrainPainter(tRocky);
createAreas(placer, [painter, paintClass(clPatch)],
avoidClasses(clPatch, 2, clPlayer, 0),
@ -188,7 +188,7 @@ createAreas(placer, [painter, paintClass(clPatch)],
RMS.SetProgress(15);
var placer = new ClumpPlacer(scaleByMapSize(25, 100), 0.2, 0.1, 0);
var placer = new ChainPlacer(1, floor(scaleByMapSize(3, 5)), floor(scaleByMapSize(15, 40)), 0);
var painter = new TerrainPainter([tRocky, tRocks]);
createAreas(placer, [painter, paintClass(clPatch)],
avoidClasses(clPatch, 2, clPlayer, 4),
@ -198,7 +198,7 @@ createAreas(placer, [painter, paintClass(clPatch)],
RMS.SetProgress(20);
log("Creating dirt patches...");
placer = new ClumpPlacer(scaleByMapSize(25, 100), 0.2, 0.1, 0);
placer = new ChainPlacer(1, floor(scaleByMapSize(3, 5)), floor(scaleByMapSize(15, 40)), 0);
painter = new TerrainPainter([tGrass]);
createAreas(placer, [painter, paintClass(clPatch)],
avoidClasses(clPatch, 2, clPlayer, 4),
@ -221,7 +221,7 @@ RMS.SetProgress(30);
// create hills
log("Creating hills...");
placer = new ClumpPlacer(scaleByMapSize(20, 150), 0.2, 0.1, 1);
placer = new ChainPlacer(1, floor(scaleByMapSize(4, 6)), floor(scaleByMapSize(16, 40)), 1);
var terrainPainter = new LayeredPainter(
[tCliff, tHill], // terrains
[2] // widths
@ -255,7 +255,7 @@ var size = numForest / (scaleByMapSize(2,8) * numPlayers);
var num = floor(size / types.length);
for (var i = 0; i < types.length; ++i)
{
placer = new ClumpPlacer(numForest / num, 0.1, 0.1, 1);
placer = new ChainPlacer(1, floor(scaleByMapSize(2, 5)), floor(size / 8), 1);
painter = new LayeredPainter(
types[i], // terrains
[2] // widths
@ -428,6 +428,5 @@ for (var i = 0; i < types.length; ++i)
);
}
setSunColour(0.733, 0.746, 0.574);
ExportMap();

View File

@ -119,6 +119,166 @@ ClumpPlacer.prototype.place = function(constraint)
return ((failed > this.size*this.failFraction) ? undefined : retVec);
};
/////////////////////////////////////////////////////////////////////////////////////////
// Chain Placer
//
// Class for generating a more random clump of points it randomly creates circles around the edges of the current clump
//
// minRadius: minimum radius of the circles
// maxRadius: maximum radius of the circles
// numCircles: the number of the circles
// failfraction: Percentage of place attempts allowed to fail (optional)
// x, z: Tile coordinates of placer center (optional)
//
/////////////////////////////////////////////////////////////////////////////////////////
function ChainPlacer(minRadius, maxRadius, numCircles, failFraction, x, z)
{
this.minRadius = minRadius;
this.maxRadius = maxRadius;
this.numCircles = numCircles
this.failFraction = (failFraction !== undefined ? failFraction : 0);
this.x = (x !== undefined ? x : -1);
this.z = (z !== undefined ? z : -1);
}
ChainPlacer.prototype.place = function(constraint)
{
// Preliminary bounds check
if (!g_Map.inMapBounds(this.x, this.z) || !constraint.allows(this.x, this.z))
{
return undefined;
}
var retVec = [];
var size = getMapSize();
var failed = 0, count = 0;
var gotRet = new Array(size);
for (var i = 0; i < size; ++i)
{
gotRet[i] = new Array(size);
for (var j = 0; j < size; ++j)
{
gotRet[i][j] = -1;
}
}
--size;
if (this.minRadius < 1) this.minRadius = 1;
if (this.minRadius > this.maxRadius) this.minRadius = this.maxRadius;
var edges = [[this.x, this.z]]
for (var i = 0; i < this.numCircles; ++i)
{
var point = edges[randInt(edges.length)];
var cx = point[0], cz = point[1];
var radius = randInt(this.minRadius, this.maxRadius);
//log (edges);
var sx = cx - radius, lx = cx + radius;
var sz = cz - radius, lz = cz + radius;
sx = (sx < 0 ? 0 : sx);
sz = (sz < 0 ? 0 : sz);
lx = (lx > size ? size : lx);
lz = (lz > size ? size : lz);
var radius2 = radius * radius;
var dx, dz;
//log (uneval([sx, sz, lx, lz]));
for (var ix = sx; ix <= lx; ++ix)
{
for (var iz = sz; iz <= lz; ++ iz)
{
dx = ix - cx;
dz = iz - cz;
if (dx * dx + dz * dz <= radius2)
{
if (g_Map.inMapBounds(ix, iz) && constraint.allows(ix, iz))
{
var state = gotRet[ix][iz];
if (state == -1)
{
retVec.push(new PointXZ(ix, iz));
gotRet[ix][iz] = -2;
}
/*else if (state >= 0)
{
log (uneval(edges));
log (state)
var s = edges.splice(state, 1);
log (uneval(s));
log (uneval(edges));
gotRet[ix][iz] = -2;
}*/
}
else
{
++failed;
}
++count;
}
}
}
for (var ix = sx; ix <= lx; ++ix)
{
for (var iz = sz; iz <= lz; ++ iz)
{
if (gotRet[ix][iz] == -2)
{
if (ix > 0)
{
if (gotRet[ix-1][iz] == -1)
{
edges.push([ix, iz]);
gotRet[ix][iz] = edges.length - 1;
continue;
}
}
if (iz > 0)
{
if (gotRet[ix][iz-1] == -1)
{
edges.push([ix, iz]);
gotRet[ix][iz] = edges.length - 1;
continue;
}
}
if (ix < size)
{
if (gotRet[ix+1][iz] == -1)
{
edges.push([ix, iz]);
gotRet[ix][iz] = edges.length - 1;
continue;
}
}
if (iz < size)
{
if (gotRet[ix][iz+1] == -1)
{
edges.push([ix, iz]);
gotRet[ix][iz] = edges.length - 1;
continue;
}
}
}
}
}
}
return ((failed > count*this.failFraction) ? undefined : retVec);
};
/////////////////////////////////////////////////////////////////////////////////////////
// RectPlacer
//