mirror of
https://gitea.wildfiregames.com/0ad/0ad.git
synced 2026-06-21 13:04:10 +00:00
Implement an EntitiesObstructionPlacer that allows random maps to avoid exactly the obstruction area of given entities (rather than avoiding a guesstimated disk area).
This was SVN commit r21555.
This commit is contained in:
@@ -61,6 +61,23 @@ function actorTemplate(templateName)
|
||||
return g_ActorPrefix + templateName + ".xml";
|
||||
}
|
||||
|
||||
function getObstructionSize(templateName, margin = 0)
|
||||
{
|
||||
let obstruction = Engine.GetTemplate(templateName).Obstruction;
|
||||
|
||||
let obstructionSize =
|
||||
obstruction.Static ?
|
||||
new Vector2D(obstruction.Static["@depth"], obstruction.Static["@width"]) :
|
||||
// Used for gates, should consider the position too
|
||||
obstruction.Obstructions ?
|
||||
new Vector2D(
|
||||
Object.keys(obstruction.Obstructions).reduce((depth, key) => Math.max(depth, +obstruction.Obstructions[key]["@depth"]), 0),
|
||||
Object.keys(obstruction.Obstructions).reduce((width, key) => width + +obstruction.Obstructions[key]["@width"], 0)) :
|
||||
new Vector2D(0, 0);
|
||||
|
||||
return obstructionSize.div(TERRAIN_TILE_SIZE).add(new Vector2D(2, 2).mult(margin));
|
||||
}
|
||||
|
||||
function fractionToTiles(f)
|
||||
{
|
||||
return g_MapSettings.Size * f;
|
||||
|
||||
@@ -7,11 +7,7 @@ function CityPainter(templates, angle, playerID)
|
||||
this.playerID = playerID;
|
||||
this.templates = templates.map(template => {
|
||||
|
||||
let obstructionSize = Engine.GetTemplate(template.templateName).Obstruction.Static;
|
||||
|
||||
let depth = obstructionSize["@depth"] / TERRAIN_TILE_SIZE + 2 * (template.margin || 0);
|
||||
let width = obstructionSize["@width"] / TERRAIN_TILE_SIZE + 2 * (template.margin || 0);
|
||||
|
||||
let obstructionSize = getObstructionSize(template.templateName, template.margin || 0);
|
||||
return {
|
||||
"templateName": template.templateName,
|
||||
"maxCount": template.maxCount !== undefined ? template.maxCount : Infinity,
|
||||
@@ -19,9 +15,9 @@ function CityPainter(templates, angle, playerID)
|
||||
"painter": template.painters && new MultiPainter(template.painters),
|
||||
"obstructionCorners": [
|
||||
new Vector2D(0, 0),
|
||||
new Vector2D(depth, 0),
|
||||
new Vector2D(0, width),
|
||||
new Vector2D(depth, width)
|
||||
new Vector2D(obstructionSize.x, 0),
|
||||
new Vector2D(0, obstructionSize.y),
|
||||
obstructionSize
|
||||
]
|
||||
};
|
||||
});
|
||||
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* The EntityObstructionPlacer returns all points on the obstruction of the given template at the given position and angle that meet the constraint.
|
||||
* It can be used for more concise collision avoidance.
|
||||
*/
|
||||
function EntitiesObstructionPlacer(entities, margin = 0, failFraction = Infinity)
|
||||
{
|
||||
this.entities = entities;
|
||||
this.margin = margin;
|
||||
this.failFraction = failFraction;
|
||||
}
|
||||
|
||||
EntitiesObstructionPlacer.prototype.place = function(constraint)
|
||||
{
|
||||
let points = [];
|
||||
|
||||
for (let entity of this.entities)
|
||||
{
|
||||
let halfObstructionSize = getObstructionSize(entity.templateName, this.margin).div(2);
|
||||
|
||||
// Place the entity if all points are within the boundaries and don't collide with the other entities
|
||||
let obstructionCorners = [
|
||||
new Vector2D(-halfObstructionSize.x, -halfObstructionSize.y),
|
||||
new Vector2D(-halfObstructionSize.x, +halfObstructionSize.y),
|
||||
new Vector2D(+halfObstructionSize.x, -halfObstructionSize.y),
|
||||
new Vector2D(+halfObstructionSize.x, +halfObstructionSize.y)
|
||||
].map(corner => Vector2D.add(entity.GetPosition2D(), corner.rotate(-entity.rotation.y)));
|
||||
|
||||
points = points.concat(new ConvexPolygonPlacer(obstructionCorners, this.failFraction).place(constraint))
|
||||
}
|
||||
|
||||
return points;
|
||||
};
|
||||
Reference in New Issue
Block a user