diff --git a/OpenRa.Game/Game.cs b/OpenRa.Game/Game.cs index 964f9012e7..a068834f48 100644 --- a/OpenRa.Game/Game.cs +++ b/OpenRa.Game/Game.cs @@ -73,6 +73,7 @@ namespace OpenRa.Game var worldActor = new Actor(null, new int2(int.MaxValue, int.MaxValue), null); worldActor.traits.Add(new Traits.WaterPaletteRotation(worldActor)); + worldActor.traits.Add(new Traits.ChronoshiftPaletteEffect(worldActor)); Game.world.Add(worldActor); Rules.Map.InitOreDensity(); diff --git a/OpenRa.Game/OpenRa.Game.csproj b/OpenRa.Game/OpenRa.Game.csproj index d13fdbe492..68cfee2a41 100644 --- a/OpenRa.Game/OpenRa.Game.csproj +++ b/OpenRa.Game/OpenRa.Game.csproj @@ -198,6 +198,7 @@ + diff --git a/OpenRa.Game/Traits/ChronoshiftDeploy.cs b/OpenRa.Game/Traits/ChronoshiftDeploy.cs index 6208a7ef4e..cd02343320 100644 --- a/OpenRa.Game/Traits/ChronoshiftDeploy.cs +++ b/OpenRa.Game/Traits/ChronoshiftDeploy.cs @@ -1,21 +1,14 @@ using System.Collections.Generic; using System.Linq; using OpenRa.Game.Orders; -using System.Drawing; -using OpenRa.Game.Graphics; namespace OpenRa.Game.Traits { - class ChronoshiftDeploy : IOrder, ISpeedModifier, ITick, IPips, IPaletteModifier + class ChronoshiftDeploy : IOrder, ISpeedModifier, ITick, IPips { // Recharge logic int chargeTick = 0; // How long until we can chronoshift again? int chargeLength = (int)(Rules.Aftermath.ChronoTankDuration * 60 * 25); // How long between shifts? - - // Screen fade logic - int animationTick = 0; - int animationLength = 10; - bool animationStarted = false; public ChronoshiftDeploy(Actor self) { } @@ -23,19 +16,6 @@ namespace OpenRa.Game.Traits { if (chargeTick > 0) chargeTick--; - - if (animationStarted) - { - if (animationTick < animationLength) - animationTick++; - else - animationStarted = false; - } - if (!animationStarted) - { - if (animationTick > 0) - animationTick--; - } } public Order IssueOrder(Actor self, int2 xy, MouseInput mi, Actor underCursor) @@ -62,7 +42,9 @@ namespace OpenRa.Game.Traits self.QueueActivity(new Activities.Teleport(order.TargetLocation)); Sound.Play("chrotnk1.aud"); chargeTick = chargeLength; - animationStarted = true; + + foreach (var a in Game.world.Actors.Where(a => a.traits.Contains())) + a.traits.Get().DoChronoshift(); } } @@ -100,51 +82,5 @@ namespace OpenRa.Game.Traits } } } - - public void AdjustPalette(Bitmap bmp) - { - if (!animationStarted && animationTick == 0) - return; - - // saturation modifier - var f = 1 - (animationTick * 1.0f / animationLength); - - using (var bitmapCopy = new Bitmap(bmp)) - for (int j = 0; j < (int)PaletteType.Chrome; j++) - for (int i = 0; i < bmp.Width; i++) - { - var h = bitmapCopy.GetPixel(i, j).GetHue(); // 0-360 - var s = f * bitmapCopy.GetPixel(i, j).GetSaturation(); // 0-1.0 - var l = bitmapCopy.GetPixel(i, j).GetBrightness(); // 0-1.0 - var alpha = bitmapCopy.GetPixel(i, j).A; - - // Convert from HSL to RGB - // Refactor me! - var q = (l < 0.5f) ? l * (1 + s) : l + s - (l * s); - var p = 2 * l - q; - var hk = h / 360.0f; - - double[] trgb = { hk + 1 / 3.0f, - hk, - hk - 1/3.0f }; - double[] rgb = { 0, 0, 0 }; - - for (int k = 0; k < 3; k++) - { - // mod doesn't seem to work right... do it manually - while (trgb[k] < 0) trgb[k] += 1.0f; - while (trgb[k] > 1) trgb[k] -= 1.0f; - } - - for (int k = 0; k < 3; k++) - { - if (trgb[k] < 1 / 6.0f) { rgb[k] = (p + ((q - p) * 6 * trgb[k])); } - else if (trgb[k] >= 1 / 6.0f && trgb[k] < 0.5) { rgb[k] = q; } - else if (trgb[k] >= 0.5f && trgb[k] < 2.0f / 3) { rgb[k] = (p + ((q - p) * 6 * (2.0f / 3 - trgb[k]))); } - else { rgb[k] = p; } - } - bmp.SetPixel(i, j, Color.FromArgb(alpha, (int)(rgb[0] * 255), (int)(rgb[1] * 255), (int)(rgb[2] * 255))); - } - } } } diff --git a/OpenRa.Game/Traits/ChronoshiftPaletteEffect.cs b/OpenRa.Game/Traits/ChronoshiftPaletteEffect.cs new file mode 100644 index 0000000000..09efc58efb --- /dev/null +++ b/OpenRa.Game/Traits/ChronoshiftPaletteEffect.cs @@ -0,0 +1,54 @@ +using System.Drawing; +using OpenRa.Game.Graphics; + +namespace OpenRa.Game.Traits +{ + class ChronoshiftPaletteEffect : IPaletteModifier, ITick + { + const int chronoEffectLength = 10; + int remainingFrames; + + public ChronoshiftPaletteEffect(Actor self) { } + + public void DoChronoshift() + { + remainingFrames = chronoEffectLength; + } + + public void Tick(Actor self) + { + if (remainingFrames > 0) + remainingFrames--; + } + + public void AdjustPalette(Bitmap b) + { + if (remainingFrames == 0) + return; + + var frac = (float)remainingFrames / chronoEffectLength; + for( var y = 0; y < (int)PaletteType.Chrome; y++ ) + for (var x = 0; x < 256; x++) + { + var orig = b.GetPixel(x, y); + var lum = (int)(255 * orig.GetBrightness()); + var desat = Color.FromArgb(orig.A, lum, lum, lum); + b.SetPixel(x, y, Lerp(frac, orig, desat)); + } + } + + static Color Lerp(float t, Color a, Color b) + { + return Color.FromArgb( + LerpChannel(t, a.A, b.A), + LerpChannel(t, a.R, b.R), + LerpChannel(t, a.G, b.G), + LerpChannel(t, a.B, b.B)); + } + + static int LerpChannel(float t, int a, int b) + { + return (int)((1 - t) * a + t * b); + } + } +} diff --git a/OpenRa.Game/Traits/Chronoshiftable.cs b/OpenRa.Game/Traits/Chronoshiftable.cs index 84f004a310..bbdbb88048 100644 --- a/OpenRa.Game/Traits/Chronoshiftable.cs +++ b/OpenRa.Game/Traits/Chronoshiftable.cs @@ -6,31 +6,16 @@ using System.Drawing; namespace OpenRa.Game.Traits { - class Chronoshiftable : IOrder, ISpeedModifier, ITick, IPaletteModifier + class Chronoshiftable : IOrder, ISpeedModifier, ITick { // Return-to-sender logic int2 chronoshiftOrigin; int chronoshiftReturnTicks = 0; - // Screen fade logic - int animationTick = 0; - int animationLength = 10; - bool animationStarted = false; - public Chronoshiftable(Actor self) { } public void Tick(Actor self) { - if (animationStarted) - { - if (animationTick < animationLength) - animationTick++; - else - animationStarted = false; - } - else if (animationTick > 0) - animationTick--; - if (chronoshiftReturnTicks <= 0) return; @@ -68,7 +53,9 @@ namespace OpenRa.Game.Traits self.CancelActivity(); self.QueueActivity(new Activities.Teleport(order.TargetLocation)); Sound.Play("chrono2.aud"); - animationStarted = true; + + foreach (var a in Game.world.Actors.Where(a => a.traits.Contains())) + a.traits.Get().DoChronoshift(); } } @@ -77,51 +64,5 @@ namespace OpenRa.Game.Traits // ARGH! You must not do this, it will desync! return (Game.controller.orderGenerator is ChronoshiftDestinationOrderGenerator) ? 0f : 1f; } - - public void AdjustPalette(Bitmap bmp) - { - if (!animationStarted && animationTick == 0) - return; - - // saturation modifier - var f = 1 - (animationTick * 1.0f / animationLength); - - using (var bitmapCopy = new Bitmap(bmp)) - for (int j = 0; j < 8; j++) - for (int i = 0; i < bmp.Width; i++) - { - var h = bitmapCopy.GetPixel(i, j).GetHue(); // 0-360 - var s = f * bitmapCopy.GetPixel(i, j).GetSaturation(); // 0-1.0 - var l = bitmapCopy.GetPixel(i, j).GetBrightness(); // 0-1.0 - var alpha = bitmapCopy.GetPixel(i, j).A; - - // Convert from HSL to RGB - // Refactor me! - var q = (l < 0.5f) ? l * (1 + s) : l + s - (l * s); - var p = 2 * l - q; - var hk = h / 360.0f; - - double[] trgb = { hk + 1 / 3.0f, - hk, - hk - 1/3.0f }; - double[] rgb = { 0, 0, 0 }; - - for (int k = 0; k < 3; k++) - { - // mod doesn't seem to work right... do it manually - while (trgb[k] < 0) trgb[k] += 1.0f; - while (trgb[k] > 1) trgb[k] -= 1.0f; - } - - for (int k = 0; k < 3; k++) - { - if (trgb[k] < 1 / 6.0f) { rgb[k] = (p + ((q - p) * 6 * trgb[k])); } - else if (trgb[k] >= 1 / 6.0f && trgb[k] < 0.5) { rgb[k] = q; } - else if (trgb[k] >= 0.5f && trgb[k] < 2.0f / 3) { rgb[k] = (p + ((q - p) * 6 * (2.0f / 3 - trgb[k]))); } - else { rgb[k] = p; } - } - bmp.SetPixel(i, j, Color.FromArgb(alpha, (int)(rgb[0] * 255), (int)(rgb[1] * 255), (int)(rgb[2] * 255))); - } - } } }