forked from mirrors/0ad
6eb8a814ce
RandomPathPlacer.js diff proposed and reviewed by FeXoR This was SVN commit r21425.
85 lines
3.0 KiB
JavaScript
85 lines
3.0 KiB
JavaScript
/**
|
|
* @file An Object tries to find locations around a location and returns an array of Entity items holding the template names, owners and locations on success.
|
|
*/
|
|
|
|
/**
|
|
* The SimpleObject attempts to find locations for a random amount of entities with a random distance to the given center.
|
|
*/
|
|
function SimpleObject(templateName, minCount, maxCount, minDistance, maxDistance, minAngle = 0, maxAngle = 2 * Math.PI, avoidDistance = 1)
|
|
{
|
|
this.templateName = templateName;
|
|
this.minCount = minCount;
|
|
this.maxCount = maxCount;
|
|
this.minDistance = minDistance;
|
|
this.maxDistance = maxDistance;
|
|
this.minAngle = minAngle;
|
|
this.maxAngle = maxAngle;
|
|
this.avoidDistanceSquared = Math.square(avoidDistance);
|
|
|
|
if (minCount > maxCount)
|
|
throw new Error("SimpleObject: minCount should be less than or equal to maxCount");
|
|
|
|
if (minDistance > maxDistance)
|
|
throw new Error("SimpleObject: minDistance should be less than or equal to maxDistance");
|
|
|
|
if (minAngle > maxAngle)
|
|
throw new Error("SimpleObject: minAngle should be less than or equal to maxAngle");
|
|
}
|
|
|
|
SimpleObject.prototype.place = function(centerPosition, playerID, avoidPositions, constraint, maxRetries)
|
|
{
|
|
let entitySpecs = [];
|
|
let numRetries = 0;
|
|
let validTile = pos => this.templateName.startsWith(g_ActorPrefix) ? g_Map.validTile(pos) : g_Map.validTilePassable(pos);
|
|
|
|
for (let i = 0; i < randIntInclusive(this.minCount, this.maxCount); ++i)
|
|
while (true)
|
|
{
|
|
let distance = randFloat(this.minDistance, this.maxDistance);
|
|
let angle = randomAngle();
|
|
|
|
let position = Vector2D.sum([centerPosition, new Vector2D(0.5, 0.5), new Vector2D(distance, 0).rotate(-angle)]);
|
|
|
|
if (validTile(position) &&
|
|
(!avoidPositions ||
|
|
entitySpecs.every(entSpec => entSpec.position.distanceToSquared(position) >= this.avoidDistanceSquared) &&
|
|
avoidPositions.every(avoid => avoid.position.distanceToSquared(position) >= Math.max(this.avoidDistanceSquared, avoid.distanceSquared))) &&
|
|
constraint.allows(position.clone().floor()))
|
|
{
|
|
entitySpecs.push({
|
|
"templateName": this.templateName,
|
|
"playerID": playerID,
|
|
"position": position,
|
|
"angle": randFloat(this.minAngle, this.maxAngle)
|
|
});
|
|
break;
|
|
}
|
|
|
|
if (numRetries++ > maxRetries)
|
|
return undefined;
|
|
}
|
|
|
|
return entitySpecs;
|
|
};
|
|
|
|
/**
|
|
* Same as SimpleObject, but choses one of the given templates at random.
|
|
*/
|
|
function RandomObject(templateNames, minCount, maxCount, minDistance, maxDistance, minAngle, maxAngle, avoidDistance = 1)
|
|
{
|
|
this.templateNames = templateNames;
|
|
this.minCount = minCount;
|
|
this.maxCount = maxCount;
|
|
this.minDistance = minDistance;
|
|
this.maxDistance = maxDistance;
|
|
this.minAngle = minAngle;
|
|
this.maxAngle = maxAngle;
|
|
this.avoidDistance = avoidDistance;
|
|
}
|
|
|
|
RandomObject.prototype.place = function(centerPosition, player, avoidPositions, constraint, maxRetries)
|
|
{
|
|
return new SimpleObject(pickRandom(this.templateNames), this.minCount, this.maxCount, this.minDistance, this.maxDistance, this.minAngle, this.maxAngle, this.avoidDistance).place(
|
|
centerPosition, player, avoidPositions, constraint, maxRetries);
|
|
};
|