Game skeleton — the smallest complete game: title -> play -> over. More...
Macros | |
| #define | PLAYER_SPEED 2 |
| #define | PX_MAX 240 |
| #define | PX_MIN 8 |
| #define | PY_MAX 208 |
| #define | PY_MIN 24 |
| #define | SPR_VRAM 0x4000 |
| #define | ST_OVER 2 |
| #define | ST_PLAY 1 |
| #define | ST_TITLE 0 |
| Game states — the whole game is a switch over these. | |
| #define | START_TIME 30 |
| #define | TILE_COIN 1 |
| #define | TILE_PLAYER 0 |
Functions | |
| static void | build_tile (const u8 *rows, u8 idx, u16 tile) |
Build an 8x8 tile from an 8-row bitmap, using palette index idx. | |
| static void | draw_hud_labels (void) |
| Print the fixed HUD labels once (numbers refreshed as they change). | |
| static void | draw_score (void) |
| Refresh the SCORE number (clear the field first so it never smears). | |
| static void | draw_sprites (void) |
| Draw the two gameplay sprites into the OAM buffer. | |
| static void | draw_time (void) |
| Refresh the TIME number. | |
| static void | encode_4bpp (void) |
| Pack pixbuf[] (8x8 palette indices) into a 4bpp planar tile. | |
| int | main (void) |
| static void | show_over (void) |
| Game-over screen. | |
| static void | show_title (void) |
| Title screen text. | |
| static void | spawn_coin (void) |
| Move the coin to a fresh pseudo-random spot. | |
| static void | start_game (void) |
| Enter the play state: reset score/timer, centre the player. | |
| static void | update_play (u16 held) |
| One frame of gameplay. | |
Variables | |
| static u8 | cx |
| static u8 | cy |
| u8 | game_state |
| Probe oracle: current state (0 title, 1 play, 2 over). | |
| static u8 | pixbuf [64] |
| static u8 | px |
| static u8 | py |
| u16 | score |
| Probe oracle: coins collected. | |
| static u16 | seed_ctr |
| static u8 | tick |
| static u8 | tilebuf [32] |
| u8 | time_left |
| Probe oracle: seconds remaining in a round. | |
Game skeleton — the smallest complete game: title -> play -> over.
The capstone the curriculum was missing: not a feature demo but the shape of a whole game, small enough to read in one sitting and fork for your own. It recombines the rungs you've climbed — input drives a sprite, a second sprite is a goal, a bounding-box test scores it, text is the HUD, and a hand-rolled state machine ties title, play and game-over together.
The one structural idea: a game is a state machine around one loop. Every frame you WaitForVBlank(), read the pad, then switch (game_state) to the code for the screen you're on. Transitions are just assignments to game_state plus a one-time setup for the new screen. That is the skeleton under every SNES game; basics/scene_stack shows the same idea lifted into the opt-in scene framework once the enum + switch starts to sprawl.
The game: steer the arrow with the D-pad, touch the coin to score, before the timer runs out. Zero assets — both sprites are built in C.
ROM mode: LoROM (project default).
| #define PLAYER_SPEED 2 |
| #define PX_MAX 240 |
| #define PX_MIN 8 |
| #define PY_MAX 208 |
| #define PY_MIN 24 |
| #define SPR_VRAM 0x4000 |
sprite tiles (text font is at $0000)
| #define ST_OVER 2 |
| #define ST_PLAY 1 |
| #define ST_TITLE 0 |
Game states — the whole game is a switch over these.
| #define START_TIME 30 |
seconds on the clock
| #define TILE_COIN 1 |
| #define TILE_PLAYER 0 |
Build an 8x8 tile from an 8-row bitmap, using palette index idx.
< sprite tiles (text font is at $0000)
|
static |
Print the fixed HUD labels once (numbers refreshed as they change).
|
static |
Refresh the SCORE number (clear the field first so it never smears).
|
static |
Draw the two gameplay sprites into the OAM buffer.
|
static |
Refresh the TIME number.
|
static |
Pack pixbuf[] (8x8 palette indices) into a 4bpp planar tile.
| int main | ( | void | ) |
< sprite tiles (text font is at $0000)
|
static |
Game-over screen.
|
static |
Title screen text.
|
static |
Move the coin to a fresh pseudo-random spot.
|
static |
Enter the play state: reset score/timer, centre the player.
< seconds on the clock
|
static |
One frame of gameplay.
|
static |
|
static |
| u8 game_state |
Probe oracle: current state (0 title, 1 play, 2 over).
|
static |
|
static |
|
static |
| u16 score |
Probe oracle: coins collected.
|
static |
|
static |
|
static |
| u8 time_left |
Probe oracle: seconds remaining in a round.