configmaxxing
This commit is contained in:
parent
414ac1ed4c
commit
22702ae8a4
55
Cargo.lock
generated
55
Cargo.lock
generated
@ -610,6 +610,9 @@ dependencies = [
|
|||||||
"rand",
|
"rand",
|
||||||
"rodio",
|
"rodio",
|
||||||
"sdl2",
|
"sdl2",
|
||||||
|
"serde",
|
||||||
|
"toml",
|
||||||
|
"xdg",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -669,6 +672,35 @@ dependencies = [
|
|||||||
"version-compare",
|
"version-compare",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde"
|
||||||
|
version = "1.0.218"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e8dfc9d19bdbf6d17e22319da49161d5d0108e4188e8b680aef6299eed22df60"
|
||||||
|
dependencies = [
|
||||||
|
"serde_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_derive"
|
||||||
|
version = "1.0.218"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_spanned"
|
||||||
|
version = "0.6.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "shlex"
|
name = "shlex"
|
||||||
version = "1.3.0"
|
version = "1.3.0"
|
||||||
@ -770,11 +802,26 @@ version = "0.1.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml"
|
||||||
|
version = "0.8.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
"serde_spanned",
|
||||||
|
"toml_datetime",
|
||||||
|
"toml_edit",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml_datetime"
|
name = "toml_datetime"
|
||||||
version = "0.6.8"
|
version = "0.6.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
|
checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml_edit"
|
name = "toml_edit"
|
||||||
@ -783,6 +830,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474"
|
checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap",
|
"indexmap",
|
||||||
|
"serde",
|
||||||
|
"serde_spanned",
|
||||||
"toml_datetime",
|
"toml_datetime",
|
||||||
"winnow",
|
"winnow",
|
||||||
]
|
]
|
||||||
@ -1094,6 +1143,12 @@ dependencies = [
|
|||||||
"bitflags 2.9.0",
|
"bitflags 2.9.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "xdg"
|
||||||
|
version = "2.5.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "213b7324336b53d2414b2db8537e56544d981803139155afa84f76eeebb7a546"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerocopy"
|
name = "zerocopy"
|
||||||
version = "0.7.35"
|
version = "0.7.35"
|
||||||
|
@ -6,6 +6,9 @@ edition = "2021"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
rand = "0.9.0"
|
rand = "0.9.0"
|
||||||
rodio = "0.20.1"
|
rodio = "0.20.1"
|
||||||
|
serde = { version = "1.0.218", features = ["serde_derive"] }
|
||||||
|
toml = "0.8.20"
|
||||||
|
xdg = "2.5.2"
|
||||||
|
|
||||||
[dependencies.sdl2]
|
[dependencies.sdl2]
|
||||||
version = "0.37.0"
|
version = "0.37.0"
|
||||||
|
340
src/gui/sdl.rs
340
src/gui/sdl.rs
@ -6,6 +6,8 @@ use sdl2::pixels::Color;
|
|||||||
use sdl2::rect::Rect;
|
use sdl2::rect::Rect;
|
||||||
use sdl2::render::{Texture, TextureCreator, WindowCanvas};
|
use sdl2::render::{Texture, TextureCreator, WindowCanvas};
|
||||||
use sdl2::ttf::Sdl2TtfContext;
|
use sdl2::ttf::Sdl2TtfContext;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::fs;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use super::audio::{self};
|
use super::audio::{self};
|
||||||
@ -111,11 +113,228 @@ impl UiCtx<String> for SdlUiCtx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
#[serde(tag = "key")]
|
||||||
|
enum Key {
|
||||||
|
Zero,
|
||||||
|
One,
|
||||||
|
Two,
|
||||||
|
Three,
|
||||||
|
Four,
|
||||||
|
Five,
|
||||||
|
Six,
|
||||||
|
Seven,
|
||||||
|
Eight,
|
||||||
|
Nine,
|
||||||
|
A,
|
||||||
|
B,
|
||||||
|
C,
|
||||||
|
D,
|
||||||
|
E,
|
||||||
|
F,
|
||||||
|
G,
|
||||||
|
H,
|
||||||
|
I,
|
||||||
|
J,
|
||||||
|
K,
|
||||||
|
L,
|
||||||
|
M,
|
||||||
|
N,
|
||||||
|
O,
|
||||||
|
P,
|
||||||
|
Q,
|
||||||
|
R,
|
||||||
|
S,
|
||||||
|
T,
|
||||||
|
U,
|
||||||
|
V,
|
||||||
|
W,
|
||||||
|
X,
|
||||||
|
Y,
|
||||||
|
Z,
|
||||||
|
Up,
|
||||||
|
Down,
|
||||||
|
Left,
|
||||||
|
Right,
|
||||||
|
Enter,
|
||||||
|
Backspace,
|
||||||
|
Space,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Key {
|
||||||
|
fn from_sdl_keycode(keycode: Keycode) -> Option<Key> {
|
||||||
|
let v = match keycode {
|
||||||
|
Keycode::Num0 | Keycode::Kp0 => Key::Zero,
|
||||||
|
Keycode::Num1 | Keycode::Kp1 => Key::One,
|
||||||
|
Keycode::Num2 | Keycode::Kp2 => Key::Two,
|
||||||
|
Keycode::Num3 | Keycode::Kp3 => Key::Three,
|
||||||
|
Keycode::Num4 | Keycode::Kp4 => Key::Four,
|
||||||
|
Keycode::Num5 | Keycode::Kp5 => Key::Five,
|
||||||
|
Keycode::Num6 | Keycode::Kp6 => Key::Six,
|
||||||
|
Keycode::Num7 | Keycode::Kp7 => Key::Seven,
|
||||||
|
Keycode::Num8 | Keycode::Kp8 => Key::Eight,
|
||||||
|
Keycode::Num9 | Keycode::Kp9 => Key::Nine,
|
||||||
|
Keycode::A => Key::A,
|
||||||
|
Keycode::B => Key::B,
|
||||||
|
Keycode::C => Key::C,
|
||||||
|
Keycode::D => Key::D,
|
||||||
|
Keycode::E => Key::E,
|
||||||
|
Keycode::F => Key::F,
|
||||||
|
Keycode::G => Key::G,
|
||||||
|
Keycode::H => Key::H,
|
||||||
|
Keycode::I => Key::I,
|
||||||
|
Keycode::J => Key::J,
|
||||||
|
Keycode::K => Key::K,
|
||||||
|
Keycode::L => Key::L,
|
||||||
|
Keycode::M => Key::M,
|
||||||
|
Keycode::N => Key::N,
|
||||||
|
Keycode::O => Key::O,
|
||||||
|
Keycode::P => Key::P,
|
||||||
|
Keycode::Q => Key::Q,
|
||||||
|
Keycode::R => Key::R,
|
||||||
|
Keycode::S => Key::S,
|
||||||
|
Keycode::T => Key::T,
|
||||||
|
Keycode::U => Key::U,
|
||||||
|
Keycode::V => Key::V,
|
||||||
|
Keycode::W => Key::W,
|
||||||
|
Keycode::X => Key::X,
|
||||||
|
Keycode::Y => Key::Y,
|
||||||
|
Keycode::Z => Key::Z,
|
||||||
|
Keycode::Up => Key::Up,
|
||||||
|
Keycode::Down => Key::Down,
|
||||||
|
Keycode::Left => Key::Left,
|
||||||
|
Keycode::Right => Key::Right,
|
||||||
|
Keycode::Return => Key::Enter,
|
||||||
|
Keycode::Backspace => Key::Backspace,
|
||||||
|
Keycode::Space => Key::Space,
|
||||||
|
_ => return None,
|
||||||
|
};
|
||||||
|
Some(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for Key {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
let val = match self {
|
||||||
|
Key::Zero => "0",
|
||||||
|
Key::One => "1",
|
||||||
|
Key::Two => "2",
|
||||||
|
Key::Three => "3",
|
||||||
|
Key::Four => "4",
|
||||||
|
Key::Five => "5",
|
||||||
|
Key::Six => "6",
|
||||||
|
Key::Seven => "7",
|
||||||
|
Key::Eight => "8",
|
||||||
|
Key::Nine => "9",
|
||||||
|
Key::A => "A",
|
||||||
|
Key::B => "B",
|
||||||
|
Key::C => "C",
|
||||||
|
Key::D => "D",
|
||||||
|
Key::E => "E",
|
||||||
|
Key::F => "F",
|
||||||
|
Key::G => "G",
|
||||||
|
Key::H => "H",
|
||||||
|
Key::I => "I",
|
||||||
|
Key::J => "J",
|
||||||
|
Key::K => "K",
|
||||||
|
Key::L => "L",
|
||||||
|
Key::M => "M",
|
||||||
|
Key::N => "N",
|
||||||
|
Key::O => "O",
|
||||||
|
Key::P => "P",
|
||||||
|
Key::Q => "Q",
|
||||||
|
Key::R => "R",
|
||||||
|
Key::S => "S",
|
||||||
|
Key::T => "T",
|
||||||
|
Key::U => "U",
|
||||||
|
Key::V => "V",
|
||||||
|
Key::W => "W",
|
||||||
|
Key::X => "X",
|
||||||
|
Key::Y => "Y",
|
||||||
|
Key::Z => "Z",
|
||||||
|
Key::Up => "Up",
|
||||||
|
Key::Down => "Down",
|
||||||
|
Key::Left => "Left",
|
||||||
|
Key::Right => "Right",
|
||||||
|
Key::Enter => "Enter",
|
||||||
|
Key::Backspace => "Backspace",
|
||||||
|
Key::Space => "Space",
|
||||||
|
};
|
||||||
|
write!(f, "{val}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
struct Config {
|
||||||
|
reimtris1_feature_parity: bool,
|
||||||
|
restart: Vec<Key>,
|
||||||
|
left: Vec<Key>,
|
||||||
|
right: Vec<Key>,
|
||||||
|
rotate_cw: Vec<Key>,
|
||||||
|
rotate_ccw: Vec<Key>,
|
||||||
|
soft_drop: Vec<Key>,
|
||||||
|
hard_drop: Vec<Key>,
|
||||||
|
swap: Vec<Key>,
|
||||||
|
pause: Vec<Key>,
|
||||||
|
toggle_mute: Vec<Key>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Config {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
reimtris1_feature_parity: false,
|
||||||
|
restart: vec![Key::Enter, Key::Space],
|
||||||
|
left: vec![Key::Left],
|
||||||
|
right: vec![Key::Right],
|
||||||
|
rotate_cw: vec![Key::X],
|
||||||
|
rotate_ccw: vec![Key::Z],
|
||||||
|
soft_drop: vec![Key::Down],
|
||||||
|
hard_drop: vec![Key::Space],
|
||||||
|
swap: vec![Key::C],
|
||||||
|
pause: vec![Key::P],
|
||||||
|
toggle_mute: vec![Key::M],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn config_from_file<P: AsRef<std::path::Path>>(path: P) -> Result<Config, String> {
|
||||||
|
let Some(config) = fs::read_to_string(path.as_ref()).ok() else {
|
||||||
|
let config = Config::default();
|
||||||
|
{
|
||||||
|
println!("could not get config! attempting to create default...");
|
||||||
|
let config = toml::to_string(&config).map_err(|err| err.to_string())?;
|
||||||
|
fs::write(path, config).map_err(|err| err.to_string())?;
|
||||||
|
}
|
||||||
|
return Ok(config);
|
||||||
|
};
|
||||||
|
let Some(config) = toml::from_str(&config).ok() else {
|
||||||
|
println!("womp womp, config contains an invalid config, attempting to reset to default...");
|
||||||
|
let config = Config::default();
|
||||||
|
{
|
||||||
|
let config = toml::to_string(&config).map_err(|err| err.to_string())?;
|
||||||
|
fs::write(path, config).map_err(|err| err.to_string())?;
|
||||||
|
}
|
||||||
|
return Ok(config);
|
||||||
|
};
|
||||||
|
Ok(config)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn start_game() -> Result<(), String> {
|
pub fn start_game() -> Result<(), String> {
|
||||||
let mut game = Game::new();
|
let mut game = Game::new();
|
||||||
let mut actions = ActionsHeld::new();
|
let mut actions = ActionsHeld::new();
|
||||||
let mut paused = false;
|
let mut paused = false;
|
||||||
|
|
||||||
|
let config = {
|
||||||
|
let base = xdg::BaseDirectories::new().map_err(|err| err.to_string())?;
|
||||||
|
let path = base
|
||||||
|
.place_config_file("reimtris2/config.toml")
|
||||||
|
.map_err(|err| err.to_string())?;
|
||||||
|
let config = config_from_file(path)?;
|
||||||
|
config
|
||||||
|
};
|
||||||
|
|
||||||
|
const FONT: &'static str = "resources/josenfin_sans_regular.ttf";
|
||||||
|
|
||||||
let audio_thread = audio::audio_thread();
|
let audio_thread = audio::audio_thread();
|
||||||
|
|
||||||
let sdl_context = sdl2::init()?;
|
let sdl_context = sdl2::init()?;
|
||||||
@ -125,6 +344,7 @@ pub fn start_game() -> Result<(), String> {
|
|||||||
let window = video_subsystem
|
let window = video_subsystem
|
||||||
.window("reimtris2", 1000, 800)
|
.window("reimtris2", 1000, 800)
|
||||||
.resizable()
|
.resizable()
|
||||||
|
.maximized()
|
||||||
.position_centered()
|
.position_centered()
|
||||||
.build()
|
.build()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@ -144,50 +364,77 @@ pub fn start_game() -> Result<(), String> {
|
|||||||
keycode: Some(Keycode::Escape),
|
keycode: Some(Keycode::Escape),
|
||||||
..
|
..
|
||||||
} => break 'running Ok(()),
|
} => break 'running Ok(()),
|
||||||
|
Event::MouseMotion { .. } => {
|
||||||
|
if config.reimtris1_feature_parity {
|
||||||
|
break 'running Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
Event::KeyDown {
|
Event::KeyDown {
|
||||||
keycode: Some(keycode),
|
keycode: Some(keycode),
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
let keycode = match keycode {
|
let Some(key) = Key::from_sdl_keycode(keycode) else {
|
||||||
Keycode::Return if !paused && game.game_over => {
|
continue;
|
||||||
game = Game::new();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Keycode::M => {
|
|
||||||
audio_thread.send(audio::Command::ToggleMuted).unwrap();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Keycode::P => {
|
|
||||||
paused = !paused;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Keycode::Left | Keycode::A => Action::Left,
|
|
||||||
Keycode::Right | Keycode::D => Action::Right,
|
|
||||||
Keycode::Down | Keycode::S => Action::SoftDrop,
|
|
||||||
Keycode::Space => Action::HardDrop,
|
|
||||||
Keycode::Z => Action::RotateCcw,
|
|
||||||
Keycode::X => Action::RotateCw,
|
|
||||||
Keycode::C => Action::Swap,
|
|
||||||
_ => continue,
|
|
||||||
};
|
};
|
||||||
actions.insert(keycode, game.ticks);
|
if config.pause.contains(&key) {
|
||||||
|
paused = !paused;
|
||||||
|
};
|
||||||
|
if config.restart.contains(&key) && !paused && game.game_over {
|
||||||
|
game = Game::new();
|
||||||
|
}
|
||||||
|
if config.toggle_mute.contains(&key) {
|
||||||
|
audio_thread.send(audio::Command::ToggleMuted).unwrap();
|
||||||
|
}
|
||||||
|
if config.left.contains(&key) {
|
||||||
|
actions.insert(Action::Left, game.ticks);
|
||||||
|
}
|
||||||
|
if config.right.contains(&key) {
|
||||||
|
actions.insert(Action::Right, game.ticks);
|
||||||
|
}
|
||||||
|
if config.soft_drop.contains(&key) {
|
||||||
|
actions.insert(Action::SoftDrop, game.ticks);
|
||||||
|
}
|
||||||
|
if config.hard_drop.contains(&key) {
|
||||||
|
actions.insert(Action::HardDrop, game.ticks);
|
||||||
|
}
|
||||||
|
if config.rotate_cw.contains(&key) {
|
||||||
|
actions.insert(Action::RotateCw, game.ticks);
|
||||||
|
}
|
||||||
|
if config.rotate_ccw.contains(&key) {
|
||||||
|
actions.insert(Action::RotateCcw, game.ticks);
|
||||||
|
}
|
||||||
|
if config.swap.contains(&key) {
|
||||||
|
actions.insert(Action::Swap, game.ticks);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Event::KeyUp {
|
Event::KeyUp {
|
||||||
keycode: Some(keycode),
|
keycode: Some(keycode),
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
let keycode = match keycode {
|
let Some(key) = Key::from_sdl_keycode(keycode) else {
|
||||||
Keycode::Left | Keycode::A => Action::Left,
|
continue;
|
||||||
Keycode::Right | Keycode::D => Action::Right,
|
|
||||||
Keycode::Down | Keycode::S => Action::SoftDrop,
|
|
||||||
Keycode::Space => Action::HardDrop,
|
|
||||||
Keycode::Z => Action::RotateCcw,
|
|
||||||
Keycode::X => Action::RotateCw,
|
|
||||||
Keycode::C => Action::Swap,
|
|
||||||
_ => continue,
|
|
||||||
};
|
};
|
||||||
actions.remove(&keycode);
|
if config.left.contains(&key) {
|
||||||
|
actions.remove(&Action::Left);
|
||||||
|
}
|
||||||
|
if config.right.contains(&key) {
|
||||||
|
actions.remove(&Action::Right);
|
||||||
|
}
|
||||||
|
if config.soft_drop.contains(&key) {
|
||||||
|
actions.remove(&Action::SoftDrop);
|
||||||
|
}
|
||||||
|
if config.hard_drop.contains(&key) {
|
||||||
|
actions.remove(&Action::HardDrop);
|
||||||
|
}
|
||||||
|
if config.rotate_cw.contains(&key) {
|
||||||
|
actions.remove(&Action::RotateCw);
|
||||||
|
}
|
||||||
|
if config.rotate_ccw.contains(&key) {
|
||||||
|
actions.remove(&Action::RotateCcw);
|
||||||
|
}
|
||||||
|
if config.swap.contains(&key) {
|
||||||
|
actions.remove(&Action::Swap);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
@ -195,17 +442,28 @@ pub fn start_game() -> Result<(), String> {
|
|||||||
|
|
||||||
ctx.draw_board(&game.board, &game.current_tetromino)?;
|
ctx.draw_board(&game.board, &game.current_tetromino)?;
|
||||||
ctx.draw_bag(&game.held_tetromino, &game.next_tetrominos)?;
|
ctx.draw_bag(&game.held_tetromino, &game.next_tetrominos)?;
|
||||||
|
ctx.draw_score(FONT, &game.score)?;
|
||||||
|
|
||||||
if paused {
|
if paused {
|
||||||
ctx.draw_important_text(
|
let keys = config
|
||||||
"resources/josenfin_sans_regular.ttf",
|
.pause
|
||||||
"game paused o_o... press [p] to unpause !!",
|
.iter()
|
||||||
)?;
|
.map(|v| v.to_string().to_lowercase())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(" | ");
|
||||||
|
let paused = format!("game paused o_o... press [{keys}] to unpause !!");
|
||||||
|
|
||||||
|
ctx.draw_important_text(FONT, paused)?;
|
||||||
} else if game.game_over {
|
} else if game.game_over {
|
||||||
ctx.draw_important_text(
|
let keys = config
|
||||||
"resources/josenfin_sans_regular.ttf",
|
.restart
|
||||||
"game over T_T... press [enter] 2 restart :D",
|
.iter()
|
||||||
)?;
|
.map(|v| v.to_string().to_lowercase())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(" | ");
|
||||||
|
|
||||||
|
let game_over = format!("game over T_T... press [{keys}] 2 restart :D");
|
||||||
|
ctx.draw_important_text(FONT, game_over)?;
|
||||||
} else {
|
} else {
|
||||||
let effects = game.step(&actions);
|
let effects = game.step(&actions);
|
||||||
effects.into_iter().for_each(|effect| {
|
effects.into_iter().for_each(|effect| {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
board::Board,
|
board::Board,
|
||||||
game::CurrentTetromino,
|
game::{CurrentTetromino, Score},
|
||||||
tetromino::{Direction, Tetromino},
|
tetromino::{Direction, Tetromino},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -180,6 +180,30 @@ pub trait GameUiCtx<Err>: UiCtx<Err> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn draw_score<P: AsRef<std::path::Path>>(&mut self, font: P, score: &Score) -> Result<(), Err> {
|
||||||
|
let (win_width, win_height) = self.window_size()?;
|
||||||
|
let board_width = self.tile_size() * Board::WIDTH as i32;
|
||||||
|
let board_height = self.tile_size() * Board::HEIGHT as i32;
|
||||||
|
let x = center(board_width, win_width) + board_width + self.tile_size();
|
||||||
|
let y = center(board_height, win_height) + self.tile_size();
|
||||||
|
|
||||||
|
let level = format!("level: {}", score.level);
|
||||||
|
let lines = format!("lines: {}", score.lines);
|
||||||
|
let points = format!("points: {}", score.points);
|
||||||
|
|
||||||
|
let level_size = self.text_size(font.as_ref(), &level)?;
|
||||||
|
let lines_size = self.text_size(font.as_ref(), &lines)?;
|
||||||
|
let points_size = self.text_size(font.as_ref(), &points)?;
|
||||||
|
|
||||||
|
self.fill_text(font.as_ref(), level, x, y, level_size.0, level_size.1)?;
|
||||||
|
let y = y + level_size.1 + self.tile_size();
|
||||||
|
self.fill_text(font.as_ref(), lines, x, y, lines_size.0, lines_size.1)?;
|
||||||
|
let y = y + lines_size.1 + self.tile_size();
|
||||||
|
self.fill_text(font.as_ref(), points, x, y, points_size.0, points_size.1)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn draw_board(&mut self, board: &Board, current: &CurrentTetromino) -> Result<(), Err> {
|
fn draw_board(&mut self, board: &Board, current: &CurrentTetromino) -> Result<(), Err> {
|
||||||
let (win_width, win_height) = self.window_size()?;
|
let (win_width, win_height) = self.window_size()?;
|
||||||
self.outline_rect(
|
self.outline_rect(
|
||||||
|
Loading…
Reference in New Issue
Block a user