A configurable, embeddable chess GUI built with Macroquad and the chess crate.
This library provides a ready-to-use chess board widget with rendering, move validation, local play, optional UCI engine integration, clocks, undo/redo, PGN export, and more.
- Rendering from a texture atlas
- Built-in default piece sprites
- Legal move validation via the
chesscrate - Local two-player play
- Optional UCI engine integration
- Undo / redo
- Move history in SAN
- PGN export
- FEN export
- Chess clocks with increment
- Resign and draw buttons
- Draw detection:
- checkmate
- stalemate
- insufficient material
- fifty-move rule
- threefold repetition
- Board themes
- Responsive board sizing
- Move animation
- Last-move highlighting
- Legal-move dots
- Capture indicators
- King-in-check highlighting
- Promotion popup
- Coordinate labels
- egui-based control panel
Add to your Cargo.toml:
[dependencies]
chess-render = "0.5.0"To enable UCI support:
[dependencies]
chess-render = { version = "0.5.0", features = ["uci"] }use chess_render::{ChessConfig, ChessGui};
use macroquad::prelude::*;
#[macroquad::main("Chess Render")]
async fn main() {
let config = ChessConfig::default();
let mut gui = ChessGui::new(config);
gui.load_pieces()
.await
.expect("Failed to load piece texture");
loop {
gui.update().await;
next_frame().await;
}
}use chess_render::{ChessConfig, ChessGui};
use macroquad::prelude::*;
#[macroquad::main("Chess Render")]
async fn main() {
let config = ChessConfig::builder()
.square_size(72.0)
.animate_moves(true)
.show_move_list(true)
.show_clock(true)
.clock(300.0, 2.0)
.build();
let mut gui = ChessGui::new(config);
gui.load_pieces()
.await
.expect("Failed to load piece texture");
loop {
gui.update().await;
next_frame().await;
}
}Enable the uci feature and set an engine path.
use chess_render::{ChessConfig, ChessGui, EngineSide};
use macroquad::prelude::*;
#[macroquad::main("Chess Render")]
async fn main() {
let config = ChessConfig::builder()
.uci_engine_path("/usr/bin/stockfish")
.engine_plays_as(EngineSide::Black)
.uci_move_time_ms(500)
.build();
let mut gui = ChessGui::new(config);
gui.load_pieces()
.await
.expect("Failed to initialize GUI");
loop {
gui.update().await;
next_frame().await;
}
}You can also run the included demo with:
CHESS_ENGINE=/usr/bin/stockfish cargo run --example demo --features uciChessConfig is highly customizable.
You can use:
let config = ChessConfig::builder()
.square_size(80.0)
.responsive_board(true)
.animate_moves(true)
.show_grid(true)
.clock(180.0, 2.0)
.build();or construct it directly and use ..Default::default().
| Key | Action |
|---|---|
R |
New game |
F |
Flip board |
U |
Undo |
Y |
Redo |
Shortcuts are ignored when egui keyboard focus is active.
new(config: ChessConfig) -> Selfasync load_pieces(&mut self) -> Result<(), ChessError>async update(&mut self)try_move(&mut self, m: ChessMove) -> boolundo(&mut self)redo(&mut self)resign(&mut self)offer_draw(&mut self)set_fen(&mut self, fen: &str) -> Result<(), ChessError>set_board(&mut self, board: Board)board(&self) -> &Boardfen(&self) -> Stringexport_pgn(&self) -> Stringlegal_moves(&self) -> Vec<ChessMove>move_records(&self) -> &[MoveRecord]game_result(&self) -> Option<GameResult>game_end_reason(&self) -> Option<GameEndReason>
Default piece texture size:
384 × 128
Layout:
- Row 0: White pieces
- Row 1: Black pieces
Piece order:
King, Queen, Bishop, Knight, Rook, Pawn
Each tile is:
64 × 64
Code: MIT
Default chess pieces are adapted from work by Cburnett and jurgenwesterhof, licensed under CC BY-SA 3.0.
Attribution:
Chess Pieces
By jurgenwesterhof (adapted from work of Cburnett) – Template:SVG chess pieces, CC BY-SA 3.0
Pull requests and issues are welcome.
If you add features, please also:
- update documentation
- add tests where practical
- keep the API ergonomic