Action bar
<ActionBar slots onPress> draws a game’s abilities as a fan of buttons round the bottom-right corner, where the right thumb rests. primary puts one larger button on the fan’s centre. The buttons are circles; shape={ActionBarShape.Square} draws them as rounded squares. The slots arrive up the arc one after another as the bar mounts. The bar holds four slots round the primary and leaves out a fifth.
Its props are in ActionBarProps, and a slot’s in ActionSlot.
A slot fires on the press, not on the release, as Tap does. A keyboard or a screen reader activates it too, and fires it once. The bar shows a slot’s hotkey as a badge and binds no key: the game binds the key and calls the same function the press does. The badge shows only where the pointer is fine; a phone has no key to press, so it shows none.
A slot shows its press as the pointer goes down, or as Enter or Space goes down on a focused slot: it shrinks and brightens until the pointer or the key comes up. A key press shows the same way when the game sets the slot’s pressed while the key is held, so the button answers on the key’s frame rather than when the cast or its cooldown comes back.
The bar sizes an icon to about half its button. An icon given a size of its own, such as <Icon className="size-8" />, keeps it.
The player’s abilities on the bar
Section titled “The player’s abilities on the bar”<AbilityBar /> in a Hud is the bar for a game whose abilities the engine judges: every ability the player holds, from any source, on a slot and a key. It reads the engine’s CastingTrait, cooldowns, TargetTrait and resources, so each slot fills its rim over the cast from the moment she casts, which her page starts on that frame, as What her page shows as she casts says, shows its own cooldown, and, on the slot last pressed, the global one too, whichever ends later, tints red while her target stands beyond its range and blue while she cannot pay its cost, and shows a held key’s press. A refused cast’s reason shows under the bar until her next cast. Its props are in AbilityBarProps, and every default is one of them:
primary: the ability on the large centre button, by name. Left out, every ability sits on the fan.order: abilities on the keys they keep, in key order. A name here keeps its key while another is missing, so a spell never moves when the item that grants the first comes off; an ability past the list takes a free key. Left out, the keys follow the grants’ order.keys: theKeyboardEvent.codeper slot, in slot order, and its length is the slot count, up to the four the fan holds and one more forprimarywhile she holds it. Left out,Digit1toDigit4. The badge is the code’s last character for a digit or a letter key.icons: an element per ability, over theiconregistered with the ability. A name with neither shows a star.refusal: whether the bar shows why the last cast was refused. Left out, it does; a game that draws the line its own way readsuseCast’srefusalText.
After a release, the engine’s 1 s global cooldown sweeps the slot the player pressed and pops there when it ends, and the other slots only lock, dim and still, until it does. An ability’s own cooldown sweeps and pops on its own slot. World of Warcraft sweeps the global cooldown on every button, which its players mute with an addon; Diablo Immortal and Wild Rift dim the other buttons and animate the pressed one, and this bar does the same, because four buttons moving at once pull the eye from the fight.
shapeandclassNamego to theActionBarunder it.
import { AbilityBar, Hud } from "@spawnite/engine";
export function MageHud() { return ( <Hud> <AbilityBar primary="arcane-bolt" order={["arcane-bolt", "crystal-lance", "frost-nova"]} /> </Hud> );}A game with abilities of its own shape builds on ActionBar as the sections below say.
Showing a cast
Section titled “Showing a cast”Pass the slot whose cast is winding up its casting, in the cooldown’s shape: seconds is the ability’s castSeconds and left is the secondsLeft of the engine’s CastingTrait. The slot stays lit and still takes a press, a gold rim fills round its edge over the cast, and every other slot dims. A game that plays the cast before the room answers passes { seconds, left: seconds } from the press, so the rim starts on the press.
Showing why a slot cannot cast
Section titled “Showing why a slot cannot cast”Two states tint the icon, as World of Warcraft’s action buttons do. Neither stops the press: the rules still judge the cast and say why they refuse it.
outOfRange: the icon tints red while the target stands beyond the ability’s range.noResource: the cost the player cannot pay, such as25. The icon tints blue and the button shows the number.
Showing a cooldown
Section titled “Showing a cooldown”Pass a slot its cooldown, the { seconds, left } that useCooldown returns. While a slot has one, it does the following:
- It takes no press.
- It shows the whole seconds left, rounded up, so it never reads 0 while the ability is out.
- It tucks its icon small beneath the number.
- It fills a bright rim round its edge as the cooldown runs.
When the cooldown goes, the icon springs back and a ring flies off the button. A player who asked for less motion gets the rim and the number, and no spring or arrival.
A slot with locked takes no press either, and draws nothing for it: dim, with no rim, no number and no pop. It is for a lock that is not the slot’s own, such as the global cooldown another ability started, so the one button the player pressed is the one that moves.
The rim sweeps on its own between the steps that count the cooldown or the cast down, so it moves every frame and the bar renders only when the cooldown changes. A rim more than a tenth of a second off the cooldown is set to it, as after a pause.
What the other engines do
Section titled “What the other engines do”On Roblox, Unity, Unreal, Godot, Phaser and PlayCanvas, a game builds an ability bar from buttons and images, with a radial fill for the cooldown. Unity’s Image has a radial fill mode and Unreal’s Lyra draws its own. Godot’s BaseButton flashes its pressed look when its shortcut key fires it, which is what pressed gives a key here. Mobile action games, such as Genshin Impact and Honor of Kings, put the abilities on an arc round the attack button, which is where this layout comes from. Diablo Immortal and Wild Rift fill the pressed skill’s rim over its cast in place of a cast bar, and World of Warcraft tints a button red out of range and blue short of mana.
This engine ships the bar because a creator with no code cannot build one, and because the cooldown’s polish, a rim, a number and a pop that agree, is slow to get right.
Sample
Section titled “Sample”A bolt on key 1, with its cooldown:
import { ActionBar, Hud, Icon, useCharacter, useCooldown,} from "@spawnite/engine";
export function Abilities({ onCast }: { onCast: (id: string) => void }) { const entity = useCharacter() ?? null; const cooldown = useCooldown(entity, "bolt"); return ( <Hud> <ActionBar slots={[ { id: "bolt", label: "Bolt", hotkey: "1", icon: <Icon name="zap" />, cooldown, }, ]} onPress={onCast} /> </Hud> );}Where it runs
Section titled “Where it runs”Client. The bar shows a cooldown and asks for a cast; the system that casts checks the cooldown again, where the simulation has the say.