gohud

가독성은 재서 지킨다

← 테마

"예쁘다" 는 취향이지만 "읽힌다" 는 측정할 수 있다. 흐린 회색 글자는 좋은 모니터에서는 멀쩡해 보이고 햇빛 아래 폰에서는 사라진다 — 눈으로 고르면 반드시 그렇게 된다.

python3 addons/gohud/tools/check_contrast.py

테마 파일의 색 짝과 버튼 상태별 패널 위의 글자를 WCAG 기준으로 잰다. 반투명한 색은 깔린 배경 위에 합성한 뒤 잰다 — 그대로 재면 화면에 보이는 것보다 좋게 나온다.

대상필요한 대비
본문 글자4.5 : 1
큰 글자(24px 이상)3 : 1
강조 테두리·아이콘3 : 1
장식 테두리2 : 1 — WCAG 는 장식에 3:1 을 요구하지 않는다
맞닿은 표면1.12 : 1 — 카드가 바탕과 떨어져 보일 만큼

같은 색 틴트 위의 같은 색 글자

이 함정은 이 코드베이스에서 세 번 나타났다 — 눌린 버튼(강조색 패널 + 강조색 글자), 위험 버튼, 그리고 칩. 색 견본으로 보면 예쁜데, 같은 색조라 명도 차가 없어 측정하면 곧바로 무너진다.

그래서 글자색을 손으로 고르지 않는다. 테마 생성기와 GoSkin 이 각각 배경 위에서 기준을 넘을 때까지 명도만 민다 — 색조와 채도는 지키므로 팔레트의 성격이 남고, 팔레트를 바꿔도 대비가 따라온다.

글자로 읽히는 색과 면으로 칠하는 색은 요구가 반대다

밝은 테마에서 경고색은 글자로 읽히려고 어두워진다(#96500A). 그런데 막대 채움이 그 색을 물려받으면 경험치 막대가 갈색이 된다. 색만으로는 풀 수 없다 — 노랑은 휘도가 본래 높아 어떤 회색 바탕 위에서도 3:1 이 나오지 않고, 트랙을 어둡게 하면 오히려 더 나빠진다 (1.52 → 1.06).

그래서 둘로 가른다. 색은 선명하게 — 팔레트에 warning_vivid 처럼 채움 전용 원색을 둔다. 경계는 윤곽이 — 바탕에서 3:1 이 안 나오는 채움에는 GoSkin 이 1dp 윤곽을 둘러 "어디까지 찼는지" 를 만든다.

MY_LIGHT = dict(
    warning=hexc("9A5407"),         # 글자로 읽히는 색
    warning_vivid=hexc("F2A007"),   # 막대에 칠하는 색
)
빠뜨리면 알려 준다. *_vivid 없이 채움이 어두워지면 생성기가 the bar looks drab — add warning_vivid to the palette 라고 한 줄 남긴다. 말없이 나빠지는 자리를 말하게 만든 것이다.

떠 있는 패널은 뒤에 무엇이 올지 모른다

HUD 는 게임 화면 위에 얹힌다 — 눈밭일 수도, 동굴일 수도 있다. 패널이 반투명이면 뒤가 비쳐 패널 색 자체가 달라지고, 그 위 글자의 대비도 따라 무너진다. 어두운 테마의 HUD 패널이 82% 불투명일 때, 뒤가 밝으면 흐린 글자가 3.74:1 까지 떨어졌다 — 기준 아래다.

그래서 반투명한 패널은 순백과 순흑을 깔아 보고 잰다. 게임 화면의 최악이 그 둘이기 때문이다. 기본 테마들의 HUD 패널은 이 검사를 통과하는 선(92%)까지 불투명하다 — 유리 느낌은 남기면서.

같은 이유로 아이콘 색도 고정하지 않는다. 퀵슬롯의 그림이 흰색으로 박혀 있어 밝은 테마에서 1.11:1 로 패널에 묻힌 적이 있다 — 글자와 똑같이, 자기가 놓인 패널 위에서 읽히는 색을 따른다.

Python 검사와 Godot 검사가 범위를 나눈다. check_contrast.py 는 테마 .tres 를 읽고, 스킨이 실행 중에 섞는 색(칩·슬롯)은 검사 스위트의 skin contrast 섹션이 Godot 안에서 잰다.