I built ToonTones around a small loop. You see a color, it disappears, and you rebuild it from memory.
The controls use HSL because hue, saturation, and lightness make sense to players. The scoring code uses RGB instead.
That split solved several problems.
Why I did not score the HSL sliders
A direct HSL comparison looks tempting. Add the hue, saturation, and lightness differences, then map the total to ten points.
Hue breaks that approach. Zero degrees and 359 degrees are neighbors, not opposites.
Saturation also behaves strangely near gray. A hue difference can be mathematically large while the visible difference stays small.
I kept HSL for input and converted both colors before scoring.
The weighted RGB distance
The target starts as a hex color. The player's HSL choice becomes hex, then both values become RGB.
Here is the distance calculation:
function colorDistance(a, b) {
const [r1, g1, b1] = hexToRgb(a);
const [r2, g2, b2] = hexToRgb(b);
const redMean = (r1 + r2) / 2;
return Math.sqrt(
(2 + redMean / 256) * (r1 - r2) ** 2 +
4 * (g1 - g2) ** 2 +
(2 + (255 - redMean) / 256) * (b1 - b2) ** 2
);
}
Green gets the largest fixed weight. Red and blue weights change with the average red level.
This is not Delta E. It does not model human vision perfectly.
It is fast, deterministic, and easy to run after every round in a browser game.
Turning distance into a 0–10 score
The largest distance under this formula is about 764.833. I use that value to normalize each result.
const normalized = Math.min(1, distance / 764.833);
const score = 10 * (1 - normalized) ** 0.72;
The exponent makes the game forgiving. A nearly correct answer should feel nearly correct.
For one red target, an exact match scores 10.00. A small visible miss scores 9.87.
A very different cyan guess scores 3.76. Black against white reaches zero.
Those numbers made more sense during play than a harsh linear scale.
Five rounds reduce lucky guesses
One color can flatter or punish a player by accident. ToonTones averages five independent rounds.
That average becomes the final score. It also gives players enough feedback to spot a pattern.
Some players miss hue. Others remember vivid colors as darker or less saturated.
The scorer does not diagnose those mistakes yet. The round-by-round swatches make them visible.
What I would change next
A proper Lab-space comparison would be a useful experiment. Delta E could better match visible color differences.
I would test it beside the current method before replacing anything. Better math does not always create better game feedback.
The current formula is short, stable, and understandable. That matters for a game that explains every score immediately.
I wrote a shorter player-facing scoring guide with practical tips for reading each result.
Top comments (0)