Add basic colour-determining functionality

This commit is contained in:
Liru 2020-05-17 23:23:10 +02:00
parent 45e5465a08
commit 266842afd4
3 changed files with 163 additions and 0 deletions

79
Seraphina/ColorHelper.cs Normal file
View File

@ -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),
};
}
/// <summary>
/// Gets a colour from the provided HSL values.
/// </summary>
/// <param name="hue">The hue, from 0 to 360.</param>
/// <param name="sat">The saturation, from 0 to 1.</param>
/// <param name="lightness">The lightness, from 0 to 1.</param>
/// <returns></returns>
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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}