changes facing (and desireFacing) on Mobile and on Turreted. range is now 0..255
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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>();
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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 ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
47
OpenRa.Game/Traits/Util.cs
Executable 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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user