moved directions to a shared place; fixed pathfinder to use the appropriate movement type

This commit is contained in:
Chris Forbes
2009-10-26 10:45:29 +13:00
parent e61ef4a93f
commit 482273f604
4 changed files with 47 additions and 28 deletions

View File

@@ -5,6 +5,7 @@ using System.Text;
using OpenRa.Game.GameRules; using OpenRa.Game.GameRules;
using IjwFramework.Types; using IjwFramework.Types;
using IjwFramework.Collections; using IjwFramework.Collections;
using OpenRa.Game.Graphics;
namespace OpenRa.Game namespace OpenRa.Game
{ {
@@ -66,7 +67,7 @@ namespace OpenRa.Game
if (c.distance + 1 > maxDistance) continue; if (c.distance + 1 > maxDistance) continue;
foreach (var d in PathFinder.directions) foreach (var d in Util.directions)
{ {
var e = c.location + d; var e = c.location + d;
if (e.X < min.X || e.Y < min.Y || e.X > max.X || e.Y > max.Y) if (e.X < min.X || e.Y < min.Y || e.X > max.X || e.Y > max.Y)

View File

@@ -42,6 +42,18 @@ namespace OpenRa.Game.Graphics
return result; return result;
} }
public static readonly int2[] directions =
new int2[] {
new int2( -1, -1 ),
new int2( -1, 0 ),
new int2( -1, 1 ),
new int2( 0, -1 ),
new int2( 0, 1 ),
new int2( 1, -1 ),
new int2( 1, 0 ),
new int2( 1, 1 ),
};
static float[] channelSelect = { 0.75f, 0.25f, -0.25f, -0.75f }; static float[] channelSelect = { 0.75f, 0.25f, -0.25f, -0.75f };
public static void FastCreateQuad(Vertex[] vertices, ushort[] indices, float2 o, Sprite r, int palette, int nv, int ni) public static void FastCreateQuad(Vertex[] vertices, ushort[] indices, float2 o, Sprite r, int palette, int nv, int ni)

View File

@@ -2,27 +2,35 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using IjwFramework.Collections; using IjwFramework.Collections;
using OpenRa.FileFormats; using OpenRa.FileFormats;
using OpenRa.Game.Graphics;
namespace OpenRa.Game namespace OpenRa.Game
{ {
class PathFinder class PathFinder
{ {
double[ , ] passableCost = new double[ 128, 128 ]; double[][,] passableCost = new double[4][,];
Map map; Map map;
public PathFinder(Map map, TileSet tileSet) public PathFinder(Map map, TileSet tileSet)
{ {
this.map = map; this.map = map;
for (var umt = UnitMovementType.Foot; umt <= UnitMovementType.Float; umt++)
passableCost[(int)umt] = new double[128, 128];
for( int x = 0 ; x < 128 ; x++ ) for( int x = 0 ; x < 128 ; x++ )
for( int y = 0 ; y < 128 ; y++ ) for( int y = 0 ; y < 128 ; y++ )
for (var umt = UnitMovementType.Foot; umt <= UnitMovementType.Float; umt++ )
passableCost[ x, y ] = ( map.IsInMap( x, y ) ) passableCost[(int)umt][ x, y ] = ( map.IsInMap( x, y ) )
? TerrainCosts.Cost( UnitMovementType.Wheel, tileSet.GetWalkability( map.MapTiles[ x, y ] ) ) ? TerrainCosts.Cost( umt, tileSet.GetWalkability( map.MapTiles[ x, y ] ) )
: double.PositiveInfinity; : double.PositiveInfinity;
} }
public List<int2> FindUnitPath( int2 unitLocation, Func<int2,double> estimator ) public List<int2> FindUnitPath(int2 src, int2 dest, UnitMovementType umt)
{
return FindUnitPath(src, DefaultEstimator(dest), umt);
}
List<int2> FindUnitPath( int2 unitLocation, Func<int2,double> estimator, UnitMovementType umt )
{ {
var startLocation = unitLocation + map.Offset; var startLocation = unitLocation + map.Offset;
@@ -32,10 +40,10 @@ namespace OpenRa.Game
for( int y = 0 ; y < 128 ; y++ ) for( int y = 0 ; y < 128 ; y++ )
cellInfo[ x, y ] = new CellInfo( double.PositiveInfinity, new int2( x, y ), false ); cellInfo[ x, y ] = new CellInfo( double.PositiveInfinity, new int2( x, y ), false );
return FindUnitPath( new[] {startLocation}, estimator, map.Offset, cellInfo ); return FindUnitPath( new[] {startLocation}, estimator, umt, map.Offset, cellInfo );
} }
List<int2> FindUnitPath(IEnumerable<int2> startLocations, Func<int2, double> estimator, int2 offset, CellInfo[,] cellInfo) List<int2> FindUnitPath(IEnumerable<int2> startLocations, Func<int2, double> estimator, UnitMovementType umt, int2 offset, CellInfo[,] cellInfo)
{ {
var queue = new PriorityQueue<PathDistance>(); var queue = new PriorityQueue<PathDistance>();
@@ -54,20 +62,20 @@ namespace OpenRa.Game
if( estimator( here - offset ) == 0.0 ) if( estimator( here - offset ) == 0.0 )
return MakePath( cellInfo, here, offset ); return MakePath( cellInfo, here, offset );
foreach( int2 d in directions ) foreach( int2 d in Util.directions )
{ {
int2 newHere = here + d; int2 newHere = here + d;
if( cellInfo[ newHere.X, newHere.Y ].Seen ) if( cellInfo[ newHere.X, newHere.Y ].Seen )
continue; continue;
if( passableCost[ newHere.X, newHere.Y ] == double.PositiveInfinity ) if( passableCost[(int)umt][ newHere.X, newHere.Y ] == double.PositiveInfinity )
continue; continue;
if (Game.BuildingInfluence.GetBuildingAt(newHere - offset) != null) if (Game.BuildingInfluence.GetBuildingAt(newHere - offset) != null)
continue; continue;
if (Game.UnitInfluence.GetUnitAt(newHere - offset) != null) if (Game.UnitInfluence.GetUnitAt(newHere - offset) != null)
continue; continue;
double cellCost = ( ( d.X * d.Y != 0 ) ? 1.414213563 : 1.0 ) * passableCost[ newHere.X, newHere.Y ]; double cellCost = ( ( d.X * d.Y != 0 ) ? 1.414213563 : 1.0 ) * passableCost[(int)umt][ newHere.X, newHere.Y ];
double newCost = cellInfo[ here.X, here.Y ].MinCost + cellCost; double newCost = cellInfo[ here.X, here.Y ].MinCost + cellCost;
if( newCost >= cellInfo[ newHere.X, newHere.Y ].MinCost ) if( newCost >= cellInfo[ newHere.X, newHere.Y ].MinCost )
@@ -98,19 +106,7 @@ namespace OpenRa.Game
return ret; return ret;
} }
public static readonly int2[] directions = static Func<int2, double> DefaultEstimator(int2 destination)
new int2[] {
new int2( -1, -1 ),
new int2( -1, 0 ),
new int2( -1, 1 ),
new int2( 0, -1 ),
new int2( 0, 1 ),
new int2( 1, -1 ),
new int2( 1, 0 ),
new int2( 1, 1 ),
};
public static Func<int2, double> DefaultEstimator(int2 destination)
{ {
return here => return here =>
{ {

View File

@@ -66,6 +66,15 @@ namespace OpenRa.Game.Traits
public IEnumerable<int2> OccupiedCells() public IEnumerable<int2> OccupiedCells()
{ {
return new[] { fromCell, toCell }; return new[] { fromCell, toCell };
}
public UnitMovementType GetMovementType()
{
/* todo: boats, planes */
var vi = self.unitInfo as UnitInfo.VehicleInfo;
if (vi == null) return UnitMovementType.Foot;
return vi.Tracked ? UnitMovementType.Track : UnitMovementType.Wheel;
} }
public interface CurrentAction public interface CurrentAction
@@ -138,7 +147,7 @@ namespace OpenRa.Game.Traits
} }
if( path == null ) if( path == null )
path = Game.pathFinder.FindUnitPath( self.Location, PathFinder.DefaultEstimator( destination ) ); path = Game.pathFinder.FindUnitPath( self.Location, destination, mobile.GetMovementType() );
if( path.Count == 0 ) if( path.Count == 0 )
{ {
destination = mobile.toCell; destination = mobile.toCell;
@@ -189,7 +198,7 @@ namespace OpenRa.Game.Traits
void CalculateMoveFraction() void CalculateMoveFraction()
{ {
var d = to - from; var d = to - from;
moveFractionTotal = (int)Math.Sqrt( d.X * d.X + d.Y * d.Y ) * (25 / 6); moveFractionTotal = (int)d.Length * (25 / 6);
} }
static float2 CenterOfCell( int2 loc ) static float2 CenterOfCell( int2 loc )
@@ -216,7 +225,8 @@ namespace OpenRa.Game.Traits
mobile.fromCell = mobile.toCell; mobile.fromCell = mobile.toCell;
mobile.toCell = nextCell; mobile.toCell = nextCell;
fromFacing = mobile.facing; fromFacing = mobile.facing;
toFacing = Util.GetNearestFacing( fromFacing, Util.GetFacing( mobile.toCell-mobile.fromCell, fromFacing ) ); toFacing = Util.GetNearestFacing( fromFacing,
Util.GetFacing( mobile.toCell-mobile.fromCell, fromFacing ) );
OnComplete = OnCompleteFirstHalf; OnComplete = OnCompleteFirstHalf;
return; return;
} }