Lucky Robots Blog Open Roles

2.12 · Input

A tiny static API for keyboard, mouse, and controller state. Frame-accurate edge detection — this key just went down, this key is being held, this key was just released.

Module: Hazel/src/Hazel/Core/ Key header: Input.h all static
Released idle Pressed IsKeyPressed Held IsKeyDown Released IsKeyReleased key down event Update() key up event Update() — back to idle
A key passes through four states across frames. Update() advances PressedHeld and ReleasedReleased (idle).

Overview

Input is a small static class in Hazel/src/Hazel/Core/Input.h. It answers three questions per key, button, and gamepad axis: is it down right now?, did it transition to down this frame?, and did it transition to up this frame?. Together those let gameplay code react both to held state (movement, aiming) and to one-shot events (jump, fire) without writing its own state machine.

Ownership & lifecycle

Nothing instantiates Input — all methods are static. The Application calls Input::Update() exactly once per frame after polling the OS event queue. That single call advances Pressed states into Held and clears Released states back to Released (idle), giving the frame-accurate semantics the API promises.

One Update per frame — no more, no less

Don't call Input::Update() yourself. Calling it twice in a frame discards your own Pressed edges before gameplay sees them; never calling it leaves stale Pressed flags so a single tap reads as down every frame. Trust the Application.

Frame-accurate queries

CallTrue whenUse for
Input::IsKeyPressed(key) The key transitioned from up to down this frame. One-shot triggers — jump, fire, open menu.
Input::IsKeyDown(key) The key is currently held, regardless of when it went down. Continuous actions — movement, charge, aim.
Input::IsKeyReleased(key) The key transitioned from down to up this frame. Release-on-letgo — loose a charged shot, end a drag.

Mouse buttons and controller buttons mirror the same three calls (IsMouseButtonPressed, IsMouseButtonDown, etc.). Axes and cursor positions are read as straight values rather than edges.

Pitfalls

Pressed is single-frame

IsKeyPressed is true for exactly one frame — the frame the key went down. If two systems both want to react to the same press, both query it the same frame; do not stash it in a boolean across frames or you will mis-handle the next press.

Editor vs. play focus

The input layer reads OS events, so a key tapped while the editor has keyboard focus on a text field will not always reach gameplay. If a panel is consuming input via ImGui, the play viewport will not see it.

Extending

Adding a new platform's input plumbing means implementing the platform-specific backend that pushes events into Input — the public static API stays the same. For gameplay-level features like remappable bindings, build them on top of Input; do not modify Input itself.