Add rotateAround Vector2D function.

Remove the rmgen rotateCoordinates helper function from 4256744e26 and
clean the implementation of that commit, refs #4845, #4804.
Deepfreeze mapCenter vector from 5256d8497e used here to prevent
accidental overwrites with the mutating Vector2D functions, refs #4854.

This was SVN commit r20468.
This commit is contained in:
elexis
2017-11-17 00:10:29 +00:00
parent a2f7dba96c
commit eb96b61954
5 changed files with 30 additions and 26 deletions
@@ -83,6 +83,14 @@ Vector2D.prototype.rotate = function(angle)
this.y * cos - this.x * sin);
};
/**
* Rotate radians anti-clockwise around the specified rotation center.
*/
Vector2D.prototype.rotateAround = function(angle, center)
{
return this.sub(center).rotate(angle).add(center);
};
// Numeric 2D info functions (non-mutating)
//
// These methods serve to get numeric info on the vector, they don't modify the vector
@@ -45,6 +45,7 @@ InitMap();
const numPlayers = getNumPlayers();
const mapSize = getMapSize();
const mapCenter = getMapCenter();
var clPlayer = createTileClass();
var clForest = createTileClass();
@@ -60,32 +61,33 @@ var clHill = createTileClass();
var landHeight = getMapBaseHeight();
var waterHeight = -4;
log("Creating the main river");
var riverWidth = scaleByMapSize(15, 70);
var riverAngle = -Math.PI / 4;
var riverStart = new Vector2D(mapCenter.x, 0).rotateAround(riverAngle, mapCenter);
var riverEnd = new Vector2D(mapCenter.x, mapSize).rotateAround(riverAngle, mapCenter);
var riv1 = [0, 0.5];
var riv2 = [1, 0.5];
log("Creating the main river");
var [riverX1, riverZ1] = rotateCoordinates(...riv1, riverAngle).map(f => fractionToTiles(f));
var [riverX2, riverZ2] = rotateCoordinates(...riv2, riverAngle).map(f => fractionToTiles(f));
createArea(
new PathPlacer(riverX1, riverZ1, riverX2, riverZ2, riverWidth, 0.2, 15 * scaleByMapSize(1, 3), 0.04, 0.01),
new PathPlacer(riverStart.x, riverStart.y, riverEnd.x, riverEnd.y, riverWidth, 0.2, 15 * scaleByMapSize(1, 3), 0.04, 0.01),
new SmoothElevationPainter(ELEVATION_SET, waterHeight, 4),
null);
log("Creating small puddles at the map border to ensure players being separated...");
for (let [x, z] of [[riverX1, riverZ1], [riverX2, riverZ2]])
for (let point of [riverStart, riverEnd])
createArea(
new ClumpPlacer(Math.floor(diskArea(riverWidth / 2)), 0.95, 0.6, 10, x, z),
new ClumpPlacer(Math.floor(diskArea(riverWidth / 2)), 0.95, 0.6, 10, point.x, point.y),
new SmoothElevationPainter(ELEVATION_SET, waterHeight, 4),
null);
log("Creating passage connecting the two riversides...");
var passageStart = riverStart.rotateAround(Math.PI / 2, mapCenter);
var passageEnd = riverEnd.rotateAround(Math.PI / 2, mapCenter);
createArea(
new PathPlacer(
...rotateCoordinates(...riv1, riverAngle + Math.PI / 2).map(f => fractionToTiles(f)),
...rotateCoordinates(...riv2, riverAngle + Math.PI / 2).map(f => fractionToTiles(f)),
passageStart.x,
passageStart.y,
passageEnd.x,
passageEnd.y,
scaleByMapSize(10, 30),
0.5,
3 * scaleByMapSize(1, 4),
@@ -358,7 +358,7 @@ function getMapArea()
function getMapCenter()
{
return new Vector2D(g_Map.size / 2, g_Map.size / 2);
return deepfreeze(new Vector2D(g_Map.size / 2, g_Map.size / 2));
}
function getNumPlayers()
@@ -12,20 +12,6 @@ function getAngle(x1, z1, x2, z2)
return Math.atan2(z2 - z1, x2 - x1);
}
/**
* Revolve the given point around the given rotation center.
*/
function rotateCoordinates(x, z, angle, centerX = 0.5, centerZ = 0.5)
{
let sin = Math.sin(angle);
let cos = Math.cos(angle);
return [
cos * (x - centerX) - sin * (z - centerZ) + centerX,
sin * (x - centerX) + cos * (z - centerZ) + centerZ
];
}
/**
* Get pointCount points equidistantly located on a circle.
*/
@@ -74,6 +74,14 @@ var brokenVector = {
}
}
// Test Vector2D rotation around a center
{
let epsilon = 0.00000001;
let v1 = new Vector2D(-4, 8).rotateAround(Math.PI / 3, new Vector2D(-1, -3));
TS_ASSERT_EQUALS_APPROX(v1.x, 7.02627944, epsilon);
TS_ASSERT_EQUALS_APPROX(v1.y, 5.09807617, epsilon);
}
// Test Vector2D dot product
{
TS_ASSERT_EQUALS(new Vector2D(2, 3).dot(new Vector2D(4, 5)), 23);