From 5ef6d86f6613b4528c5b462a153c2e02a1866391 Mon Sep 17 00:00:00 2001 From: Huw Pascoe Date: Thu, 29 Oct 2015 16:54:52 +0000 Subject: [PATCH] Added HitShapes New IHitShape interface. Added Circle, Capsule and Rectangle shapes. --- OpenRA.Mods.Common/HitShapes/Capsule.cs | 93 ++++++++++++++++++++ OpenRA.Mods.Common/HitShapes/Circle.cs | 46 ++++++++++ OpenRA.Mods.Common/HitShapes/IHitShape.cs | 25 ++++++ OpenRA.Mods.Common/HitShapes/Rectangle.cs | 80 +++++++++++++++++ OpenRA.Mods.Common/OpenRA.Mods.Common.csproj | 4 + 5 files changed, 248 insertions(+) create mode 100644 OpenRA.Mods.Common/HitShapes/Capsule.cs create mode 100644 OpenRA.Mods.Common/HitShapes/Circle.cs create mode 100644 OpenRA.Mods.Common/HitShapes/IHitShape.cs create mode 100644 OpenRA.Mods.Common/HitShapes/Rectangle.cs diff --git a/OpenRA.Mods.Common/HitShapes/Capsule.cs b/OpenRA.Mods.Common/HitShapes/Capsule.cs new file mode 100644 index 0000000000..614ecce97e --- /dev/null +++ b/OpenRA.Mods.Common/HitShapes/Capsule.cs @@ -0,0 +1,93 @@ +#region Copyright & License Information +/* + * Copyright 2007-2015 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation. For more information, + * see COPYING. + */ +#endregion + +using System; +using System.Drawing; +using OpenRA.Graphics; +using OpenRA.Mods.Common.Graphics; + +namespace OpenRA.Mods.Common.HitShapes +{ + public class CapsuleShape : IHitShape + { + public WDist OuterRadius { get; private set; } + + [FieldLoader.Require] + public readonly int2 PointA; + + [FieldLoader.Require] + public readonly int2 PointB; + + public readonly WDist Radius = new WDist(426); + + int2 ab; + int abLenSq; + + public CapsuleShape() { } + + public CapsuleShape(int2 a, int2 b, WDist radius) + { + PointA = a; + PointB = b; + Radius = radius; + } + + public void Initialize() + { + ab = PointB - PointA; + abLenSq = ab.LengthSquared / 1024; + + if (abLenSq == 0) + throw new YamlException("This Capsule describes a circle. Use a Circle HitShape instead."); + + OuterRadius = Radius + new WDist(Math.Max(PointA.Length, PointB.Length)); + } + + public WDist DistanceFromEdge(WVec v) + { + var p = new int2(v.X, v.Y); + + var t = int2.Dot(p - PointA, ab) / abLenSq; + + if (t < 0) + return new WDist(Math.Max(0, (PointA - p).Length - Radius.Length)); + if (t > 1024) + return new WDist(Math.Max(0, (PointB - p).Length - Radius.Length)); + + var projection = PointA + new int2( + (ab.X * t) / 1024, + (ab.Y * t) / 1024); + + var distance = (projection - p).Length; + + return new WDist(Math.Max(0, distance - Radius.Length)); + } + + public WDist DistanceFromEdge(WPos pos, Actor actor) + { + return DistanceFromEdge((pos - actor.CenterPosition).Rotate(-actor.Orientation)); + } + + public void DrawCombatOverlay(WorldRenderer wr, RgbaColorRenderer wcr, Actor actor) + { + var a = actor.CenterPosition + new WVec(PointA.X, PointA.Y, 0).Rotate(actor.Orientation); + var b = actor.CenterPosition + new WVec(PointB.X, PointB.Y, 0).Rotate(actor.Orientation); + + var offset = new WVec(a.Y - b.Y, b.X - a.X, 0); + offset = offset * Radius.Length / offset.Length; + + var c = Color.Yellow; + RangeCircleRenderable.DrawRangeCircle(wr, a, Radius, 1, c, 0, c); + RangeCircleRenderable.DrawRangeCircle(wr, b, Radius, 1, c, 0, c); + wcr.DrawLine(new[] { wr.ScreenPosition(a - offset), wr.ScreenPosition(b - offset) }, 1, c); + wcr.DrawLine(new[] { wr.ScreenPosition(a + offset), wr.ScreenPosition(b + offset) }, 1, c); + } + } +} \ No newline at end of file diff --git a/OpenRA.Mods.Common/HitShapes/Circle.cs b/OpenRA.Mods.Common/HitShapes/Circle.cs new file mode 100644 index 0000000000..1636350537 --- /dev/null +++ b/OpenRA.Mods.Common/HitShapes/Circle.cs @@ -0,0 +1,46 @@ +#region Copyright & License Information +/* + * Copyright 2007-2015 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation. For more information, + * see COPYING. + */ +#endregion + +using System; +using System.Drawing; +using OpenRA.Graphics; +using OpenRA.Mods.Common.Graphics; + +namespace OpenRA.Mods.Common.HitShapes +{ + public class CircleShape : IHitShape + { + public WDist OuterRadius { get { return Radius; } } + + [FieldLoader.Require] + public readonly WDist Radius = new WDist(426); + + public CircleShape() { } + + public CircleShape(WDist radius) { Radius = radius; } + + public void Initialize() { } + + public WDist DistanceFromEdge(WVec v) + { + return new WDist(Math.Max(0, v.Length - Radius.Length)); + } + + public WDist DistanceFromEdge(WPos pos, Actor actor) + { + return DistanceFromEdge(pos - actor.CenterPosition); + } + + public void DrawCombatOverlay(WorldRenderer wr, RgbaColorRenderer wcr, Actor actor) + { + RangeCircleRenderable.DrawRangeCircle(wr, actor.CenterPosition, Radius, 1, Color.Yellow, 0, Color.Yellow); + } + } +} diff --git a/OpenRA.Mods.Common/HitShapes/IHitShape.cs b/OpenRA.Mods.Common/HitShapes/IHitShape.cs new file mode 100644 index 0000000000..b60c23a3ab --- /dev/null +++ b/OpenRA.Mods.Common/HitShapes/IHitShape.cs @@ -0,0 +1,25 @@ +#region Copyright & License Information +/* + * Copyright 2007-2015 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation. For more information, + * see COPYING. + */ +#endregion + +using OpenRA.Graphics; + +namespace OpenRA.Mods.Common.HitShapes +{ + public interface IHitShape + { + WDist OuterRadius { get; } + + WDist DistanceFromEdge(WVec v); + WDist DistanceFromEdge(WPos pos, Actor actor); + + void Initialize(); + void DrawCombatOverlay(WorldRenderer wr, RgbaColorRenderer wcr, Actor actor); + } +} diff --git a/OpenRA.Mods.Common/HitShapes/Rectangle.cs b/OpenRA.Mods.Common/HitShapes/Rectangle.cs new file mode 100644 index 0000000000..776a8d8bf7 --- /dev/null +++ b/OpenRA.Mods.Common/HitShapes/Rectangle.cs @@ -0,0 +1,80 @@ +#region Copyright & License Information +/* + * Copyright 2007-2015 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation. For more information, + * see COPYING. + */ +#endregion + +using System; +using System.Drawing; +using System.Linq; +using OpenRA.Graphics; + +namespace OpenRA.Mods.Common.HitShapes +{ + public class RectangleShape : IHitShape + { + public WDist OuterRadius { get; private set; } + + [FieldLoader.Require] + public readonly int2 TopLeft; + + [FieldLoader.Require] + public readonly int2 BottomRight; + + int2 quadrantSize; + int2 center; + + WVec[] combatOverlayVerts; + + public RectangleShape() { } + + public RectangleShape(int2 tl, int2 br) + { + TopLeft = tl; + BottomRight = br; + } + + public void Initialize() + { + if (TopLeft.X >= BottomRight.X || TopLeft.Y >= BottomRight.Y) + throw new YamlException("TopLeft and BottomRight points are invalid."); + + quadrantSize = (BottomRight - TopLeft) / 2; + center = TopLeft + quadrantSize; + + OuterRadius = new WDist(Math.Max(TopLeft.Length, BottomRight.Length)); + + combatOverlayVerts = new WVec[] + { + new WVec(TopLeft.X, TopLeft.Y, 0), + new WVec(BottomRight.X, TopLeft.Y, 0), + new WVec(BottomRight.X, BottomRight.Y, 0), + new WVec(TopLeft.X, BottomRight.Y, 0) + }; + } + + public WDist DistanceFromEdge(WVec v) + { + var r = new int2( + Math.Max(Math.Abs(v.X - center.X) - quadrantSize.X, 0), + Math.Max(Math.Abs(v.Y - center.Y) - quadrantSize.Y, 0)); + + return new WDist(r.Length); + } + + public WDist DistanceFromEdge(WPos pos, Actor actor) + { + return DistanceFromEdge((pos - actor.CenterPosition).Rotate(-actor.Orientation)); + } + + public void DrawCombatOverlay(WorldRenderer wr, RgbaColorRenderer wcr, Actor actor) + { + var verts = combatOverlayVerts.Select(v => wr.ScreenPosition(actor.CenterPosition + v.Rotate(actor.Orientation))); + wcr.DrawPolygon(verts.ToArray(), 1, Color.Yellow); + } + } +} diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj index b77937ff83..5a48825910 100644 --- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj +++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj @@ -177,6 +177,10 @@ + + + +