gohud

La lisibilité se mesure

← Thématisation

« Joli » relève du goût ; « lisible » se mesure. Un gris pâle paraît très bien sur un bon écran et disparaît sur un téléphone en plein jour — choisir à l'œil finit toujours par y mener.

python3 addons/gohud/tools/check_contrast.py
QuoiExigence
Texte courant4.5 : 1
Grand texte (24 px et plus)3 : 1
Bordures et icônes d'accent3 : 1
Bordures décoratives2 : 1 — les WCAG n'appliquent pas leur règle des 3:1 à la décoration
Surfaces adjacentes1.12 : 1 — assez pour qu'une carte se détache de son fond

Du texte sur une teinte de la même couleur

Ce piège est apparu trois fois dans ce code — les boutons enfoncés (panneau d'accent, libellé d'accent), les boutons de danger et les puces. C'est joli sur un nuancier et cela s'effondre dès qu'on le mesure, parce que les deux partagent une teinte et n'ont donc aucun écart de clarté.

Les couleurs de libellé ne sont donc pas choisies à la main. Le générateur de thèmes et GoSkin poussent chacun la clarté — et rien que la clarté — jusqu'à franchir le seuil sur le panneau où le texte se pose réellement. La teinte et la saturation survivent : la palette garde son caractère, et la modifier conserve son contraste.

Une couleur lue comme du texte et une couleur peinte en aplat veulent des choses opposées

Sur un thème clair, une couleur d'avertissement doit s'assombrir pour rester lisible en tant que texte (#96500A). Quand le remplissage de la barre en hérite, la barre d'expérience vire au brun. La couleur seule ne peut rien y faire : le jaune est intrinsèquement clair, il ne franchit donc le 3:1 sur aucune gouttière grise, et assombrir la gouttière aggrave les choses (1.52 → 1.06).

Les deux sont donc séparées. La couleur reste vive — la palette porte des couleurs réservées au remplissage comme warning_vivid. C'est l'arête qui porte le contrasteGoSkin dessine un contour de 1 dp sur tout remplissage qui n'atteint pas 3:1 face à sa gouttière, pour que « où en est le remplissage » reste lisible.

MY_LIGHT = dict(
    warning=hexc("9A5407"),         # lu comme du texte
    warning_vivid=hexc("F2A007"),   # peint sur la barre
)
L'oubli est signalé. Sans un *_vivid, un remplissage qui ressort sombre fait afficher au générateur the bar looks drab — add warning_vivid to the palette (« la barre est terne — ajoutez warning_vivid à la palette »). Un endroit qui se dégradait en silence le dit désormais.

Un panneau flottant ne peut pas savoir ce qu'il y a derrière lui

Un HUD est dessiné par-dessus le jeu — un champ de neige, ou une grotte. Si son panneau est translucide, ce qui se trouve derrière transparaît et change la couleur du panneau, entraînant avec lui le contraste du texte. À 82 % d'opacité, le texte atténué des thèmes sombres tombait à 3.74:1 sur un fond clair — en dessous du minimum.

Les panneaux translucides sont donc mesurés avec du blanc pur et du noir pur derrière eux ; c'est le pire qu'une scène de jeu puisse offrir. Le panneau de HUD des thèmes fournis est assez opaque pour passer (92 %) tout en gardant son aspect vitré.

Pour la même raison, les couleurs d'icônes ne sont pas figées non plus. Le glyphe de l'emplacement rapide était codé en dur en blanc et mesurait 1.11:1 sur un thème clair — il suit désormais le panneau qui le porte, exactement comme les libellés.

Deux vérificateurs, deux portées. check_contrast.py lit les fichiers de thème ; les couleurs qu'un skin compose à l'exécution (puces, emplacements) sont mesurées par la section skin contrast de la suite de tests, à l'intérieur de Godot.