From 1ff2d6c8bf138ba460dec4258c55e72a1945984f Mon Sep 17 00:00:00 2001 From: windysha <834828088@qq.com> Date: Wed, 24 Jan 2024 00:37:52 +0800 Subject: [PATCH] 1. add 7 bags random system; 2. optimize binary file size; 3. fix some bugs --- Cargo.lock | 357 --------------------------------------------------- Cargo.toml | 16 +-- src/brick.rs | 36 +++++- src/game.rs | 247 ++++++++++++++++++++++------------- 4 files changed, 196 insertions(+), 460 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c223a2a..8add391 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -184,25 +184,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "arboard" -version = "3.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aafb29b107435aa276664c1db8954ac27a6e105cdad3c88287a199eb0e313c08" -dependencies = [ - "clipboard-win", - "core-graphics", - "image", - "log", - "objc", - "objc-foundation", - "objc_id", - "parking_lot", - "thiserror", - "winapi", - "x11rb", -] - [[package]] name = "arrayref" version = "0.3.7" @@ -358,45 +339,6 @@ dependencies = [ "bevy_internal", ] -[[package]] -name = "bevy-inspector-egui" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d65b98d6fca1209c36c4d403c377f303aad22d940281fe1a9e431217516f0622" -dependencies = [ - "bevy-inspector-egui-derive", - "bevy_app", - "bevy_asset", - "bevy_core", - "bevy_core_pipeline", - "bevy_ecs", - "bevy_egui", - "bevy_hierarchy", - "bevy_log", - "bevy_math", - "bevy_pbr", - "bevy_reflect", - "bevy_render", - "bevy_utils", - "bevy_window", - "egui", - "image", - "once_cell", - "pretty-type-name", - "smallvec", -] - -[[package]] -name = "bevy-inspector-egui-derive" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec800b7cf98151b5dbff80f0eb6dffcb4bcfceef6e457888b395ead4eb7e75ba" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] - [[package]] name = "bevy_a11y" version = "0.12.1" @@ -602,19 +544,6 @@ dependencies = [ "syn 2.0.48", ] -[[package]] -name = "bevy_egui" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85450af551b7e1cb766f710763b60a12a82ffd6323945a8f776c6334c59ccdc1" -dependencies = [ - "arboard", - "bevy", - "egui", - "thread_local", - "webbrowser", -] - [[package]] name = "bevy_encase_derive" version = "0.12.1" @@ -1330,17 +1259,6 @@ dependencies = [ "libloading 0.8.1", ] -[[package]] -name = "clipboard-win" -version = "4.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7191c27c2357d9b7ef96baac1773290d4ca63b24205b82a3fd8a0637afcf0362" -dependencies = [ - "error-code", - "str-buf", - "winapi", -] - [[package]] name = "codespan-reporting" version = "0.11.1" @@ -1563,35 +1481,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" -[[package]] -name = "ecolor" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfdf4e52dbbb615cfd30cf5a5265335c217b5fd8d669593cea74a517d9c605af" -dependencies = [ - "bytemuck", -] - -[[package]] -name = "egui" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bd69fed5fcf4fbb8225b24e80ea6193b61e17a625db105ef0c4d71dde6eb8b7" -dependencies = [ - "ahash", - "epaint", - "nohash-hasher", -] - -[[package]] -name = "emath" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ef2b29de53074e575c18b694167ccbe6e5191f7b25fe65175a0d905a32eeec0" -dependencies = [ - "bytemuck", -] - [[package]] name = "encase" version = "0.6.1" @@ -1624,21 +1513,6 @@ dependencies = [ "syn 2.0.48", ] -[[package]] -name = "epaint" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58067b840d009143934d91d8dcb8ded054d8301d7c11a517ace0a99bb1e1595e" -dependencies = [ - "ab_glyph", - "ahash", - "bytemuck", - "ecolor", - "emath", - "nohash-hasher", - "parking_lot", -] - [[package]] name = "equivalent" version = "1.0.1" @@ -1654,16 +1528,6 @@ dependencies = [ "serde", ] -[[package]] -name = "error-code" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64f18991e7bf11e7ffee451b5318b5c1a73c52d0d0ada6e5a3017c8c1ced6a21" -dependencies = [ - "libc", - "str-buf", -] - [[package]] name = "euclid" version = "0.22.9" @@ -1788,15 +1652,6 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" -[[package]] -name = "form_urlencoded" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" -dependencies = [ - "percent-encoding", -] - [[package]] name = "futures-core" version = "0.3.30" @@ -1837,16 +1692,6 @@ dependencies = [ "pin-project-lite", ] -[[package]] -name = "gethostname" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb65d4ba3173c56a500b555b532f72c42e8d1fe64962b518897f8959fae2c177" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "getrandom" version = "0.2.12" @@ -2091,25 +1936,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" -[[package]] -name = "home" -version = "0.5.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" -dependencies = [ - "windows-sys 0.52.0", -] - -[[package]] -name = "idna" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - [[package]] name = "image" version = "0.24.8" @@ -2121,7 +1947,6 @@ dependencies = [ "color_quant", "num-traits", "png", - "tiff", ] [[package]] @@ -2226,22 +2051,6 @@ dependencies = [ "walkdir", ] -[[package]] -name = "jni" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" -dependencies = [ - "cesu8", - "cfg-if", - "combine", - "jni-sys", - "log", - "thiserror", - "walkdir", - "windows-sys 0.45.0", -] - [[package]] name = "jni-sys" version = "0.3.0" @@ -2257,12 +2066,6 @@ dependencies = [ "libc", ] -[[package]] -name = "jpeg-decoder" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" - [[package]] name = "js-sys" version = "0.3.67" @@ -2411,15 +2214,6 @@ version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" -[[package]] -name = "memoffset" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" -dependencies = [ - "autocfg", -] - [[package]] name = "metal" version = "0.26.0" @@ -2544,18 +2338,6 @@ dependencies = [ "libc", ] -[[package]] -name = "nix" -version = "0.26.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" -dependencies = [ - "bitflags 1.3.2", - "cfg-if", - "libc", - "memoffset", -] - [[package]] name = "nix" version = "0.27.1" @@ -2567,12 +2349,6 @@ dependencies = [ "libc", ] -[[package]] -name = "nohash-hasher" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" - [[package]] name = "nom" version = "7.1.3" @@ -2680,17 +2456,6 @@ dependencies = [ "objc_exception", ] -[[package]] -name = "objc-foundation" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" -dependencies = [ - "block", - "objc", - "objc_id", -] - [[package]] name = "objc-sys" version = "0.2.0-beta.2" @@ -2726,15 +2491,6 @@ dependencies = [ "cc", ] -[[package]] -name = "objc_id" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" -dependencies = [ - "objc", -] - [[package]] name = "object" version = "0.32.2" @@ -2914,12 +2670,6 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" -[[package]] -name = "pretty-type-name" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f73cdaf19b52e6143685c3606206e114a4dfa969d6b14ec3894c88eb38bd4b" - [[package]] name = "proc-macro-crate" version = "1.3.1" @@ -3252,12 +3002,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" -[[package]] -name = "str-buf" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e08d8363704e6c71fc928674353e6b7c23dcea9d82d7012c8faf2a3a025f8d0" - [[package]] name = "svg_fmt" version = "0.4.1" @@ -3326,7 +3070,6 @@ name = "tetris" version = "0.1.0" dependencies = [ "bevy", - "bevy-inspector-egui", "lazy_static", "rand", ] @@ -3381,17 +3124,6 @@ dependencies = [ "once_cell", ] -[[package]] -name = "tiff" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e" -dependencies = [ - "flate2", - "jpeg-decoder", - "weezl", -] - [[package]] name = "tinyvec" version = "1.6.0" @@ -3534,27 +3266,12 @@ dependencies = [ "static_assertions", ] -[[package]] -name = "unicode-bidi" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" - [[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" -[[package]] -name = "unicode-normalization" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" -dependencies = [ - "tinyvec", -] - [[package]] name = "unicode-width" version = "0.1.11" @@ -3567,17 +3284,6 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" -[[package]] -name = "url" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", -] - [[package]] name = "uuid" version = "1.7.0" @@ -3715,29 +3421,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "webbrowser" -version = "0.8.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82b2391658b02c27719fc5a0a73d6e696285138e8b12fba9d4baa70451023c71" -dependencies = [ - "core-foundation", - "home", - "jni 0.21.1", - "log", - "ndk-context", - "objc", - "raw-window-handle", - "url", - "web-sys", -] - -[[package]] -name = "weezl" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb" - [[package]] name = "wgpu" version = "0.17.2" @@ -3868,15 +3551,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "winapi-wsapoll" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c17110f57155602a80dca10be03852116403c9ff3cd25b079d666f2aa3df6e" -dependencies = [ - "winapi", -] - [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -3971,15 +3645,6 @@ dependencies = [ "windows-targets 0.48.5", ] -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets 0.52.0", -] - [[package]] name = "windows-targets" version = "0.42.2" @@ -4201,28 +3866,6 @@ dependencies = [ "pkg-config", ] -[[package]] -name = "x11rb" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1641b26d4dec61337c35a1b1aaf9e3cba8f46f0b43636c609ab0291a648040a" -dependencies = [ - "gethostname", - "nix 0.26.4", - "winapi", - "winapi-wsapoll", - "x11rb-protocol", -] - -[[package]] -name = "x11rb-protocol" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82d6c3f9a0fb6701fab8f6cea9b0c0bd5d6876f1f89f7fada07e558077c344bc" -dependencies = [ - "nix 0.26.4", -] - [[package]] name = "xi-unicode" version = "0.3.0" diff --git a/Cargo.toml b/Cargo.toml index 2e9d3da..b1329c0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,18 +13,16 @@ opt-level = 1 # https://github.com/johnthagen/min-sized-rust [profile.release] -lto = "thin" -strip = true # Automatically strip symbols from the binary. -opt-level = "z" # Optimize for size. -panic = "abort" +opt-level = "z" +debug = false +lto = true +debug-assertions = false codegen-units = 1 - -# Enable high optimizations for dependencies (incl. Bevy), but not for our code: -[profile.dev.package."*"] -opt-level = 3 +panic = "abort" +strip = true [dependencies] bevy = "0.12.1" -bevy-inspector-egui="0.21.0" +# bevy-inspector-egui="0.21.0" rand = "0.8.5" lazy_static = "1.4" diff --git a/src/brick.rs b/src/brick.rs index 5f9fbce..9e63a86 100644 --- a/src/brick.rs +++ b/src/brick.rs @@ -1,3 +1,5 @@ +use std::collections::VecDeque; +use std::sync::{Mutex, OnceLock}; use rand::prelude::*; @@ -20,10 +22,34 @@ pub enum BrickType { pub struct Brick(pub BrickType, pub [Position; 4]); impl Brick { - pub fn new() -> Self { - let type_size = BRICKS_MAP.len(); - // choose a brick type - let type_index: usize = rand::thread_rng().gen_range(0..type_size); + pub fn new(use_bag7: bool) -> Self { + let type_index: usize; + if use_bag7 { + // use 7 bag randomization algorithm + static S_BRICK_BAG_VEC: OnceLock>> = OnceLock::new(); + let brick_bag_vec = S_BRICK_BAG_VEC.get_or_init(|| { + let mut m = VecDeque::new(); + m.reserve(7); + Mutex::new(m) + }); + + let mut data = brick_bag_vec.lock().unwrap(); + + if data.len() == 0 { + let mut items = vec![0, 1, 2, 3, 4, 5, 6]; + let mut rng = thread_rng(); + items.shuffle(&mut rng); + + for item in items { + data.push_back(item); + } + } + type_index = data.pop_front().unwrap_or(0); + } else { + // use normal randomization algorithm + type_index = rand::thread_rng().gen_range(0..BRICKS_MAP.len()); + } + let brick_type = match type_index { 0 => BrickType::O, 1 => BrickType::I, @@ -65,4 +91,4 @@ impl Brick { brick_kind[(rotate_index + rotate_len - 1) % rotate_len] } } -} \ No newline at end of file +} diff --git a/src/game.rs b/src/game.rs index a2492a3..899d928 100644 --- a/src/game.rs +++ b/src/game.rs @@ -1,6 +1,6 @@ use bevy::{ prelude::{OnEnter, OnExit, Plugin, Update}, - window::{WindowFocused}, + window::WindowFocused, }; use crate::{ @@ -10,7 +10,7 @@ use crate::{ data::PauseStateRes, menu::{GameLevelRes, GameSelectedLevel}, position::Position, - utils::{despawn_with_component, get_speed, get_level, get_score}, + utils::{despawn_with_component, get_level, get_score, get_speed}, GameState, }; @@ -43,6 +43,7 @@ pub struct GameScoresRes { static ENABLE_SHOWING_SHADOW_BRICK: AtomicBool = AtomicBool::new(true); static ENABLE_SHOWING_BOARD_LINES: AtomicBool = AtomicBool::new(true); +static ENABLE_7_BAG_RANDOMIZATION: AtomicBool = AtomicBool::new(true); lazy_static! { pub static ref BRICK_COLOR_MAP: HashMap = HashMap::from([ @@ -106,18 +107,28 @@ impl Plugin for GamePlugin { .insert_resource(PauseStateRes::new(false, false)) .add_systems( Update, - ( + (( brick_fall_down_system, + apply_deferred, rotate_brick_key_event, + apply_deferred, + hard_drop_key_event, + apply_deferred, + move_brick_key_event, + apply_deferred, soft_drop_key_event, ) + .chain(),) .run_if(is_not_pause_state.and_then(in_state(GameState::Game))), ) .add_systems( Update, pause_state_changed_event.run_if(in_state(GameState::Game)), ) - .add_systems(OnEnter(GameState::Game), (setup_game_data, apply_deferred, setup_tetris).chain()) + .add_systems( + OnEnter(GameState::Game), + (setup_game_data, apply_deferred, setup_tetris).chain(), + ) .add_systems( OnExit(GameState::Game), despawn_with_component::, @@ -167,6 +178,12 @@ fn setup_game_data( Ordering::Relaxed, Ordering::Relaxed, ); + let _ = ENABLE_7_BAG_RANDOMIZATION.compare_exchange( + false, + true, + Ordering::Relaxed, + Ordering::Relaxed, + ); } GameSelectedLevel::Normal => { duration = DEFAULT_NORMAL_FALLING_SPEED; @@ -182,6 +199,12 @@ fn setup_game_data( Ordering::Relaxed, Ordering::Relaxed, ); + let _ = ENABLE_7_BAG_RANDOMIZATION.compare_exchange( + false, + true, + Ordering::Relaxed, + Ordering::Relaxed, + ); } GameSelectedLevel::Hard => { duration = DEFAULT_HARD_FALLING_SPEED; @@ -197,6 +220,12 @@ fn setup_game_data( Ordering::Relaxed, Ordering::Relaxed, ); + let _ = ENABLE_7_BAG_RANDOMIZATION.compare_exchange( + true, + false, + Ordering::Relaxed, + Ordering::Relaxed, + ); } } @@ -212,14 +241,11 @@ fn setup_game_data( game_scores_stored.lines = 0; } -fn setup_tetris( - mut commands: Commands, - asset_server: Res, -) { +fn setup_tetris(mut commands: Commands, asset_server: Res) { spawn_board(&mut commands, &Board::new()); spawn_game_info(&mut commands, &asset_server); spawn_next_brick_title(&mut commands, &asset_server); - spawn_next_brick(&mut commands, Brick::new()); + spawn_next_brick(&mut commands, Brick::new(ENABLE_7_BAG_RANDOMIZATION.load(Ordering::Relaxed))); } #[inline] @@ -261,28 +287,21 @@ fn brick_fall_down_system( let create_new_next_brick_func = |commands: &mut Commands| { commands.entity(next_brick.0).despawn_recursive(); - spawn_next_brick(commands, Brick::new()); + spawn_next_brick(commands, Brick::new(ENABLE_7_BAG_RANDOMIZATION.load(Ordering::Relaxed))); }; let Ok(mut moving_brick) = moving_brick_query.get_single_mut() else { - // in the initial state, no moving exists, so create a new one and the shadow brick - let brick = &next_brick.1.0; + // in the initial state, no moving exists, so create a new one and the shadow brick + let brick = &next_brick.1 .0; let init_brick_position = create_brick_start_position(&brick.0); - let bottom_pos = board.1.0.get_bottom_valid_brick_pos( - brick, - &init_brick_position); - - spawn_brick( - &mut commands, - brick, - &init_brick_position - ); - spawn_shadow_brick( - &mut commands, - brick, - &bottom_pos - ); + let bottom_pos = board + .1 + .0 + .get_bottom_valid_brick_pos(brick, &init_brick_position); + + spawn_brick(&mut commands, brick, &init_brick_position); + spawn_shadow_brick(&mut commands, brick, &bottom_pos); // recreate the next brick create_new_next_brick_func(&mut commands); @@ -396,6 +415,30 @@ fn soft_drop_key_event( } } +fn hard_drop_key_event( + keyboard_input: Res>, + mut moving_brick_query: Query<(Entity, &mut MovingBrickBundle, &mut Transform)>, + board_query: Query<&mut BoardBundle>, +) { + if keyboard_input.just_pressed(KeyCode::Space) { + let Ok(mut moving_brick) = moving_brick_query.get_single_mut() else { + return; + }; + let Ok(board) = board_query.get_single() else { + return; + }; + let current_brick = moving_brick.1.brick; + let moving_pos = &mut moving_brick.1.moving_pos; + + while board.0.is_valid_brick(¤t_brick, &moving_pos.down()) { + moving_pos.down_assign(); + moving_brick.2.translation.y -= BLOCK_WIDTH; + } + // hard dropped, then it cannot be moved again + moving_brick.1.movable = false; + } +} + fn rotate_brick_key_event( mut commands: Commands, keyboard_input: Res>, @@ -403,12 +446,7 @@ fn rotate_brick_key_event( shadow_brick_query: Query>, board_query: Query<&mut BoardBundle>, ) { - if !(keyboard_input.just_pressed(KeyCode::Up) - || keyboard_input.just_pressed(KeyCode::W) - || keyboard_input.just_pressed(KeyCode::Left) - || keyboard_input.just_pressed(KeyCode::Right) - || keyboard_input.just_pressed(KeyCode::Space)) - { + if !(keyboard_input.just_pressed(KeyCode::Up)) { return; } @@ -425,65 +463,77 @@ fn rotate_brick_key_event( return; } - if keyboard_input.just_pressed(KeyCode::Up) || keyboard_input.just_pressed(KeyCode::W) { - let rotated_brick = moving_brick.1.brick.rotate_right(); - let moving_pos = &mut moving_brick.1.moving_pos; + let rotated_brick = moving_brick.1.brick.rotate_right(); + let moving_pos = &mut moving_brick.1.moving_pos; - if board + if board + .0 + .is_valid_brick_for_rotation(&rotated_brick, moving_pos) + { + let bottom_pos = board .0 - .is_valid_brick_for_rotation(&rotated_brick, moving_pos) - { - let bottom_pos = board - .0 - .get_bottom_valid_brick_pos(&rotated_brick, moving_pos); - spawn_brick(&mut commands, &rotated_brick, moving_pos); - spawn_shadow_brick(&mut commands, &rotated_brick, &bottom_pos); - if let Ok(shadow_bricks) = shadow_brick_query.get_single() { - commands.entity(shadow_bricks).despawn_recursive(); - } - commands.entity(moving_brick.0).despawn_recursive(); + .get_bottom_valid_brick_pos(&rotated_brick, moving_pos); + spawn_brick(&mut commands, &rotated_brick, moving_pos); + spawn_shadow_brick(&mut commands, &rotated_brick, &bottom_pos); + if let Ok(shadow_bricks) = shadow_brick_query.get_single() { + commands.entity(shadow_bricks).despawn_recursive(); } - } else if keyboard_input.just_pressed(KeyCode::Left) - || keyboard_input.just_pressed(KeyCode::Right) + commands.entity(moving_brick.0).despawn_recursive(); + } +} + +fn move_brick_key_event( + mut commands: Commands, + keyboard_input: Res>, + mut moving_brick_query: Query<(Entity, &mut MovingBrickBundle, &mut Transform)>, + shadow_brick_query: Query>, + board_query: Query<&mut BoardBundle>, +) { + if !(keyboard_input.just_pressed(KeyCode::Left) || keyboard_input.just_pressed(KeyCode::Right)) { - let is_left_moving = keyboard_input.just_pressed(KeyCode::Left); + return; + } - let current_brick = moving_brick.1.brick; - let moving_pos = moving_brick.1.moving_pos; + // use "let else" + let Ok(mut moving_brick) = moving_brick_query.get_single_mut() else { + return; + }; + let Ok(board) = board_query.get_single() else { + return; + }; - let next_pos = if is_left_moving { - moving_pos.left() - } else { - moving_pos.right() - }; + // when the brick fast dropped down, it become non movable. + if !moving_brick.1.movable { + return; + } - if board.0.is_valid_brick(¤t_brick, &next_pos) { - moving_brick.1.moving_pos = next_pos; - if is_left_moving { - moving_brick.2.translation.x -= BLOCK_WIDTH; - } else { - moving_brick.2.translation.x += BLOCK_WIDTH; - } - // dismiss shadow brick - if let Ok(shadow_bricks) = shadow_brick_query.get_single() { - commands.entity(shadow_bricks).despawn_recursive(); - } - let bottom_pos = board - .0 - .get_bottom_valid_brick_pos(¤t_brick, &next_pos); - // redraw shadow brick - spawn_shadow_brick(&mut commands, ¤t_brick, &bottom_pos); - } - } else if keyboard_input.just_pressed(KeyCode::Space) { - let current_brick = moving_brick.1.brick; - let moving_pos = &mut moving_brick.1.moving_pos; + let is_left_moving = keyboard_input.just_pressed(KeyCode::Left); - while board.0.is_valid_brick(¤t_brick, &moving_pos.down()) { - moving_pos.down_assign(); - moving_brick.2.translation.y -= BLOCK_WIDTH; + let current_brick = moving_brick.1.brick; + let moving_pos = moving_brick.1.moving_pos; + + let next_pos = if is_left_moving { + moving_pos.left() + } else { + moving_pos.right() + }; + + if board.0.is_valid_brick(¤t_brick, &next_pos) { + moving_brick.1.moving_pos = next_pos; + if is_left_moving { + moving_brick.2.translation.x -= BLOCK_WIDTH; + } else { + moving_brick.2.translation.x += BLOCK_WIDTH; } - // hard dropped, then it cannot be moved again - moving_brick.1.movable = false; + // dismiss shadow brick + if let Ok(shadow_bricks) = shadow_brick_query.get_single() { + commands.entity(shadow_bricks).despawn_recursive(); + } + let bottom_pos = board + .0 + .get_bottom_valid_brick_pos(¤t_brick, &next_pos); + // redraw shadow brick + spawn_shadow_brick(&mut commands, ¤t_brick, &bottom_pos); } } @@ -503,12 +553,16 @@ fn spawn_brick(commands: &mut Commands, brick: &Brick, moving_pos: &Position) { .insert(MovingBrickBundle { moving_pos: *moving_pos, brick: brick.clone(), - movable: true + movable: true, }) .with_children(|parent| { for pos in brick.1 { let color = Color::hex(&BRICK_COLOR_MAP[&brick.0]).unwrap(); - parent.spawn(sprite_bundle(BLOCK_WIDTH, color, position_to_vec2(&pos, 0.3))); + parent.spawn(sprite_bundle( + BLOCK_WIDTH, + color, + position_to_vec2(&pos, 0.3), + )); } }); } @@ -533,8 +587,12 @@ fn spawn_shadow_brick(commands: &mut Commands, brick: &Brick, shadow_pos: &Posit .insert(ShadowBrickBundle) .with_children(|parent| { for pos in brick.1 { - let color = Color::rgb_u8(90,90,90); - parent.spawn(sprite_bundle(BLOCK_WIDTH, color, position_to_vec2(&pos, 0.2))); + let color = Color::rgb_u8(90, 90, 90); + parent.spawn(sprite_bundle( + BLOCK_WIDTH, + color, + position_to_vec2(&pos, 0.2), + )); } }); } @@ -585,12 +643,19 @@ fn spawn_board(commands: &mut Commands, board: &Board) { // this is the background color view parent.spawn(SpriteBundle { transform: Transform { - translation: Vec3::new((board_width) / 2. - BLOCK_WIDTH / 2., (board_height) / 2. - BLOCK_WIDTH / 2., 0.0), + translation: Vec3::new( + (board_width) / 2. - BLOCK_WIDTH / 2., + (board_height) / 2. - BLOCK_WIDTH / 2., + 0.0, + ), ..default() }, sprite: Sprite { color: line_color, - custom_size: Some(Vec2::new(board_width + BLOCK_INSET, board_height + BLOCK_INSET)), + custom_size: Some(Vec2::new( + board_width + BLOCK_INSET, + board_height + BLOCK_INSET, + )), ..default() }, ..default() @@ -684,7 +749,11 @@ fn spawn_next_brick(commands: &mut Commands, brick: Brick) { .with_children(|parent| { for pos in brick.1 { let color = Color::hex(&BRICK_COLOR_MAP[&brick.0]).unwrap(); - parent.spawn(sprite_bundle(BLOCK_WIDTH, color, position_to_vec2(&pos, 0.1))); + parent.spawn(sprite_bundle( + BLOCK_WIDTH, + color, + position_to_vec2(&pos, 0.1), + )); } }) .insert(NextBrickBundle(brick));