changes facing (and desireFacing) on Mobile and on Turreted. range is now 0..255

This commit is contained in:
Bob
2009-10-19 23:45:14 +13:00
parent 451fdc1615
commit a7ce0f97d1
14 changed files with 162 additions and 150 deletions

View File

@@ -45,12 +45,12 @@ namespace OpenRa.Game
case "1tnk":
case "2tnk":
case "3tnk":
case "4tnk":
traits.Add( new Traits.Mobile( this ) );
traits.Add( new Traits.Turreted( this ) );
traits.Add( new Traits.AttackTurreted( this ) );
traits.Add( new Traits.RenderUnitTurreted( this ) );
break;
case "4tnk":
traits.Add( new Traits.Mobile( this ) );
traits.Add( new Traits.Turreted( this ) );
traits.Add( new Traits.AttackTurreted( this ) );
traits.Add( new Traits.RenderUnitTurreted( this ) );
break;
case "mrj":
case "mgg":
// TODO: these aren't actually turreted; they just have spinning-things

View File

@@ -1,20 +1,20 @@
using System.Collections.Generic;
using OpenRa.FileFormats;
using OpenRa.Game.Graphics;
using OpenRa.TechTree;
using System.Drawing;
using System.Linq;
using IrrKlang;
using OpenRa.FileFormats;
using OpenRa.Game.Graphics;
using OpenRa.TechTree;
using System.Drawing;
using System.Linq;
using IrrKlang;
using IjwFramework.Collections;
namespace OpenRa.Game
{
class Game
{
{
public static readonly int CellSize = 24;
public readonly World world;
public readonly Map map;
public readonly Map map;
readonly TreeCache treeCache;
public readonly TerrainRenderer terrain;
public readonly Viewport viewport;
@@ -27,9 +27,9 @@ namespace OpenRa.Game
public readonly Dictionary<int, Player> players = new Dictionary<int, Player>();
public Player LocalPlayer { get { return players[localPlayerIndex]; } }
public BuildingInfluenceMap LocalPlayerBuildings;
public Player LocalPlayer { get { return players[localPlayerIndex]; } }
public BuildingInfluenceMap LocalPlayerBuildings;
ISoundEngine soundEngine;
public Game(string mapName, Renderer renderer, int2 clientSize)
@@ -49,8 +49,8 @@ namespace OpenRa.Game
treeCache = new TreeCache(map);
foreach( TreeReference treeReference in map.Trees )
world.Add( new Actor( treeReference, treeCache, map.Offset ) );
world.Add( new Actor( treeReference, treeCache, map.Offset ) );
LocalPlayerBuildings = new BuildingInfluenceMap(world, LocalPlayer);
pathFinder = new PathFinder(map, terrain.tileSet, LocalPlayerBuildings);
@@ -58,34 +58,34 @@ namespace OpenRa.Game
network = new Network();
controller = new Controller(this); // CAREFUL THERES AN UGLY HIDDEN DEPENDENCY HERE STILL
worldRenderer = new WorldRenderer(renderer, this);
soundEngine = new ISoundEngine();
sounds = new Cache<string, ISoundSource>(LoadSound);
worldRenderer = new WorldRenderer(renderer, this);
soundEngine = new ISoundEngine();
sounds = new Cache<string, ISoundSource>(LoadSound);
PlaySound("intro.aud", false);
}
readonly Cache<string, ISoundSource> sounds;
ISoundSource LoadSound(string filename)
{
var data = AudLoader.LoadSound(FileSystem.Open(filename));
return soundEngine.AddSoundSourceFromPCMData(data, filename,
new AudioFormat()
{
ChannelCount = 1,
FrameCount = data.Length / 2,
Format = SampleFormat.Signed16Bit,
SampleRate = 22050
});
}
public void PlaySound(string name, bool loop)
{
var sound = sounds[name];
// todo: positioning
soundEngine.Play2D(sound, loop, false, false);
}
readonly Cache<string, ISoundSource> sounds;
ISoundSource LoadSound(string filename)
{
var data = AudLoader.LoadSound(FileSystem.Open(filename));
return soundEngine.AddSoundSourceFromPCMData(data, filename,
new AudioFormat()
{
ChannelCount = 1,
FrameCount = data.Length / 2,
Format = SampleFormat.Signed16Bit,
SampleRate = 22050
});
}
public void PlaySound(string name, bool loop)
{
var sound = sounds[name];
// todo: positioning
soundEngine.Play2D(sound, loop, false, false);
}
public void Tick()
@@ -94,28 +94,28 @@ namespace OpenRa.Game
world.Update();
viewport.DrawRegions();
}
public bool IsCellBuildable(int2 a)
{
if (LocalPlayerBuildings[a] != null) return false;
a += map.Offset;
return map.IsInMap(a.X, a.Y) &&
TerrainCosts.Cost(UnitMovementType.Wheel,
terrain.tileSet.GetWalkability(map.MapTiles[a.X, a.Y])) < double.PositiveInfinity;
}
public IEnumerable<Actor> FindUnits(float2 a, float2 b)
{
var min = float2.Min(a, b);
var max = float2.Max(a, b);
var rect = new RectangleF(min.X, min.Y, max.X - min.X, max.Y - min.Y);
return world.Actors
.Where(x => (x.Owner == LocalPlayer) && (x.Bounds.IntersectsWith(rect)));
}
public bool IsCellBuildable(int2 a)
{
if (LocalPlayerBuildings[a] != null) return false;
a += map.Offset;
return map.IsInMap(a.X, a.Y) &&
TerrainCosts.Cost(UnitMovementType.Wheel,
terrain.tileSet.GetWalkability(map.MapTiles[a.X, a.Y])) < double.PositiveInfinity;
}
public IEnumerable<Actor> FindUnits(float2 a, float2 b)
{
var min = float2.Min(a, b);
var max = float2.Max(a, b);
var rect = new RectangleF(min.X, min.Y, max.X - min.X, max.Y - min.Y);
return world.Actors
.Where(x => (x.Owner == LocalPlayer) && (x.Bounds.IntersectsWith(rect)));
}
}
}

View File

@@ -57,10 +57,10 @@ using System.Runtime.InteropServices;
game.world.Add( new Actor( "mcv", new int2( 5, 5 ), game.players[ 3 ]) );
game.world.Add( new Actor( "mcv", new int2( 7, 5 ), game.players[ 2 ] ) );
game.world.Add( new Actor( "mcv", new int2( 9, 5 ), game.players[ 0 ] ) );
game.world.Add( new Actor( "mcv", new int2( 9, 5 ), game.players[ 0 ] ) );
var jeep = new Actor( "jeep", new int2( 9, 7 ), game.players[ 1 ] );
game.world.Add( jeep );
var tank = new Actor( "3tnk", new int2( 12, 7 ), game.players[ 1 ] );
game.world.Add( jeep );
var tank = new Actor( "3tnk", new int2( 12, 7 ), game.players[ 1 ] );
game.world.Add( tank );
tank.traits.Get<Traits.AttackTurreted>().target = jeep;
@@ -68,8 +68,8 @@ using System.Runtime.InteropServices;
renderer.BuildPalette(game.map);
ShowCursor(false);
ShowCursor(false);
game.world.ResetTimer();
}

View File

@@ -21,27 +21,29 @@ namespace OpenRa.Game
}
public override void Apply( Game game, bool leftMouseButton )
{
if (leftMouseButton) return;
if (game.LocalPlayer == Unit.Owner)
{
if (leftMouseButton) return;
if (game.LocalPlayer == Unit.Owner)
game.PlaySound("ackno.r00", false);
Unit.traits.Get<Traits.Mobile>().destination = Destination;
var mobile = Unit.traits.Get<Traits.Mobile>();
mobile.destination = Destination;
mobile.desiredFacing = null;
}
}
class DeployMcvOrder : Order
{
Actor Unit;
Actor Unit;
int2 Location;
public DeployMcvOrder( Actor unit, int2 location )
{
Unit = unit;
Unit = unit;
Location = location;
}
public override void Apply( Game game, bool leftMouseButton )
{
{
if (leftMouseButton) return;
Unit.traits.Get<Traits.McvDeploy>().DeployLocation = Location;
var mobile = Unit.traits.Get<Traits.Mobile>();

View File

@@ -140,6 +140,7 @@
<Compile Include="Traits\TraitsInterfaces.cs" />
<Compile Include="Traits\Tree.cs" />
<Compile Include="Traits\Turreted.cs" />
<Compile Include="Traits\Util.cs" />
<Compile Include="UiOverlay.cs" />
<Compile Include="Graphics\UnitSheetBuilder.cs" />
<Compile Include="Graphics\Util.cs" />

View File

@@ -30,7 +30,7 @@ namespace OpenRa.Game.Traits
var mobile = self.traits.Get<Mobile>();
var turreted = self.traits.Get<Turreted>();
turreted.desiredFacing = mobile.GetFacing( target.Location - self.Location );
turreted.desiredFacing = Util.GetFacing( target.CenterLocation - self.CenterLocation, turreted.turretFacing );
if( turreted.desiredFacing != turreted.turretFacing )
return;

View File

@@ -15,6 +15,7 @@ namespace OpenRa.Game.Traits
public Order Order(Actor self, Game game, int2 xy)
{
DeployLocation = null;
// TODO: check that there's enough space at the destination.
if( xy == self.Location )
return new DeployMcvOrder( self, xy );
@@ -24,24 +25,21 @@ namespace OpenRa.Game.Traits
public void Tick(Actor self, Game game, int dt)
{
var mobile = self.traits.Get<Mobile>();
if( self.Location != DeployLocation )
return;
var mobile = self.traits.Get<Mobile>();
mobile.desiredFacing = 96;
if( mobile.moveFraction < mobile.moveFractionTotal )
return;
if( self.Location != DeployLocation )
{
DeployLocation = null;
return;
}
if (mobile.Turn(12))
if( mobile.facing != mobile.desiredFacing )
return;
game.world.AddFrameEndTask(_ =>
{
game.world.Remove(self);
game.world.Add(new Actor("fact", self.Location - new int2(1, 1), self.Owner));
game.world.Remove(self);
game.world.Add(new Actor("fact", self.Location - new int2(1, 1), self.Owner));
});
}
}

View File

@@ -15,6 +15,7 @@ namespace OpenRa.Game.Traits
public int2 toCell { get { return self.Location; } }
public int moveFraction, moveFractionTotal;
public int facing;
public int? desiredFacing;
public Mobile(Actor self)
{
@@ -22,41 +23,6 @@ namespace OpenRa.Game.Traits
fromCell = destination = self.Location;
}
public bool Turn(int desiredFacing)
{
if (facing == desiredFacing)
return false;
int df = (desiredFacing - facing + 32) % 32;
facing = (facing + (df > 16 ? 31 : 1)) % 32;
return true;
}
static float2[] fvecs = Util.MakeArray<float2>(32,
i => -float2.FromAngle(i / 16.0f * (float)Math.PI) * new float2(1f, 1.3f));
// TODO: move this somewhere more appropriate, now that AttackTurreted uses it.
public int GetFacing(float2 d)
{
if (float2.WithinEpsilon(d, float2.Zero, 0.001f))
return facing;
int highest = -1;
float highestDot = -1.0f;
for (int i = 0; i < fvecs.Length; i++)
{
float dot = float2.Dot(fvecs[i], d);
if (dot > highestDot)
{
highestDot = dot;
highest = i;
}
}
return highest;
}
void UpdateCenterLocation()
{
float fraction = (moveFraction > 0) ? (float)moveFraction / moveFractionTotal : 0f;
@@ -71,13 +37,19 @@ namespace OpenRa.Game.Traits
void Move(Actor self, Game game, int dt)
{
if (fromCell != toCell)
{
if (Turn(GetFacing(toCell - fromCell)))
return;
if( fromCell != toCell )
desiredFacing = Util.GetFacing( toCell - fromCell, facing );
moveFraction += dt * ((UnitInfo.MobileInfo)self.unitInfo).Speed;
if( desiredFacing != null && desiredFacing != facing )
{
Util.TickFacing( ref facing, desiredFacing.Value, self.unitInfo.ROT );
return;
}
desiredFacing = null;
if( fromCell != toCell )
moveFraction += dt * ((UnitInfo.MobileInfo)self.unitInfo).Speed;
if (moveFraction < moveFractionTotal)
return;

View File

@@ -10,8 +10,8 @@ namespace OpenRa.Game.Traits
public RenderBuildingTurreted(Actor self)
: base(self)
{
anim.PlayThen("make", () => anim.PlayFetchIndex("idle",
() => self.traits.Get<Turreted>().turretFacing));
anim.PlayThen( "make", () => anim.PlayFetchIndex( "idle",
() => self.traits.Get<Turreted>().turretFacing / 8 ) );
}
}
}

View File

@@ -12,7 +12,7 @@ namespace OpenRa.Game.Traits
public RenderUnit(Actor self)
: base(self)
{
anim.PlayFetchIndex("idle", () => self.traits.Get<Mobile>().facing);
anim.PlayFetchIndex("idle", () => self.traits.Get<Mobile>().facing / 8);
}
protected static Pair<Sprite, float2> Centered(Sprite s, float2 location)

View File

@@ -15,7 +15,7 @@ namespace OpenRa.Game.Traits
: base(self)
{
turretAnim = new Animation(self.unitInfo.Name);
turretAnim.PlayFetchIndex("turret", () => self.traits.Get<Turreted>().turretFacing);
turretAnim.PlayFetchIndex("turret", () => self.traits.Get<Turreted>().turretFacing / 8);
}
public override IEnumerable<Pair<Sprite, float2>> Render(Actor self)

View File

@@ -14,21 +14,13 @@ namespace OpenRa.Game.Traits
{
}
public void Tick(Actor self, Game game, int dt)
public void Tick( Actor self, Game game, int dt )
{
// TODO: desiredFacing should follow the base unit's facing only when not in combat.
// also, we want to be able to use this for GUN; avoid referencing Mobile.
var df = desiredFacing ?? self.traits.Get<Mobile>().facing;
if( turretFacing != desiredFacing )
{
var leftTurn = ( 32 + turretFacing - desiredFacing ) % 32;
var rightTurn = ( 32 + desiredFacing - turretFacing ) % 32;
if( leftTurn > rightTurn )
turretFacing = ( turretFacing + 1 ) % 32;
else
turretFacing = ( turretFacing + 31 ) % 32;
}
Util.TickFacing( ref turretFacing, df, self.unitInfo.ROT );
}
}
}

47
OpenRa.Game/Traits/Util.cs Executable file
View File

@@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace OpenRa.Game.Traits
{
static class Util
{
public static void TickFacing( ref int facing, int desiredFacing, int rot )
{
var leftTurn = ( facing - desiredFacing ) & 0xFF;
var rightTurn = ( desiredFacing - facing ) & 0xFF;
if( Math.Min( leftTurn, rightTurn ) < rot )
facing = desiredFacing;
else if( rightTurn < leftTurn )
facing = ( facing + rot ) & 0xFF;
else
facing = ( facing - rot ) & 0xFF;
}
static float2[] fvecs = Graphics.Util.MakeArray<float2>( 32,
i => -float2.FromAngle( i / 16.0f * (float)Math.PI ) * new float2( 1f, 1.3f ) );
public static int GetFacing( float2 d, int currentFacing )
{
if( float2.WithinEpsilon( d, float2.Zero, 0.001f ) )
return currentFacing;
int highest = -1;
float highestDot = -1.0f;
for( int i = 0 ; i < fvecs.Length ; i++ )
{
float dot = float2.Dot( fvecs[ i ], d );
if( dot > highestDot )
{
highestDot = dot;
highest = i;
}
}
return highest * 8;
}
}
}

View File

@@ -25,11 +25,11 @@ namespace OpenRa.Game
public void AddFrameEndTask( Action<World> a ) { frameEndActions.Add( a ); }
public event Action<Actor> ActorAdded = _ => { };
public event Action<Actor> ActorRemoved = _ => { };
public void ResetTimer()
{
lastTime = Environment.TickCount;
public event Action<Actor> ActorRemoved = _ => { };
public void ResetTimer()
{
lastTime = Environment.TickCount;
}
public void Update()