43 lines
1.8 KiB
Markdown
43 lines
1.8 KiB
Markdown
---
|
|
id: phase-update
|
|
name: Update
|
|
category: phases
|
|
kind: phase
|
|
tokens: Update
|
|
sig: phase Update
|
|
tip: The ordinary per-frame game-logic step, run after Input and FixedUpdate.
|
|
order: 3
|
|
---
|
|
|
|
`Update` is the everyday game-logic phase, run each frame after `Input` and `FixedUpdate` and before `LateUpdate` and `Render`. It is where most gameplay lives when you are not being strict about determinism: spawn waves on a timer, apply the intent that `Input` recorded, check win/lose conditions, advance animations. Reach for `Update` by default and reserve `FixedUpdate` for the simulation you specifically want reproducible. Because it runs after `Input`, the current frame's key press is already reflected in your program `var`s by the time `Update` reads them.
|
|
|
|
```ludic
|
|
program UpdateExample {
|
|
property Position { column: int = 0, row: int = 0 }
|
|
model Enemy { Position }
|
|
|
|
const GRID_WIDTH: int = 20
|
|
state UpdateExampleState {
|
|
elapsed_frames: int = 0
|
|
score: int = 0
|
|
}
|
|
|
|
handler SpawnWave(update_example_st: mut UpdateExampleState) phase Update {
|
|
update_example_st.elapsed_frames = update_example_st.elapsed_frames + 1
|
|
if update_example_st.elapsed_frames % 30 == 0 {
|
|
let spawn_column = Random.range(low: 0, high: GRID_WIDTH - 1)
|
|
spawn Enemy { Position { column: spawn_column, row: 0 } }
|
|
update_example_st.score = update_example_st.score + 1
|
|
}
|
|
}
|
|
|
|
handler DrawWorld(update_example_st: UpdateExampleState) phase Render {
|
|
Screen.clear(Color.MidnightBlue)
|
|
for (current_position) in query [Position, {Enemy}] {
|
|
Screen.fill_rectangle(x: current_position.column * 16, y: current_position.row * 16, width: 16, height: 16, color: Color.Crimson)
|
|
}
|
|
Screen.draw_number(x: 4, y: 4, value: update_example_st.score, color: Color.Gold, scale: 1)
|
|
Screen.show()
|
|
}
|
|
}
|
|
```
|