From f65d2eea6316a53c2c81a2471345586036ce8115 Mon Sep 17 00:00:00 2001 From: Elijah Voigt Date: Fri, 13 Dec 2024 11:09:55 -0800 Subject: [PATCH] saving my place --- .cargo/config.toml | 12 +- .gitignore | 3 + Cargo.lock | 99 +++++++-------- Cargo.toml | 9 +- Makefile | 35 ++++++ flake.nix | 11 +- index.html | 27 ++++ rust-toolchain.toml | 2 +- src/boot.rs | 2 +- src/debug.rs | 84 ++++++++++++- src/main.rs | 16 ++- src/menu.rs | 296 +++++++++++++++++++++++++++++++++++++------- src/play.rs | 8 +- src/setup.rs | 34 +---- src/view.rs | 21 +++- todo.txt | 7 ++ 16 files changed, 513 insertions(+), 153 deletions(-) create mode 100644 Makefile create mode 100644 index.html diff --git a/.cargo/config.toml b/.cargo/config.toml index 56992b6..0b6db5f 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,11 +1,11 @@ -[unstable] -codegen-backend = true +# [unstable] +# codegen-backend = true -[profile.dev] -codegen-backend = "cranelift" +# [profile.dev] +# codegen-backend = "cranelift" -[profile.dev.package."*"] -codegen-backend = "llvm" +# [profile.dev.package."*"] +# codegen-backend = "llvm" # for Linux [target.x86_64-unknown-linux-gnu] diff --git a/.gitignore b/.gitignore index 2a188ef..7e6f013 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,6 @@ # Nix generated files .direnv/ result/ + +# Web target +out/ diff --git a/Cargo.lock b/Cargo.lock index 25c4393..c8df7c7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -306,7 +306,6 @@ version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6a01cd51a5cd310e4e7aa6e1560b1aabf29efc6a095a01e6daa8bf0a19f1fea" dependencies = [ - "bevy_dylib", "bevy_internal", ] @@ -525,15 +524,6 @@ dependencies = [ "sysinfo", ] -[[package]] -name = "bevy_dylib" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2b0c60e568493ac23c001d22f47b99818efe1e992253e2ab3fdb69603b2aa1c" -dependencies = [ - "bevy_internal", -] - [[package]] name = "bevy_ecs" version = "0.15.0" @@ -1409,9 +1399,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.2" +version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f34d93e62b03caf570cccc334cbc6c2fceca82f39211051345108adcba3eebdc" +checksum = "27f657647bcff5394bf56c7317665bbf790a137a50eaaa5c6bfbb9e27a518f2d" dependencies = [ "jobserver", "libc", @@ -1912,15 +1902,15 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "fdeflate" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07c6f4c64c1d33a3111c4466f7365ebdcc37c5bd1ea0d62aae2e3d722aacbedb" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" dependencies = [ "simd-adler32", ] @@ -2418,11 +2408,10 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.74" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a865e038f7f6ed956f788f0d7d60c541fff74c7bd74272c5d4cf15c63743e705" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" dependencies = [ - "once_cell", "wasm-bindgen", ] @@ -2471,9 +2460,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.167" +version = "0.2.168" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc" +checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d" [[package]] name = "libloading" @@ -2499,7 +2488,7 @@ checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ "bitflags 2.6.0", "libc", - "redox_syscall 0.5.7", + "redox_syscall 0.5.8", ] [[package]] @@ -3096,7 +3085,7 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.7", + "redox_syscall 0.5.8", "smallvec", "windows-targets 0.52.6", ] @@ -3170,9 +3159,9 @@ checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "png" -version = "0.17.14" +version = "0.17.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52f9d46a34a05a6a57566bc2bfae066ef07585a6e3fa30fbbdff5936380623f0" +checksum = "b67582bd5b65bdff614270e2ea89a1cf15bef71245cc1e5f7ea126977144211d" dependencies = [ "bitflags 1.3.2", "crc32fast", @@ -3349,9 +3338,9 @@ dependencies = [ [[package]] name = "read-fonts" -version = "0.22.5" +version = "0.22.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a04b892cb6f91951f144c33321843790c8574c825aafdb16d815fd7183b5229" +checksum = "69aacb76b5c29acfb7f90155d39759a29496aebb49395830e928a9703d2eec2f" dependencies = [ "bytemuck", "font-types", @@ -3374,9 +3363,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" dependencies = [ "bitflags 2.6.0", ] @@ -3468,15 +3457,15 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustix" -version = "0.38.41" +version = "0.38.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6" +checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" dependencies = [ "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -3528,9 +3517,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "self_cell" -version = "1.0.4" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d369a96f978623eb3dc28807c4852d6cc617fed53da5d3c400feff1ef34a714a" +checksum = "c2fdfc24bc566f839a2da4c4295b82db7d25a24253867d5c64355abb5799bdbe" [[package]] name = "send_wrapper" @@ -3540,18 +3529,18 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" -version = "1.0.215" +version = "1.0.216" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" +checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.215" +version = "1.0.216" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" +checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e" dependencies = [ "proc-macro2", "quote", @@ -3575,6 +3564,7 @@ name = "set" version = "0.1.0" dependencies = [ "bevy", + "wasm-bindgen", ] [[package]] @@ -4026,9 +4016,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.97" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d15e63b4482863c109d70a7b8706c1e364eb6ea449b201a76c5b89cedcec2d5c" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" dependencies = [ "cfg-if", "once_cell", @@ -4037,9 +4027,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.97" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d36ef12e3aaca16ddd3f67922bc63e48e953f126de60bd33ccc0101ef9998cd" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" dependencies = [ "bumpalo", "log", @@ -4052,22 +4042,21 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.47" +version = "0.4.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dfaf8f50e5f293737ee323940c7d8b08a66a95a419223d9f41610ca08b0833d" +checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" dependencies = [ "cfg-if", "js-sys", - "once_cell", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.97" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "705440e08b42d3e4b36de7d66c944be628d579796b8090bfa3471478a2260051" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4075,9 +4064,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.97" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98c9ae5a76e46f4deecd0f0255cc223cfa18dc9b261213b8aa0c7b36f61b3f1d" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", @@ -4088,15 +4077,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.97" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ee99da9c5ba11bd675621338ef6fa52296b76b83305e9b6e5c77d4c286d6d49" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" [[package]] name = "web-sys" -version = "0.3.74" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a98bc3c33f0fe7e59ad7cd041b89034fa82a7c2d4365ca538dda6cdaf513863c" +checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" dependencies = [ "js-sys", "wasm-bindgen", @@ -4697,9 +4686,9 @@ checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" [[package]] name = "xml-rs" -version = "0.8.23" +version = "0.8.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af310deaae937e48a26602b730250b4949e125f468f11e6990be3e5304ddd96f" +checksum = "ea8b391c9a790b496184c29f7f93b9ed5b16abb306c05415b68bcc16e4d06432" [[package]] name = "yazi" diff --git a/Cargo.toml b/Cargo.toml index 31b0587..2646d4c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,8 @@ version = "0.1.0" edition = "2021" [dependencies] -bevy = { package = "bevy", version = "0.15"} +wasm-bindgen = { version = "= 0.2.95" } +bevy = "0.15" [profile.dev] opt-level = 1 @@ -12,5 +13,7 @@ opt-level = 1 [profile.dev.package."*"] opt-level = 3 -[features] -default = ["bevy/dynamic_linking"] +[profile.release] +lto = true +codegen-units = 1 +opt-level = 'z' # 's' diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..50c5ecc --- /dev/null +++ b/Makefile @@ -0,0 +1,35 @@ +ifeq ($(PROFILE),release) +RELEASE = --release +PROFILE = release +else +PROFILE = debug +endif + +target/x86_64-unknown-linux-gnu/$(PROFILE)/set: src/* + cargo build --target x86_64-unknown-linux-gnu --features bevy/dynamic_linking $(RELEASE) + +target/wasm32-unknown-unknown/$(PROFILE)/set.wasm: src/* + cargo build --target wasm32-unknown-unknown $(RELEASE) + +out/$(PROFILE)/set.js: target/wasm32-unknown-unknown/$(PROFILE)/set.wasm + wasm-bindgen --no-typescript --target web --out-dir "./out/$(PROFILE)" ./target/wasm32-unknown-unknown/$(PROFILE)/set.wasm + +out/$(PROFILE)/assets: + rm -rf ./out/$(PROFILE)/assets + cp -r ./assets ./out/$(PROFILE)/ + +out/$(PROFILE)/index.html: + cp index.html ./out/$(PROFILE)/index.html + +native/build: target/x86_64-unknown-linux-gnu/$(PROFILE)/set + +native/run: native/build + cargo run --target x86_64-unknown-linux-gnu --features bevy/dynamic_linking $(RELEASE) + +web/build: out/$(PROFILE)/set.js out/$(PROFILE)/assets out/$(PROFILE)/index.html + +web/serve: web/build + cd ./out/$(PROFILE)/; simple-http-server + +clean: + rm ./target/*/*/set* diff --git a/flake.nix b/flake.nix index a7c443a..59105ad 100644 --- a/flake.nix +++ b/flake.nix @@ -28,10 +28,10 @@ ]; nativeBuildInputs = with pkgs; [ libxkbcommon - (rust-bin.selectLatestNightlyWith - (toolchain: toolchain.default.override { - extensions = [ "rust-src" "clippy" "rustc-codegen-cranelift-preview"]; - })) + (rust-bin.stable.latest.default.override { + extensions = [ "rust-src" "clippy" ]; + targets = [ "x86_64-unknown-linux-gnu" "wasm32-unknown-unknown" ]; + }) ]; all_deps = with pkgs; [ cargo-flamegraph @@ -39,6 +39,9 @@ nixpkgs-fmt cmake rx + wasm-pack + wasm-bindgen-cli + simple-http-server ] ++ buildInputs ++ nativeBuildInputs; in rec { diff --git a/index.html b/index.html new file mode 100644 index 0000000..014d16b --- /dev/null +++ b/index.html @@ -0,0 +1,27 @@ + + + + + s e t + + + diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 307a00d..eece77f 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly" +channel = "stable" components = [ "rust-src", "clippy", "rustc-codegen-cranelift-preview"]; diff --git a/src/boot.rs b/src/boot.rs index ec23e13..b9c1211 100644 --- a/src/boot.rs +++ b/src/boot.rs @@ -6,7 +6,7 @@ pub struct BootPlugin; impl Plugin for BootPlugin { fn build(&self, app: &mut App) { - app.add_systems(Startup, (boot::load, boot::start_setup).chain()); + app.add_systems(Startup, (load, start_setup).chain()); } } diff --git a/src/debug.rs b/src/debug.rs index 6f96a8d..1224639 100644 --- a/src/debug.rs +++ b/src/debug.rs @@ -1,4 +1,4 @@ -use bevy::prelude::*; +use bevy::{color::palettes::css::BLACK, prelude::*, window::WindowResized}; use crate::deck::Card; @@ -8,6 +8,7 @@ pub struct DebugPlugin; impl Plugin for DebugPlugin { fn build(&self, app: &mut App) { app.add_observer(track_card_info) + .add_systems(Update, update_window_info) .add_systems(Startup, init_ui); } } @@ -15,6 +16,9 @@ impl Plugin for DebugPlugin { #[derive(Component)] pub(crate) struct DebugText; +#[derive(Component)] +pub(crate) struct WindowInfoText; + fn init_ui(mut commands: Commands) { commands .spawn(( @@ -32,6 +36,45 @@ fn init_ui(mut commands: Commands) { PickingBehavior::IGNORE, )); }); + + commands + .spawn(( + Node { + position_type: PositionType::Absolute, + top: Val::Px(0.0), + right: Val::Px(0.0), + ..default() + }, + BackgroundColor(BLACK.into()), + GlobalZIndex(1), + )) + .with_children(|parent| { + parent + .spawn(Button) + .with_children(|parent| { + parent.spawn(( + Text("-".into()), + TextFont { + font_size: 60.0, + ..default() + }, + )); + }) + .observe(decrease_scale_ratio); + parent + .spawn(Button) + .with_children(|parent| { + parent.spawn(( + Text("+".into()), + TextFont { + font_size: 60.0, + ..default() + }, + )); + }) + .observe(increase_scale_ratio); + parent.spawn((Text("????x????".to_string()), WindowInfoText)); + }); } fn track_card_info( @@ -71,3 +114,42 @@ pub(crate) fn hide_debug_card( *v = Visibility::Hidden; }); } + +fn update_window_info( + mut events: EventReader, + windows: Query<&mut Window>, + mut infos: Query<&mut Text, With>, +) { + events.read().for_each(|_| { + info!("Window resized"); + let window = windows.single(); + let width = window.resolution.width(); + let height = window.resolution.height(); + let scale_factor = window.resolution.scale_factor(); + + let mut info = infos.single_mut(); + info.0 = format!("{:.0}x{:.0} ({:.03})", width, height, scale_factor,); + }); +} + +fn increase_scale_ratio( + _trigger: Trigger>, + // TODO: Move window scale factor out to non-debug system + mut windows: Query<&mut Window>, +) { + info!("increase scale ratio"); + let mut window = windows.single_mut(); + let current = window.scale_factor(); + window.resolution.set_scale_factor(current + 0.05); +} + +fn decrease_scale_ratio( + _trigger: Trigger>, + // TODO: Move window scale factor out to non-debug system + mut windows: Query<&mut Window>, +) { + info!("decrease scale ratio"); + let mut window = windows.single_mut(); + let current = window.scale_factor(); + window.resolution.set_scale_factor(current - 0.05); +} diff --git a/src/main.rs b/src/main.rs index 478ca02..4d180df 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,8 +9,20 @@ mod view; use bevy::prelude::*; fn main() { + let primary_window = Some(Window { + // web: fill the window + fit_canvas_to_parent: true, + ..default() + }); App::new() - .add_plugins(DefaultPlugins.set(ImagePlugin::default_nearest())) + .add_plugins( + DefaultPlugins + .set(ImagePlugin::default_nearest()) + .set(WindowPlugin { + primary_window, + ..default() + }), + ) .add_plugins(( view::ViewPlugin, deck::DeckPlugin, @@ -18,7 +30,7 @@ fn main() { setup::SetupPlugin, play::PlayPlugin, menu::MenuPlugin, - debug::DebugPlugin, + // debug::DebugPlugin, )) .init_state::() .run(); diff --git a/src/menu.rs b/src/menu.rs index 2d2a977..9d1e4d6 100644 --- a/src/menu.rs +++ b/src/menu.rs @@ -1,10 +1,12 @@ use bevy::{ - color::palettes::css::{BLACK, GREEN, INDIGO, ORANGE, PURPLE, RED, TEAL}, + color::palettes::css::{BLACK, WHITE}, prelude::*, }; use crate::{ - play::check_for_sets, + boot, + deck::{Card, Deck, ItemColor, ItemNumber, ItemPattern, ItemShape}, + play::{check_for_sets, check_set}, view::{button_set_state, ViewState}, }; @@ -18,70 +20,126 @@ impl Plugin for MenuPlugin { ( setup, setup_about, - setup_how_to_play, + setup_how_to_play.after(boot::load), setup_deck, setup_sets, + setup_set_check_button, ), ); } } +fn button_builder(node: Node) -> (Button, BackgroundColor, Node, BorderColor) { + ( + Button, + BackgroundColor(BLACK.with_alpha(0.9).into()), + Node { + padding: UiRect::all(Val::Px(10.)), + margin: UiRect::top(Val::Px(25.)), + border: UiRect::all(Val::Px(1.0)), + ..node + }, + BorderColor(WHITE.into()), + ) +} + fn setup(mut commands: Commands) { commands - .spawn((ViewState::Menu, Node::default())) + .spawn(( + ViewState::Menu, + Node { + position_type: PositionType::Absolute, + justify_content: JustifyContent::Center, + align_items: AlignItems::Center, + width: Val::Percent(100.0), + height: Val::Percent(100.0), + ..default() + }, + )) .with_children(|parent| { parent - .spawn((Button, BackgroundColor(TEAL.into()))) - .with_children(|parent| { - parent.spawn(Text("Play".to_string())); + .spawn(Node { + flex_direction: FlexDirection::Column, + align_items: AlignItems::Center, + justify_content: JustifyContent::Center, + ..default() }) - .observe(button_set_state(ViewState::Play)); - parent - .spawn((Button, BackgroundColor(ORANGE.into()))) .with_children(|parent| { - parent.spawn(Text("About".to_string())); - }) - .observe(button_set_state(ViewState::About)); - parent - .spawn((Button, BackgroundColor(PURPLE.into()))) - .with_children(|parent| { - parent.spawn(Text("How to Play".to_string())); - }) - .observe(button_set_state(ViewState::HowToPlay)); - parent - .spawn((Button, BackgroundColor(RED.into()))) - .with_children(|parent| { - parent.spawn(Text("Quit".to_string())); - }) - .observe(quit_button); + parent + .spawn(button_builder(Node::default())) + .with_children(|parent| { + parent.spawn(Text("Play".to_string())); + }) + .observe(button_hover_on) + .observe(button_hover_off) + .observe(button_set_state(ViewState::Play)); + parent + .spawn(button_builder(Node::default())) + .with_children(|parent| { + parent.spawn(Text("About".to_string())); + }) + .observe(button_hover_on) + .observe(button_hover_off) + .observe(button_set_state(ViewState::About)); + parent + .spawn(button_builder(Node::default())) + .with_children(|parent| { + parent.spawn(Text("How to Play".to_string())); + }) + .observe(button_hover_on) + .observe(button_hover_off) + .observe(button_set_state(ViewState::HowToPlay)); + + #[cfg(not(target_arch = "wasm32"))] + parent + .spawn(button_builder(Node::default())) + .with_children(|parent| { + parent.spawn(Text("Quit".to_string())); + }) + .observe(button_hover_on) + .observe(button_hover_off) + .observe(quit_button); + }); }); commands .spawn((ViewState::Play, Node::default())) .with_children(|parent| { parent - .spawn((Button, BackgroundColor(TEAL.into()), GlobalZIndex(1))) + .spawn((button_builder(Node::default()), GlobalZIndex(1))) .with_children(|parent| { parent.spawn(Text("Menu".to_string())); }) + .observe(button_hover_on) + .observe(button_hover_off) .observe(button_set_state(ViewState::Menu)); + /* parent - .spawn((Button, BackgroundColor(INDIGO.into()), GlobalZIndex(1))) + .spawn((button_builder(Node::default()), GlobalZIndex(1))) .with_children(|parent| { parent.spawn(Text("Deck".to_string())); }) + .observe(button_hover_on) + .observe(button_hover_off) .observe(button_set_state(ViewState::Deck)); + */ + /* parent - .spawn((Button, BackgroundColor(ORANGE.into()), GlobalZIndex(1))) + .spawn((button_builder(Node::default()), GlobalZIndex(1))) .with_children(|parent| { parent.spawn(Text("Sets".to_string())); }) + .observe(button_hover_on) + .observe(button_hover_off) .observe(button_set_state(ViewState::Sets)); + */ parent - .spawn((Button, BackgroundColor(GREEN.into()), GlobalZIndex(1))) + .spawn((button_builder(Node::default()), GlobalZIndex(1))) .with_children(|parent| { parent.spawn(Text("Help!".to_string())); }) + .observe(button_hover_on) + .observe(button_hover_off) .observe(check_for_sets); }); } @@ -91,32 +149,150 @@ fn setup_about(mut commands: Commands) { .spawn((ViewState::About, Node::default())) .with_children(|parent| { parent - .spawn((Button, BackgroundColor(TEAL.into()))) + .spawn(button_builder(Node::default())) .with_children(|parent| { parent.spawn(Text("Menu".to_string())); }) .observe(button_set_state(ViewState::Menu)); - parent.spawn(( - Text("This is the about page".to_string()), - BackgroundColor(BLACK.into()), - )); }); } -fn setup_how_to_play(mut commands: Commands) { +fn setup_how_to_play(mut commands: Commands, deck: Res) { commands - .spawn((ViewState::HowToPlay, Node::default())) + .spawn(( + ViewState::HowToPlay, + Node { + position_type: PositionType::Absolute, + width: Val::Percent(100.0), + height: Val::Percent(100.0), + ..default() + }, + )) .with_children(|parent| { parent - .spawn((Button, BackgroundColor(TEAL.into()))) + .spawn(button_builder(Node { + position_type: PositionType::Absolute, + top: Val::Px(0.0), + left: Val::Px(0.0), + ..default() + })) .with_children(|parent| { parent.spawn(Text("Menu".to_string())); }) .observe(button_set_state(ViewState::Menu)); - parent.spawn(( - Text("This is the how to play page".to_string()), - BackgroundColor(BLACK.into()), - )); + + parent.spawn((Node { + align_items: AlignItems::Center, + justify_content: JustifyContent::Center, + flex_direction: FlexDirection::Column, + ..default() + }, + BackgroundColor(BLACK.with_alpha(0.9).into()), + )).with_children(|parent| { + let most_matching = ( + Card { + color: ItemColor::Red, + shape: ItemShape::Squiggle, + number: ItemNumber::One, + pattern: ItemPattern::Solid, + }, + Card { + color: ItemColor::Red, + shape: ItemShape::Squiggle, + number: ItemNumber::Two, + pattern: ItemPattern::Solid, + }, + Card { + color: ItemColor::Red, + shape: ItemShape::Squiggle, + number: ItemNumber::Three, + pattern: ItemPattern::Solid, + } + ); + let most_not_matching = ( + Card { + color: ItemColor::Green, + shape: ItemShape::Oval, + number: ItemNumber::Three, + pattern: ItemPattern::Solid, + }, + Card { + color: ItemColor::Purple, + shape: ItemShape::Squiggle, + number: ItemNumber::Three, + pattern: ItemPattern::Striped, + }, + Card { + color: ItemColor::Red, + shape: ItemShape::Diamond, + number: ItemNumber::Three, + pattern: ItemPattern::Open, + } + ); + let not_valid = ( + Card { + color: ItemColor::Purple, + shape: ItemShape::Oval, + number: ItemNumber::Three, + pattern: ItemPattern::Striped, + }, + Card { + color: ItemColor::Purple, + shape: ItemShape::Oval, + number: ItemNumber::Two, + pattern: ItemPattern::Striped, + }, + Card { + color: ItemColor::Purple, + shape: ItemShape::Oval, + number: ItemNumber::Three, + pattern: ItemPattern::Open, + } + ); + [ + ("Find groups of 3 cards", None), + ("All cards in a set must match or differ in their traits: Color, Number, Shading, and Shape.", None), + ("For example all agree on Color, Shading, and Shape but not Number...", Some(most_matching)), + ("...or all agree on Number but not Color, Number, Shading, and Shape...", Some(most_not_matching)), + ("...but never partial agreement on a trait...", Some(not_valid)), + ("When in doubt, click the 'Help!' button to get an assist", None), + ] + .iter() + .for_each(|(t, example)| { + parent.spawn(( + Node { + flex_direction: FlexDirection::Row, + align_items: AlignItems::Center, + ..default() + }, + )).with_children(|parent| { + parent.spawn(( + Node { + margin: UiRect::all(Val::Px(5.0)), + padding: UiRect::all(Val::Px(5.0)), + ..default() + }, + Text(t.to_string()), + )); + if let Some((a, b, c)) = example { + [a, b, c].iter().for_each(|x| { + let sprite = deck.cards.get(*x).unwrap(); + parent.spawn(( + Node { + height: Val::Px(100.0), + ..default() + }, + ImageNode { + image: sprite.image.clone(), + texture_atlas: sprite.texture_atlas.clone(), + ..default() + } + )); + }); + }; + }); + }); + }); }); } @@ -125,7 +301,7 @@ fn setup_deck(mut commands: Commands) { .spawn((ViewState::Deck, Node::default())) .with_children(|parent| { parent - .spawn((Button, BackgroundColor(TEAL.into()))) + .spawn(button_builder(Node::default())) .with_children(|parent| { parent.spawn(Text("Back".to_string())); }) @@ -138,7 +314,7 @@ fn setup_sets(mut commands: Commands) { .spawn((ViewState::Sets, Node::default())) .with_children(|parent| { parent - .spawn((Button, BackgroundColor(TEAL.into()))) + .spawn(button_builder(Node::default())) .with_children(|parent| { parent.spawn(Text("Back".to_string())); }) @@ -146,6 +322,40 @@ fn setup_sets(mut commands: Commands) { }); } +pub(crate) fn setup_set_check_button(mut commands: Commands) { + commands + .spawn(( + Node { + width: Val::Percent(100.0), + position_type: PositionType::Absolute, + top: Val::Px(0.0), + flex_direction: FlexDirection::Column, + align_items: AlignItems::Center, + ..default() + }, + Visibility::default(), + ViewState::Play, + )) + .with_children(|parent| { + parent + .spawn(button_builder(Node::default())) + .with_children(|parent| { + parent.spawn(Text("Set!".to_string())); + }) + .observe(check_set); + }); +} + fn quit_button(_trigger: Trigger>, mut exit_event: EventWriter) { exit_event.send(AppExit::Success); } + +fn button_hover_on(trigger: Trigger>, mut query: Query<&mut BackgroundColor>) { + let mut background_color = query.get_mut(trigger.entity()).unwrap(); + background_color.0.set_alpha(1.0); +} + +fn button_hover_off(trigger: Trigger>, mut query: Query<&mut BackgroundColor>) { + let mut background_color = query.get_mut(trigger.entity()).unwrap(); + background_color.0.set_alpha(0.9); +} diff --git a/src/play.rs b/src/play.rs index d3595ef..d099c52 100644 --- a/src/play.rs +++ b/src/play.rs @@ -189,11 +189,11 @@ pub(crate) fn place_card( query.get_mut(trigger.entity()).unwrap(); // Set it's transform based on it's placement - let CARD_SIZE = [100.0, 160.0]; - let offset = Vec2::new(CARD_SIZE[0] * 4.0, CARD_SIZE[1] * 4.0) / 2.5; + let card_size = [100.0, 160.0]; + let offset = Vec2::new(card_size[0] * 4.0, card_size[1] * 4.0) / 2.5; transform.translation = Vec3::new( - ((*x as f32) * CARD_SIZE[0]) - offset.x, - ((*y as f32) * CARD_SIZE[1]) - offset.y, + ((*x as f32) * card_size[0]) - offset.x, + ((*y as f32) * card_size[1]) - offset.y, 0.0, ); diff --git a/src/setup.rs b/src/setup.rs index 45f1d81..aaa3ffc 100644 --- a/src/setup.rs +++ b/src/setup.rs @@ -1,5 +1,5 @@ use crate::{deck::*, *}; -use bevy::{color::palettes::css::TEAL, prelude::*}; +use bevy::prelude::*; use view::ViewState; pub struct SetupPlugin; @@ -8,14 +8,7 @@ impl Plugin for SetupPlugin { fn build(&self, app: &mut App) { app.add_systems( OnEnter(GameState::Setup), - ( - setup_background, - setup_cards, - setup_set_check_button, - setup_camera, - start_play, - ) - .chain(), + (setup_background, setup_cards, setup_camera, start_play).chain(), ); } } @@ -75,29 +68,6 @@ pub(crate) fn setup_background( )); } -pub(crate) fn setup_set_check_button(mut commands: Commands) { - commands - .spawn(( - Node { - width: Val::Percent(100.0), - flex_direction: FlexDirection::Column, - align_items: AlignItems::Center, - ..default() - }, - Visibility::default(), - ViewState::Play, - BackgroundColor(Color::BLACK.into()), - )) - .with_children(|parent| { - parent - .spawn((Button, BackgroundColor(TEAL.into()))) - .with_children(|parent| { - parent.spawn(Text("Set!?".to_string())); - }) - .observe(play::check_set); - }); -} - /// Finish the setup state by progressing to the play state pub(crate) fn start_play( mut game_state: ResMut>, diff --git a/src/view.rs b/src/view.rs index 2ba7e0c..ed0a4b1 100644 --- a/src/view.rs +++ b/src/view.rs @@ -1,4 +1,4 @@ -use bevy::{prelude::*, state::state::FreelyMutableState}; +use bevy::{prelude::*, state::state::FreelyMutableState, window::WindowResized}; /// Deck and Cards pub struct ViewPlugin; @@ -6,6 +6,7 @@ pub struct ViewPlugin; impl Plugin for ViewPlugin { fn build(&self, app: &mut App) { app.init_state::() + .add_systems(Update, update_window_info) .add_systems(Update, state_monitor); } } @@ -47,3 +48,21 @@ fn state_monitor( }); }); } + +fn update_window_info(mut events: EventReader, mut _windows: Query<&mut Window>) { + events + .read() + .for_each(|WindowResized { height, width, .. }| { + info!("Window resized {} {}", height, width); + + let new_scale_factor = { + let height_ratio = 800.0 / height; + let width_ratio = 500.0 / width; + height_ratio.min(width_ratio) + }; + // let window = windows.single_mut(); + // window.resolution.set_scale_factor(new_scale_factor); + + info!("Proposed scale factor: {:?}", new_scale_factor); + }); +} diff --git a/todo.txt b/todo.txt index 8b9361d..31d5604 100644 --- a/todo.txt +++ b/todo.txt @@ -11,3 +11,10 @@ TODO: * Menu * About/Credits * How To Play + +Exclude for now: +* deck +* sets + +Exclude in wasm: +* quit