gohud

Shapes games actually use

← Widgets

Familiar web shapes, rebuilt around what a game needs from them.

GoRewardCalendar — daily attendance

A date picker is almost never useful in a game. A calendar shape is — for attendance rewards, where what matters is which day you are on, not which date it is.

var attendance := GoRewardCalendar.make(days, claimed_until)
attendance.claimed.connect(func(day: int) -> void: server.claim_day(day))

Only today's cell can be pressed — a button that does nothing when pressed reads as broken. Claimed, today and future differ by three things at once: a tick glyph, an accent border and dimming.

GoRadar and GoDonut — stats at a glance

var stats := GoRadar.make({"STR": 0.85, "AGI": 0.5, "INT": 0.3, "VIT": 0.7, "LUK": 0.45})
stats.set_compare(with_new_sword)          # a dashed overlay

var share := GoDonut.make([{"label": "Physical", "value": 620}, {"label": "Magic", "value": 340}])
card.add_child(share.legend())

Radar values are 0–1 because what counts as full is a game decision — raw 120 STR beside 45 INT would draw a lie. Donut values are raw and it divides for you; past five slices it collapses the rest, since a sixth slice is a thread nobody can read. The comparison line is dashed, not just another colour, and the legend prints the percentage in words.

GoCarousel — banners and character select

banners.set_pages([promo, event, pack])
banners.autoplay_seconds = 5.0             # off by default

It does not advance on its own unless you ask, and five seconds is the floor: a banner that changes every three takes the text away before it is read. Touching it resets the timer, and with reduce_motion on it never advances by itself. The dots are pressable at the touch minimum even though the drawn dot is small.

GoKbd — key hints that do not lie

hint.add_child(GoKbd.for_action(&"interact"))   # reads the real binding

A hard-coded "Press F" keeps saying F after the player rebinds — the most common lie in a PC UI. for_action() reads InputMap; if the action is bound to a pad instead, it returns empty and the widget hides, because "None" would be its own lie. On Android and iOS it hides itself.