diff --git a/Seraphina/ColorHelper.cs b/Seraphina/ColorHelper.cs new file mode 100644 index 0000000..3dd3e40 --- /dev/null +++ b/Seraphina/ColorHelper.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Text; + +namespace Seraphina +{ + public static class ColorHelper + { + public static void ColorToHSV(Color color, out double hue, out double saturation, out double value) + { + int max = Math.Max(color.R, Math.Max(color.G, color.B)); + int min = Math.Min(color.R, Math.Min(color.G, color.B)); + + hue = color.GetHue(); + saturation = (max == 0) ? 0 : 1d - (1d * min / max); + value = max / 255d; + } + + public static Color ColorFromHSV(double hue, double saturation = 1, double value = 1) + { + int hi = Convert.ToInt32(Math.Floor(hue / 60)) % 6; + double f = hue / 60 - Math.Floor(hue / 60); + + value *= 255; + int v = Convert.ToInt32(value); + int p = Convert.ToInt32(value * (1 - saturation)); + int q = Convert.ToInt32(value * (1 - f * saturation)); + int t = Convert.ToInt32(value * (1 - (1 - f) * saturation)); + + return hi switch + { + 0 => Color.FromArgb(v, t, p), + 1 => Color.FromArgb(q, v, p), + 2 => Color.FromArgb(p, v, t), + 3 => Color.FromArgb(p, q, v), + 4 => Color.FromArgb(t, p, v), + _ => Color.FromArgb(v, p, q), + }; + } + + /// + /// Gets a colour from the provided HSL values. + /// + /// The hue, from 0 to 360. + /// The saturation, from 0 to 1. + /// The lightness, from 0 to 1. + /// + public static Color ColorFromHSL(double hue, double sat = 1, double lightness = 0.5) + { + if (sat == 0) + { + int L = (int)lightness; + return Color.FromArgb(255, L, L, L); + } + + double min, max, h; + h = hue / 360d; + + max = lightness < 0.5d ? lightness * (1 + sat) : (lightness + sat) - (lightness * sat); + min = (lightness * 2d) - max; + + return Color.FromArgb(255, (int)(255 * RGBChannelFromHue(min, max, h + 1 / 3d)), + (int)(255 * RGBChannelFromHue(min, max, h)), + (int)(255 * RGBChannelFromHue(min, max, h - 1 / 3d))); + } + + static double RGBChannelFromHue(double m1, double m2, double h) + { + h = (h + 1d) % 1d; + if (h < 0) h += 1; + if (h * 6 < 1) return m1 + (m2 - m1) * 6 * h; + else if (h * 2 < 1) return m2; + else if (h * 3 < 2) return m1 + (m2 - m1) * 6 * (2d / 3d - h); + else return m1; + + } + } +} diff --git a/Seraphina/PlayerHealthColor.cs b/Seraphina/PlayerHealthColor.cs new file mode 100644 index 0000000..ff097fc --- /dev/null +++ b/Seraphina/PlayerHealthColor.cs @@ -0,0 +1,45 @@ +using Seraphina.Core; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Text; + +namespace Seraphina +{ + public static class PlayerHealthColor + { + + const int MinHp = 100; + const int MaxHp = 500; + const int HpDiff = MaxHp - MinHp; + + const int MinHue = 100; + const int MaxHue = 300; + const int HueDiff = MaxHue - MinHue; + static readonly Color ZeroHp = Color.FromArgb(0, 255, 0, 0); + public static Color GetColor(HitPoint numerator, HitPoint denominator) + { + if (numerator <= 0) return ZeroHp; // Transparent red, for calculation consistency. + // XXX: Calculate the colour before rendering it transparent? Would it be a waste? + + // Scale the HitPoint based on its percentage. + double pct = numerator.Value * 1.0 / denominator.Value; + if (denominator < MinHp) + { + return ColorHelper.ColorFromHSV(pct * 100); + } + + // Scale the maximum hue by dividing anything over 100 by 2. + // ie 100 => 100, 200 => 150, 300 => 200, 500 => 300 + var maxHue = ((denominator.Value - MinHp) / 2) + MinHp; + + // Cap at 300 hue if max HitPoint is over 500 for some reason. + maxHue = Math.Min(MaxHue, maxHue); + + var color = ColorHelper.ColorFromHSV(maxHue * pct); + + return color; + } + + } +} diff --git a/Seraphina/PlayerManaColor.cs b/Seraphina/PlayerManaColor.cs new file mode 100644 index 0000000..55d58cf --- /dev/null +++ b/Seraphina/PlayerManaColor.cs @@ -0,0 +1,39 @@ +using Seraphina.Core; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Text; + +namespace Seraphina +{ + public static class PlayerManaColor + { + // NOTE to more future self: change these around to tweak mana colour. + const double minLightness = 0.2; + const double maxLightness = 0.8; + const double range = maxLightness - minLightness; + const int BlueHue = 210; + + public static Color GetColor(ManaPoint current, ManaPoint max) + { + // NOTE to future self: + // Mana could use HSL scale with blue. + // The L value coudl follow this formula, assuming 100 max mana: + // (mana / 100 * 0.8) + 0.1 + // Basically, get the mana percentage, multiply it by 80%, + // and add 0.1. This will Make the minimum lightness 0.1 and the max 0.9/ + // This will leave some nice dark and light blues for the mana bar. + + var pct = GetBrightnessValue(current, max); + + return ColorHelper.ColorFromHSL(BlueHue, lightness: pct); + } + + public static double GetBrightnessValue(ManaPoint num, ManaPoint denom) + { + var pct = num.Value * 1.0 / denom.Value; + pct *= range; + return pct + minLightness; + } + } +}