Begin cleaning up terraintypes/movetypes

This commit is contained in:
Paul Chote
2010-06-25 15:52:12 +12:00
parent 7ac8d0cf59
commit 6a5869f2c6
6 changed files with 38 additions and 32 deletions

View File

@@ -31,21 +31,11 @@ namespace OpenRA
public class PathFinder public class PathFinder
{ {
readonly World world; readonly World world;
float[][,] passableCost = new float[5][,];
public PathFinder( World world ) public PathFinder( World world )
{ {
this.world = world; this.world = world;
var map = world.Map; var map = world.Map;
for (var umt = UnitMovementType.Foot; umt <= UnitMovementType.Fly; umt++)
passableCost[(int)umt] = new float[map.MapSize.X, map.MapSize.Y];
for( int x = 0 ; x < map.MapSize.X ; x++ )
for( int y = 0 ; y < map.MapSize.Y ; y++ )
for (var umt = UnitMovementType.Foot; umt <= UnitMovementType.Fly; umt++ )
passableCost[(int)umt][ x, y ] = (umt == UnitMovementType.Fly) ? 1f : ( world.Map.IsInMap( x, y ) )
? (float)Rules.TerrainTypes[world.TileSet.GetTerrainType(world.Map.MapTiles[x, y])]
.GetCost(umt)
: float.PositiveInfinity;
} }
class CachedPath class CachedPath
@@ -117,7 +107,7 @@ namespace OpenRA
{ {
while (!search.queue.Empty) while (!search.queue.Empty)
{ {
var p = search.Expand( world, passableCost ); var p = search.Expand( world );
PerfHistory.Increment("nodes_expanded", .01); PerfHistory.Increment("nodes_expanded", .01);
if (search.heuristic(p) == 0) if (search.heuristic(p) == 0)
@@ -154,13 +144,13 @@ namespace OpenRA
while (!fromSrc.queue.Empty && !fromDest.queue.Empty) while (!fromSrc.queue.Empty && !fromDest.queue.Empty)
{ {
/* make some progress on the first search */ /* make some progress on the first search */
var p = fromSrc.Expand( world, passableCost ); var p = fromSrc.Expand( world );
if (fromDest.cellInfo[p.X, p.Y].Seen && fromDest.cellInfo[p.X, p.Y].MinCost < float.PositiveInfinity) if (fromDest.cellInfo[p.X, p.Y].Seen && fromDest.cellInfo[p.X, p.Y].MinCost < float.PositiveInfinity)
return MakeBidiPath(fromSrc, fromDest, p); return MakeBidiPath(fromSrc, fromDest, p);
/* make some progress on the second search */ /* make some progress on the second search */
var q = fromDest.Expand( world, passableCost ); var q = fromDest.Expand( world );
if (fromSrc.cellInfo[q.X, q.Y].Seen && fromSrc.cellInfo[q.X, q.Y].MinCost < float.PositiveInfinity) if (fromSrc.cellInfo[q.X, q.Y].Seen && fromSrc.cellInfo[q.X, q.Y].MinCost < float.PositiveInfinity)
return MakeBidiPath(fromSrc, fromDest, q); return MakeBidiPath(fromSrc, fromDest, q);

View File

@@ -39,15 +39,12 @@ namespace OpenRA
Actor self; Actor self;
public bool inReverse; public bool inReverse;
BuildingInfluence buildingInfluence;
public PathSearch(Actor self) public PathSearch(Actor self)
{ {
this.self = self; this.self = self;
world = self.World; world = self.World;
cellInfo = InitCellInfo(); cellInfo = InitCellInfo();
queue = new PriorityQueue<PathDistance>(); queue = new PriorityQueue<PathDistance>();
buildingInfluence = world.WorldActor.traits.Get<BuildingInfluence>();
} }
public PathSearch InReverse() public PathSearch InReverse()
@@ -82,16 +79,16 @@ namespace OpenRA
const float LaneBias = .5f; const float LaneBias = .5f;
public int2 Expand( World world, float[][ , ] passableCost ) public int2 Expand( World world )
{ {
var umt = self.traits.Get<Mobile>().GetMovementType(); var umt = self.traits.Get<Mobile>().GetMovementType();
var p = queue.Pop(); var p = queue.Pop();
cellInfo[ p.Location.X, p.Location.Y ].Seen = true; cellInfo[ p.Location.X, p.Location.Y ].Seen = true;
var thisCost = passableCost[(int)umt][p.Location.X, p.Location.Y]* var mobile = self.traits.Get<Mobile>();
world.WorldActor.traits.WithInterface<ICustomTerrain>().Aggregate(1f, (a, x) => a * x.GetCost(p.Location,self)); var thisCost = mobile.MovementCostForCell(self, p.Location);
if (thisCost == float.PositiveInfinity) if (thisCost == float.PositiveInfinity)
return p.Location; return p.Location;
@@ -103,14 +100,11 @@ namespace OpenRA
if( cellInfo[ newHere.X, newHere.Y ].Seen ) if( cellInfo[ newHere.X, newHere.Y ].Seen )
continue; continue;
var costHere = passableCost[(int)umt][newHere.X, newHere.Y]* var costHere = mobile.MovementCostForCell(self, newHere);
world.WorldActor.traits.WithInterface<ICustomTerrain>()
.Aggregate(1f, (a, x) => a * x.GetCost(newHere,self));
if (costHere == float.PositiveInfinity) if (costHere == float.PositiveInfinity)
continue; continue;
var mobile = self.traits.Get<Mobile>();
if (checkForBlocked && !mobile.CanEnterCell(newHere, ignoreBuilding, checkForBlocked)) if (checkForBlocked && !mobile.CanEnterCell(newHere, ignoreBuilding, checkForBlocked))
continue; continue;

View File

@@ -124,15 +124,15 @@ namespace OpenRA.Traits
return CanEnterCell(p, null, true); return CanEnterCell(p, null, true);
} }
public virtual bool CanEnterCell(int2 p, Actor ignoreActor, bool checkTransientActors) public virtual bool CanEnterCell(int2 cell, Actor ignoreActor, bool checkTransientActors)
{ {
if (!self.World.WorldActor.traits.Get<BuildingInfluence>().CanMoveHere(p, ignoreActor)) if (!self.World.WorldActor.traits.Get<BuildingInfluence>().CanMoveHere(cell, ignoreActor))
return false; return false;
if (checkTransientActors) if (checkTransientActors)
{ {
var canShare = self.traits.Contains<SharesCell>(); var canShare = self.traits.Contains<SharesCell>();
var actors = self.World.WorldActor.traits.Get<UnitInfluence>().GetUnitsAt(p).Where(a => a != self && a != ignoreActor); var actors = self.World.WorldActor.traits.Get<UnitInfluence>().GetUnitsAt(cell).Where(a => a != self && a != ignoreActor);
var nonshareable = actors.Where(a => !(canShare && a.traits.Contains<SharesCell>())); var nonshareable = actors.Where(a => !(canShare && a.traits.Contains<SharesCell>()));
var shareable = actors.Where(a => canShare && a.traits.Contains<SharesCell>()); var shareable = actors.Where(a => canShare && a.traits.Contains<SharesCell>());
@@ -146,9 +146,20 @@ namespace OpenRA.Traits
return false; return false;
} }
return self.World.Map.IsInMap(p.X, p.Y) && return MovementCostForCell(self, cell) < float.PositiveInfinity;
Rules.TerrainTypes[self.World.TileSet.GetTerrainType(self.World.Map.MapTiles[p.X, p.Y])] }
.GetCost(GetMovementType()) < float.PositiveInfinity;
public float MovementCostForCell(Actor self, int2 cell)
{
if (!self.World.Map.IsInMap(cell.X,cell.Y))
return float.PositiveInfinity;
var type = self.World.TileSet.GetTerrainType(self.World.Map.MapTiles[cell.X, cell.Y]);
var umt = self.Info.Traits.Get<MobileInfo>().MovementType;
// Todo: Cache cost for each terraintype
return (float)Rules.TerrainTypes[type].GetCost(umt)*
self.World.WorldActor.traits.WithInterface<ICustomTerrain>().Aggregate(1f, (a, x) => a * x.GetCost(cell,self));
} }
public IEnumerable<float2> GetCurrentPath(Actor self) public IEnumerable<float2> GetCurrentPath(Actor self)

View File

@@ -109,6 +109,7 @@ namespace OpenRA.Traits
{ {
UnitMovementType GetMovementType(); UnitMovementType GetMovementType();
bool CanEnterCell(int2 location); bool CanEnterCell(int2 location);
float MovementCostForCell(Actor self, int2 cell);
IEnumerable<float2> GetCurrentPath(Actor self); IEnumerable<float2> GetCurrentPath(Actor self);
void SetPosition(Actor self, int2 cell); void SetPosition(Actor self, int2 cell);
} }

View File

@@ -61,6 +61,14 @@ namespace OpenRA.Traits
return self.World.WorldActor.traits.Get<AircraftInfluence>().GetUnitsAt(p).Count() == 0; return self.World.WorldActor.traits.Get<AircraftInfluence>().GetUnitsAt(p).Count() == 0;
} }
public float MovementCostForCell(Actor self, int2 cell)
{
if (!self.World.Map.IsInMap(cell.X,cell.Y))
return float.PositiveInfinity;
return self.World.WorldActor.traits.WithInterface<ICustomTerrain>().Aggregate(1f, (a, x) => a * x.GetCost(cell,self));
}
public override IEnumerable<int2> OccupiedCells() public override IEnumerable<int2> OccupiedCells()
{ {

View File

@@ -72,7 +72,9 @@ namespace OpenRA.Mods.RA
public UnitMovementType GetMovementType() { return UnitMovementType.Fly; } public UnitMovementType GetMovementType() { return UnitMovementType.Fly; }
public bool CanEnterCell(int2 location) { return true; } public bool CanEnterCell(int2 location) { return true; }
public float MovementCostForCell(Actor self, int2 cell) { return 1f; }
int2[] noCells = new int2[] { }; int2[] noCells = new int2[] { };
public IEnumerable<int2> OccupiedCells() { return noCells; } public IEnumerable<int2> OccupiedCells() { return noCells; }
} }