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

This commit is contained in:
(no author)
2007-07-28 10:30:40 +00:00
parent 5d6fbbdfc9
commit 48e5da3945
13 changed files with 252 additions and 230 deletions

View File

@@ -10,7 +10,7 @@ namespace OpenRa.Game
{ {
abstract class Actor abstract class Actor
{ {
protected readonly Game game; public readonly Game game;
public abstract float2 RenderLocation { get; } public abstract float2 RenderLocation { get; }
public Player owner; public Player owner;

View File

@@ -4,18 +4,13 @@ using System.Text;
namespace OpenRa.Game namespace OpenRa.Game
{ {
class Building : Actor class Building : PlayerOwned
{ {
protected Animation animation;
protected int2 location;
public Building( string name, int2 location, Player owner, Game game ) public Building( string name, int2 location, Player owner, Game game )
: base( game ) : base( game, name, location )
{ {
this.location = location;
this.owner = owner; this.owner = owner;
animation = new Animation( name );
animation.PlayThen( "make", delegate { animation.PlayRepeating( "idle" ); } ); animation.PlayThen( "make", delegate { animation.PlayRepeating( "idle" ); } );
owner.TechTree.Build( name, true ); owner.TechTree.Build( name, true );
} }
@@ -25,14 +20,5 @@ namespace OpenRa.Game
animation.Tick( t ); animation.Tick( t );
} }
public override Sprite[] CurrentImages
{
get { return animation.Images; }
}
public override float2 RenderLocation
{
get { return 24.0f * (float2)location; }
}
} }
} }

View File

@@ -1,60 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace OpenRa.Game
{
class Harvester : Unit
{
public Harvester( int2 cell, Player owner, Game game )
: base( "harv", cell, owner, new float2( 12, 12 ), game )
{
}
public override IOrder Order( Game game, int2 xy )
{
if( ( fromCell == toCell || moveFraction == 0 ) && fromCell == xy )
return new HarvestOrder( this );
return base.Order( game, xy );
}
void AcceptHarvestOrder()
{
TickFunc order = null;
order = nextOrder = delegate
{
// TODO: check that there's actually some ore in this cell :)
// face in one of the 8 directions
if( Turn( ( facing + 1 ) & ~3 ) )
return;
currentOrder = delegate { };
if( nextOrder == null )
nextOrder = order;
string sequenceName = string.Format( "harvest{0}", facing / 4 );
animation.PlayThen( sequenceName, delegate
{
currentOrder = null;
animation.PlayFetchIndex( "idle", delegate { return facing; } );
} );
};
}
public class HarvestOrder : IOrder
{
Harvester harvester;
public HarvestOrder( Harvester harv )
{
harvester = harv;
}
public void Apply( Game game )
{
harvester.AcceptHarvestOrder();
}
}
}
}

View File

@@ -45,9 +45,9 @@ namespace OpenRa.Game
SequenceProvider.ForcePrecache(); SequenceProvider.ForcePrecache();
game.world.Add( new Mcv( new int2( 5, 5 ), game.players[ 3 ], game ) ); game.world.Add( new Unit( "mcv", new int2( 5, 5 ), game.players[ 3 ], game ) );
game.world.Add( new Mcv( new int2( 7, 5 ), game.players[ 2 ], game ) ); game.world.Add( new Unit( "mcv", new int2( 7, 5 ), game.players[ 2 ], game ) );
Mcv mcv = new Mcv( new int2( 9, 5 ), game.players[ 1 ], game ); Unit mcv = new Unit( "mcv", new int2( 9, 5 ), game.players[ 1 ], game );
game.world.orderGenerator = mcv; game.world.orderGenerator = mcv;
game.world.Add( mcv ); game.world.Add( mcv );

View File

@@ -1,42 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
using OpenRa.FileFormats;
using System.Drawing;
using BluntDirectX.Direct3D;
namespace OpenRa.Game
{
class Mcv : Unit
{
public Mcv( int2 location, Player owner, Game game )
: base( "mcv", location, owner, new float2( 12, 12 ), game )
{
}
public void AcceptDeployOrder()
{
nextOrder = delegate( Game game, int t )
{
if( Turn( 12 ) )
return;
World world = game.world;
world.AddFrameEndTask( delegate
{
world.Remove( this );
world.Add( new ConstructionYard( fromCell - new int2( 1, 1 ), owner, game ) );
} );
currentOrder = null;
};
}
public override IOrder Order( Game game, int2 xy )
{
if( ( fromCell == toCell || moveFraction == 0 ) && fromCell == xy )
return new DeployMcvOrder( this );
return base.Order( game, xy );
}
}
}

View File

@@ -22,22 +22,37 @@ namespace OpenRa.Game
public void Apply( Game game ) public void Apply( Game game )
{ {
Unit.AcceptMoveOrder( Destination ); Unit.nextOrder = UnitMissions.Move( Unit, Destination );
} }
} }
class DeployMcvOrder : IOrder class DeployMcvOrder : IOrder
{ {
public Mcv Mcv; Unit unit;
public DeployMcvOrder( Mcv mcv ) public DeployMcvOrder( Unit unit )
{ {
this.Mcv = mcv; this.unit = unit;
} }
public void Apply( Game game ) public void Apply( Game game )
{ {
Mcv.AcceptDeployOrder(); unit.nextOrder = UnitMissions.Deploy( unit );
}
}
class HarvestOrder : IOrder
{
Unit unit;
public HarvestOrder( Unit unit )
{
this.unit = unit;
}
public void Apply( Game game )
{
unit.nextOrder = UnitMissions.Harvest( unit );
} }
} }
} }

View File

@@ -47,9 +47,9 @@
<Compile Include="IOrderGenerator.cs" /> <Compile Include="IOrderGenerator.cs" />
<Compile Include="Network\Packet.cs" /> <Compile Include="Network\Packet.cs" />
<Compile Include="Player.cs" /> <Compile Include="Player.cs" />
<Compile Include="PlayerOwned.cs" />
<Compile Include="Rules.cs" /> <Compile Include="Rules.cs" />
<Compile Include="Sheet.cs" /> <Compile Include="Sheet.cs" />
<Compile Include="Harvester.cs" />
<Compile Include="Log.cs" /> <Compile Include="Log.cs" />
<Compile Include="Network\Network.cs" /> <Compile Include="Network\Network.cs" />
<Compile Include="PathFinder.cs" /> <Compile Include="PathFinder.cs" />
@@ -63,7 +63,6 @@
<Compile Include="MainWindow.cs"> <Compile Include="MainWindow.cs">
<SubType>Form</SubType> <SubType>Form</SubType>
</Compile> </Compile>
<Compile Include="Mcv.cs" />
<Compile Include="Program.cs" /> <Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Refinery.cs" /> <Compile Include="Refinery.cs" />
@@ -80,6 +79,7 @@
<Compile Include="TreeCache.cs" /> <Compile Include="TreeCache.cs" />
<Compile Include="UiOverlay.cs" /> <Compile Include="UiOverlay.cs" />
<Compile Include="Unit.cs" /> <Compile Include="Unit.cs" />
<Compile Include="UnitMissions.cs" />
<Compile Include="UnitSheetBuilder.cs" /> <Compile Include="UnitSheetBuilder.cs" />
<Compile Include="Util.cs" /> <Compile Include="Util.cs" />
<Compile Include="Vertex.cs" /> <Compile Include="Vertex.cs" />

View File

@@ -26,9 +26,9 @@ namespace OpenRa.Game
// returns estimate to destination, 0.0 is cell is dest // returns estimate to destination, 0.0 is cell is dest
public delegate double DistanceHeuristic( int2 cell ); public delegate double DistanceHeuristic( int2 cell );
public List<int2> FindUnitPath( Unit unit, DistanceHeuristic estimator ) public List<int2> FindUnitPath( int2 unitLocation, DistanceHeuristic estimator )
{ {
int2 startLocation = unit.Location + map.Offset; int2 startLocation = unitLocation + map.Offset;
CellInfo[ , ] cellInfo = new CellInfo[ 128, 128 ]; CellInfo[ , ] cellInfo = new CellInfo[ 128, 128 ];

View File

@@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace OpenRa.Game
{
abstract class PlayerOwned : Actor
{
public Animation animation;
protected int2 location;
public UnitMission currentOrder = null;
public UnitMission nextOrder = null;
protected PlayerOwned( Game game, string name, int2 location )
: base( game )
{
animation = new Animation( name );
this.location = location;
}
public override float2 RenderLocation
{
get { return 24.0f * (float2)location; }
}
public override Sprite[] CurrentImages { get { return animation.Images; } }
}
}

View File

@@ -18,7 +18,7 @@ namespace OpenRa.Game
game.world.AddFrameEndTask(delegate game.world.AddFrameEndTask(delegate
{ {
Unit harvester = new Harvester(location + new int2(1, 2), owner, game); Unit harvester = new Unit( "harv", location + new int2( 1, 2 ), owner, game );
harvester.facing = 8; harvester.facing = 8;
game.world.Add(harvester); game.world.Add(harvester);
game.world.orderGenerator = harvester; game.world.orderGenerator = harvester;

View File

@@ -16,14 +16,14 @@ namespace OpenRa.Game
foreach (string line in Util.ReadAllLines(FileSystem.Open("units.txt"))) foreach (string line in Util.ReadAllLines(FileSystem.Open("units.txt")))
{ {
string unit = line.Substring(0, line.IndexOf(',')); string unit = line.Substring( 0, line.IndexOf( ',' ) ).ToUpperInvariant();
IniSection section = rulesIni.GetSection(unit.ToUpperInvariant()); IniSection section = rulesIni.GetSection( unit );
if (section == null) if (section == null)
{ {
Log.Write("rules.ini doesnt contain entry for unit \"{0}\"", unit); Log.Write("rules.ini doesnt contain entry for unit \"{0}\"", unit);
continue; continue;
} }
unitInfos.Add(unit, new UnitInfo(section)); unitInfos.Add( unit, new UnitInfo( unit, section ) );
} }
} }
@@ -36,37 +36,17 @@ namespace OpenRa.Game
class UnitInfo class UnitInfo
{ {
public readonly int Speed; public readonly int Speed;
public readonly SupportedMissions supportedMissions;
public UnitInfo( IniSection ini ) public UnitInfo( string unitName, IniSection ini )
{ {
Speed = int.Parse( ini.GetValue( "Speed", "0" ) ); Speed = int.Parse( ini.GetValue( "Speed", "0" ) );
}
}
//Unit Missions: supportedMissions = SupportedMissions.Stop;
//{ if( unitName == "MCV" )
// Sleep - no-op supportedMissions |= SupportedMissions.Deploy;
// Harmless - no-op, and also not considered a threat if( unitName == "HARV" )
// Sticky supportedMissions |= SupportedMissions.Harvest;
// Attack }
// Move }
// QMove
// Retreat
// Guard
// Enter
// Capture
// Harvest
// Area Guard
// [Return]
// Stop
// [Ambush]
// Hunt
// Unload
// Sabotage
// Construction
// Selling
// Repair
// Rescue
// Missile
//}
} }

View File

@@ -4,26 +4,26 @@ using System.Text;
namespace OpenRa.Game namespace OpenRa.Game
{ {
abstract class Unit : Actor, IOrderGenerator class Unit : PlayerOwned, IOrderGenerator
{ {
protected Animation animation;
public int facing = 0; public int facing = 0;
protected int2 fromCell, toCell; public int2 fromCell;
protected int moveFraction, moveFractionTotal; public int2 toCell
{
get { return location; }
set { location = value; }
}
protected delegate void TickFunc( Game game, int t ); public int moveFraction, moveFractionTotal;
protected TickFunc currentOrder = null;
protected TickFunc nextOrder = null;
protected readonly float2 renderOffset; readonly float2 renderOffset;
protected readonly UnitInfo unitInfo; public readonly UnitInfo unitInfo;
public Unit( string name, int2 cell, Player owner, float2 renderOffset, Game game ) public Unit( string name, int2 cell, Player owner, Game game )
: base( game ) : base( game, name, cell )
{ {
fromCell = toCell = cell; fromCell = toCell = cell;
this.renderOffset = renderOffset; this.renderOffset = new float2( 12, 12 ); // TODO: pull this from the sprite
this.owner = owner; this.owner = owner;
this.unitInfo = Rules.UnitInfo( name ); this.unitInfo = Rules.UnitInfo( name );
@@ -34,7 +34,7 @@ namespace OpenRa.Game
static float2[] fvecs = Util.MakeArray<float2>( 32, static float2[] fvecs = Util.MakeArray<float2>( 32,
delegate( int i ) { return -float2.FromAngle( i / 16.0f * (float)Math.PI ) * new float2( 1f, 1.3f ); } ); delegate( int i ) { return -float2.FromAngle( i / 16.0f * (float)Math.PI ) * new float2( 1f, 1.3f ); } );
int GetFacing( float2 d ) public int GetFacing( float2 d )
{ {
if( float2.WithinEpsilon( d, float2.Zero, 0.001f ) ) if( float2.WithinEpsilon( d, float2.Zero, 0.001f ) )
return facing; return facing;
@@ -65,54 +65,7 @@ namespace OpenRa.Game
} }
if( currentOrder != null ) if( currentOrder != null )
currentOrder( game, t ); currentOrder( t );
}
public void AcceptMoveOrder( int2 destination )
{
nextOrder = delegate( Game game, int t )
{
if( nextOrder != null )
destination = toCell;
if( Turn( GetFacing( toCell - fromCell ) ) )
return;
moveFraction += t * unitInfo.Speed;
if( moveFraction < moveFractionTotal )
return;
moveFraction = 0;
moveFractionTotal = 0;
fromCell = toCell;
if( toCell == destination )
{
currentOrder = null;
return;
}
List<int2> res = game.pathFinder.FindUnitPath( this, PathFinder.DefaultEstimator( destination ) );
if( res.Count != 0 )
{
toCell = res[ res.Count - 1 ];
int2 dir = toCell - fromCell;
moveFractionTotal = ( dir.X != 0 && dir.Y != 0 ) ? 2500 : 2000;
}
else
destination = toCell;
};
}
protected bool Turn( int desiredFacing )
{
if( facing == desiredFacing )
return false;
int df = ( desiredFacing - facing + 32 ) % 32;
facing = ( facing + ( df > 16 ? 31 : 1 ) ) % 32;
return true;
} }
public override float2 RenderLocation public override float2 RenderLocation
@@ -122,13 +75,27 @@ namespace OpenRa.Game
float fraction = ( moveFraction > 0 ) ? (float)moveFraction / moveFractionTotal : 0f; float fraction = ( moveFraction > 0 ) ? (float)moveFraction / moveFractionTotal : 0f;
float2 location = 24 * float2.Lerp( fromCell, toCell, fraction ); float2 location = 24 * float2.Lerp( fromCell, toCell, fraction );
return ( location - renderOffset ).Round(); ; return ( location - renderOffset ).Round();
} }
} }
public int2 Location { get { return toCell; } } bool SupportsMission( SupportedMissions mission )
public virtual IOrder Order(Game game, int2 xy) { return new MoveOrder(this, xy); } {
public override Sprite[] CurrentImages { get { return animation.Images; } } return mission == ( unitInfo.supportedMissions & mission );
}
public IOrder Order( Game game, int2 xy )
{
if( ( fromCell == toCell || moveFraction == 0 ) && fromCell == xy )
{
if( SupportsMission( SupportedMissions.Deploy ) )
return new DeployMcvOrder( this );
if( SupportsMission( SupportedMissions.Harvest ) )
return new HarvestOrder( this );
}
return new MoveOrder( this, xy );
}
public void PrepareOverlay(Game game, int2 xy) { } public void PrepareOverlay(Game game, int2 xy) { }
} }

147
OpenRa.Game/UnitMissions.cs Normal file
View File

@@ -0,0 +1,147 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace OpenRa.Game
{
//Unit Missions:
//{
//in rules.ini:
// Sleep - no-op
// Harmless - no-op, and also not considered a threat
// Sticky
// Attack
// Move
// QMove
// Retreat
// Guard
// Enter
// Capture
// Harvest
// Area Guard
// [Return] - unused
// Stop
// [Ambush] - unused
// Hunt
// Unload
// Sabotage
// Construction
// Selling
// Repair
// Rescue
// Missile
//
//not in original RA:
// Deploy (Mcv -> Fact) [should this be construction/unload?]
//}
[Flags]
enum SupportedMissions
{
Stop = 0,
Harvest = 1,
Deploy = 2,
}
delegate void UnitMission( int t );
static class UnitMissions
{
public static UnitMission Sleep()
{
return delegate { };
}
public static UnitMission Move( Unit unit, int2 destination )
{
return delegate( int t )
{
Game game = unit.game;
if( unit.nextOrder != null )
destination = unit.toCell;
if( Turn( unit, unit.GetFacing( unit.toCell - unit.fromCell ) ) )
return;
unit.moveFraction += t * unit.unitInfo.Speed;
if( unit.moveFraction < unit.moveFractionTotal )
return;
unit.moveFraction = 0;
unit.moveFractionTotal = 0;
unit.fromCell = unit.toCell;
if( unit.toCell == destination )
{
unit.currentOrder = null;
return;
}
List<int2> res = game.pathFinder.FindUnitPath( unit.toCell, PathFinder.DefaultEstimator( destination ) );
if( res.Count != 0 )
{
unit.toCell = res[ res.Count - 1 ];
int2 dir = unit.toCell - unit.fromCell;
unit.moveFractionTotal = ( dir.X != 0 && dir.Y != 0 ) ? 2500 : 2000;
}
else
destination = unit.toCell;
};
}
public static UnitMission Deploy( Unit unit )
{
return delegate( int t )
{
Game game = unit.game;
if( Turn( unit, 12 ) )
return;
game.world.AddFrameEndTask( delegate
{
game.world.Remove( unit );
game.world.Add( new ConstructionYard( unit.fromCell - new int2( 1, 1 ), unit.owner, game ) );
} );
unit.currentOrder = null;
};
}
public static UnitMission Harvest( Unit unit )
{
UnitMission order = null;
order = delegate
{
// TODO: check that there's actually some ore in this cell :)
// face in one of the 8 directions
if( Turn( unit, ( unit.facing + 1 ) & ~3 ) )
return;
unit.currentOrder = delegate { };
if( unit.nextOrder == null )
unit.nextOrder = order;
string sequenceName = string.Format( "harvest{0}", unit.facing / 4 );
unit.animation.PlayThen( sequenceName, delegate
{
unit.currentOrder = null;
unit.animation.PlayFetchIndex( "idle", delegate { return unit.facing; } );
} );
};
return order;
}
static bool Turn( Unit unit, int desiredFacing )
{
if( unit.facing == desiredFacing )
return false;
int df = ( desiredFacing - unit.facing + 32 ) % 32;
unit.facing = ( unit.facing + ( df > 16 ? 31 : 1 ) ) % 32;
return true;
}
}
}