diff --git a/OpenRa.Game/Graphics/Animation.cs b/OpenRa.Game/Graphics/Animation.cs index ebda4b49e0..6620a80674 100644 --- a/OpenRa.Game/Graphics/Animation.cs +++ b/OpenRa.Game/Graphics/Animation.cs @@ -13,6 +13,7 @@ namespace OpenRa.Game.Graphics public Animation( string name ) { this.name = name.ToLowerInvariant(); + tickFunc = () => { }; } public Sprite Image diff --git a/OpenRa.Game/Traits/Activities/Move.cs b/OpenRa.Game/Traits/Activities/Move.cs index c63702b180..ef078d05fb 100755 --- a/OpenRa.Game/Traits/Activities/Move.cs +++ b/OpenRa.Game/Traits/Activities/Move.cs @@ -169,6 +169,8 @@ namespace OpenRa.Game.Traits.Activities var oldTotal = moveFractionTotal; moveFraction += (int)Util.GetEffectiveSpeed(self); + if( moveFraction >= moveFractionTotal ) + moveFraction = moveFractionTotal; UpdateCenterLocation( self, mobile ); if( moveFraction >= moveFractionTotal ) { diff --git a/OpenRa.Game/Traits/RenderBuilding.cs b/OpenRa.Game/Traits/RenderBuilding.cs index f580d9fcce..b2b7a4c3d2 100644 --- a/OpenRa.Game/Traits/RenderBuilding.cs +++ b/OpenRa.Game/Traits/RenderBuilding.cs @@ -13,27 +13,19 @@ namespace OpenRa.Game.Traits public RenderBuilding(Actor self) : base(self) { - Make(() => - { - anim.PlayRepeating("idle"); - }, self); + if( Game.skipMakeAnims ) + Complete( self ); + else + anim.PlayThen( "make", () => Complete( self ) ); DoBib(self, false); } - protected void Make( Action after, Actor self ) + void Complete( Actor self ) { - Action newAfter = () => - { - after(); - foreach (var x in self.traits.WithInterface()) - x.BuildingComplete(self); - }; - - if (Game.skipMakeAnims) - newAfter(); - else - anim.PlayThen("make", newAfter); + anim.PlayRepeating( "idle" ); + foreach( var x in self.traits.WithInterface() ) + x.BuildingComplete( self ); } void DoBib(Actor self, bool isRemove) diff --git a/OpenRa.Game/Traits/RenderBuildingOre.cs b/OpenRa.Game/Traits/RenderBuildingOre.cs index 5b09c558b6..015db7721e 100644 --- a/OpenRa.Game/Traits/RenderBuildingOre.cs +++ b/OpenRa.Game/Traits/RenderBuildingOre.cs @@ -1,13 +1,17 @@ - +using System; + namespace OpenRa.Game.Traits { - class RenderBuildingOre : RenderBuilding + class RenderBuildingOre : RenderBuilding, INotifyBuildComplete { public RenderBuildingOre(Actor self) : base(self) { - Make( () => anim.PlayFetchIndex("idle", - () => (int)(4.9 * self.Owner.GetSiloFullness())), self); /* hack */ + } + + public void BuildingComplete( Actor self ) + { + anim.PlayFetchIndex( "idle", () => (int)( 4.9 * self.Owner.GetSiloFullness() ) ); } } } diff --git a/OpenRa.Game/Traits/RenderBuildingTurreted.cs b/OpenRa.Game/Traits/RenderBuildingTurreted.cs index 61819c3dec..628377efd2 100644 --- a/OpenRa.Game/Traits/RenderBuildingTurreted.cs +++ b/OpenRa.Game/Traits/RenderBuildingTurreted.cs @@ -1,17 +1,21 @@  namespace OpenRa.Game.Traits { - class RenderBuildingTurreted : RenderBuilding + class RenderBuildingTurreted : RenderBuilding, INotifyBuildComplete { public RenderBuildingTurreted(Actor self) : base(self) { - Make( () => PlayTurretAnim( self, "idle" ), self); } - void PlayTurretAnim(Actor self, string a) + public void BuildingComplete( Actor self ) { - anim.PlayFacing(a, () => self.traits.Get().turretFacing); + PlayTurretAnim( self, "idle" ); + } + + void PlayTurretAnim( Actor self, string a ) + { + anim.PlayFacing( a, () => self.traits.Get().turretFacing ); } public override void Damaged(Actor self, AttackInfo e) diff --git a/OpenRa.Game/Traits/RenderBuildingWarFactory.cs b/OpenRa.Game/Traits/RenderBuildingWarFactory.cs index 03b88929c2..55165c9e58 100644 --- a/OpenRa.Game/Traits/RenderBuildingWarFactory.cs +++ b/OpenRa.Game/Traits/RenderBuildingWarFactory.cs @@ -3,7 +3,7 @@ using OpenRa.Game.Graphics; namespace OpenRa.Game.Traits { - class RenderWarFactory : RenderBuilding + class RenderWarFactory : RenderBuilding, INotifyBuildComplete { public Animation roof; bool doneBuilding; @@ -15,14 +15,14 @@ namespace OpenRa.Game.Traits : base(self) { this.self = self; - roof = new Animation(self.Info.Image ?? self.Info.Name); - Make( () => - { - doneBuilding = true; - anim.Play("idle"); - roof.Play(prefix + "idle-top"); - }, self); + } + + public void BuildingComplete( Actor self ) + { + doneBuilding = true; + anim.Play( "idle" ); + roof.Play( prefix + "idle-top" ); } public IEnumerable> RenderRoof(Actor self) diff --git a/OpenRa.Game/Traits/RenderSimple.cs b/OpenRa.Game/Traits/RenderSimple.cs index dc82273fd6..a1648404cd 100644 --- a/OpenRa.Game/Traits/RenderSimple.cs +++ b/OpenRa.Game/Traits/RenderSimple.cs @@ -1,22 +1,63 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using IjwFramework.Collections; using OpenRa.Game.Graphics; namespace OpenRa.Game.Traits { abstract class RenderSimple : IRender, ITick { - public Animation anim; + public Dictionary anims = new Dictionary(); + public Animation anim { get { return anims[ "" ].Animation; } } public RenderSimple(Actor self) { - anim = new Animation(self.Info.Image ?? self.Info.Name); + anims.Add( "", new Animation( self.Info.Image ?? self.Info.Name ) ); } - public abstract IEnumerable> Render(Actor self); + public virtual IEnumerable> Render( Actor self ) + { + foreach( var a in anims.Values ) + if( a.DisableFunc == null || !a.DisableFunc() ) + yield return a.Image( self ); + } public virtual void Tick(Actor self) { - anim.Tick(); + foreach( var a in anims.Values ) + a.Animation.Tick(); + } + + public class AnimationWithOffset + { + public Animation Animation; + public Func OffsetFunc; + public Func DisableFunc; + + public AnimationWithOffset( Animation a ) + : this( a, null, null ) + { + } + + public AnimationWithOffset( Animation a, Func o, Func d ) + { + this.Animation = a; + this.OffsetFunc = o; + this.DisableFunc = d; + } + + public Tuple Image( Actor self ) + { + if( OffsetFunc != null ) + return Util.Centered( self, Animation.Image, self.CenterLocation + OffsetFunc() ); + else + return Util.Centered( self, Animation.Image, self.CenterLocation ); + } + + public static implicit operator AnimationWithOffset( Animation a ) + { + return new AnimationWithOffset( a ); + } } } } diff --git a/OpenRa.Game/Traits/RenderUnit.cs b/OpenRa.Game/Traits/RenderUnit.cs index 5d6522a651..9d293d8340 100644 --- a/OpenRa.Game/Traits/RenderUnit.cs +++ b/OpenRa.Game/Traits/RenderUnit.cs @@ -11,7 +11,8 @@ namespace OpenRa.Game.Traits : base(self) { PlayFacingAnim(self); - smoke = new Animation("smoke_m"); + + anims.Add( "smoke", new AnimationWithOffset( new Animation( "smoke_m" ), null, () => !isSmoking ) ); } void PlayFacingAnim(Actor self) @@ -25,15 +26,7 @@ namespace OpenRa.Game.Traits anim.PlayThen(newAnim, () => { PlayFacingAnim(self); if (after != null) after(); }); } - public override IEnumerable> Render(Actor self) - { - yield return Util.Centered(self, anim.Image, self.CenterLocation); - if (isSmoking) - yield return Util.Centered(self, smoke.Image, self.CenterLocation); - } - bool isSmoking; - Animation smoke; public void Damaged(Actor self, AttackInfo e) { @@ -41,17 +34,11 @@ namespace OpenRa.Game.Traits if (isSmoking) return; isSmoking = true; - smoke.PlayThen("idle", - () => smoke.PlayThen("loop", - () => smoke.PlayBackwardsThen("end", - () => isSmoking = false))); - } - - public override void Tick(Actor self) - { - base.Tick(self); - if (isSmoking) - smoke.Tick(); + var smoke = anims[ "smoke" ].Animation; + smoke.PlayThen( "idle", + () => smoke.PlayThen( "loop", + () => smoke.PlayBackwardsThen( "end", + () => isSmoking = false ) ) ); } } } diff --git a/OpenRa.Game/Traits/RenderUnitTurreted.cs b/OpenRa.Game/Traits/RenderUnitTurreted.cs index ba3f01c5e9..c06614f4bd 100644 --- a/OpenRa.Game/Traits/RenderUnitTurreted.cs +++ b/OpenRa.Game/Traits/RenderUnitTurreted.cs @@ -6,51 +6,41 @@ namespace OpenRa.Game.Traits { class RenderUnitTurreted : RenderUnit { - public Animation turretAnim; public Animation muzzleFlash; public RenderUnitTurreted(Actor self) : base(self) - { - self.traits.Get(); - turretAnim = new Animation(self.Info.Name); - - if (self.Info.MuzzleFlash) - { - var attack = self.traits.WithInterface().First(); - muzzleFlash = new Animation(self.Info.Name); - muzzleFlash.PlayFetchIndex("muzzle", - () => (Util.QuantizeFacing(self.traits.Get().turretFacing,8)) * 6 - + (int)(attack.primaryRecoil * 5.9f)); - /* hack: recoil can be 1.0f, but don't overflow into next anim */ - } - - turretAnim.PlayFacing("turret", () => self.traits.Get().turretFacing); - } - - public override IEnumerable> Render(Actor self) { var unit = self.traits.Get(); + var turreted = self.traits.Get(); var attack = self.traits.WithInterface().FirstOrDefault(); - yield return Util.Centered(self, anim.Image, self.CenterLocation); - yield return Util.Centered(self, turretAnim.Image, self.CenterLocation - + Util.GetTurretPosition(self, unit, self.Info.PrimaryOffset, attack.primaryRecoil)); - if (self.Info.SecondaryOffset != null) - yield return Util.Centered(self, turretAnim.Image, self.CenterLocation - + Util.GetTurretPosition(self, unit, self.Info.SecondaryOffset, attack.secondaryRecoil)); + var turretAnim = new Animation(self.Info.Name); + turretAnim.PlayFacing( "turret", () => turreted.turretFacing ); - if (muzzleFlash != null && attack.primaryRecoil > 0) - yield return Util.Centered(self, muzzleFlash.Image, self.CenterLocation - + Util.GetTurretPosition(self, unit, self.Info.PrimaryOffset, attack.primaryRecoil)); - } + if( self.Info.PrimaryOffset != null ) + anims.Add( "turret_1", new AnimationWithOffset( + turretAnim, + () => Util.GetTurretPosition( self, unit, self.Info.PrimaryOffset, attack.primaryRecoil ), + null ) ); - public override void Tick(Actor self) - { - base.Tick(self); - turretAnim.Tick(); - if (muzzleFlash != null) - muzzleFlash.Tick(); + if( self.Info.SecondaryOffset != null ) + anims.Add( "turret_2", new AnimationWithOffset( + turretAnim, + () => Util.GetTurretPosition( self, unit, self.Info.SecondaryOffset, attack.secondaryRecoil ), + null ) ); + + if( self.Info.MuzzleFlash ) + { + muzzleFlash = new Animation( self.Info.Name ); + muzzleFlash.PlayFetchIndex( "muzzle", + () => ( Util.QuantizeFacing( self.traits.Get().turretFacing, 8 ) ) * 6 + + (int)( attack.primaryRecoil * 5.9f ) ); /* hack: recoil can be 1.0f, but don't overflow into next anim */ + anims.Add( "muzzle_flash", new AnimationWithOffset( + muzzleFlash, + () => Util.GetTurretPosition( self, unit, self.Info.PrimaryOffset, attack.primaryRecoil ), + () => attack.primaryRecoil <= 0 ) ); + } } } } diff --git a/OpenRa.Game/Traits/Util.cs b/OpenRa.Game/Traits/Util.cs index e3a77389db..8ec7032803 100755 --- a/OpenRa.Game/Traits/Util.cs +++ b/OpenRa.Game/Traits/Util.cs @@ -86,7 +86,7 @@ namespace OpenRa.Game.Traits if (rut == null) return float2.Zero; var facing = self.traits.Get().turretFacing; - var quantizedFacing = QuantizeFacing(facing, rut.turretAnim.CurrentSequence.Length) * (256 / rut.turretAnim.CurrentSequence.Length); + var quantizedFacing = QuantizeFacing(facing, rut.anim.CurrentSequence.Length) * (256 / rut.anim.CurrentSequence.Length); return RotateVectorByFacing(new float2(0, recoil * self.Info.Recoil), quantizedFacing, .7f); }