diff --git a/OpenRa.Game/BuildingInfluenceMap.cs b/OpenRa.Game/BuildingInfluenceMap.cs index 2d531b7c61..a7846b2b8b 100644 --- a/OpenRa.Game/BuildingInfluenceMap.cs +++ b/OpenRa.Game/BuildingInfluenceMap.cs @@ -5,6 +5,7 @@ using System.Text; using OpenRa.Game.GameRules; using IjwFramework.Types; using IjwFramework.Collections; +using OpenRa.Game.Graphics; namespace OpenRa.Game { @@ -66,7 +67,7 @@ namespace OpenRa.Game if (c.distance + 1 > maxDistance) continue; - foreach (var d in PathFinder.directions) + foreach (var d in Util.directions) { var e = c.location + d; if (e.X < min.X || e.Y < min.Y || e.X > max.X || e.Y > max.Y) diff --git a/OpenRa.Game/Graphics/Util.cs b/OpenRa.Game/Graphics/Util.cs index c8e27fc167..2f3f11f181 100644 --- a/OpenRa.Game/Graphics/Util.cs +++ b/OpenRa.Game/Graphics/Util.cs @@ -42,6 +42,18 @@ namespace OpenRa.Game.Graphics 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 }; public static void FastCreateQuad(Vertex[] vertices, ushort[] indices, float2 o, Sprite r, int palette, int nv, int ni) diff --git a/OpenRa.Game/PathFinder.cs b/OpenRa.Game/PathFinder.cs index 6de7546ba2..76c0c469bc 100644 --- a/OpenRa.Game/PathFinder.cs +++ b/OpenRa.Game/PathFinder.cs @@ -2,27 +2,35 @@ using System; using System.Collections.Generic; using IjwFramework.Collections; using OpenRa.FileFormats; +using OpenRa.Game.Graphics; namespace OpenRa.Game { class PathFinder { - double[ , ] passableCost = new double[ 128, 128 ]; + double[][,] passableCost = new double[4][,]; Map map; public PathFinder(Map map, TileSet tileSet) { 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 y = 0 ; y < 128 ; y++ ) - - passableCost[ x, y ] = ( map.IsInMap( x, y ) ) - ? TerrainCosts.Cost( UnitMovementType.Wheel, tileSet.GetWalkability( map.MapTiles[ x, y ] ) ) - : double.PositiveInfinity; + for (var umt = UnitMovementType.Foot; umt <= UnitMovementType.Float; umt++ ) + passableCost[(int)umt][ x, y ] = ( map.IsInMap( x, y ) ) + ? TerrainCosts.Cost( umt, tileSet.GetWalkability( map.MapTiles[ x, y ] ) ) + : double.PositiveInfinity; } - public List FindUnitPath( int2 unitLocation, Func estimator ) + public List FindUnitPath(int2 src, int2 dest, UnitMovementType umt) + { + return FindUnitPath(src, DefaultEstimator(dest), umt); + } + + List FindUnitPath( int2 unitLocation, Func estimator, UnitMovementType umt ) { var startLocation = unitLocation + map.Offset; @@ -32,10 +40,10 @@ namespace OpenRa.Game for( int y = 0 ; y < 128 ; y++ ) 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 FindUnitPath(IEnumerable startLocations, Func estimator, int2 offset, CellInfo[,] cellInfo) + List FindUnitPath(IEnumerable startLocations, Func estimator, UnitMovementType umt, int2 offset, CellInfo[,] cellInfo) { var queue = new PriorityQueue(); @@ -54,20 +62,20 @@ namespace OpenRa.Game if( estimator( here - offset ) == 0.0 ) return MakePath( cellInfo, here, offset ); - foreach( int2 d in directions ) + foreach( int2 d in Util.directions ) { int2 newHere = here + d; if( cellInfo[ newHere.X, newHere.Y ].Seen ) continue; - if( passableCost[ newHere.X, newHere.Y ] == double.PositiveInfinity ) + if( passableCost[(int)umt][ newHere.X, newHere.Y ] == double.PositiveInfinity ) continue; if (Game.BuildingInfluence.GetBuildingAt(newHere - offset) != null) continue; if (Game.UnitInfluence.GetUnitAt(newHere - offset) != null) 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; if( newCost >= cellInfo[ newHere.X, newHere.Y ].MinCost ) @@ -98,19 +106,7 @@ namespace OpenRa.Game return ret; } - 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 ), - }; - - public static Func DefaultEstimator(int2 destination) + static Func DefaultEstimator(int2 destination) { return here => { diff --git a/OpenRa.Game/Traits/Mobile.cs b/OpenRa.Game/Traits/Mobile.cs index 8ec9c8cb20..b69ce493ee 100644 --- a/OpenRa.Game/Traits/Mobile.cs +++ b/OpenRa.Game/Traits/Mobile.cs @@ -66,6 +66,15 @@ namespace OpenRa.Game.Traits public IEnumerable OccupiedCells() { 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 @@ -138,7 +147,7 @@ namespace OpenRa.Game.Traits } 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 ) { destination = mobile.toCell; @@ -189,7 +198,7 @@ namespace OpenRa.Game.Traits void CalculateMoveFraction() { 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 ) @@ -216,7 +225,8 @@ namespace OpenRa.Game.Traits mobile.fromCell = mobile.toCell; mobile.toCell = nextCell; 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; return; }