A digital implementation of the classic Wizard card game, built in Rust using the Iced UI framework for the client and Axum for the server, designed for playing in a local network.
- Cargo, Rust toolchain (
edition=2024, the project enforces1.90.0viarust-toolchain.toml) - On Linux: the
alsalibrary for audio must be installed (e.g.sudo apt install libasound2-devon Ubuntu)
git clone https://github.com/end41r/wizard.git
cd wizard
cargo build
cargo runPrimarily for WSL > Windows for better testing experience:
./build.sh -t windows # Windows release build
./build.sh -t linux # Linux release build
./build.sh -t windows -f # Windows release build with debug features (wiz_debug)The script compiles a release binary and copies both the executable and the assets/ folder to a directory specified in DEST_PATH.
cargo testUnit are located in src/gamelogic/game.rs (UI testing was done differently).
When the application starts, the main menu is displayed with four buttons:
| Button | Action |
|---|---|
| Host | Opens the host menu to create a new game lobby |
| Beitreten | Opens the join menu to connect to an existing lobby |
| Optionen | Opens audio settings |
| Spiel Verlassen | Exits the application |
- Click Host in the main menu.
- Enter your player name.
- Select the player count (3–6 players).
- Click Lobby Erstellen — this starts the WebSocket server on port
3000and puts you in the lobby. - Share your IP address (shown in the lobby) with the other players.
- Click Beitreten in the main menu.
- Enter your player name and the host's IP address.
- Click Verbinden to join the lobby.
- All connected players are listed with a Bereit | Nicht Bereit toggle.
- The lobby includes a chat where players can send messages.
- The game starts when all players are ready and the host presses Starten.
The game follows the official Wizard card game rules. A full in-game rules screen is accessible via the Spielregeln button in Optionen.
- Card hand: Cards that are displayed at the bottom, with a right click you can also see which are playable.
- Game table: Shows other players' avatars, the current trick's cards in the middle, if you click the trick's cards you can toggle the view of all played cards in the trick, by just hovering you can temporarily see the played cards in the trick.
- Scoreboard: Displayed on the side, shows each player's current score, bid, and tricks won. The scoreboard also provides trump-suit selection buttons when the dealer must set trump.
- Avatars: Each player has an animated avatar (Elf, Knight, Mage, or Witch) with idle and casting animations. Casting is triggered when a player plays a card. Each avatar type has unique sound effects upon clicking the avatar.
- Shards: Float around the avatar of each player, indicating the amount of cards left in their hand.
- Background music plays on the menu, in the lobby, and during gameplay (different tracks for each).
- Sound effects for: button clicks, card hover, card shuffle, card deal, card play, card error, shard play, avatar-specific casting and click sounds, and game over.
- Volume control: Music and SFX volume can be adjusted via sliders in the Optionen menu.
If the host enters the name wizard_master, the game launches in a debug gameplay view — a text-based, scrollable interface showing all game states (round, trump, bids, hand, tricks, scores, log) with minimal styling. This is located in src/client/views/debug_gameplay.rs.
Compiling with the wiz_debug Cargo feature (cargo run --features wiz_debug) enables:
- The Windows console window in release builds (for logging output).
- Better testing conditions (you can start with 1 player without waiting for everybody to get ready).
The application runs on Linux, Windows, and macOS.
src/server.rs: An Axum + Tokio WebSocket server. Manages player connections, lobby state, game state, and event broadcasting. Binds to0.0.0.0:3000.src/client/: An Iced GUI application. Handles user input, animations, rendering, audio playback, and communicates with the server via WebSockets.
src/main.rs: Entry point; launches the Iced clientsrc/api.rs: Shared types, protocol messages (C,S,B), card/suit/value definitions, avatar types, lobby/player structssrc/server.rs: Axum WebSocket server, game event dispatching, lobby managementsrc/gamelogic/: Core game logic —Game(overall game flow) andRound(per-round state, bidding, trick resolution, scoring)src/client/mod.rs: Client application state (App), message enum, initializationsrc/client/update.rs: Message handling and state transitionssrc/client/ws.rs: WebSocket connection managementsrc/client/audio.rs: Music and SFX playback viarodiosrc/client/views/: UI views: main menu, host menu, join menu, options, lobby, rules, debug gameplaysrc/gameplay_ui/: Game-table UI: hand display, card rendering, avatars, scoreboard, table layoutsrc/animation.rs: Animation framework with easing functions (basic, auto-reversing, circular animations)src/ui_element_traits.rs: Shared traits for UI elements (Viewable, Animated, Resizable, etc.)
iced: UI framework (with image and tokio features)axum: Web server framework with WebSocket supporttokio: Async runtimetokio-tungstenite: WebSocket client implementationserde/serde_json: Serialization and deserialization of protocol messagesrodio: Audio playback (music and sound effects)
The project uses Unit tests for the core game logic module (src/gamelogic/game.rs). This is the only module we could write tests for.
- UI testing was done manually by running the application and verifying that all features work as intended through hours of playing together / alone, because iced doesnt provide a nice way to test it's elements.
-
Easing functions (
src/animation.rs): Claude.ai generated the mathematical logic for easing functions (ease_in_cubic,ease_out_cubic,ease_in_out_cubic,ease_in_sine,ease_out_sine,ease_in_out_sine,ease_out_elastic,ease_out_bounce). -
Animation macros (
src/animation.rs): Claude.ai helped to learn how to write Rust macros and partially generated theimpl_animation_common!macro and trait bound patterns. -
Scoreboard functions (
src/gameplay_ui/scoreboard.rs): AI helped to write thesorted_player_order_by_scorefunction and the scoreboard view placement logic. -
Pixel art rendering (
src/gameplay_ui/table/avatar.rs): Claude helped to learn how to usefilter_methodto achieve non-blurred pixel art scaling. -
Hand generics (
src/gameplay_ui/hand/mod.rs): Claude.ai suggested passing a union type for generic hand card handling and helped to learnVec::containsusage. -
Server WebSocket handler (
src/server.rs): Claude Opus helped implement the WebSocket connection handler. -
Array filtering (
src/client/mod.rs): Gemini helped to learn how to pass an array into a function and filter it.
The following image assets were created with AI assistance:
background_forall.png,ingame_background.png,menu_container.pngwizard_lobby_menu.png,wizard_main_menu*.pngbutton1.png,Menu_Button.png