z offsets

This commit is contained in:
Chris Forbes
2009-12-22 19:13:30 +13:00
parent 3c1ead59fd
commit 3bc97ac0b9
21 changed files with 134 additions and 83 deletions

View File

@@ -65,13 +65,13 @@ namespace OpenRa.Game
get get
{ {
var firstSprite = Render().FirstOrDefault(); var firstSprite = Render().FirstOrDefault();
if( firstSprite == null ) if( firstSprite.Sprite == null )
return new float2( 0, 0 ); return new float2( 0, 0 );
return firstSprite.a.size; return firstSprite.Sprite.size;
} }
} }
public IEnumerable<Tuple<Sprite, float2, int>> Render() public IEnumerable<Renderable> Render()
{ {
var mods = traits.WithInterface<IRenderModifier>(); var mods = traits.WithInterface<IRenderModifier>();
var sprites = traits.WithInterface<IRender>().SelectMany(x => x.Render(this)); var sprites = traits.WithInterface<IRender>().SelectMany(x => x.Render(this));

View File

@@ -1,6 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using OpenRa.Game.GameRules; using OpenRa.Game.GameRules;
using OpenRa.Game.Graphics; using OpenRa.Game.Graphics;
using OpenRa.Game.Traits;
namespace OpenRa.Game.Effects namespace OpenRa.Game.Effects
{ {
@@ -60,7 +61,7 @@ namespace OpenRa.Game.Effects
const float height = .1f; const float height = .1f;
public IEnumerable<Tuple<Sprite, float2, int>> Render() public IEnumerable<Renderable> Render()
{ {
if (anim != null) if (anim != null)
{ {
@@ -72,15 +73,15 @@ namespace OpenRa.Game.Effects
if (Projectile.High || Projectile.Arcing) if (Projectile.High || Projectile.Arcing)
{ {
if (Projectile.Shadow) if (Projectile.Shadow)
yield return Tuple.New(anim.Image, pos, 8); yield return new Renderable(anim.Image, pos, 8);
var at = (float)t / TotalTime(); var at = (float)t / TotalTime();
var highPos = pos - new float2(0, (VisualDest - Src).Length * height * 4 * at * (1 - at)); var highPos = pos - new float2(0, (VisualDest - Src).Length * height * 4 * at * (1 - at));
yield return Tuple.New(anim.Image, highPos, Owner.Palette); yield return new Renderable(anim.Image, highPos, Owner.Palette);
} }
else else
yield return Tuple.New(anim.Image, pos, Projectile.UnderWater ? 8 : Owner.Palette); yield return new Renderable(anim.Image, pos, Projectile.UnderWater ? 8 : Owner.Palette);
} }
} }
} }

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using OpenRa.Game.Graphics; using OpenRa.Game.Graphics;
using OpenRa.Game.Traits;
namespace OpenRa.Game.Effects namespace OpenRa.Game.Effects
{ {
@@ -24,9 +25,9 @@ namespace OpenRa.Game.Effects
public void Tick() { anim.Tick(); } public void Tick() { anim.Tick(); }
public IEnumerable<Tuple<Sprite, float2, int>> Render() public IEnumerable<Renderable> Render()
{ {
yield return Tuple.New(anim.Image, pos - .5f * anim.Image.size, owner.Palette); yield return new Renderable(anim.Image, pos - .5f * anim.Image.size, owner.Palette);
} }
} }
} }

View File

@@ -1,5 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using OpenRa.Game.Graphics; using OpenRa.Game.Graphics;
using OpenRa.Game.Traits;
namespace OpenRa.Game.Effects namespace OpenRa.Game.Effects
{ {
@@ -19,9 +20,9 @@ namespace OpenRa.Game.Effects
public void Tick() { anim.Tick(); } public void Tick() { anim.Tick(); }
public IEnumerable<Tuple<Sprite, float2, int>> Render() public IEnumerable<Renderable> Render()
{ {
yield return Tuple.New(anim.Image, pos.ToFloat2() - 0.5f * anim.Image.size, 0); yield return new Renderable(anim.Image, pos - .5f * anim.Image.size, 0);
} }
public Player Owner { get { return null; } } public Player Owner { get { return null; } }

View File

@@ -1,11 +1,12 @@
using System.Collections.Generic; using System.Collections.Generic;
using OpenRa.Game.Graphics; using OpenRa.Game.Graphics;
using OpenRa.Game.Traits;
namespace OpenRa.Game.Effects namespace OpenRa.Game.Effects
{ {
interface IEffect interface IEffect
{ {
void Tick(); void Tick();
IEnumerable<Tuple<Sprite, float2, int>> Render(); IEnumerable<Renderable> Render();
} }
} }

View File

@@ -1,6 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using OpenRa.Game.GameRules; using OpenRa.Game.GameRules;
using OpenRa.Game.Graphics; using OpenRa.Game.Graphics;
using OpenRa.Game.Traits;
namespace OpenRa.Game.Effects namespace OpenRa.Game.Effects
{ {
@@ -75,9 +76,9 @@ namespace OpenRa.Game.Effects
// todo: turbo boost vs aircraft // todo: turbo boost vs aircraft
} }
public IEnumerable<Tuple<Sprite, float2, int>> Render() public IEnumerable<Renderable> Render()
{ {
yield return Tuple.New(anim.Image, Pos - 0.5f * anim.Image.size, 0); yield return new Renderable(anim.Image, Pos - 0.5f * anim.Image.size, 0);
} }
} }
} }

View File

@@ -1,5 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using OpenRa.Game.Graphics; using OpenRa.Game.Graphics;
using OpenRa.Game.Traits;
namespace OpenRa.Game.Effects namespace OpenRa.Game.Effects
{ {
@@ -20,9 +21,9 @@ namespace OpenRa.Game.Effects
anim.Tick(); anim.Tick();
} }
public IEnumerable<Tuple<Sprite, float2, int>> Render() public IEnumerable<Renderable> Render()
{ {
yield return Tuple.New(anim.Image, pos.ToFloat2() - .5f * anim.Image.size, 0); yield return new Renderable(anim.Image, pos - .5f * anim.Image.size, 0);
} }
} }
} }

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using OpenRa.Game.Graphics; using OpenRa.Game.Graphics;
using OpenRa.Game.Traits;
namespace OpenRa.Game.Effects namespace OpenRa.Game.Effects
{ {
@@ -26,7 +27,7 @@ namespace OpenRa.Game.Effects
--timeUntilRemove; --timeUntilRemove;
} }
public IEnumerable<Tuple<Sprite, float2, int>> Render() public IEnumerable<Renderable> Render()
{ {
if( from.X < to.X ) if( from.X < to.X )
return DrawZap( from, to, tesla ); return DrawZap( from, to, tesla );
@@ -36,7 +37,7 @@ namespace OpenRa.Game.Effects
return DrawZap( from, to, tesla ); return DrawZap( from, to, tesla );
} }
static IEnumerable<Tuple<Sprite, float2, int>> DrawZap( int2 from, int2 to, Sequence tesla ) static IEnumerable<Renderable> DrawZap( int2 from, int2 to, Sequence tesla )
{ {
int2 d = to - from; int2 d = to - from;
if( d.X < 8 ) if( d.X < 8 )
@@ -45,7 +46,7 @@ namespace OpenRa.Game.Effects
var y = d.Y; var y = d.Y;
while( y >= prev.Y + 8 ) while( y >= prev.Y + 8 )
{ {
yield return Tuple.New( tesla.GetSprite( 2 ), (float2)( from + prev - new int2( 0, 8 ) ), 0 ); yield return new Renderable( tesla.GetSprite( 2 ), (float2)( from + prev - new int2( 0, 8 ) ), 0 );
prev.Y += 8; prev.Y += 8;
} }
} }
@@ -57,26 +58,26 @@ namespace OpenRa.Game.Effects
var y = i * d.Y / d.X; var y = i * d.Y / d.X;
if( y <= prev.Y - 8 ) if( y <= prev.Y - 8 )
{ {
yield return Tuple.New( tesla.GetSprite( 3 ), (float2)( from + prev - new int2( 8, 16 ) ), 0 ); yield return new Renderable(tesla.GetSprite(3), (float2)(from + prev - new int2(8, 16)), 0);
prev.Y -= 8; prev.Y -= 8;
while( y <= prev.Y - 8 ) while( y <= prev.Y - 8 )
{ {
yield return Tuple.New( tesla.GetSprite( 2 ), (float2)( from + prev - new int2( 0, 16 ) ), 0 ); yield return new Renderable(tesla.GetSprite(2), (float2)(from + prev - new int2(0, 16)), 0);
prev.Y -= 8; prev.Y -= 8;
} }
} }
else if( y >= prev.Y + 8 ) else if( y >= prev.Y + 8 )
{ {
yield return Tuple.New( tesla.GetSprite( 0 ), (float2)( from + prev - new int2( 8, 8 ) ), 0 ); yield return new Renderable(tesla.GetSprite(0), (float2)(from + prev - new int2(8, 8)), 0);
prev.Y += 8; prev.Y += 8;
while( y >= prev.Y + 8 ) while( y >= prev.Y + 8 )
{ {
yield return Tuple.New( tesla.GetSprite( 2 ), (float2)( from + prev - new int2( 0, 8 ) ), 0 ); yield return new Renderable(tesla.GetSprite(2), (float2)(from + prev - new int2(0, 8)), 0);
prev.Y += 8; prev.Y += 8;
} }
} }
else else
yield return Tuple.New( tesla.GetSprite( 1 ), (float2)( from + prev - new int2( 8, 8 ) ), 0 ); yield return new Renderable(tesla.GetSprite(1), (float2)(from + prev - new int2(8, 8)), 0);
prev.X += 8; prev.X += 8;
} }

View File

@@ -31,18 +31,30 @@ namespace OpenRa.Game.Graphics
} }
void DrawSpriteList(RectangleF rect, void DrawSpriteList(RectangleF rect,
IEnumerable<Tuple<Sprite, float2, int>> images) IEnumerable<Renderable> images)
{ {
foreach (var image in images) foreach (var image in images)
{ {
var loc = image.b; var loc = image.Pos;
if (loc.X > rect.Right || loc.X < rect.Left - image.a.bounds.Width) if (loc.X > rect.Right || loc.X < rect.Left - image.Sprite.bounds.Width)
continue; continue;
if (loc.Y > rect.Bottom || loc.Y < rect.Top - image.a.bounds.Height) if (loc.Y > rect.Bottom || loc.Y < rect.Top - image.Sprite.bounds.Height)
continue; continue;
spriteRenderer.DrawSprite(image.a, loc, image.c); spriteRenderer.DrawSprite(image.Sprite, loc, image.Palette);
}
}
class SpriteComparer : IComparer<Renderable>
{
public int Compare(Renderable x, Renderable y)
{
var result = x.ZOffset.CompareTo(y.ZOffset);
if (result == 0)
result = x.Pos.Y.CompareTo(y.Pos.Y);
return result;
} }
} }
@@ -50,17 +62,18 @@ namespace OpenRa.Game.Graphics
{ {
terrainRenderer.Draw(Game.viewport); terrainRenderer.Draw(Game.viewport);
var comparer = new SpriteComparer();
var rect = new RectangleF( var rect = new RectangleF(
Game.viewport.Location.ToPointF(), Game.viewport.Location.ToPointF(),
new SizeF( Game.viewport.Width, Game.viewport.Height )); new SizeF( Game.viewport.Width, Game.viewport.Height ));
foreach (Actor a in Game.world.Actors.OrderBy(u => u.CenterLocation.Y)) /* todo: cull to screen again */
DrawSpriteList(rect, a.Render()); var renderables = Game.world.Actors.SelectMany(a => a.Render())
.OrderBy(r => r, comparer);
foreach (var a in Game.world.Actors foreach (var r in renderables)
.Where(u => u.traits.Contains<Traits.RenderWarFactory>()) spriteRenderer.DrawSprite(r.Sprite, r.Pos, r.Palette);
.Select(u => u.traits.Get<Traits.RenderWarFactory>()))
DrawSpriteList(rect, a.RenderRoof(a.self));
foreach (var e in Game.world.Effects) foreach (var e in Game.world.Effects)
DrawSpriteList(rect, e.Render()); DrawSpriteList(rect, e.Render());

View File

@@ -164,6 +164,7 @@
<Compile Include="Traits\AttackInfo.cs" /> <Compile Include="Traits\AttackInfo.cs" />
<Compile Include="Traits\AttackTurreted.cs" /> <Compile Include="Traits\AttackTurreted.cs" />
<Compile Include="Traits\AutoTarget.cs" /> <Compile Include="Traits\AutoTarget.cs" />
<Compile Include="Traits\BelowUnits.cs" />
<Compile Include="Traits\Building.cs" /> <Compile Include="Traits\Building.cs" />
<Compile Include="Traits\Explodes.cs" /> <Compile Include="Traits\Explodes.cs" />
<Compile Include="Traits\ChronoshiftDeploy.cs" /> <Compile Include="Traits\ChronoshiftDeploy.cs" />

View File

@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace OpenRa.Game.Traits
{
class BelowUnits : IRenderModifier
{
public BelowUnits(Actor self) { }
public IEnumerable<Renderable> ModifyRender(Actor self, IEnumerable<Renderable> r)
{
return r.Select(a => a.WithZOffset(-1));
}
}
}

View File

@@ -18,16 +18,16 @@ namespace OpenRa.Game.Traits
remainingUncloakTime = (int)(Rules.General.SubmergeDelay * 60 * 25); remainingUncloakTime = (int)(Rules.General.SubmergeDelay * 60 * 25);
} }
public IEnumerable<Tuple<Sprite, float2, int>> public IEnumerable<Renderable>
ModifyRender(Actor self, IEnumerable<Tuple<Sprite, float2, int>> rs) ModifyRender(Actor self, IEnumerable<Renderable> rs)
{ {
if (remainingUncloakTime > 0) if (remainingUncloakTime > 0)
return rs; return rs;
if (self.Owner == Game.LocalPlayer) if (self.Owner == Game.LocalPlayer)
return rs.Select(a => Tuple.New(a.a, a.b, 8)); return rs.Select(a => a.WithPalette(8));
else else
return new Tuple<Sprite, float2, int>[] { }; return new Renderable[] { };
} }
public void Tick(Actor self) public void Tick(Actor self)

View File

@@ -16,7 +16,7 @@ namespace OpenRa.Game.Traits
anim.PlayRepeating("idle"); anim.PlayRepeating("idle");
} }
public IEnumerable<Tuple<Sprite, float2, int>> Render(Actor self) public IEnumerable<Renderable> Render(Actor self)
{ {
var uog = Game.controller.orderGenerator as UnitOrderGenerator; var uog = Game.controller.orderGenerator as UnitOrderGenerator;
if (uog != null && self.Owner == Game.LocalPlayer && uog.selection.Contains(self)) if (uog != null && self.Owner == Game.LocalPlayer && uog.selection.Contains(self))

View File

@@ -3,7 +3,7 @@ using OpenRa.Game.Graphics;
namespace OpenRa.Game.Traits namespace OpenRa.Game.Traits
{ {
class RenderWarFactory : RenderBuilding, INotifyBuildComplete class RenderWarFactory : IRender, INotifyBuildComplete, INotifyDamage, ITick
{ {
public Animation roof; public Animation roof;
bool doneBuilding; bool doneBuilding;
@@ -12,7 +12,6 @@ namespace OpenRa.Game.Traits
string prefix = ""; string prefix = "";
public RenderWarFactory(Actor self) public RenderWarFactory(Actor self)
: base(self)
{ {
this.self = self; this.self = self;
roof = new Animation(self.Info.Image ?? self.Info.Name); roof = new Animation(self.Info.Image ?? self.Info.Name);
@@ -21,22 +20,19 @@ namespace OpenRa.Game.Traits
public void BuildingComplete( Actor self ) public void BuildingComplete( Actor self )
{ {
doneBuilding = true; doneBuilding = true;
anim.Play( "idle" );
roof.Play( prefix + "idle-top" ); roof.Play( prefix + "idle-top" );
} }
public IEnumerable<Tuple<Sprite, float2, int>> RenderRoof(Actor self) public IEnumerable<Renderable> Render(Actor self)
{ {
if (doneBuilding) if (doneBuilding)
yield return Tuple.New(roof.Image, yield return new Renderable(roof.Image,
24f * (float2)self.Location, self.Owner.Palette); 24f * (float2)self.Location, self.Owner.Palette, 2);
} }
public override void Tick(Actor self) public void Tick(Actor self)
{ {
base.Tick(self); if (doneBuilding) roof.Tick();
if (doneBuilding)
roof.Tick();
var b = self.Bounds; var b = self.Bounds;
if (isOpen && null == Game.UnitInfluence.GetUnitAt(((1/24f) * self.CenterLocation).ToInt2())) if (isOpen && null == Game.UnitInfluence.GetUnitAt(((1/24f) * self.CenterLocation).ToInt2()))
@@ -51,10 +47,8 @@ namespace OpenRa.Game.Traits
roof.PlayThen(prefix + "build-top", () => isOpen = true); roof.PlayThen(prefix + "build-top", () => isOpen = true);
} }
public override void Damaged(Actor self, AttackInfo e) public void Damaged(Actor self, AttackInfo e)
{ {
base.Damaged(self, e);
if (!e.DamageStateChanged) return; if (!e.DamageStateChanged) return;
switch (e.DamageState) switch (e.DamageState)
{ {

View File

@@ -15,7 +15,7 @@ namespace OpenRa.Game.Traits
anims.Add( "", new Animation( self.Info.Image ?? self.Info.Name ) ); anims.Add( "", new Animation( self.Info.Image ?? self.Info.Name ) );
} }
public virtual IEnumerable<Tuple<Sprite, float2, int>> Render( Actor self ) public virtual IEnumerable<Renderable> Render( Actor self )
{ {
foreach( var a in anims.Values ) foreach( var a in anims.Values )
if( a.DisableFunc == null || !a.DisableFunc() ) if( a.DisableFunc == null || !a.DisableFunc() )
@@ -46,7 +46,7 @@ namespace OpenRa.Game.Traits
this.DisableFunc = d; this.DisableFunc = d;
} }
public Tuple<Sprite, float2, int> Image( Actor self ) public Renderable Image( Actor self )
{ {
if( OffsetFunc != null ) if( OffsetFunc != null )
return Util.Centered( self, Animation.Image, self.CenterLocation + OffsetFunc() ); return Util.Centered( self, Animation.Image, self.CenterLocation + OffsetFunc() );

View File

@@ -21,16 +21,16 @@ namespace OpenRa.Game.Traits
public void Attacking(Actor self) { DoSurface(); } public void Attacking(Actor self) { DoSurface(); }
public void Damaged(Actor self, AttackInfo e) { DoSurface(); } public void Damaged(Actor self, AttackInfo e) { DoSurface(); }
public IEnumerable<Tuple<Sprite, float2, int>> public IEnumerable<Renderable>
ModifyRender(Actor self, IEnumerable<Tuple<Sprite, float2, int>> rs) ModifyRender(Actor self, IEnumerable<Renderable> rs)
{ {
if (remainingSurfaceTime > 0) if (remainingSurfaceTime > 0)
return rs; return rs;
if (self.Owner == Game.LocalPlayer) if (self.Owner == Game.LocalPlayer)
return rs.Select(a => Tuple.New(a.a, a.b, 8)); return rs.Select(a => a.WithPalette(8));
else else
return new Tuple<Sprite, float2, int>[] { }; return new Renderable[] { };
} }
public void Tick(Actor self) public void Tick(Actor self)

View File

@@ -10,9 +10,32 @@ namespace OpenRa.Game.Traits
// depends on the order of pips in WorldRenderer.cs! // depends on the order of pips in WorldRenderer.cs!
enum PipType { Transparent, Green, Yellow, Red, Gray }; enum PipType { Transparent, Green, Yellow, Red, Gray };
enum TagType { None, Fake, Primary }; enum TagType { None, Fake, Primary };
struct Renderable
{
public readonly Sprite Sprite;
public readonly float2 Pos;
public readonly int Palette;
public readonly int ZOffset;
public Renderable(Sprite sprite, float2 pos, int palette, int zOffset)
{
Sprite = sprite;
Pos = pos;
Palette = palette;
ZOffset = zOffset;
}
public Renderable(Sprite sprite, float2 pos, int palette)
: this(sprite, pos, palette, 0) { }
public Renderable WithPalette(int newPalette) { return new Renderable(Sprite, Pos, newPalette, ZOffset); }
public Renderable WithZOffset(int newOffset) { return new Renderable(Sprite, Pos, Palette, newOffset); }
public Renderable WithPos(float2 newPos) { return new Renderable(Sprite, newPos, Palette, ZOffset); }
}
interface ITick { void Tick(Actor self); } interface ITick { void Tick(Actor self); }
interface IRender { IEnumerable<Tuple<Sprite, float2, int>> Render(Actor self); } interface IRender { IEnumerable<Renderable> Render(Actor self); }
interface INotifyDamage { void Damaged(Actor self, AttackInfo e); } interface INotifyDamage { void Damaged(Actor self, AttackInfo e); }
interface INotifyBuildComplete { void BuildingComplete (Actor self); } interface INotifyBuildComplete { void BuildingComplete (Actor self); }
interface IOrder interface IOrder
@@ -23,8 +46,7 @@ namespace OpenRa.Game.Traits
interface IProducer { bool Produce( Actor self, UnitInfo producee ); } interface IProducer { bool Produce( Actor self, UnitInfo producee ); }
interface IOccupySpace { IEnumerable<int2> OccupiedCells(); } interface IOccupySpace { IEnumerable<int2> OccupiedCells(); }
interface INotifyAttack { void Attacking(Actor self); } interface INotifyAttack { void Attacking(Actor self); }
interface IRenderModifier { IEnumerable<Tuple<Sprite, float2, int>> interface IRenderModifier { IEnumerable<Renderable> ModifyRender(Actor self, IEnumerable<Renderable> r); }
ModifyRender( Actor self, IEnumerable<Tuple<Sprite, float2, int>> r ); }
interface IDamageModifier { float GetDamageModifier(); } interface IDamageModifier { float GetDamageModifier(); }
interface ISpeedModifier { float GetSpeedModifier(); } interface ISpeedModifier { float GetSpeedModifier(); }
interface IPips { IEnumerable<PipType> GetPips(); } interface IPips { IEnumerable<PipType> GetPips(); }

View File

@@ -12,9 +12,9 @@ namespace OpenRa.Game.Traits
Image = treeImage; Image = treeImage;
} }
public IEnumerable<Tuple<Sprite, float2, int>> Render(Actor self) public IEnumerable<Renderable> Render(Actor self)
{ {
yield return Tuple.New(Image, Game.CellSize * (float2)self.Location, 0); yield return new Renderable(Image, Game.CellSize * (float2)self.Location, 0);
} }
} }
} }

View File

@@ -117,17 +117,11 @@ namespace OpenRa.Game.Traits
public static float2 RelOffset(this int[] offset) { return new float2(offset[0], offset[1]); } public static float2 RelOffset(this int[] offset) { return new float2(offset[0], offset[1]); }
public static float2 AbsOffset(this int[] offset) { return new float2(offset.ElementAtOrDefault(2), offset.ElementAtOrDefault(3)); } public static float2 AbsOffset(this int[] offset) { return new float2(offset.ElementAtOrDefault(2), offset.ElementAtOrDefault(3)); }
public static Tuple<Sprite, float2, int> Centered(Actor self, Sprite s, float2 location) public static Renderable Centered(Actor self, Sprite s, float2 location)
{ {
var pal = self.Owner == null ? 0 : self.Owner.Palette; var pal = self.Owner == null ? 0 : self.Owner.Palette;
var loc = location - 0.5f * s.size; var loc = location - 0.5f * s.size;
return Tuple.New(s, loc.Round(), pal); return new Renderable(s, loc.Round(), pal);
}
public static Tuple<Sprite, float2, int> CenteredShadow(Actor self, Sprite s, float2 location)
{
var loc = location - 0.5f * s.size;
return Tuple.New(s, loc.Round(), 8);
} }
public static float GetEffectiveSpeed(Actor self) public static float GetEffectiveSpeed(Actor self)

View File

@@ -10,11 +10,14 @@ namespace OpenRa.Game.Traits
{ {
public WithShadow(Actor self) {} public WithShadow(Actor self) {}
public IEnumerable<Tuple<Sprite, float2, int>> ModifyRender(Actor self, IEnumerable<Tuple<Sprite, float2, int>> r) public IEnumerable<Renderable> ModifyRender(Actor self, IEnumerable<Renderable> r)
{ {
var unit = self.traits.Get<Unit>(); var unit = self.traits.Get<Unit>();
var shadowSprites = r.Select( a => Tuple.New( a.a, a.b, 8 ));
var flyingSprites = r.Select( a => Tuple.New( a.a, a.b - new float2( 0, unit.Altitude ), a.c )); var shadowSprites = r.Select(a => a.WithPalette(8));
var flyingSprites = (unit.Altitude <= 0) ? r
: r.Select(a => a.WithPos(a.Pos - new float2(0, unit.Altitude)).WithZOffset(3));
return shadowSprites.Concat(flyingSprites); return shadowSprites.Concat(flyingSprites);
} }
} }

View File

@@ -331,7 +331,7 @@ SelectionPriority=3
LongDesc=Provides Allied advanced technologies.\n Special Ability: GPS Satellite LongDesc=Provides Allied advanced technologies.\n Special Ability: GPS Satellite
[WEAP] [WEAP]
Description=War Factory Description=War Factory
Traits=Building, RenderWarFactory, RallyPoint, Production Traits=Building, RenderBuilding, RenderWarFactory, RallyPoint, Production
Dimensions=3,2 Dimensions=3,2
Footprint=xxx xxx Footprint=xxx xxx
Produces=Vehicle Produces=Vehicle
@@ -381,12 +381,12 @@ LongDesc=Stores excess harvested Ore
[HPAD] [HPAD]
Description=Helipad Description=Helipad
Traits=Building, RenderBuilding, Production Traits=Building, RenderBuilding, Production, BelowUnits
Dimensions=2,2 Dimensions=2,2
Footprint=xx xx Footprint=xx xx
Produces=Plane Produces=Plane
SelectionPriority=3 SelectionPriority=3
SpawnOffset=0,0 ; todo: push this up a bit, but we've got a z-order issue first. SpawnOffset=0,-4 ; todo: push this up a bit, but we've got a z-order issue first.
LongDesc=Produces and reloads helicopters LongDesc=Produces and reloads helicopters
[DOME] [DOME]
Description=Radar Dome Description=Radar Dome
@@ -397,7 +397,7 @@ SelectionPriority=3
LongDesc=Provides an overview of the battlefield.\n Requires power to operate. LongDesc=Provides an overview of the battlefield.\n Requires power to operate.
[AFLD] [AFLD]
Description=Airstrip Description=Airstrip
Traits=Building, RenderBuilding, Production Traits=Building, RenderBuilding, Production, BelowUnits
Dimensions=3,2 Dimensions=3,2
Footprint=xxx xxx Footprint=xxx xxx
Produces=Plane Produces=Plane
@@ -452,7 +452,7 @@ SelectionPriority=3
LongDesc=Produces attack dogs LongDesc=Produces attack dogs
[FIX] [FIX]
Description=Service Depot Description=Service Depot
Traits=Building, RenderBuilding Traits=Building, RenderBuilding, BelowUnits
Dimensions=3,3 Dimensions=3,3
Footprint=_x_ xxx _x_ Footprint=_x_ xxx _x_
SelectionPriority=3 SelectionPriority=3
@@ -466,7 +466,7 @@ SelectionPriority=3
LongDesc=Looks like a Construction Yard. LongDesc=Looks like a Construction Yard.
[WEAF] [WEAF]
Description=Fake War Factory Description=Fake War Factory
Traits=Building, RenderWarFactory, Fake Traits=Building, RenderBuilding, RenderWarFactory, Fake
Dimensions=3,2 Dimensions=3,2
Footprint=xxx xxx Footprint=xxx xxx
SelectionPriority=3 SelectionPriority=3