Skip to content

About

Arcade style fixed-shooter experience with modern engineering quality

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

Pebble Blaster

A playable C++23 vector arcade game using SFML 3.1 and Bazel. No external fonts, textures, working-directory assumptions, or SFML DLL installation. Bazel fetches and builds the pinned SFML and GoogleTest dependencies.

Documentation

Run on Windows

Prerequisite: Visual Studio 2022 or newer with Desktop development with C++ and a Windows SDK. A recent MSVC toolset is needed for C++23. Internet access is needed on the first build; subsequent builds use Bazel's cache.

From the project directory:

powershell -ExecutionPolicy Bypass -File .\run.ps1

To run the Bazel target directly through the repository wrapper:

.\tools\invoke-bazel.ps1 run //:pebble_blaster

After building, the game executable is available at bazel-bin\pebble_blaster.exe and can be launched directly.

The launcher detects Visual Studio and downloads checksum-verified Bazelisk 1.26.0 to your local application cache. Bazelisk selects Bazel 8.4.2 using .bazelversion. No administrator privileges are needed by the launcher. It uses Windows' trusted certificate store, including enterprise certificates, without turning off TLS verification. Setup errors report the missing tool.

The first source build of SFML and its dependencies takes a few minutes. The game opens with a START action; click it or press Enter.

Controls

Action Key Gamepad
Turn Left/Right or A/D Left stick X or D-pad left/right
Thrust Up or W Hold left stick up or D-pad up
Fire Space A or B (buttons 0 or 1; hold for repeated shots)
Pause/resume P or Escape Start (button 7)
Start/resume/play again Enter or click the menu action Start (button 7)
Restart R -
Quit Close the window -

Gamepad Input Test

Run the live controller diagnostic from the repository root:

.\tools\invoke-bazel.ps1 run //:gamepad_test

The diagnostic displays both stick candidates, POV D-pad, extra axes, device identification, and live numbered buttons. SFML reports generic axis names, so the right-stick display uses Z/R and shows U/V separately for verification.

Three lives, six simultaneous player shots, large/medium/small asteroid splitting, hostile saucers, and increasing waves. Rocks award 20/50/100 points; saucers award 200. Each 10,000 points earns a life. Respawns give three seconds of blinking protection. Best score is retained for the current session. Losing focus pauses the game. Resizing letterboxes the same playfield rather than stretching it or changing the simulation.

On Linux, run:

bazelisk run //:gamepad_test

The window displays the first connected controller, its detected axes and buttons, and highlights the inputs mapped to turn, thrust, fire, and Start. Close the window to exit.

Pairing a controller

Pair the Bluetooth controller with your operating system before starting the diagnostic. Pairing controls vary by model; consult the controller's manual for the correct button combination, then add it as a Bluetooth device in your OS.

Since this question comes up from time to time:

Pairing mode of the controller is often activated by

  • pressing a button share and home/PS together for 3 to 5 seconds or
  • pressing a button ❤️ followed by an additional button to activate pairing

Tests and coverage

Windows

Run these commands from the repository root. To compile the unit-test binary without executing it:

powershell -ExecutionPolicy Bypass -File .\tools\invoke-bazel.ps1 build //:core_test

To build and execute all Bazel tests, or only the gameplay core tests:

powershell -ExecutionPolicy Bypass -File .\run.ps1 test
powershell -ExecutionPolicy Bypass -File .\tools\invoke-bazel.ps1 test //:core_test

The //:core_test target compiles tests/core_test.cpp and runs its GoogleTest cases. Bazel handles building, test execution, and test logs; the Windows executable is available at bazel-bin\core_test.exe after a successful build.

Coverage additionally requires C++ Clang tools for Windows in Visual Studio Installer, or a standalone LLVM installation (BAZEL_LLVM can select it). Run:

powershell -ExecutionPolicy Bypass -File .\run.ps1 coverage

This builds the GTests with Clang-cl instrumentation, executes them, and writes LLVM JSON and HTML reports under .artifacts/coverage (summary.json and html\index.html). It fails below 95% line or 95% branch coverage. Measurement includes the gameplay core and the pure input_mapping module, excluding GTest, SFML, device polling, and presentation code. Rendering and window/input integration are checked separately by the smoke command, not counted as unit-test coverage.

Render smoke check

The smoke check advances the simulation and renders eight screenshots; an OpenGL-capable display is required:

powershell -ExecutionPolicy Bypass -File .\run.ps1 smoke

The render smoke check saves eight PNGs under .artifacts/screenshots, covering title, gameplay, pause, and game-over screens at 960x640 and 600x800. It fails if rendering is blank or image saving fails; an OpenGL-capable display is required. Tests of the simulation need no display or SFML context.

Linux and macOS

Install Bazelisk, a C++23 compiler (GCC 13+/Clang 17+ recommended), and platform development libraries. On Debian/Ubuntu:

sudo apt-get install g++ libgl-dev libudev-dev libx11-dev libxrandr-dev libxcursor-dev libxi-dev
bazelisk run //:pebble_blaster
bazelisk build //:core_test
bazelisk test //:core_test
bazelisk test //...

bazelisk build //:core_test compiles the test binary without running it. Use bazelisk test //:core_test for just the gameplay core suite, or bazelisk test //... for every test target.

On macOS install Xcode command-line tools and Bazelisk, then use the same bazelisk commands. Windows is locally verified; Linux is configured for CI. Native Bazel LCOV coverage for the gameplay core on Linux is available with:

bazelisk coverage //:core_test --combined_report=lcov --instrumentation_filter='//:core$'

On a headless Linux host, run the display-free simulation smoke check with:

bazelisk run //:pebble_blaster -- --simulation-smoke-test

The screenshot smoke test uses SFML's GLX-backed render textures and requires an X server with compatible GLX visuals. Xvfb may not provide a suitable visual; CI runs the full rendering smoke check on Windows instead.

Design

  • core: SFML-free simulation with value types and an explicit world snapshot. Game::update is the only simulation tick; the renderer gets const state.
  • input_mapping: pure value-in/value-out joystick mapping and keyboard/gamepad input composition; source inputs are not mutated.
  • renderer: procedural game geometry and HUD/menu layout.
  • text_renderer: bitmap glyph table, text measurement, and text drawing; no external font assets.
  • keyboard_input: keyboard command mapping and held-key sampling.
  • application: SFML event/focus handling and a bounded accumulator stepping the simulation at 120 Hz independently of rendering speed.
  • smoke_test: display-free simulation check and screenshot render check.
  • main: command-line mode dispatch and top-level error handling.
  • gamepad_test: standalone live controller diagnostics using the shared joystick input adapter.
  • core_test: deterministic GTest scenarios covering movement, wrapping, collisions, splitting, scoring, lives, cooldowns, timers, and state transitions.

The random seed is injectable; the snapshot constructor supports isolated scenarios. Gameplay uses circle collision bounds and a toroidal playfield, including collisions across opposite edges. Wave size caps at twelve rocks. Long frames are capped to prevent runaway catch-up; pause stops game time.

SFML and GoogleTest retain their upstream licenses. This project uses procedural graphics and does not bundle copyrighted arcade assets.

About

Arcade style fixed-shooter experience with modern engineering quality

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages