One root state.
struct GameState {
score: i32;
player_x: f32;
player_y: f32;
}
global state: GameState;Invariant: gameplay facts have one visible owner; render reads them.
These patterns are small on purpose. Keep ownership and invariants near the data they protect.
struct GameState {
score: i32;
player_x: f32;
player_y: f32;
}
global state: GameState;Invariant: gameplay facts have one visible owner; render reads them.
function tick(): i32 {
if (is_key_down(Scancode.Left)) { state.player_x -= state.speed; }
if (is_key_down(Scancode.Right)) { state.player_x += state.speed; }
if (state.player_x < 0.0) { state.player_x = 0.0; }
return 0;
}Invariant: changing system order is a deliberate behavior change.
global bullets: Bullet[128];
function spawn_bullet(): bool {
for (let i = 0; i < 128; i += 1) {
if (!bullets[i].active) {
bullets[i].active = true;
return true;
}
}
return false;
}Invariant: a tick has a known maximum scan and no hidden growth.
let hit = aabb_intersects(
state.player_x, state.player_y, state.player_x + 16.0, state.player_y + 16.0,
state.target_x, state.target_y, state.target_x + 16.0, state.target_y + 16.0
);
if (hit) { state.target_health -= 1; }Invariant: intermediate queries do not partially mutate the authoritative model.
test `score increments once`(): bool {
state.score = 0;
state.score += 1;
return state.score == 1;
}Invariant: tests pin observable transitions, not implementation details.
function render(): i32 {
begin_frame();
fill_rect(state.player_x, state.player_y, 16.0, 16.0, 1.0, 1.0, 1.0, 1.0);
end_frame();
return 0;
}Invariant: rendering cannot become a second gameplay authority.
if (state.ball_x < 0.0) {
state.right_score += 1;
state.ball_x = 400.0;
}Invariant: one boundary crossing produces one score and one reset.
if (aabb_intersects(ball.x, ball.y, ball.x + 8.0, ball.y + 8.0,
brick.x, brick.y, brick.x + 32.0, brick.y + 12.0)) {
brick.active = false;
ball.dy = -ball.dy;
}Invariant: a resolved brick cannot be resolved again in the same active slot.
if (player.y < platform.top &&
player.y + player.height >= platform.top) {
player.y = platform.top - player.height;
player.grounded = true;
player.vy = 0.0;
}Invariant: landing snaps to the platform boundary and clears downward velocity.
if (requested.x != -state.direction.x ||
requested.y != -state.direction.y) {
state.next_direction = requested;
}Invariant: a single tick cannot reverse the snake into its own head.