https://github.com/phantie/snake
Singleplayer/Multiplayer browser game on modern Rust stack (Yew, Axum) and WebSocket
https://github.com/phantie/snake
async axum data-compresssion k8s multiplayer nix snake websocket yew
Last synced: about 2 months ago
JSON representation
Singleplayer/Multiplayer browser game on modern Rust stack (Yew, Axum) and WebSocket
- Host: GitHub
- URL: https://github.com/phantie/snake
- Owner: phantie
- License: mit
- Created: 2024-03-04T18:56:11.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2025-06-06T00:37:41.000Z (about 1 year ago)
- Last Synced: 2025-10-07T06:58:38.703Z (9 months ago)
- Topics: async, axum, data-compresssion, k8s, multiplayer, nix, snake, websocket, yew
- Language: Rust
- Homepage:
- Size: 176 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Snake game
https://github.com/phantie/snake/assets/43893037/2cdbeae7-6fd6-4bb2-97e4-82d1cfe65562
### Modes
Frontend self-contains singleplayer mode.\
Websocket connection to backend enables multiplayer mode.
### Stack
k8s, yew, nix, axum
Deployed on kubernetes. Dev environment and docker images built by Nix. Compiled frontend artifacts, served by dedicated cache-optimized http server.
### Backend
Performant concurrent event handling on asynchronous multi-threaded tokio runtime, similar to Erlang's light-weight processes.
### Frontend
Based on SPA application framework similar to React. Custom theme support (click right top corner).
### Messages
Frontend and backend reuse message schemas, compile-time checked. Request/response model over Websockets implemented for frontend and backend. Reliable communication provided by request/response model (acknowledgements), idempotency and (potentially) request retries.
### Development guide
Refer to dev.md
### Optimizations
#### Space efficient ser/de for snake form
Reduces required space for snake form ser/de by encoding directions intead of positions after initial position. \
Old payload: {pos1 pos2 pos3} \
New payload: {pos1 dir1 dir2} \
Position as json is {"x":x,"y":y} taking 11 + 2 * (1 to 5 (1 for possible minus sign)) bytes = 13 to 21 bytes. Encoded position as a direction takes 2 bits. Resulting in space efficiency per position increased by up to (max(13, 21) * 8) / 2 = 84 times.
### Room for improvement
- State reconciliation using partial update, instead of pushing full state to client on server update. Goal: smaller payloads.
- Compress messages, for example, leaving field names out of payloads. Goal: smaller payloads.
- Push updates only for possibly visible to client objects. Goal: smaller payloads.
- Root frontend component refactoring. Goal: reduce technical debt.