shweet b96defa1e6 Profile stats, first-run hints, tiered balance, a wave-driven whip, and more options
- Profile Stats: damage dealt, kills and wins (single player and multiplayer) and the most and least played weapons
  and trinkets, counted from running totals in the simulation so online rewinds correct them. Protocol 6.
- First-run control hints in the sandbox (and Chat in lobbies), each gone for good once used.
- The ready countdown and a timed round's last five seconds beep (new countdown sound), and those seconds show big.
  When time runs out, everyone short of the most health dies.
- Weapon balance tuned into tiers: Whip and Grenade Launcher on top, then melee, ranged, and utility (Vacuum,
  Grapple, Uzi) at the bottom.
- The whip's lash is a chain of links a wave rolls down: windup, loop, crack, then a floppy recoil.
- Muzzles come from Muzzle nulls in weapons.anm2 (read in at build time), for shots and the flash, which now follows
  the weapon.
- Settings: Quit, Scale (1x-4x or Free), FPS meter and limit beside Vsync, Mute on Unfocus, Damage Numbers, Rumble,
  Stick Deadzone, and an Online section (Host, Chat, Ping) shared with the Multiplayer page.
- The menu header lays out tabs and buttons by their names. About is sandbox-only. The score no longer shifts with
  the menu's tab.
- Smaller meters, 90 tips (all ending in !), and a shorter lobby welcome.
2026-11-10 18:32:31 -05:00
2026-11-08 01:30:33 -05:00
2026-11-08 17:09:11 -05:00
2026-11-08 01:30:33 -05:00
2026-11-08 01:30:33 -05:00

Smack a Brother

1

2

3

4

Online platform fighter. Lobbies of up to 16 players, games of up to 8. Play it in the browser here.

Clarification

This application was developed with the assistance of a large language model.

Build

After cloning and entering the repository's directory, make sure to initialize the submodules:

git submodule update --init --recursive

Everything (SDL, libdatachannel, simdjson) is built statically from the submodules. The game's resources are in resources/ and get linked next to the executable.

Linux

Needs OpenSSL, plus the X11/Wayland and audio headers SDL builds against.

mkdir build
cd build
cmake ..
make

Web

Needs the Emscripten SDK.

emcmake cmake -B build-web -DCMAKE_BUILD_TYPE=Release
cmake --build build-web

This makes smack-a-brother.html, .js, .wasm and .data. Rename the .html to index.html and serve all four.

Server

The server builds on its own, without SDL. It needs OpenSSL (libssl-dev on Debian).

cmake -S server -B build-server -DCMAKE_BUILD_TYPE=Release
cmake --build build-server

Run it with:

smack-a-brother-server [port] [first UDP port] [last UDP port]

Defaults are 47800, 47810 and 47899. It only listens on 127.0.0.1, so put it behind a reverse proxy that handles TLS. For nginx:

location /smack-a-brother/ws {
    proxy_pass http://127.0.0.1:47800;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
    proxy_read_timeout 120s;
}

Open the UDP range in the firewall (e.g. ufw allow 47810:47899/udp).

Netcode

  • The server runs every lobby: a sandbox everyone in the lobby shares, plus the games queued in it. Each is its own simulation. All of them run on one thread, at 60 ticks a second.
  • Clients send their inputs ahead of time. Each tick the server takes what has arrived (repeating a player's last inputs if they're late), steps the simulation, and sends everyone the inputs it used. Every 60 ticks it also sends a checksum.
  • Clients run the same simulation about 3 ticks ahead of the server, guessing other players' inputs. When the server's inputs differ from the guess, the client rolls back and replays.
  • The simulation is deterministic on every platform (strict floating point, own maths functions), so desktop and web play together.
  • Clients connect over a WebSocket first (lobbies, chat, WebRTC signaling). Then they open a WebRTC connection to the server with two data channels: a reliable one, and an unreliable one for inputs and frames. If WebRTC can't connect, everything stays on the WebSocket.
  • STUN: stun.l.google.com:19302.
  • The server address is set in Settings. Default: wss://shweetz.net/smack-a-brother/ws.

Joining a lobby directly

  • Desktop: smack-a-brother --join CODE
  • Web: https://shweetz.net/smack-a-brother/?lobby=CODE

Environment variables

  • SAB_SERVER_URL: use a different server, e.g. ws://127.0.0.1:47800
  • SAB_NET_LAG: add this many milliseconds of lag
  • SAB_NET_LOSS: drop this percent of input packets
  • SAB_NET_STATS: log how the client is keeping up with the server

License

The game's code and art are released into the public domain under CC0 1.0. Not covered by that: the Ithaca font (SIL Open Font License, see resources/font/LICENSE.txt), the sound effects cut from the Sound Ideas libraries (see resources/sfx/SOURCES.md), and the libraries in external/, each under its own license.

S
Description
No description provided
Readme CC0-1.0
2.6 MiB
0 Stars 1 Watchers 0 Forks
Languages
C++ 99%
CMake 0.8%