git-svn-id: svn://svn.ijw.co.nz/svn/OpenRa@1299 993157c7-ee19-0410-b2c4-bb4e9862e678

This commit is contained in:
(no author)
2007-07-18 10:42:31 +00:00
parent f06d1aa5d5
commit edf0feb265
8 changed files with 229 additions and 26 deletions

View File

@@ -5,7 +5,7 @@ using System.Diagnostics;
namespace OpenRa.DataStructures
{
class PriorityQueue<T>
public class PriorityQueue<T>
where T : IComparable<T>
{
List<T[]> items = new List<T[]>();
@@ -36,10 +36,16 @@ namespace OpenRa.DataStructures
{
index = 0;
++level;
items.Add( new T[ 1 << level ] );
if( items.Count <= level )
items.Add( new T[ 1 << level ] );
}
}
public bool Empty
{
get { return ( level == 0 ); }
}
T At( int level, int index )
{
return items[ level ][ index ];
@@ -123,7 +129,7 @@ namespace OpenRa.DataStructures
// System.Diagnostics.Debug.Assert( At( i, j ).CompareTo( Above( i, j ) ) < 0, "At( i, j ) > Above( i, j )" );
//}
private int RowLength( int i )
int RowLength( int i )
{
if( i == level )
return index;

View File

@@ -41,7 +41,7 @@ namespace OpenRa.Game
Location = Point.Empty;
Visible = true;
renderer = new Renderer(this, GetResolution(settings), false);
renderer = new Renderer(this, GetResolution(settings), true);
map = new Map(new IniFile(File.OpenRead("../../../" + settings.GetValue("map", "scm12ea.ini"))));
@@ -71,6 +71,7 @@ namespace OpenRa.Game
sidebar = new Sidebar(Race.Soviet, renderer, viewport);
PathFinder.Instance = new PathFinder( map, terrain.tileSet );
}
void PrecacheStructure(string name)

View File

@@ -95,9 +95,16 @@ namespace OpenRa.Game
currentOrder = null;
else
{
int2 dir = destination - fromCell;
toCell = fromCell + dir.Sign();
moveFractionTotal = ( dir.X != 0 && dir.Y != 0 ) ? 250 : 200;
List<int2> res = PathFinder.Instance.FindUnitPath( world, this, destination );
if( res.Count != 0 )
{
toCell = res[ res.Count - 1 ];
int2 dir = toCell - fromCell;
moveFractionTotal = ( dir.X != 0 && dir.Y != 0 ) ? 250 : 200;
}
else
destination = toCell;
}
}
}
@@ -148,5 +155,10 @@ namespace OpenRa.Game
else
return new MoveOrder( this, xy );
}
public int2 Location
{
get { return toCell; }
}
}
}

View File

@@ -79,6 +79,10 @@
<Compile Include="World.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\OpenRa.DataStructures\OpenRa.DataStructures.csproj">
<Project>{2F9E7A23-56C0-4286-9C8E-1060A9B2F073}</Project>
<Name>OpenRa.DataStructures</Name>
</ProjectReference>
<ProjectReference Include="..\OpenRa.FileFormats\OpenRa.FileFormats.csproj">
<Project>{BDAEAB25-991E-46A7-AF1E-4F0E03358DAA}</Project>
<Name>OpenRa.FileFormats</Name>

168
OpenRa.Game/PathFinder.cs Normal file
View File

@@ -0,0 +1,168 @@
using System;
using System.Collections.Generic;
using System.Text;
using OpenRa.FileFormats;
using OpenRa.DataStructures;
using System.Windows.Forms;
namespace OpenRa.Game
{
class PathFinder
{
public static PathFinder Instance;
bool[ , ] passable = new bool[ 128, 128 ];
Map map;
public PathFinder( Map map, TileSet tileSet )
{
this.map = map;
for( int x = 0 ; x < 128 ; x++ )
{
for( int y = 0 ; y < 128 ; y++ )
{
if( x < map.XOffset || y < map.YOffset || x >= map.XOffset + map.Width || y >= map.YOffset + map.Height )
passable[ x, y ] = false;
else
{
// HACK: water( tiles 1 and 2) are impassable
passable[ x, y ] = ( map.MapTiles[ x, y ].tile != 1 && map.MapTiles[ x, y ].tile != 2 );
// TODO: implement all the different terrain classes, including bonuses for roads etc
}
}
}
}
static bool first = true;
public List<int2> FindUnitPath( World world, Mcv unit, int2 destination )
{
int2 offset = new int2( map.XOffset, map.YOffset );
destination += offset;
int2 startLocation = unit.Location + offset;
bool[ , ] seen = new bool[ 128, 128 ];
int2[ , ] path = new int2[ 128, 128 ];
double[ , ] minCost = new double[ 128, 128 ];
for( int x = 0 ; x < 128 ; x++ )
{
for( int y = 0 ; y < 128 ; y++ )
{
path[ x, y ] = new int2( x, y );
minCost[ x, y ] = double.PositiveInfinity;
}
}
PriorityQueue<PathDistance> queue = new PriorityQueue<PathDistance>();
queue.Add( new PathDistance( Estimate( startLocation, destination ), startLocation ) );
minCost[ startLocation.X, startLocation.Y ] = Estimate( startLocation, destination );
int hax = 0;
int seenCount = 0;
int impassableCount = 0;
while( !queue.Empty )
{
++hax;
PathDistance p = queue.Pop();
int2 here = p.Location;
seen[ here.X, here.Y ] = true;
if( hax < 128 )
world.AddFrameEndTask( delegate { world.Add( new Mcv( here - offset, 2 ) ); } );
if( p.Location == destination )
{
Log.Write( "{0}, {1}, {2}", hax, seenCount, impassableCount );
first = false;
return MakePath( path, destination, offset );
}
foreach( int2 d in directions )
{
int2 newHere = here + d;
if( seen[ newHere.X, newHere.Y ] )
{
++seenCount;
continue;
}
if( !passable[ newHere.X, newHere.Y ] )
{
++impassableCount;
continue;
}
double newCost = minCost[ here.X, here.Y ] + ( ( d.X * d.Y != 0 ) ? 1.414213563 : 1.0 );
if( newCost >= minCost[ newHere.X, newHere.Y ] )
continue;
path[ newHere.X, newHere.Y ] = here;
minCost[ newHere.X, newHere.Y ] = newCost;
queue.Add( new PathDistance( newCost + Estimate( newHere, destination ), newHere ) );
}
}
// no path exists
return new List<int2>();
}
List<int2> MakePath( int2[ , ] path, int2 destination, int2 offset )
{
List<int2> ret = new List<int2>();
int2 pathNode = destination;
while( path[ pathNode.X, pathNode.Y ] != pathNode )
{
ret.Add( pathNode - offset );
pathNode = path[ pathNode.X, pathNode.Y ];
}
Log.Write( "Path Length: {0}", ret.Count );
return ret;
}
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 ),
};
double Estimate( int2 here, int2 destination )
{
int2 d = ( here - destination ).Abs();
int diag = Math.Min( d.X, d.Y );
int straight = Math.Abs( d.X - d.Y );
return 1.5 * diag + straight;
}
struct PathDistance : IComparable<PathDistance>
{
public double EstTotal;
public int2 Location;
public PathDistance( double estTotal, int2 location )
{
EstTotal = estTotal;
Location = location;
}
public int CompareTo( PathDistance other )
{
return Math.Sign( EstTotal - other.EstTotal );
}
}
}
}

View File

@@ -10,14 +10,15 @@ namespace OpenRa.Game
[STAThread]
static void Main( string[] args )
{
if( System.Diagnostics.Debugger.IsAttached )
{
Run( args );
return;
}
try
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault( false );
Settings settings = new Settings(args);
new MainWindow( settings ).Run();
Run( args );
}
catch( Exception e )
{
@@ -26,5 +27,15 @@ namespace OpenRa.Game
throw;
}
}
private static void Run( string[] args )
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault( false );
Settings settings = new Settings( args );
new MainWindow( settings ).Run();
}
}
}

View File

@@ -14,7 +14,7 @@ namespace OpenRa.Game
FvfVertexBuffer<Vertex> vertexBuffer;
IndexBuffer indexBuffer;
Sheet terrainSheet;
TileSet tileSet;
public TileSet tileSet;
Viewport viewport;
Renderer renderer;
@@ -32,30 +32,30 @@ namespace OpenRa.Game
Dictionary<TileReference, Sprite> tileMapping =
new Dictionary<TileReference, Sprite>();
Size tileSize = new Size(24, 24);
Size tileSize = new Size( 24, 24 );
List<Vertex> vertices = new List<Vertex>();
List<ushort> indices = new List<ushort>();
for (int j = 0; j < map.Height; j++)
for (int i = 0; i < map.Width; i++)
for( int j = 0 ; j < map.Height ; j++ )
for( int i = 0 ; i < map.Width ; i++ )
{
TileReference tileRef = map.MapTiles[i + map.XOffset, j + map.YOffset];
TileReference tileRef = map.MapTiles[ i + map.XOffset, j + map.YOffset ];
Sprite tile;
if (!tileMapping.TryGetValue(tileRef, out tile))
tileMapping.Add(tileRef, tile = SheetBuilder.Add(tileSet.GetBytes(tileRef), tileSize));
if( !tileMapping.TryGetValue( tileRef, out tile ) )
tileMapping.Add( tileRef, tile = SheetBuilder.Add( tileSet.GetBytes( tileRef ), tileSize ) );
terrainSheet = tile.sheet;
Util.CreateQuad(vertices, indices, 24 * new float2(i,j), tile, 0);
Util.CreateQuad( vertices, indices, 24 * new float2( i, j ), tile, 0 );
}
vertexBuffer = new FvfVertexBuffer<Vertex>(renderer.Device, vertices.Count, Vertex.Format);
vertexBuffer.SetData(vertices.ToArray());
vertexBuffer = new FvfVertexBuffer<Vertex>( renderer.Device, vertices.Count, Vertex.Format );
vertexBuffer.SetData( vertices.ToArray() );
indexBuffer = new IndexBuffer(renderer.Device, indices.Count);
indexBuffer.SetData(indices.ToArray());
indexBuffer = new IndexBuffer( renderer.Device, indices.Count );
indexBuffer.SetData( indices.ToArray() );
}
void Draw()

View File

@@ -24,6 +24,7 @@ namespace OpenRa.Game
public static bool operator !=(int2 me, int2 other) { return !(me == other); }
public int2 Sign() { return new int2(Math.Sign(X), Math.Sign(Y)); }
public int2 Abs() { return new int2( Math.Abs( X ), Math.Abs( Y ) ); }
public override int GetHashCode() { return X.GetHashCode() ^ Y.GetHashCode(); }
public override bool Equals(object obj)