|
Banjo API 1.0.0-rc.2
Low-level C99 game development API
|
Capstone tutorial - a complete two-player Pong, tying together the subsystems you've seen so far: window, input, drawing, and timing.
Capstone tutorial - a complete two-player Pong, tying together the subsystems you've seen so far: window, input, drawing, and timing.This is the finale of the tutorial series. By the end of audio_pcm.c you knew how to open a window, draw to it, react to input, and time your frames. pong.c is the first tutorial that does all of those things together in a real (if minimal) game.
It is deliberately kept small. It stays with the simple variable-timestep loop from the earlier tutorials rather than the fixed-step API (via a bj_app_fixed_step_fn callback). Reach for fixed-step when determinism across machines matters (networked play, physics that must replay identically); see physics_particle.c and physics_kinematics.c. Pong does not need it, and the simpler loop keeps the capstone readable.
update / draw split, and the lifecycle callbacks holding the pieces.Earlier tutorials used file-scope globals (window, data, ...). That works for one-screen demos; it scales badly. Pong gathers everything into pong_t, declared zero-initialised on the stack in main (pong_t pong = {0}), and passes a pointer through the setup, step, and teardown callbacks via the App API's user_data parameter (registered with each bj_set_*_callback call). The zero-init matters: bj_stopwatch's "zero-init = valid" property means we don't need an explicit reset call.
Pong uses the default frame rate (60 Hz), so there's nothing to set. bj_run_app measures how long each iteration took and sleeps off just the time left to reach 60 iterations per second, so the loop yields the CPU instead of melting a core. Non-default rates can be set inside the setup callback with bj_set_frame_rate.
bj_step_delay_stopwatch returns the seconds elapsed since the last call and advances the internal step in one go. Every motion computation is then position += velocity * dt, so the game runs at the same speed whether the frame is 1 ms or 16 ms.
The clamped_dt line caps the step at 50 ms. Without it, alt-tabbing away for a few seconds (or any pause longer than a few frames) would resume with a giant dt and teleport the ball through a paddle. Cap-and-continue is the standard remedy.
start.c and event_callbacks.c used the callback style, perfect for one-shot events ("ESC was pressed"). For paddles you want the opposite: "is W *currently held*?" bj_get_key answers exactly that. We still use the ESC callback (via bj_close_on_escape), so this tutorial shows the two styles cooperating: callbacks for discrete events, polling for continuous state.
Reverse of init: window, then bj_end. The state struct lives on the stack in main, so there is nothing to free; once bj_run_app returns, main drops it automatically.
You've finished the tutorial series. From here you can:
examples/ that look interesting (each is now slotted into its topic; visit Bitmap, Audio, Random, Network, …).