-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Loading status checks…
chore: refactor codebase
1 parent
aa5fa66
commit 0dee83e
Showing
4 changed files
with
203 additions
and
139 deletions.
There are no files selected for viewing
File renamed without changes
File renamed without changes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,197 @@ | ||
use std::str::FromStr; | ||
|
||
use ataxx::{Board, File, Rank, Square}; | ||
use raylib::prelude::*; | ||
|
||
use strum::IntoEnumIterator; | ||
|
||
pub struct GuiBuilder { | ||
title: String, | ||
fen: String, | ||
width: i32, | ||
height: i32, | ||
scale: f32, | ||
} | ||
|
||
impl GuiBuilder { | ||
pub fn new() -> GuiBuilder { | ||
GuiBuilder { | ||
title: "Ataxx GUI".to_string(), | ||
fen: "x5o/7/7/7/7/7/o5x x 0 1".to_string(), | ||
width: 1280, | ||
height: 720, | ||
scale: 3.0, | ||
} | ||
} | ||
|
||
pub fn build(&self) -> Gui { | ||
let (mut raylib, thread) = raylib::init() | ||
.size(self.width, self.height) | ||
.title(&self.title) | ||
.build(); | ||
let textures = Textures::load(&mut raylib, &thread); | ||
let board = Board::from_str(&self.fen).unwrap(); | ||
|
||
Gui { | ||
raylib, | ||
thread, | ||
options: GuiOptions { | ||
width: self.width, | ||
height: self.height, | ||
scale: self.scale, | ||
board, | ||
textures, | ||
}, | ||
} | ||
} | ||
} | ||
|
||
pub struct Gui { | ||
raylib: RaylibHandle, | ||
thread: RaylibThread, | ||
|
||
options: GuiOptions, | ||
} | ||
|
||
impl Gui { | ||
pub fn new_drawer(&mut self) -> Drawer { | ||
Drawer { | ||
gui: &self.options, | ||
drawer: self.raylib.begin_drawing(&self.thread), | ||
} | ||
} | ||
|
||
pub fn should_quit(&self) -> bool { | ||
self.raylib.window_should_close() | ||
} | ||
} | ||
|
||
pub struct GuiOptions { | ||
width: i32, | ||
height: i32, | ||
|
||
scale: f32, | ||
|
||
board: ataxx::Board, | ||
|
||
textures: Textures, | ||
} | ||
|
||
pub struct Drawer<'a> { | ||
gui: &'a GuiOptions, | ||
drawer: RaylibDrawHandle<'a>, | ||
} | ||
|
||
const SQUARE_SIZE: f32 = 27.0; | ||
|
||
impl<'a> Drawer<'a> { | ||
pub fn draw(&mut self) { | ||
self.draw_board(); | ||
} | ||
|
||
pub fn draw_board(&mut self) { | ||
self.drawer.clear_background(Color::BLACK); | ||
|
||
for rank in Rank::iter().rev() { | ||
for file in File::iter() { | ||
self.draw_square(Square::new(file, rank)); | ||
} | ||
} | ||
|
||
let src_rec = Rectangle::new( | ||
0.0, | ||
0.0, | ||
self.gui.textures.border.width() as f32, | ||
self.gui.textures.border.height() as f32, | ||
); | ||
let dst_rec = Rectangle::new( | ||
self.gui.width as f32 / 2.0 | ||
- self.gui.textures.border.width() as f32 * self.gui.scale / 2.0, | ||
self.gui.height as f32 / 2.0 | ||
- self.gui.textures.border.height() as f32 * self.gui.scale / 2.0, | ||
self.gui.textures.border.width() as f32 * self.gui.scale, | ||
self.gui.textures.border.height() as f32 * self.gui.scale, | ||
); | ||
|
||
self.drawer.draw_texture_pro( | ||
&self.gui.textures.border, | ||
src_rec, | ||
dst_rec, | ||
Vector2::zero(), | ||
0.0, | ||
Color::WHITE, | ||
); | ||
} | ||
|
||
pub fn draw_square(&mut self, sq: Square) { | ||
let pc = self.gui.board.at(sq); | ||
let a = match pc { | ||
ataxx::Color::White => 0.0, | ||
ataxx::Color::Black => 1.0, | ||
ataxx::Color::None => 0.0, // unused | ||
}; | ||
|
||
let top_left = Vector2::new( | ||
self.gui.width as f32 / 2.0 - 183.0 * self.gui.scale / 2.0 | ||
+ sq.file() as u32 as f32 * (SQUARE_SIZE - 1.0) * self.gui.scale, | ||
self.gui.height as f32 / 2.0 - 183.0 * self.gui.scale / 2.0 | ||
+ sq.rank() as u32 as f32 * (SQUARE_SIZE - 1.0) * self.gui.scale, | ||
); | ||
|
||
let sq_src_rec = Rectangle::new(0.0, 0.0, SQUARE_SIZE, SQUARE_SIZE); | ||
let pc_src_rec = Rectangle::new(a * SQUARE_SIZE, 0.0, SQUARE_SIZE, SQUARE_SIZE); | ||
|
||
let dst_rec = Rectangle::new( | ||
top_left.x, | ||
top_left.y, | ||
SQUARE_SIZE * self.gui.scale, | ||
SQUARE_SIZE * self.gui.scale, | ||
); | ||
|
||
self.drawer.draw_texture_pro( | ||
&self.gui.textures.square, | ||
sq_src_rec, | ||
dst_rec, | ||
Vector2::new(0.0, 0.0), | ||
0.0, | ||
Color::WHITE, | ||
); | ||
|
||
if pc == ataxx::Color::None { | ||
return; | ||
} | ||
|
||
self.drawer.draw_texture_pro( | ||
&self.gui.textures.pieces, | ||
pc_src_rec, | ||
dst_rec, | ||
Vector2::new(0.0, 0.0), | ||
0.0, | ||
Color::WHITE, | ||
); | ||
} | ||
} | ||
|
||
pub struct Textures { | ||
pieces: Texture2D, | ||
square: Texture2D, | ||
border: Texture2D, | ||
} | ||
|
||
macro_rules! load_png_texture { | ||
($rl:expr, $thread:expr, $file:expr) => {{ | ||
let raw = include_bytes!($file); | ||
let img = Image::load_image_from_mem(".png", &raw.to_vec(), raw.len() as i32).unwrap(); | ||
$rl.load_texture_from_image($thread, &img).unwrap() | ||
}}; | ||
} | ||
|
||
impl Textures { | ||
pub fn load(rl: &mut RaylibHandle, thread: &RaylibThread) -> Textures { | ||
Textures { | ||
pieces: load_png_texture!(rl, thread, "../assets/ataxx-pieces.png"), | ||
square: load_png_texture!(rl, thread, "../assets/ataxx-square.png"), | ||
border: load_png_texture!(rl, thread, "../assets/ataxx-border.png"), | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,144 +1,11 @@ | ||
use std::path::Path; | ||
use std::str::FromStr; | ||
|
||
use strum::IntoEnumIterator; | ||
|
||
use ataxx::{Board, File, Rank, Square}; | ||
|
||
use raylib::prelude::*; | ||
|
||
const SCALE: f32 = 3.0; | ||
const SQUARE_SIZE: f32 = 27.0; | ||
|
||
const WIDTH: i32 = 1280; | ||
const HEIGHT: i32 = 720; | ||
mod gui; | ||
use gui::*; | ||
|
||
fn main() { | ||
let board = Board::from_str("x5o/7/7/7/7/7/o5x x 0 1").unwrap(); | ||
let (mut rl, thread) = raylib::init() | ||
.size(WIDTH, HEIGHT) | ||
.title("Ataxx GUI") | ||
.build(); | ||
|
||
while !rl.window_should_close() { | ||
draw_board(&mut rl, &thread, &board).unwrap(); | ||
} | ||
} | ||
|
||
fn draw_board(rl: &mut RaylibHandle, thread: &RaylibThread, board: &Board) -> Result<(), String> { | ||
let squares_txt = load_texture(rl, thread, "ataxx-squares.png")?; | ||
let pieces_txt = load_texture(rl, thread, "ataxx-pieces.png")?; | ||
let border_txt = load_texture(rl, thread, "ataxx-board-border.png")?; | ||
|
||
let mut d = rl.begin_drawing(thread); | ||
d.clear_background(Color::BLACK); | ||
|
||
let top_left = Vector2::new( | ||
WIDTH as f32 / 2.0 - 183.0 * SCALE / 2.0, | ||
HEIGHT as f32 / 2.0 - 183.0 * SCALE / 2.0, | ||
); | ||
for rank in Rank::iter().rev() { | ||
for file in File::iter() { | ||
let square = Square::new(file, rank); | ||
draw_square( | ||
&mut d, | ||
&squares_txt, | ||
&pieces_txt, | ||
Vector2::new( | ||
top_left.x + file as u32 as f32 * (SQUARE_SIZE - 1.0) * SCALE, | ||
top_left.y + rank as u32 as f32 * (SQUARE_SIZE - 1.0) * SCALE, | ||
), | ||
board.at(square), | ||
)?; | ||
} | ||
} | ||
let mut gui = GuiBuilder::new().build(); | ||
|
||
let src_rec = Rectangle::new( | ||
0.0, | ||
0.0, | ||
border_txt.width() as f32, | ||
border_txt.height() as f32, | ||
); | ||
let dst_rec = Rectangle::new( | ||
WIDTH as f32 / 2.0 - border_txt.width() as f32 * SCALE / 2.0, | ||
HEIGHT as f32 / 2.0 - border_txt.height() as f32 * SCALE / 2.0, | ||
border_txt.width() as f32 * SCALE, | ||
border_txt.height() as f32 * SCALE, | ||
); | ||
|
||
d.draw_texture_pro( | ||
&border_txt, | ||
src_rec, | ||
dst_rec, | ||
Vector2::zero(), | ||
0.0, | ||
Color::WHITE, | ||
); | ||
|
||
Ok(()) | ||
} | ||
|
||
fn draw_square( | ||
d: &mut RaylibDrawHandle, | ||
sq_txt: &Texture2D, | ||
pc_txt: &Texture2D, | ||
top_left: Vector2, | ||
pc: ataxx::Color, | ||
) -> Result<(), String> { | ||
let a = match pc { | ||
ataxx::Color::White => 0.0, | ||
ataxx::Color::Black => 1.0, | ||
ataxx::Color::None => 0.0, // unused | ||
}; | ||
|
||
let sq_src_rec = Rectangle::new(0.0, 0.0, SQUARE_SIZE, SQUARE_SIZE); | ||
let pc_src_rec = Rectangle::new(a * SQUARE_SIZE, 0.0, SQUARE_SIZE, SQUARE_SIZE); | ||
|
||
let dst_rec = Rectangle::new( | ||
top_left.x, | ||
top_left.y, | ||
SQUARE_SIZE * SCALE, | ||
SQUARE_SIZE * SCALE, | ||
); | ||
|
||
d.draw_texture_pro( | ||
sq_txt, | ||
sq_src_rec, | ||
dst_rec, | ||
Vector2::new(0.0, 0.0), | ||
0.0, | ||
Color::WHITE, | ||
); | ||
|
||
if pc == ataxx::Color::None { | ||
return Ok(()); | ||
while !gui.should_quit() { | ||
let mut drawer = gui.new_drawer(); | ||
drawer.draw(); | ||
} | ||
|
||
d.draw_texture_pro( | ||
pc_txt, | ||
pc_src_rec, | ||
dst_rec, | ||
Vector2::new(0.0, 0.0), | ||
0.0, | ||
Color::WHITE, | ||
); | ||
|
||
Ok(()) | ||
} | ||
|
||
fn load_texture( | ||
rl: &mut RaylibHandle, | ||
thread: &RaylibThread, | ||
name: &str, | ||
) -> Result<Texture2D, String> { | ||
let path = Path::new(file!()) | ||
.parent() | ||
.unwrap() | ||
.parent() | ||
.unwrap() | ||
.to_str() | ||
.unwrap() | ||
.to_owned(); | ||
let img = Image::load_image(&(path + "/assets/" + name))?; | ||
rl.load_texture_from_image(thread, &img) | ||
} |