From 5de4329fd5325e2e167fc16e145a04ea95fa09c4 Mon Sep 17 00:00:00 2001 From: Alcibiades Athens Date: Fri, 27 Dec 2024 03:05:34 -0500 Subject: [PATCH] feat: optimized wasm packaging --- .github/workflows/ci.yml | 14 +- Cargo.lock | 424 +------------------------------- Cargo.toml | 76 +++--- README.md | 10 +- assets/social-card.png | Bin 0 -> 67408 bytes src/audio.rs | 71 ++++-- src/endgame.rs | 4 +- src/splash.rs | 2 +- src/window.rs | 2 + web/index.html | 516 +++++++++++++++++++++++++-------------- 10 files changed, 441 insertions(+), 678 deletions(-) create mode 100644 assets/social-card.png diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7efabe1..37ae27f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,9 +8,9 @@ on: branches: - master tags: - - 'v*.*.*' + - "v*.*.*" pull_request: - types: [ opened, synchronize, reopened ] + types: [opened, synchronize, reopened] branches: - master @@ -58,8 +58,8 @@ jobs: strategy: fail-fast: false matrix: - rust: [ "stable", "beta", "nightly", "1.82" ] # MSRV - flags: [ "--no-default-features", "", "--all-features" ] + rust: ["stable", "beta", "nightly", "1.82"] # MSRV + flags: ["--no-default-features", "", "--all-features"] exclude: - rust: "1.82" flags: "--all-features" @@ -155,7 +155,7 @@ jobs: # Build WASM bundle and deploy to GitHub Pages build-and-deploy: name: Build and Deploy - needs: [ test, coverage, feature-checks, docs ] + needs: [test, coverage, feature-checks, docs] runs-on: ubuntu-latest if: github.ref == 'refs/heads/master' permissions: @@ -184,7 +184,7 @@ jobs: cargo build --release --target wasm32-unknown-unknown mkdir -p dist wasm-bindgen --out-dir ./dist --target web target/wasm32-unknown-unknown/release/rusty_pong.wasm - find ./dist -name "*.wasm" -exec wasm-opt -O3 -o {}.opt {} \; -exec mv {}.opt {} \; + find ./dist -name "*.wasm" -exec wasm-opt -Oz --zero-filled-memory --strip-producers -o {}.opt {} \; -exec mv {}.opt {} \; - name: Prepare deployment run: | mkdir -p dist/assets @@ -195,4 +195,4 @@ jobs: with: folder: dist branch: gh-pages - clean: true \ No newline at end of file + clean: true diff --git a/Cargo.lock b/Cargo.lock index 0c4fac8..2fb44e5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -306,12 +306,6 @@ version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" -[[package]] -name = "base64" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" - [[package]] name = "bevy" version = "0.15.0" @@ -334,38 +328,6 @@ dependencies = [ "bevy_reflect", ] -[[package]] -name = "bevy_animation" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee48f3fc65f583e5e320e38874053e20e7a71205a62aaace5d607446781bd742" -dependencies = [ - "bevy_app", - "bevy_asset", - "bevy_color", - "bevy_core", - "bevy_derive", - "bevy_ecs", - "bevy_hierarchy", - "bevy_log", - "bevy_math", - "bevy_reflect", - "bevy_render", - "bevy_time", - "bevy_transform", - "bevy_utils", - "blake3", - "derive_more", - "downcast-rs", - "either", - "petgraph", - "ron", - "serde", - "smallvec", - "thread_local", - "uuid", -] - [[package]] name = "bevy_app" version = "0.15.0" @@ -434,24 +396,6 @@ dependencies = [ "syn", ] -[[package]] -name = "bevy_audio" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20e378c4005d9c47b7ebaf637a6a197e3953463615516ab709ba8b0c3c215c2e" -dependencies = [ - "bevy_app", - "bevy_asset", - "bevy_derive", - "bevy_ecs", - "bevy_hierarchy", - "bevy_math", - "bevy_reflect", - "bevy_transform", - "bevy_utils", - "rodio", -] - [[package]] name = "bevy_color" version = "0.15.1" @@ -532,7 +476,6 @@ dependencies = [ "bevy_time", "bevy_utils", "const-fnv1a-hash", - "sysinfo", ] [[package]] @@ -580,21 +523,6 @@ dependencies = [ "encase_derive_impl", ] -[[package]] -name = "bevy_gilrs" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adc3a5f9e872133d7f5c2fab82e17781c19ed0b98f371362a23ed972bb538d20" -dependencies = [ - "bevy_app", - "bevy_ecs", - "bevy_input", - "bevy_time", - "bevy_utils", - "derive_more", - "gilrs", -] - [[package]] name = "bevy_gizmos" version = "0.15.0" @@ -609,7 +537,6 @@ dependencies = [ "bevy_gizmos_macros", "bevy_image", "bevy_math", - "bevy_pbr", "bevy_reflect", "bevy_render", "bevy_sprite", @@ -631,38 +558,6 @@ dependencies = [ "syn", ] -[[package]] -name = "bevy_gltf" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b21ed694796a001a5cf63de9ddc62fc017302b0e2998a361ef1126880ec93555" -dependencies = [ - "base64 0.22.1", - "bevy_animation", - "bevy_app", - "bevy_asset", - "bevy_color", - "bevy_core", - "bevy_core_pipeline", - "bevy_ecs", - "bevy_hierarchy", - "bevy_image", - "bevy_math", - "bevy_pbr", - "bevy_reflect", - "bevy_render", - "bevy_scene", - "bevy_tasks", - "bevy_transform", - "bevy_utils", - "derive_more", - "gltf", - "percent-encoding", - "serde", - "serde_json", - "smallvec", -] - [[package]] name = "bevy_hierarchy" version = "0.15.0" @@ -694,8 +589,6 @@ dependencies = [ "derive_more", "futures-lite", "image", - "ktx2", - "ruzstd", "serde", "wgpu", ] @@ -723,19 +616,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4237e6e9b03902321032f00f931f18a4a211093bd9a7cf81276a0228a2a4417" dependencies = [ "bevy_a11y", - "bevy_animation", "bevy_app", "bevy_asset", - "bevy_audio", "bevy_color", "bevy_core", "bevy_core_pipeline", "bevy_derive", "bevy_diagnostic", "bevy_ecs", - "bevy_gilrs", "bevy_gizmos", - "bevy_gltf", "bevy_hierarchy", "bevy_image", "bevy_input", @@ -891,14 +780,12 @@ dependencies = [ "bevy_hierarchy", "bevy_input", "bevy_math", - "bevy_mesh", "bevy_reflect", "bevy_render", "bevy_time", "bevy_transform", "bevy_utils", "bevy_window", - "crossbeam-channel", "uuid", ] @@ -936,7 +823,6 @@ dependencies = [ "downcast-rs", "erased-serde", "glam 0.29.2", - "petgraph", "serde", "smallvec", "smol_str", @@ -990,7 +876,6 @@ dependencies = [ "futures-lite", "image", "js-sys", - "ktx2", "naga", "naga_oil", "nonmax", @@ -1249,11 +1134,9 @@ dependencies = [ "approx", "bevy_a11y", "bevy_app", - "bevy_asset", "bevy_derive", "bevy_ecs", "bevy_hierarchy", - "bevy_image", "bevy_input", "bevy_log", "bevy_math", @@ -1261,13 +1144,11 @@ dependencies = [ "bevy_tasks", "bevy_utils", "bevy_window", - "bytemuck", "cfg-if", "crossbeam-channel", "raw-window-handle", "wasm-bindgen", "web-sys", - "wgpu-types", "winit", ] @@ -1443,9 +1324,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.5" +version = "1.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31a0499c1dc64f458ad13872de75c0eb7e3fdb0e67964610c914b034fc5956e" +checksum = "8d6dbb628b8f8555f86d0323c2eb39e3ec81901f4b83e091db8a6a76d316a333" dependencies = [ "jobserver", "libc", @@ -1598,16 +1479,6 @@ dependencies = [ "libc", ] -[[package]] -name = "core-foundation" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -1621,7 +1492,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" dependencies = [ "bitflags 1.3.2", - "core-foundation 0.9.4", + "core-foundation", "core-graphics-types", "foreign-types", "libc", @@ -1634,7 +1505,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" dependencies = [ "bitflags 1.3.2", - "core-foundation 0.9.4", + "core-foundation", "libc", ] @@ -2021,12 +1892,6 @@ dependencies = [ "miniz_oxide", ] -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - [[package]] name = "foldhash" version = "0.1.4" @@ -2149,40 +2014,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "gilrs" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbb2c998745a3c1ac90f64f4f7b3a54219fd3612d7705e7798212935641ed18f" -dependencies = [ - "fnv", - "gilrs-core", - "log", - "uuid", - "vec_map", -] - -[[package]] -name = "gilrs-core" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "495af945e45efd6386227613cd9fb7bd7c43d3c095040e30c5304c489e6abed5" -dependencies = [ - "core-foundation 0.10.0", - "inotify", - "io-kit-sys", - "js-sys", - "libc", - "libudev-sys", - "log", - "nix", - "uuid", - "vec_map", - "wasm-bindgen", - "web-sys", - "windows 0.58.0", -] - [[package]] name = "gl_generator" version = "0.14.0" @@ -2232,42 +2063,6 @@ dependencies = [ "web-sys", ] -[[package]] -name = "gltf" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3ce1918195723ce6ac74e80542c5a96a40c2b26162c1957a5cd70799b8cacf7" -dependencies = [ - "byteorder", - "gltf-json", - "lazy_static", - "serde_json", -] - -[[package]] -name = "gltf-derive" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14070e711538afba5d6c807edb74bcb84e5dbb9211a3bf5dea0dfab5b24f4c51" -dependencies = [ - "inflections", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "gltf-json" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6176f9d60a7eab0a877e8e96548605dedbde9190a7ae1e80bbcc1c9af03ab14" -dependencies = [ - "gltf-derive", - "serde", - "serde_derive", - "serde_json", -] - [[package]] name = "glutin_wgl_sys" version = "0.6.0" @@ -2417,42 +2212,6 @@ dependencies = [ "hashbrown 0.15.2", ] -[[package]] -name = "inflections" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a257582fdcde896fd96463bf2d40eefea0580021c0712a0e2b028b60b47a837a" - -[[package]] -name = "inotify" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3" -dependencies = [ - "bitflags 2.6.0", - "inotify-sys", - "libc", -] - -[[package]] -name = "inotify-sys" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" -dependencies = [ - "libc", -] - -[[package]] -name = "io-kit-sys" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "617ee6cf8e3f66f3b4ea67a4058564628cde41901316e19f559e14c7c72c5e7b" -dependencies = [ - "core-foundation-sys", - "mach2", -] - [[package]] name = "itertools" version = "0.13.0" @@ -2462,12 +2221,6 @@ dependencies = [ "either", ] -[[package]] -name = "itoa" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" - [[package]] name = "jni" version = "0.21.1" @@ -2541,32 +2294,12 @@ dependencies = [ "symphonia", ] -[[package]] -name = "ktx2" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87d65e08a9ec02e409d27a0139eaa6b9756b4d81fe7cde71f6941a83730ce838" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "lazy_static" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" -[[package]] -name = "lewton" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "777b48df9aaab155475a83a7df3070395ea1ac6902f5cd062b8f2b028075c030" -dependencies = [ - "byteorder", - "ogg", - "tinyvec", -] - [[package]] name = "libc" version = "0.2.169" @@ -2600,16 +2333,6 @@ dependencies = [ "redox_syscall 0.5.8", ] -[[package]] -name = "libudev-sys" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c8469b4a23b962c1396b9b451dda50ef5b283e8dd309d69033475fa9b334324" -dependencies = [ - "libc", - "pkg-config", -] - [[package]] name = "linux-raw-sys" version = "0.4.14" @@ -2878,15 +2601,6 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "610a5acd306ec67f907abe5567859a3c693fb9886eb1f012ab8f2a47bef3db51" -[[package]] -name = "ntapi" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" -dependencies = [ - "winapi", -] - [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -3223,15 +2937,6 @@ dependencies = [ "nonmax", ] -[[package]] -name = "ogg" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6951b4e8bf21c8193da321bcce9c9dd2e13c858fe078bf9054a288b419ae5d6e" -dependencies = [ - "byteorder", -] - [[package]] name = "once_cell" version = "1.20.2" @@ -3336,8 +3041,6 @@ checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset 0.4.2", "indexmap", - "serde", - "serde_derive", ] [[package]] @@ -3690,24 +3393,13 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cbf4a6aa5f6d6888f39e980649f3ad6b666acdce1d78e95b8a2cb076e687ae30" -[[package]] -name = "rodio" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6006a627c1a38d37f3d3a85c6575418cfe34a5392d60a686d0071e1c8d427acb" -dependencies = [ - "cpal", - "lewton", - "thiserror", -] - [[package]] name = "ron" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" dependencies = [ - "base64 0.21.7", + "base64", "bitflags 2.6.0", "serde", "serde_derive", @@ -3771,21 +3463,6 @@ dependencies = [ "unicode-script", ] -[[package]] -name = "ruzstd" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fad02996bfc73da3e301efe90b1837be9ed8f4a462b6ed410aa35d00381de89f" -dependencies = [ - "twox-hash", -] - -[[package]] -name = "ryu" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" - [[package]] name = "safe_arch" version = "0.7.4" @@ -3842,18 +3519,6 @@ dependencies = [ "syn", ] -[[package]] -name = "serde_json" -version = "1.0.134" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d00f4175c42ee48b15416f6193a959ba3a0d67fc699a0db9ad12df9f83991c7d" -dependencies = [ - "itoa", - "memchr", - "ryu", - "serde", -] - [[package]] name = "sharded-slab" version = "0.1.7" @@ -4060,19 +3725,6 @@ dependencies = [ "libc", ] -[[package]] -name = "sysinfo" -version = "0.32.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c33cd241af0f2e9e3b5c32163b873b29956890b5342e6745b917ce9d490f4af" -dependencies = [ - "core-foundation-sys", - "libc", - "memchr", - "ntapi", - "windows 0.57.0", -] - [[package]] name = "taffy" version = "0.5.2" @@ -4265,16 +3917,6 @@ version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c591d83f69777866b9126b24c6dd9a18351f177e49d625920d19f989fd31cf8" -[[package]] -name = "twox-hash" -version = "1.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" -dependencies = [ - "cfg-if", - "static_assertions", -] - [[package]] name = "typeid" version = "1.0.2" @@ -4364,12 +4006,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" -[[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - [[package]] name = "version_check" version = "0.9.5" @@ -4636,16 +4272,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "windows" -version = "0.57.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143" -dependencies = [ - "windows-core 0.57.0", - "windows-targets 0.52.6", -] - [[package]] name = "windows" version = "0.58.0" @@ -4666,42 +4292,19 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "windows-core" -version = "0.57.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d" -dependencies = [ - "windows-implement 0.57.0", - "windows-interface 0.57.0", - "windows-result 0.1.2", - "windows-targets 0.52.6", -] - [[package]] name = "windows-core" version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" dependencies = [ - "windows-implement 0.58.0", - "windows-interface 0.58.0", + "windows-implement", + "windows-interface", "windows-result 0.2.0", "windows-strings", "windows-targets 0.52.6", ] -[[package]] -name = "windows-implement" -version = "0.57.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "windows-implement" version = "0.58.0" @@ -4713,17 +4316,6 @@ dependencies = [ "syn", ] -[[package]] -name = "windows-interface" -version = "0.57.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "windows-interface" version = "0.58.0" @@ -4982,7 +4574,7 @@ dependencies = [ "calloop", "cfg_aliases 0.2.1", "concurrent-queue", - "core-foundation 0.9.4", + "core-foundation", "core-graphics", "cursor-icon", "dpi", diff --git a/Cargo.toml b/Cargo.toml index 26514f1..38d6d44 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,58 +1,50 @@ +# Project metadata [package] name = "rusty_pong" version = "0.1.0" edition = "2021" authors = ["0xAlcibiades "] +# Dependencies with minimal feature selection for optimal binary size while maintaining functionality [dependencies] -bevy = { version = "0.15.0", features = ["animation", - "bevy_asset", - "bevy_color", - "bevy_core_pipeline", - "bevy_gilrs", - "bevy_gizmos", - "bevy_gltf", - "bevy_mesh_picking_backend", - "bevy_pbr", - "bevy_picking", - "bevy_render", - "bevy_scene", - "bevy_sprite", - "bevy_sprite_picking_backend", - "bevy_state", - "bevy_text", - "bevy_ui", - "bevy_ui_picking_backend", - "bevy_window", - "bevy_winit", - "custom_cursor", - "default_font", - "hdr", - "multi_threaded", - "png", - "smaa_luts", - "sysinfo_plugin", - "tonemapping_luts", - "vorbis", - "webgl2", - "x11", - "webgpu"], default-features = false } -# Kira audio works in WASM, supports FLAC, and works in local runs +# Bevy game engine with carefully selected features: +bevy = { version = "0.15.0", features = [ + "bevy_asset", # Asset loading system + "bevy_core_pipeline", # Core rendering pipeline + "bevy_render", # Basic rendering functionality + "bevy_sprite", # 2D sprite support + "bevy_text", # Text rendering for UI + "bevy_ui", # User interface system + "bevy_window", # Window management + "bevy_winit", # Window creation and event handling + "default_font", # Include default font for text + "multi_threaded", # Enable multithreading for native builds + "png", # PNG image support + "webgl2", # WebGL 2.0 support for web buildsr + "webgpu", # WebGPU support for modern browsers + "x11", # Linux display server support + "bevy_state", # For GameState management +], default-features = false } # Disable default features to minimize size + +# Audio system that works with WASM bevy_kira_audio = { version = "0.21.0", features = ["flac"], default-features = false } +# 2D physics engine for ball and paddle physics bevy_rapier2d = "0.28.0" +# Random number generation for game mechanics rand = "0.8.5" -# Enable max optimizations for all dependencies in release builds +# Release build optimization settings [profile.release] -opt-level = 3 # Maximum optimization -lto = true # Enable link-time optimization -panic = 'abort' # Abort on panic for smaller binary size -strip = true # Strip symbols from binary -overflow-checks = false # Disable integer overflow checks +opt-level = 'z' # Optimize for size rather than speed +lto = true # Enable link-time optimization +panic = 'abort' # Remove panic handling code +strip = true # Strip symbols from binary +overflow-checks = false # Disable integer overflow checks -# Optimize all dependencies even in debug builds for faster runs +# Optimize dependencies even in debug builds [profile.dev.package."*"] -opt-level = 3 +opt-level = 3 # Maximum optimization for dependencies +# Debug build settings for the main package [profile.dev] -opt-level = 1 # Minimum optimization for primary package +opt-level = 1 # Minimal optimization for faster compilation diff --git a/README.md b/README.md index 4d6b729..4802c92 100644 --- a/README.md +++ b/README.md @@ -28,10 +28,10 @@ Through the lens of Fun: - Pause functionality - Background music toggle (M key) - Clean state management flow: - - Splash screen - - Active gameplay - - Pause menu - - Victory/defeat screen + - Splash screen + - Active gameplay + - Pause menu + - Victory/defeat screen ## Controls @@ -97,4 +97,4 @@ MIT - See LICENSE file for details. ## Acknowledgments - The Bevy community for their excellent documentation and examples -- Classic Pong for providing timeless gameplay inspiration \ No newline at end of file +- Classic Pong for providing timeless gameplay inspiration diff --git a/assets/social-card.png b/assets/social-card.png new file mode 100644 index 0000000000000000000000000000000000000000..1ed2ea2a508b6d1929b6bbecf5106c5464aa509a GIT binary patch literal 67408 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 K9yeX~`~L!HQ5cy3 literal 0 HcmV?d00001 diff --git a/src/audio.rs b/src/audio.rs index 67b1d46..81adb19 100644 --- a/src/audio.rs +++ b/src/audio.rs @@ -5,24 +5,37 @@ use bevy::input::ButtonInput; use bevy::prelude::{KeyCode, OnEnter, OnExit, ParamSet, Res, ResMut, Resource}; use bevy_kira_audio::{Audio, AudioControl, AudioInstance, AudioPlugin, AudioTween}; -/// Plugin that manages background music functionality, including playing, pausing, -/// and toggling music based on game state and user input. +/// The MusicPlugin manages all background music functionality for the game. +/// +/// This plugin handles: +/// - Playing background music during gameplay +/// - Pausing/resuming music based on game state +/// - Toggling music on/off with the 'M' key +/// - Managing the music state across game state transitions pub struct MusicPlugin; -/// Resource that tracks the current state of the background music +/// Tracks the current state of the background music system. +/// +/// This resource maintains information about: +/// - Whether music is currently enabled +/// - The handle to the current audio instance (if one exists) +/// +/// The state persists across game state changes to maintain user preferences +/// for music playback. #[derive(Resource)] struct MusicState { - /// Whether the music is currently enabled + /// Indicates if music should be playing (true) or muted (false) playing: bool, - /// Handle to the current audio instance, if one exists + /// Optional handle to the current audio instance + /// None if no music has been started or if music was explicitly stopped handle: Option>, } impl Default for MusicState { fn default() -> Self { Self { - playing: false, // Start with music disabled - handle: None, + playing: false, // Start with music disabled by default + handle: None, // No audio instance at initialization } } } @@ -31,9 +44,9 @@ impl Plugin for MusicPlugin { fn build(&self, app: &mut App) { app.add_plugins(AudioPlugin) .init_resource::() - // Add system to handle M key press for toggling music + // System to handle manual music toggling via 'M' key .add_systems(Update, handle_music_toggle) - // Add systems to handle music state changes based on game state + // Systems to manage music across different game states .add_systems(OnEnter(GameState::Playing), start_background_music) .add_systems(OnExit(GameState::Playing), pause_background_music) .add_systems(OnEnter(GameState::Paused), pause_background_music) @@ -41,21 +54,31 @@ impl Plugin for MusicPlugin { } } -/// Starts playing background music if it's not already playing +/// Initiates background music playback if it's not already playing. +/// +/// This system: +/// 1. Checks if music is currently disabled +/// 2. Loads the music asset +/// 3. Starts playback in a looped configuration +/// 4. Stores the audio handle for future reference fn start_background_music( audio: Res