Compare commits
No commits in common. "1d22c11cde12798dbbda9ec80e9999831786bffd" and "12e58b3fc08a599057d9a13c82f275fffe361f9e" have entirely different histories.
1d22c11cde
...
12e58b3fc0
16 changed files with 344 additions and 768 deletions
147
Cargo.lock
generated
147
Cargo.lock
generated
|
@ -208,9 +208,9 @@ checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
|
|||
|
||||
[[package]]
|
||||
name = "bevy"
|
||||
version = "0.8.1"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fea147ef1ebb92d41294cfad804c40de151b174c711ce6e0a4a40eba23eae1a4"
|
||||
checksum = "55f08528a4e59d607460513a823b40f602d013c1a00f57b824f1075d5d48c3cd"
|
||||
dependencies = [
|
||||
"bevy_internal",
|
||||
]
|
||||
|
@ -241,9 +241,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bevy_animation"
|
||||
version = "0.8.1"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4365465fca7bd78295eb81d0a04afc049399852793d562eb017849bb5d6c55e"
|
||||
checksum = "e243169af495ad616ff701247c0d3e40078a26ed8de231cf9e54bde6b3c4bb45"
|
||||
dependencies = [
|
||||
"bevy_app",
|
||||
"bevy_asset",
|
||||
|
@ -259,9 +259,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bevy_app"
|
||||
version = "0.8.1"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e4ae0a6ed2adf3b153511b4645241660a93f747c05ecd1e5a909dafc803cad4"
|
||||
checksum = "53d26d6ffdf493609d2fedc1018a2ef0cb4d8e48f6d3bcea56fa2df81867e464"
|
||||
dependencies = [
|
||||
"bevy_derive",
|
||||
"bevy_ecs",
|
||||
|
@ -274,9 +274,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bevy_asset"
|
||||
version = "0.8.1"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2ec773c861a7e9d9978771f59f385500ec6da3a1ab5487705cddb054393d3d19"
|
||||
checksum = "3d8fb95306d5f18fa70df40632cd984993aeb71e91ce059ae99699098a4f9ce9"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bevy_app",
|
||||
|
@ -302,9 +302,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bevy_audio"
|
||||
version = "0.8.1"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e5cf4713a24f318841f73a9e030854cfd5bad46bc81fa1acc9590cdab053c6f"
|
||||
checksum = "eee08ac575397ce17477dd291862bafa15226334bdfb82c02bbc3d10bad7bdb8"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bevy_app",
|
||||
|
@ -316,23 +316,11 @@ dependencies = [
|
|||
"rodio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bevy_common_assets"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f7be9ee39085d8319d5cd853447b0b5c4f8b4bfd647aec91e2bd996e9db67ef"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bevy",
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bevy_core"
|
||||
version = "0.8.1"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c53172003d5cde7780870b5403c66c8ede3581faf3e510e916d8b4baa5b538d2"
|
||||
checksum = "c6712146d54fff9e1865362e9f39a7b63c7b037ddb72a3d7bb05b959213fb61e"
|
||||
dependencies = [
|
||||
"bevy_app",
|
||||
"bevy_ecs",
|
||||
|
@ -345,9 +333,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bevy_core_pipeline"
|
||||
version = "0.8.1"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e60efd10d593f6d122f2687f74c09ad55835a8f999c35bed6380ddd8e6ff7f2"
|
||||
checksum = "080bb00399b6d7697e505f871d67c6de8b52eb06b47b0cda2be80c2396805983"
|
||||
dependencies = [
|
||||
"bevy_app",
|
||||
"bevy_asset",
|
||||
|
@ -363,9 +351,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bevy_derive"
|
||||
version = "0.8.1"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e6345431bbe6d7b6c165cd860ecd0b35da929779571259c5df970ac256d45f9"
|
||||
checksum = "a4b8f0786d1fc7e0d35297917be463db3d0886f7bd8d4221ca3d565502579ffb"
|
||||
dependencies = [
|
||||
"bevy_macro_utils",
|
||||
"quote",
|
||||
|
@ -374,9 +362,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bevy_diagnostic"
|
||||
version = "0.8.1"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "58ac9f4c2815f412be4b6e21e4b299cdafa710f651d064f6d40b2a8377a0d17c"
|
||||
checksum = "adab74ee5375fbf5d2b1d3da41de8d1491a8a706d17441b5e31214b65349d692"
|
||||
dependencies = [
|
||||
"bevy_app",
|
||||
"bevy_ecs",
|
||||
|
@ -387,9 +375,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bevy_ecs"
|
||||
version = "0.8.1"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c174066a24ed8a14d15ea58b0aea1c1f5c763f4bb36ebdc2b1dc78026007d0f5"
|
||||
checksum = "a5643dc27b7d6778e3a66c8e0f6ad1fd33309aa2fa61d935f360ccc85b7be6a2"
|
||||
dependencies = [
|
||||
"async-channel",
|
||||
"bevy_ecs_macros",
|
||||
|
@ -406,9 +394,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bevy_ecs_macros"
|
||||
version = "0.8.1"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cc50c39e49e8febccc74e8e731680adb0cb4aef1f53275740cbaa95c6da71f4f"
|
||||
checksum = "a5f2f12677f8725d40930d0a19652f007fe0ef5ac38e23817cfc4930c61f5680"
|
||||
dependencies = [
|
||||
"bevy_macro_utils",
|
||||
"proc-macro2",
|
||||
|
@ -431,9 +419,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bevy_encase_derive"
|
||||
version = "0.8.1"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68bc194009c5e9b97da64a08142dd183c264885d99c985cf849868103018adf1"
|
||||
checksum = "76a767adc36ce1fc917a736843b026d4de7069d90ed5e669c852481ef69fd5aa"
|
||||
dependencies = [
|
||||
"bevy_macro_utils",
|
||||
"encase_derive_impl",
|
||||
|
@ -441,9 +429,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bevy_gilrs"
|
||||
version = "0.8.1"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb15a3427d9707be92b457e5d66900b02d853b475c21dd8662bdda387ba9f24e"
|
||||
checksum = "963940426127533164af2a556971a03c493143c0afb95afadb4a070b6ab8c3df"
|
||||
dependencies = [
|
||||
"bevy_app",
|
||||
"bevy_ecs",
|
||||
|
@ -454,9 +442,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bevy_gltf"
|
||||
version = "0.8.1"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79db7d7e71b47a69953fbe8407ded5c6308eaeecf9a05efd5dfb42992f400a16"
|
||||
checksum = "150cc6782c4472600c2ade5d78c6ce481c992690f0499e63765aba752d7e0f04"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"base64",
|
||||
|
@ -483,9 +471,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bevy_hierarchy"
|
||||
version = "0.8.1"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5eb1ec76099ea5a716de08ea42ff41f036ebe2502df1d569168b58f16458a85e"
|
||||
checksum = "8e2e4c20d7c843cd26ef3c5d7b4c20e3e32c275943e2437ecaca1cfd6cfe3b30"
|
||||
dependencies = [
|
||||
"bevy_app",
|
||||
"bevy_ecs",
|
||||
|
@ -496,9 +484,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bevy_input"
|
||||
version = "0.8.1"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1821c4b760ba6ddb4fe61806e9cc33f40b09a884557aca4553a29b8c7d73c6b4"
|
||||
checksum = "a11c70573fb4d4c056ba32cfa553daa7e6e1245cb876ccfbe322640928b7ee1c"
|
||||
dependencies = [
|
||||
"bevy_app",
|
||||
"bevy_ecs",
|
||||
|
@ -508,9 +496,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bevy_internal"
|
||||
version = "0.8.1"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee63ad1e3f95a26ff2c227fadb1534a7bfe3a098e0e45c347f2f2575a573d9bc"
|
||||
checksum = "0d603b597772130782eab6e604706cbb764fb037f9cf0a1904b6f342845b6f44"
|
||||
dependencies = [
|
||||
"bevy_animation",
|
||||
"bevy_app",
|
||||
|
@ -546,9 +534,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bevy_log"
|
||||
version = "0.8.1"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "092daf498887814a064331dfcd1cf487a5ddab01fd38629b84a35b8b664462a1"
|
||||
checksum = "8cafb12fc84734236e36f407ab62c72d5d4279fa4777e40a95d7cc973cbabcd1"
|
||||
dependencies = [
|
||||
"android_log-sys",
|
||||
"bevy_app",
|
||||
|
@ -561,9 +549,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bevy_macro_utils"
|
||||
version = "0.8.1"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43fb5137e5198302d7c6c33d1e454cf48a586e7c6fd12f4860f12863951e16b9"
|
||||
checksum = "4d081af83b701e16cad209255ba6b383744dfa49efa99eb6505989f293305ab3"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn",
|
||||
|
@ -572,18 +560,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bevy_math"
|
||||
version = "0.8.1"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "531f2b90c7e861a96f418b3d560131b3354c5e67a67eba3953a45a56ea0114d2"
|
||||
checksum = "db5394e86c5708d3aa506c6e98ec4ed2a4083a7a018c6693d9ac0e77ebfabfc2"
|
||||
dependencies = [
|
||||
"glam",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bevy_mikktspace"
|
||||
version = "0.8.1"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "941e7d3d4e1dbb735f040e4cdc1558be1d3c38d43f1d9fdbb039c39a7849a00b"
|
||||
checksum = "40b299a61175a6f7e7398f83cd5b50920fd8bad4df674e614ad94f25f8426509"
|
||||
dependencies = [
|
||||
"glam",
|
||||
]
|
||||
|
@ -611,9 +599,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bevy_ptr"
|
||||
version = "0.8.1"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9960c19e582b43cebe1894b6679520a4f50802d1cc5b6fa432f8d685ed232f09"
|
||||
checksum = "d92d5679e89602a18682a37846573dcd1979410179e14204280460ba9fb8713a"
|
||||
|
||||
[[package]]
|
||||
name = "bevy_rapier2d"
|
||||
|
@ -630,9 +618,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bevy_reflect"
|
||||
version = "0.8.1"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fc689dd7a7df3b3768884a4754711d406aa302ea48da483c03b52715fa95045"
|
||||
checksum = "08798e67f2d4e6898ef117d8c99cf3b50a8eebc8da4159e6dad2657a0fbe9a4e"
|
||||
dependencies = [
|
||||
"bevy_ptr",
|
||||
"bevy_reflect_derive",
|
||||
|
@ -649,9 +637,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bevy_reflect_derive"
|
||||
version = "0.8.1"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8c36fa5100832c787c10558d31632ddc454c221e8dfacbbef836938f59614754"
|
||||
checksum = "19209a7f0238053802b7de04e6724bd90d4ed7d90e87101dbd1b64cca64ff694"
|
||||
dependencies = [
|
||||
"bevy_macro_utils",
|
||||
"proc-macro2",
|
||||
|
@ -662,9 +650,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bevy_render"
|
||||
version = "0.8.1"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "600bcef85c7efac6e38ed725707f0e5b7c59b510430034ba2f743f472493f845"
|
||||
checksum = "bb49530388ef17cff3fb8bd5e47372fb3cfeb4befc73e3036f6462ac20f049ef"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bevy_app",
|
||||
|
@ -705,9 +693,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bevy_render_macros"
|
||||
version = "0.8.1"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1be90adc9e5d5808833e363670818da5fe68ccafd7ca983a457f90957d2a430b"
|
||||
checksum = "e7d0b7a51fa819c20c64f43856c5aaea40f853050bbb09b9ba3672e5ff2688a5"
|
||||
dependencies = [
|
||||
"bevy_macro_utils",
|
||||
"proc-macro2",
|
||||
|
@ -717,9 +705,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bevy_scene"
|
||||
version = "0.8.1"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a045d575d2c8f776d8ea965363c81660243fefbfc3712ead938b00dfd6797216"
|
||||
checksum = "0064d73ebb0de39901478b493604a1a6d448fd337b66803004c60f41f1fa6c37"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bevy_app",
|
||||
|
@ -765,9 +753,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bevy_tasks"
|
||||
version = "0.8.1"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "719b753acb3d5b9dbfd77038560fe1893c17d4ee0a4242c2ee70da9d59430537"
|
||||
checksum = "ff874c91a36eaac3ef957c6f3b590fb71332d9d136671cc858847d56fe9f80a3"
|
||||
dependencies = [
|
||||
"async-channel",
|
||||
"async-executor",
|
||||
|
@ -780,9 +768,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bevy_text"
|
||||
version = "0.8.1"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c265b7515faf55a3b92fd6ce0ab65dd246f247e11d737d6f5cdaf49c2be42c63"
|
||||
checksum = "ef05a788c2c04aaa5db95b22a8f0fff0d3a0b08a7bcd1a71f050a628b38eec6e"
|
||||
dependencies = [
|
||||
"ab_glyph",
|
||||
"anyhow",
|
||||
|
@ -803,9 +791,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bevy_time"
|
||||
version = "0.8.1"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "22830665b8476292b861216383fd79922aef2b540f9fd09d49144e3e5e94550e"
|
||||
checksum = "74ec681d641371df81d7bfbcb0eea725ed873f38a094f34b5f7b436f0889e77c"
|
||||
dependencies = [
|
||||
"bevy_app",
|
||||
"bevy_ecs",
|
||||
|
@ -816,9 +804,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bevy_transform"
|
||||
version = "0.8.1"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4bb8760f03e9667e7499a5ceec1f7630fc3e45702781ac0df56cb969e8ae668"
|
||||
checksum = "42e1528e35f30bede46a50ee4134f150efc01f5c1002c340b3b2e6a0bfcb8aa5"
|
||||
dependencies = [
|
||||
"bevy_app",
|
||||
"bevy_ecs",
|
||||
|
@ -857,9 +845,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bevy_utils"
|
||||
version = "0.8.1"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6e9aa1866c1cf7ee000f281ce9e90d02d701f5c7380a107252017e58e2f5246"
|
||||
checksum = "8bda6dada53e546845887ae7357eec57b8d547ef71627b716b33839b4a98b687"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"getrandom",
|
||||
|
@ -886,9 +874,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bevy_winit"
|
||||
version = "0.8.1"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "98b15fee4b75472e3441b0c7221467303e4ce59b342a94a328e447e7cdb5a43c"
|
||||
checksum = "57537a56ac4f4e1ffcad95227bcab37cd17b51770dacff82374a2d88be376322"
|
||||
dependencies = [
|
||||
"approx",
|
||||
"bevy_app",
|
||||
|
@ -910,15 +898,12 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"bevy",
|
||||
"bevy-inspector-egui",
|
||||
"bevy_common_assets",
|
||||
"bevy_rapier2d",
|
||||
"cpal 0.14.0",
|
||||
"crossbeam-channel",
|
||||
"hexodsp",
|
||||
"rand",
|
||||
"rand_distr",
|
||||
"rapier2d",
|
||||
"serde",
|
||||
"ticktock",
|
||||
]
|
||||
|
||||
|
|
|
@ -6,15 +6,12 @@ license = "AGPL-3.0-only"
|
|||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
bevy = "0.8.1"
|
||||
bevy_common_assets = { version = "0.3.0", features = ["json"] }
|
||||
bevy = "0.8.0"
|
||||
bevy-inspector-egui = "0.12.1"
|
||||
bevy_rapier2d = "0.16.2"
|
||||
crossbeam-channel = "0.5.6"
|
||||
rand = "0.8.5"
|
||||
rand_distr = "0.4.3"
|
||||
rapier2d = "0.14.0"
|
||||
serde = { version = "1.0.144", features = ["derive"] }
|
||||
|
||||
[target."cfg(not(target_arch = \"wasm32\"))".dependencies]
|
||||
cpal = "0.14.0"
|
||||
|
|
|
@ -5,19 +5,16 @@
|
|||
* **Move**: arrows
|
||||
* **Switch character**: Tab
|
||||
* **Level up**: Enter (when character is white)
|
||||
* **Reset**: R
|
||||
|
||||
## TODO
|
||||
|
||||
* name
|
||||
* more filters
|
||||
* despawn black characters
|
||||
* despawn character when too far
|
||||
* color filters
|
||||
* level design
|
||||
* (?) can jump only from a surface (no mid-air jump)
|
||||
* (?) multiplayer
|
||||
* level reset
|
||||
* more audio
|
||||
* "jumpable" component to avoid jumping on sensors
|
||||
* bug: in level2, move the blue character to win, then reset. The characters are lighter than expected.
|
||||
|
||||
## Build
|
||||
|
||||
|
|
BIN
assets/bevy.png
BIN
assets/bevy.png
Binary file not shown.
Before Width: | Height: | Size: 8.7 KiB |
|
@ -1,119 +0,0 @@
|
|||
{
|
||||
"levels": [
|
||||
{
|
||||
"comment": "Movement tutorial",
|
||||
"platforms": [
|
||||
{"pos": [0, -256], "size": [800, 16]}
|
||||
],
|
||||
"characters": [
|
||||
{"pos": [0, -192], "color": [1,0,0,1]},
|
||||
{"pos": [-128, -192], "color": [0,1,0,1]},
|
||||
{"pos": [128, -192], "color": [0,0,1,1]}
|
||||
],
|
||||
"absorbing_filters": [],
|
||||
"rotating_filters": [],
|
||||
"texts": [
|
||||
{
|
||||
"pos": [0, 0],
|
||||
"font_size": 32,
|
||||
"text": "Combine the colors to synthetize a white light.\nUse arrows to move."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "Switch tutorial",
|
||||
"platforms": [
|
||||
{"pos": [0, -256], "size": [800, 16]},
|
||||
{"pos": [128, 256], "size": [96, 16]}
|
||||
],
|
||||
"characters": [
|
||||
{"pos": [0, -192], "color": [0,1,0,1]},
|
||||
{"pos": [-128, -192], "color": [1,0,0,1]},
|
||||
{"pos": [128, 320], "color": [0,0,1,1]}
|
||||
],
|
||||
"absorbing_filters": [],
|
||||
"rotating_filters": [],
|
||||
"texts": [
|
||||
{
|
||||
"pos": [0, 0],
|
||||
"font_size": 32,
|
||||
"text": "Press Tab to switch."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "Absorbing filter tutorial",
|
||||
"platforms": [
|
||||
{"pos": [0, -256], "size": [800, 16]},
|
||||
{"pos": [0, -128], "size": [800, 16]}
|
||||
],
|
||||
"characters": [
|
||||
{"pos": [-128, -192], "color": [1,0.64,0,1]},
|
||||
{"pos": [128, -192], "color": [0,0.37,1,1]}
|
||||
],
|
||||
"absorbing_filters": [
|
||||
{
|
||||
"pos": [0, -192],
|
||||
"size": [16, 112],
|
||||
"color": [1,0,0,1]
|
||||
}
|
||||
],
|
||||
"rotating_filters": [],
|
||||
"texts": [
|
||||
{
|
||||
"pos": [0, 0],
|
||||
"font_size": 32,
|
||||
"text": "Press R to reset."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "Rotating filter tutorial",
|
||||
"platforms": [
|
||||
{"pos": [0, -256], "size": [800, 16]}
|
||||
],
|
||||
"characters": [
|
||||
{"pos": [0, -192], "color": [1,0,0,1]},
|
||||
{"pos": [-128, -192], "color": [1,0,0,1]},
|
||||
{"pos": [128, -192], "color": [1,0,0,1]}
|
||||
],
|
||||
"absorbing_filters": [],
|
||||
"rotating_filters": [
|
||||
{
|
||||
"pos": [0, -64],
|
||||
"angle": 45
|
||||
}
|
||||
],
|
||||
"texts": [
|
||||
{
|
||||
"pos": [0, 0],
|
||||
"font_size": 32,
|
||||
"text": "Let's rotate the hue!"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "Game over",
|
||||
"platforms": [
|
||||
{"pos": [0, -256], "size": [800, 16]}
|
||||
],
|
||||
"characters": [
|
||||
{"pos": [0, -64], "color": [1,0,0,1]}
|
||||
],
|
||||
"absorbing_filters": [],
|
||||
"rotating_filters": [],
|
||||
"texts": [
|
||||
{
|
||||
"pos": [0, 128],
|
||||
"font_size": 48,
|
||||
"text": "Thank you for playing!"
|
||||
},
|
||||
{
|
||||
"pos": [0, 0],
|
||||
"font_size": 32,
|
||||
"text": "There is no more light to combine."
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
File diff suppressed because one or more lines are too long
|
@ -2,7 +2,6 @@
|
|||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8"/>
|
||||
<title>Bevyjam</title>
|
||||
</head>
|
||||
<body>
|
||||
<script type="module">
|
||||
|
|
16
src/audio.rs
16
src/audio.rs
|
@ -33,18 +33,9 @@ pub fn setup(event_channel: Receiver<AudioMsg>) {
|
|||
let color_mix_b_gain = color_mix.inp_param("gain3").unwrap();
|
||||
let jump_ad = NodeId::Ad(0);
|
||||
let jump_ad_trig = jump_ad.inp_param("trig").unwrap();
|
||||
let switch_ad = NodeId::Ad(1);
|
||||
let switch_ad_trig = switch_ad.inp_param("trig").unwrap();
|
||||
let fusion_ad = NodeId::Ad(2);
|
||||
let fusion_ad_trig = fusion_ad.inp_param("trig").unwrap();
|
||||
let fusion_ad2 = NodeId::Ad(3);
|
||||
let fusion_ad2_trig = fusion_ad2.inp_param("trig").unwrap();
|
||||
|
||||
for (_tick, _now) in Clock::framerate(20.0).iter() {
|
||||
for (_tick, _now) in Clock::framerate(10.0).iter() {
|
||||
matrix.set_param(jump_ad_trig, (0.0).into());
|
||||
matrix.set_param(switch_ad_trig, (0.0).into());
|
||||
matrix.set_param(fusion_ad_trig, (0.0).into());
|
||||
matrix.set_param(fusion_ad2_trig, (0.0).into());
|
||||
|
||||
if let Ok(msg) = event_channel.try_recv() {
|
||||
match msg {
|
||||
|
@ -53,12 +44,7 @@ pub fn setup(event_channel: Receiver<AudioMsg>) {
|
|||
matrix.set_param(color_mix_g_gain, g.into());
|
||||
matrix.set_param(color_mix_b_gain, b.into());
|
||||
}
|
||||
AudioMsg::Fusion => {
|
||||
matrix.set_param(fusion_ad_trig, (1.0).into());
|
||||
matrix.set_param(fusion_ad2_trig, (1.0).into());
|
||||
}
|
||||
AudioMsg::Jump => matrix.set_param(jump_ad_trig, (1.0).into()),
|
||||
AudioMsg::Switch => matrix.set_param(switch_ad_trig, (1.0).into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,99 +0,0 @@
|
|||
use crate::game::Level;
|
||||
|
||||
use bevy::prelude::{shape::Quad, *};
|
||||
use bevy_rapier2d::prelude::*;
|
||||
|
||||
#[derive(Component)]
|
||||
pub enum PassThroughFilter {
|
||||
/// Absorbs this color (ignoring alpha)
|
||||
Absorbing(Color),
|
||||
/// Rotates hue by this angle (in degrees)
|
||||
Rotating(f32),
|
||||
}
|
||||
|
||||
impl PassThroughFilter {
|
||||
pub fn apply(&self, color: Color) -> Color {
|
||||
match self {
|
||||
PassThroughFilter::Absorbing(filter_color) => Vec4::from(color)
|
||||
.mul_add(
|
||||
-Vec4::from(*filter_color) * Vec4::from([1., 1., 1., 0.]),
|
||||
Vec4::from(color),
|
||||
)
|
||||
.into(),
|
||||
PassThroughFilter::Rotating(filter_angle) => {
|
||||
let mut hsla = color.as_hsla_f32();
|
||||
hsla[0] = (hsla[0] + filter_angle) % 360.;
|
||||
Color::hsla(hsla[0], hsla[1], hsla[2], hsla[3])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Bundle)]
|
||||
pub struct AbsorbingFilter {
|
||||
#[bundle]
|
||||
pub mesh: ColorMesh2dBundle,
|
||||
pub collider: Collider,
|
||||
pub sensor: Sensor,
|
||||
pub filter: PassThroughFilter,
|
||||
}
|
||||
|
||||
pub fn spawn_absorbing_filter(
|
||||
commands: &mut Commands,
|
||||
meshes: &mut ResMut<Assets<Mesh>>,
|
||||
materials: &mut ResMut<Assets<ColorMaterial>>,
|
||||
|
||||
transform: Transform,
|
||||
size: Vec2,
|
||||
color: Color,
|
||||
) {
|
||||
let mut material_color = color;
|
||||
material_color.set_a(0.5);
|
||||
commands
|
||||
.spawn_bundle(AbsorbingFilter {
|
||||
mesh: ColorMesh2dBundle {
|
||||
mesh: meshes.add(Mesh::from(Quad { size, flip: false })).into(),
|
||||
material: materials.add(material_color.into()),
|
||||
transform,
|
||||
..Default::default()
|
||||
},
|
||||
collider: Collider::cuboid(size.x / 2., size.y / 2.),
|
||||
sensor: Sensor,
|
||||
filter: PassThroughFilter::Absorbing(color),
|
||||
})
|
||||
.insert(Level);
|
||||
}
|
||||
|
||||
#[derive(Bundle)]
|
||||
pub struct RotatingFilter {
|
||||
#[bundle]
|
||||
pub sprite: SpriteBundle,
|
||||
pub collider: Collider,
|
||||
pub sensor: Sensor,
|
||||
pub filter: PassThroughFilter,
|
||||
pub velocity: Velocity,
|
||||
pub rigid_body: RigidBody,
|
||||
}
|
||||
|
||||
pub fn spawn_rotating_filter(
|
||||
commands: &mut Commands,
|
||||
asset_server: &Res<AssetServer>,
|
||||
|
||||
transform: Transform,
|
||||
angle: f32,
|
||||
) {
|
||||
commands
|
||||
.spawn_bundle(RotatingFilter {
|
||||
sprite: SpriteBundle {
|
||||
texture: asset_server.get_handle("bevy.png"),
|
||||
transform,
|
||||
..Default::default()
|
||||
},
|
||||
collider: Collider::ball(32.),
|
||||
sensor: Sensor,
|
||||
filter: PassThroughFilter::Rotating(angle),
|
||||
velocity: Velocity::angular(1.),
|
||||
rigid_body: RigidBody::KinematicVelocityBased,
|
||||
})
|
||||
.insert(Level);
|
||||
}
|
291
src/game.rs
291
src/game.rs
|
@ -1,28 +1,20 @@
|
|||
#![allow(clippy::precedence)]
|
||||
#![allow(clippy::too_many_arguments)]
|
||||
|
||||
pub use crate::filters::*;
|
||||
|
||||
use crate::AppState;
|
||||
|
||||
use bevy::{
|
||||
ecs::system::EntityCommands,
|
||||
input::{keyboard::KeyCode, Input},
|
||||
prelude::{shape::Quad, *},
|
||||
sprite::Mesh2dHandle,
|
||||
sprite::Mesh2dHandle, ecs::system::EntityCommands,
|
||||
};
|
||||
use bevy_rapier2d::prelude::*;
|
||||
use rapier2d::geometry::CollisionEventFlags;
|
||||
|
||||
pub enum AudioMsg {
|
||||
Color([f32; 3]),
|
||||
Fusion,
|
||||
Jump,
|
||||
Switch,
|
||||
}
|
||||
|
||||
pub struct FirstLevel(pub LevelId);
|
||||
|
||||
#[derive(Clone, Copy, Eq, Hash, PartialEq)]
|
||||
pub struct LevelId(pub u32);
|
||||
|
||||
|
@ -43,14 +35,12 @@ impl Plugin for GamePlugin {
|
|||
.with_system(crate::levels::post_setup_level)
|
||||
.with_system(change_character_system)
|
||||
.with_system(player_movement_system)
|
||||
.with_system(level_keyboard_system)
|
||||
.with_system(move_camera)
|
||||
.with_system(character_particle_effect_system),
|
||||
)
|
||||
.add_system_set(
|
||||
SystemSet::on_update(AppState::Win)
|
||||
.with_system(player_movement_system)
|
||||
.with_system(level_keyboard_system)
|
||||
.with_system(move_camera)
|
||||
.with_system(character_particle_effect_system),
|
||||
)
|
||||
|
@ -60,7 +50,7 @@ impl Plugin for GamePlugin {
|
|||
|
||||
// Events
|
||||
|
||||
pub struct LevelStartupEvent;
|
||||
pub struct LevelStartupEvent(pub Entity);
|
||||
|
||||
// Resources
|
||||
|
||||
|
@ -95,41 +85,52 @@ pub struct CharacterColor(pub Color);
|
|||
#[derive(Component)]
|
||||
pub struct Player;
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct CollisionCount(usize);
|
||||
|
||||
// Systems
|
||||
|
||||
fn setup(
|
||||
first_level: Res<FirstLevel>,
|
||||
mut commands: Commands,
|
||||
mut current_level: ResMut<CurrentLevel>,
|
||||
mut level_startup_event: EventWriter<LevelStartupEvent>,
|
||||
mut camera_query: Query<&mut Transform, With<Camera>>,
|
||||
) {
|
||||
if current_level.0.is_none() {
|
||||
current_level.0 = Some(first_level.0);
|
||||
}
|
||||
|
||||
crate::levels::setup_level(&mut level_startup_event, &mut camera_query);
|
||||
let level_id = LevelId(current_level.0.map_or(0, |level_id| level_id.0 + 1));
|
||||
crate::levels::setup_level(
|
||||
&mut commands,
|
||||
&mut current_level,
|
||||
&mut level_startup_event,
|
||||
&mut camera_query,
|
||||
level_id,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn spawn_characters<I: IntoIterator<Item = (Transform, Color)>>(
|
||||
pub fn spawn_characters(
|
||||
commands: &mut Commands,
|
||||
character_meshes: &Res<CharacterMeshes>,
|
||||
materials: &mut ResMut<Assets<ColorMaterial>>,
|
||||
audio: &Res<crossbeam_channel::Sender<AudioMsg>>,
|
||||
|
||||
characters: I,
|
||||
transforms: &mut Vec<Transform>,
|
||||
colors: &Vec<Color>,
|
||||
) {
|
||||
for (i, (transform, color)) in characters.into_iter().enumerate() {
|
||||
spawn_character(
|
||||
commands,
|
||||
character_meshes,
|
||||
materials,
|
||||
audio,
|
||||
transform,
|
||||
color,
|
||||
i == 0,
|
||||
transforms[0],
|
||||
colors[0],
|
||||
true,
|
||||
);
|
||||
|
||||
for c in 1 .. transforms.len() {
|
||||
spawn_character(
|
||||
commands,
|
||||
character_meshes,
|
||||
materials,
|
||||
audio,
|
||||
transforms[c],
|
||||
colors[c],
|
||||
false,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -159,6 +160,7 @@ pub fn spawn_character(
|
|||
.insert(CharacterColor(color))
|
||||
.insert(RigidBody::Dynamic)
|
||||
.insert(Collider::cuboid(32., 32.))
|
||||
.insert(ExternalForce::default())
|
||||
.insert(Velocity::default())
|
||||
.insert(GravityScale(10.0))
|
||||
.insert(LockedAxes::ROTATION_LOCKED)
|
||||
|
@ -167,16 +169,8 @@ pub fn spawn_character(
|
|||
linear_damping: 0.5,
|
||||
angular_damping: 0.5,
|
||||
})
|
||||
.insert(ActiveEvents::COLLISION_EVENTS)
|
||||
.with_children(|c| {
|
||||
c.spawn_bundle(TransformBundle::from_transform(Transform::from_xyz(
|
||||
0., -33., 0.,
|
||||
)))
|
||||
.insert(Sensor)
|
||||
.insert(Collider::cuboid(30., 0.5))
|
||||
.insert(ActiveEvents::COLLISION_EVENTS)
|
||||
.insert(CollisionCount(0));
|
||||
});
|
||||
.insert(ExternalImpulse::default())
|
||||
.insert(ActiveEvents::COLLISION_EVENTS);
|
||||
|
||||
if is_player {
|
||||
entity_commands.insert(Player);
|
||||
|
@ -186,62 +180,24 @@ pub fn spawn_character(
|
|||
}
|
||||
}
|
||||
|
||||
pub fn spawn_platforms<I: IntoIterator<Item = (Transform, Vec2)>>(
|
||||
commands: &mut Commands,
|
||||
meshes: &mut ResMut<Assets<Mesh>>,
|
||||
materials: &mut ResMut<Assets<ColorMaterial>>,
|
||||
|
||||
platforms: I,
|
||||
) {
|
||||
for (transform, size) in platforms.into_iter() {
|
||||
spawn_platform(commands, meshes, materials, transform, size);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn spawn_platform(
|
||||
commands: &mut Commands,
|
||||
meshes: &mut ResMut<Assets<Mesh>>,
|
||||
materials: &mut ResMut<Assets<ColorMaterial>>,
|
||||
|
||||
transform: Transform,
|
||||
size: Vec2,
|
||||
) {
|
||||
commands
|
||||
.spawn_bundle(ColorMesh2dBundle {
|
||||
mesh: meshes.add(Mesh::from(Quad { size, flip: false })).into(),
|
||||
material: materials.add(ColorMaterial::from(Color::GRAY)),
|
||||
transform,
|
||||
..default()
|
||||
})
|
||||
.insert(Collider::cuboid(size.x / 2., size.y / 2.))
|
||||
.insert(Level);
|
||||
}
|
||||
|
||||
fn collision_event_system(
|
||||
mut commands: Commands,
|
||||
character_meshes: Res<CharacterMeshes>,
|
||||
mut materials: ResMut<Assets<ColorMaterial>>,
|
||||
mut collision_events: EventReader<CollisionEvent>,
|
||||
mut character_query: Query<(
|
||||
&mut CharacterColor,
|
||||
&Transform,
|
||||
&mut Handle<ColorMaterial>,
|
||||
Option<&Player>,
|
||||
)>,
|
||||
pass_through_filter_query: Query<&PassThroughFilter>,
|
||||
mut collision_counter_query: Query<&mut CollisionCount>,
|
||||
character_query: Query<(&CharacterColor, &Transform, Option<&Player>)>,
|
||||
mut app_state: ResMut<State<AppState>>,
|
||||
audio: Res<crossbeam_channel::Sender<AudioMsg>>,
|
||||
) {
|
||||
for collision_event in collision_events.iter() {
|
||||
match collision_event {
|
||||
CollisionEvent::Started(e1, e2, flags) => {
|
||||
if let CollisionEvent::Started(e1, e2, flags) = collision_event {
|
||||
if flags.is_empty() {
|
||||
if let (
|
||||
Ok((c1_color, c1_transform, _c1_material, c1_player)),
|
||||
Ok((c2_color, c2_transform, _c2_material, c2_player)),
|
||||
) = (character_query.get(*e1), character_query.get(*e2))
|
||||
Ok((c1_color, c1_transform, c1_player)),
|
||||
Ok((c2_color, c2_transform, c2_player))) =
|
||||
(character_query.get(*e1), character_query.get(*e2))
|
||||
{
|
||||
// TODO completely remove particles
|
||||
commands.entity(*e1).despawn_recursive();
|
||||
commands.entity(*e2).despawn_recursive();
|
||||
|
||||
|
@ -256,87 +212,26 @@ fn collision_event_system(
|
|||
}
|
||||
|
||||
// position character based on current player location
|
||||
if let Some(_player) = c1_player {
|
||||
spawn_character(
|
||||
&mut commands,
|
||||
&character_meshes,
|
||||
&mut materials,
|
||||
&audio,
|
||||
if c1_player.is_some() {
|
||||
*c1_transform
|
||||
} else if c2_player.is_some() {
|
||||
*c2_transform
|
||||
} else {
|
||||
Transform::identity().with_translation(
|
||||
(c1_transform.translation + c2_transform.translation) / 2.,
|
||||
)
|
||||
},
|
||||
*c1_transform,
|
||||
new_color.into(),
|
||||
c1_player.is_some() || c2_player.is_some(),
|
||||
true,
|
||||
);
|
||||
} else if let Some(_player) = c2_player {
|
||||
spawn_character(
|
||||
&mut commands,
|
||||
&character_meshes,
|
||||
&mut materials,
|
||||
&audio,
|
||||
*c2_transform,
|
||||
new_color.into(),
|
||||
true,
|
||||
);
|
||||
|
||||
audio.send(AudioMsg::Fusion).ok();
|
||||
}
|
||||
} else if *flags == CollisionEventFlags::SENSOR {
|
||||
if let (Ok((mut c_color, _c_transform, mut c_material, c_player)), Ok(filter)) = (
|
||||
character_query.get_mut(*e1),
|
||||
pass_through_filter_query.get(*e2),
|
||||
) {
|
||||
c_color.0 = filter.apply(c_color.0);
|
||||
*c_material = materials.add(ColorMaterial::from(c_color.0));
|
||||
|
||||
if c_player.is_some() {
|
||||
audio
|
||||
.send(AudioMsg::Color([
|
||||
c_color.0.r(),
|
||||
c_color.0.g(),
|
||||
c_color.0.b(),
|
||||
]))
|
||||
.ok();
|
||||
}
|
||||
} else if let (
|
||||
Ok((mut c_color, _c_transform, mut c_material, c_player)),
|
||||
Ok(filter),
|
||||
) = (
|
||||
character_query.get_mut(*e2),
|
||||
pass_through_filter_query.get(*e1),
|
||||
) {
|
||||
c_color.0 = filter.apply(c_color.0);
|
||||
*c_material = materials.add(ColorMaterial::from(c_color.0));
|
||||
|
||||
if c_player.is_some() {
|
||||
audio
|
||||
.send(AudioMsg::Color([
|
||||
c_color.0.r(),
|
||||
c_color.0.g(),
|
||||
c_color.0.b(),
|
||||
]))
|
||||
.ok();
|
||||
}
|
||||
} else if let (Ok(mut collision_count), Err(_)) = (
|
||||
collision_counter_query.get_mut(*e1),
|
||||
character_query.get_mut(*e2),
|
||||
) {
|
||||
collision_count.0 += 1;
|
||||
} else if let (Ok(mut collision_count), Err(_)) = (
|
||||
collision_counter_query.get_mut(*e2),
|
||||
character_query.get_mut(*e1),
|
||||
) {
|
||||
collision_count.0 += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
CollisionEvent::Stopped(e1, e2, flags) => {
|
||||
if *flags == CollisionEventFlags::SENSOR {
|
||||
if let (Ok(mut collision_count), Err(_)) = (
|
||||
collision_counter_query.get_mut(*e1),
|
||||
character_query.get_mut(*e2),
|
||||
) {
|
||||
collision_count.0 = collision_count.0.saturating_sub(1);
|
||||
} else if let (Ok(mut collision_count), Err(_)) = (
|
||||
collision_counter_query.get_mut(*e2),
|
||||
character_query.get_mut(*e1),
|
||||
) {
|
||||
collision_count.0 = collision_count.0.saturating_sub(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -351,16 +246,14 @@ fn change_character_system(
|
|||
characters: Query<(Entity, &CharacterColor, Option<&Player>)>,
|
||||
audio: Res<crossbeam_channel::Sender<AudioMsg>>,
|
||||
) {
|
||||
if !keyboard_input.just_pressed(KeyCode::Tab) {
|
||||
return;
|
||||
}
|
||||
if !keyboard_input.just_pressed(KeyCode::Tab) { return; }
|
||||
|
||||
let mut player_idx: usize = 0;
|
||||
let mut player_count: usize = 0;
|
||||
|
||||
// find player idx
|
||||
for (_entity, _color, player) in characters.iter() {
|
||||
if player.is_some() {
|
||||
if let Some(_player) = player {
|
||||
player_idx = player_count;
|
||||
}
|
||||
player_count += 1;
|
||||
|
@ -381,7 +274,7 @@ fn change_character_system(
|
|||
audio
|
||||
.send(AudioMsg::Color([color.0.r(), color.0.g(), color.0.b()]))
|
||||
.ok();
|
||||
audio.send(AudioMsg::Switch).ok();
|
||||
audio.send(AudioMsg::Jump).ok();
|
||||
}
|
||||
|
||||
player_count += 1;
|
||||
|
@ -390,69 +283,53 @@ fn change_character_system(
|
|||
|
||||
fn player_movement_system(
|
||||
keyboard_input: Res<Input<KeyCode>>,
|
||||
mut characters: Query<(&mut Velocity, &Children), With<Player>>,
|
||||
collision_counter_query: Query<&CollisionCount>,
|
||||
mut characters: Query<&mut Velocity, With<Player>>,
|
||||
mut app_state: ResMut<State<AppState>>,
|
||||
audio: Res<crossbeam_channel::Sender<AudioMsg>>,
|
||||
) {
|
||||
|
||||
let right_pressed: bool =
|
||||
keyboard_input.pressed(KeyCode::Right) || keyboard_input.pressed(KeyCode::D);
|
||||
let left_pressed: bool =
|
||||
keyboard_input.pressed(KeyCode::Left) || keyboard_input.pressed(KeyCode::A);
|
||||
|
||||
for (mut velocity, children) in characters.iter_mut() {
|
||||
for mut velocity in characters.iter_mut() {
|
||||
velocity.linvel.x = 200. * (right_pressed as i8 - left_pressed as i8) as f32;
|
||||
|
||||
if keyboard_input.just_pressed(KeyCode::Space)
|
||||
&& collision_counter_query.get(children[0]).unwrap().0 != 0
|
||||
{
|
||||
if keyboard_input.just_pressed(KeyCode::Space) {
|
||||
audio.send(AudioMsg::Jump).ok();
|
||||
velocity.linvel.y = 700.;
|
||||
velocity.linvel.y = 500.;
|
||||
}
|
||||
}
|
||||
|
||||
if app_state.current() == &AppState::Win && keyboard_input.just_pressed(KeyCode::Return) {
|
||||
app_state.replace(AppState::Game).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
fn character_particle_effect_system(
|
||||
player_character: Query<(&Transform, &CharacterColor), With<Player>>,
|
||||
characters: Query<(&Transform, &CharacterColor), With<Player>>,
|
||||
mut particle_effect: ResMut<crate::particle_effect::ParticleEffectResource>,
|
||||
) {
|
||||
if let Ok((transform, color)) = player_character.get_single() {
|
||||
for (transform, color) in characters.iter() {
|
||||
particle_effect.translation = transform.translation;
|
||||
particle_effect.color = color.0;
|
||||
}
|
||||
}
|
||||
|
||||
fn win_setup(
|
||||
mut commands: Commands,
|
||||
mut meshes: ResMut<Assets<Mesh>>,
|
||||
mut materials: ResMut<Assets<ColorMaterial>>,
|
||||
asset_server: Res<AssetServer>,
|
||||
) {
|
||||
fn win_setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||
let font = asset_server.get_handle("UacariLegacy-Thin.ttf");
|
||||
commands
|
||||
.spawn_bundle(ColorMesh2dBundle {
|
||||
mesh: meshes
|
||||
.add(Mesh::from(Quad {
|
||||
size: Vec2 { x: 512., y: 64. },
|
||||
flip: false,
|
||||
}))
|
||||
.into(),
|
||||
material: materials.add(ColorMaterial::from(Color::rgba(0., 0., 0., 0.9))),
|
||||
transform: Transform::from_xyz(0., 0., 3.),
|
||||
..default()
|
||||
})
|
||||
.insert(Level);
|
||||
commands
|
||||
.spawn_bundle(Text2dBundle {
|
||||
text: Text::from_section(
|
||||
"Press ENTER to level up",
|
||||
TextStyle {
|
||||
font,
|
||||
font_size: 36.0,
|
||||
font_size: 32.0,
|
||||
color: Color::WHITE,
|
||||
},
|
||||
)
|
||||
.with_alignment(TextAlignment::CENTER),
|
||||
transform: Transform::from_xyz(0., 0., 4.),
|
||||
..Default::default()
|
||||
})
|
||||
.insert(Level);
|
||||
|
@ -467,44 +344,18 @@ fn move_camera(
|
|||
const FOLLOW_SPEED: f32 = std::f32::consts::PI;
|
||||
|
||||
for character_transform in characters.iter() {
|
||||
let (camera, mut camera_transform) = camera_query.single_mut();
|
||||
let (camera, mut camera_transform) =
|
||||
camera_query.single_mut();
|
||||
|
||||
let size: Vec2 = camera.logical_viewport_size().unwrap();
|
||||
let half_height: f32 = size.y * 0.5;
|
||||
camera_transform.translation = camera_transform.translation.lerp(
|
||||
character_transform.translation,
|
||||
time.delta_seconds() * FOLLOW_SPEED,
|
||||
character_transform.translation, time.delta_seconds() * FOLLOW_SPEED
|
||||
);
|
||||
|
||||
// prevent camera from going too low
|
||||
camera_transform.translation.y = camera_transform.translation.y.max(half_height - MARGIN);
|
||||
camera_transform.translation.y = camera_transform.translation.y.max(half_height-MARGIN);
|
||||
// always make sure that camera is away from the object in order to render them
|
||||
camera_transform.translation.z = 999.0;
|
||||
}
|
||||
}
|
||||
|
||||
fn level_keyboard_system(
|
||||
mut commands: Commands,
|
||||
mut current_level: ResMut<CurrentLevel>,
|
||||
mut level_startup_event: EventWriter<LevelStartupEvent>,
|
||||
mut camera_query: Query<&mut Transform, With<Camera>>,
|
||||
keyboard_input: Res<Input<KeyCode>>,
|
||||
level_query: Query<Entity, With<Level>>,
|
||||
mut app_state: ResMut<State<AppState>>,
|
||||
) {
|
||||
if app_state.current() == &AppState::Win && keyboard_input.just_pressed(KeyCode::Return) {
|
||||
current_level.0 = Some(LevelId(
|
||||
current_level.0.map_or(0, |level_id| level_id.0 + 1),
|
||||
));
|
||||
app_state.replace(AppState::Game).unwrap();
|
||||
}
|
||||
|
||||
if keyboard_input.just_pressed(KeyCode::R) {
|
||||
for entity in level_query.iter() {
|
||||
commands.entity(entity).despawn_recursive();
|
||||
}
|
||||
if app_state.replace(AppState::Game).is_err() {
|
||||
crate::levels::setup_level(&mut level_startup_event, &mut camera_query);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
169
src/levels.rs
169
src/levels.rs
|
@ -1,17 +1,29 @@
|
|||
#![allow(clippy::too_many_arguments)]
|
||||
|
||||
mod game_over;
|
||||
mod level0;
|
||||
mod level1;
|
||||
|
||||
use crate::game::*;
|
||||
|
||||
use bevy::{prelude::*, reflect::TypeUuid};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use bevy::prelude::*;
|
||||
|
||||
pub fn setup_level(
|
||||
commands: &mut Commands,
|
||||
current_level: &mut ResMut<CurrentLevel>,
|
||||
level_startup_event: &mut EventWriter<LevelStartupEvent>,
|
||||
camera_query: &mut Query<&mut Transform, With<Camera>>,
|
||||
level_id: LevelId,
|
||||
) {
|
||||
let level_entity = commands
|
||||
.spawn()
|
||||
.insert(Level)
|
||||
.id();
|
||||
current_level.0 = Some(level_id);
|
||||
|
||||
camera_query.single_mut().translation = Default::default();
|
||||
|
||||
level_startup_event.send(LevelStartupEvent);
|
||||
level_startup_event.send(LevelStartupEvent(level_entity));
|
||||
}
|
||||
|
||||
pub fn despawn_level(mut commands: Commands, level_query: Query<Entity, With<Level>>) {
|
||||
|
@ -24,158 +36,29 @@ pub fn despawn_level(mut commands: Commands, level_query: Query<Entity, With<Lev
|
|||
pub fn post_setup_level(
|
||||
mut commands: Commands,
|
||||
character_meshes: Res<CharacterMeshes>,
|
||||
mut meshes: ResMut<Assets<Mesh>>,
|
||||
mut materials: ResMut<Assets<ColorMaterial>>,
|
||||
current_level: Res<CurrentLevel>,
|
||||
mut level_startup_event: EventReader<LevelStartupEvent>,
|
||||
asset_server: Res<AssetServer>,
|
||||
audio: Res<crossbeam_channel::Sender<AudioMsg>>,
|
||||
stored_levels_assets: Res<Assets<StoredLevels>>,
|
||||
stored_levels_handle: Res<Handle<StoredLevels>>,
|
||||
) {
|
||||
for _ in level_startup_event.iter() {
|
||||
for LevelStartupEvent(level_entity) in level_startup_event.iter() {
|
||||
if let Some(level_id) = current_level.0 {
|
||||
if let Some(stored_level) = stored_levels_assets
|
||||
.get(&stored_levels_handle)
|
||||
.unwrap()
|
||||
.levels
|
||||
.get(level_id.0 as usize)
|
||||
{
|
||||
spawn_stored_level(
|
||||
match level_id.0 {
|
||||
0 => level0::setup(
|
||||
&mut commands,
|
||||
&character_meshes,
|
||||
&mut meshes,
|
||||
&mut materials,
|
||||
&asset_server,
|
||||
&audio,
|
||||
stored_level,
|
||||
);
|
||||
),
|
||||
1 => level1::setup(
|
||||
&mut commands,
|
||||
&character_meshes,
|
||||
&mut materials,
|
||||
&audio,
|
||||
),
|
||||
_ => game_over::setup(&mut commands, &asset_server),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, TypeUuid)]
|
||||
#[uuid = "1fbba930-644b-0d62-2514-4b302b945327"]
|
||||
pub struct StoredLevels {
|
||||
levels: Vec<StoredLevel>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, TypeUuid)]
|
||||
#[uuid = "a1464a30-1f57-a654-d56c-ded41032af0b"]
|
||||
pub struct StoredLevel {
|
||||
pub comment: String,
|
||||
pub characters: Vec<StoredCharacter>,
|
||||
pub platforms: Vec<StoredPlatform>,
|
||||
pub absorbing_filters: Vec<StoredAbsorbingFilter>,
|
||||
pub rotating_filters: Vec<StoredRotatingFilter>,
|
||||
pub texts: Vec<StoredText>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, TypeUuid)]
|
||||
#[uuid = "1c798f8c-ef15-c528-693e-76becdef6b10"]
|
||||
pub struct StoredCharacter {
|
||||
pub pos: Vec2,
|
||||
pub color: Vec4,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, TypeUuid)]
|
||||
#[uuid = "31696095-59de-93be-b5e9-333c2afbc900"]
|
||||
pub struct StoredPlatform {
|
||||
pub pos: Vec2,
|
||||
pub size: Vec2,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, TypeUuid)]
|
||||
#[uuid = "bcad7fff-0605-c4e3-3cd4-42d5bbaad926"]
|
||||
pub struct StoredAbsorbingFilter {
|
||||
pub pos: Vec2,
|
||||
pub size: Vec2,
|
||||
pub color: Vec4,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, TypeUuid)]
|
||||
#[uuid = "fa2843f2-6e34-601b-6c46-4827b0370b3f"]
|
||||
pub struct StoredRotatingFilter {
|
||||
pub pos: Vec2,
|
||||
pub angle: f32,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, TypeUuid)]
|
||||
#[uuid = "72f6321a-f01f-6eea-9b17-3159837a2fd3"]
|
||||
pub struct StoredText {
|
||||
pub pos: Vec2,
|
||||
pub font_size: f32,
|
||||
pub text: String,
|
||||
}
|
||||
|
||||
pub fn spawn_stored_level(
|
||||
commands: &mut Commands,
|
||||
character_meshes: &Res<CharacterMeshes>,
|
||||
meshes: &mut ResMut<Assets<Mesh>>,
|
||||
materials: &mut ResMut<Assets<ColorMaterial>>,
|
||||
asset_server: &Res<AssetServer>,
|
||||
audio: &Res<crossbeam_channel::Sender<AudioMsg>>,
|
||||
|
||||
stored_level: &StoredLevel,
|
||||
) {
|
||||
let font = asset_server.get_handle("UacariLegacy-Thin.ttf");
|
||||
spawn_platforms(
|
||||
commands,
|
||||
meshes,
|
||||
materials,
|
||||
stored_level.platforms.iter().map(|platform| {
|
||||
(
|
||||
Transform::from_xyz(platform.pos.x, platform.pos.y, 0.),
|
||||
platform.size,
|
||||
)
|
||||
}),
|
||||
);
|
||||
spawn_characters(
|
||||
commands,
|
||||
character_meshes,
|
||||
materials,
|
||||
audio,
|
||||
stored_level.characters.iter().map(|character| {
|
||||
(
|
||||
Transform::from_xyz(character.pos.x, character.pos.y, 0.),
|
||||
character.color.into(),
|
||||
)
|
||||
}),
|
||||
);
|
||||
for absorbing_filter in stored_level.absorbing_filters.iter() {
|
||||
spawn_absorbing_filter(
|
||||
commands,
|
||||
meshes,
|
||||
materials,
|
||||
Transform::from_xyz(absorbing_filter.pos.x, absorbing_filter.pos.y, 2.),
|
||||
absorbing_filter.size,
|
||||
absorbing_filter.color.into(),
|
||||
);
|
||||
}
|
||||
for rotating_filter in stored_level.rotating_filters.iter() {
|
||||
spawn_rotating_filter(
|
||||
commands,
|
||||
asset_server,
|
||||
Transform::from_xyz(rotating_filter.pos.x, rotating_filter.pos.y, 2.),
|
||||
rotating_filter.angle,
|
||||
);
|
||||
}
|
||||
for text in stored_level.texts.iter() {
|
||||
commands
|
||||
.spawn_bundle(Text2dBundle {
|
||||
text: Text::from_section(
|
||||
&text.text,
|
||||
TextStyle {
|
||||
font: font.clone(),
|
||||
font_size: text.font_size,
|
||||
color: Color::WHITE,
|
||||
},
|
||||
)
|
||||
.with_alignment(TextAlignment::CENTER),
|
||||
transform: Transform::from_xyz(text.pos.x, text.pos.y, 0.),
|
||||
..Default::default()
|
||||
})
|
||||
.insert(Level);
|
||||
}
|
||||
}
|
||||
|
|
36
src/levels/game_over.rs
Normal file
36
src/levels/game_over.rs
Normal file
|
@ -0,0 +1,36 @@
|
|||
use crate::game::*;
|
||||
|
||||
use bevy::prelude::*;
|
||||
|
||||
pub fn setup(commands: &mut Commands, asset_server: &Res<AssetServer>) {
|
||||
let font = asset_server.get_handle("UacariLegacy-Thin.ttf");
|
||||
commands
|
||||
.spawn_bundle(Text2dBundle {
|
||||
text: Text::from_section(
|
||||
"GAME OVER",
|
||||
TextStyle {
|
||||
font: font.clone(),
|
||||
font_size: 48.0,
|
||||
color: Color::WHITE,
|
||||
},
|
||||
)
|
||||
.with_alignment(TextAlignment::CENTER),
|
||||
transform: Transform::from_xyz(0., 128.0, 0.),
|
||||
..Default::default()
|
||||
})
|
||||
.insert(Level);
|
||||
commands
|
||||
.spawn_bundle(Text2dBundle {
|
||||
text: Text::from_section(
|
||||
"There is no more light to combine.",
|
||||
TextStyle {
|
||||
font,
|
||||
font_size: 32.0,
|
||||
color: Color::WHITE,
|
||||
},
|
||||
)
|
||||
.with_alignment(TextAlignment::CENTER),
|
||||
..Default::default()
|
||||
})
|
||||
.insert(Level);
|
||||
}
|
46
src/levels/level0.rs
Normal file
46
src/levels/level0.rs
Normal file
|
@ -0,0 +1,46 @@
|
|||
use crate::game::*;
|
||||
|
||||
use bevy::prelude::*;
|
||||
use bevy_rapier2d::prelude::*;
|
||||
|
||||
pub fn setup(
|
||||
commands: &mut Commands,
|
||||
character_meshes: &Res<CharacterMeshes>,
|
||||
materials: &mut ResMut<Assets<ColorMaterial>>,
|
||||
// selected_character_id: &mut Mut<SelectedCharacterId>,
|
||||
// character_id_list: &mut Mut<CharacterIdList>,
|
||||
audio: &Res<crossbeam_channel::Sender<AudioMsg>>,
|
||||
) {
|
||||
commands
|
||||
.spawn_bundle(TransformBundle::from(Transform::from_xyz(0.0, -256.0, 0.0)))
|
||||
.insert(Collider::cuboid(400., 10.))
|
||||
.insert(Level);
|
||||
|
||||
spawn_character(
|
||||
commands,
|
||||
character_meshes,
|
||||
materials,
|
||||
audio,
|
||||
Transform::from_xyz(-128., -64., 0.),
|
||||
Color::RED,
|
||||
true,
|
||||
);
|
||||
spawn_character(
|
||||
commands,
|
||||
character_meshes,
|
||||
materials,
|
||||
audio,
|
||||
Transform::from_xyz(0., -64., 0.),
|
||||
Color::GREEN,
|
||||
false,
|
||||
);
|
||||
spawn_character(
|
||||
commands,
|
||||
character_meshes,
|
||||
materials,
|
||||
audio,
|
||||
Transform::from_xyz(128., -64., 0.),
|
||||
Color::BLUE,
|
||||
false,
|
||||
);
|
||||
}
|
50
src/levels/level1.rs
Normal file
50
src/levels/level1.rs
Normal file
|
@ -0,0 +1,50 @@
|
|||
use crate::game::*;
|
||||
|
||||
use bevy::prelude::*;
|
||||
use bevy_rapier2d::prelude::*;
|
||||
|
||||
pub fn setup(
|
||||
commands: &mut Commands,
|
||||
character_meshes: &Res<CharacterMeshes>,
|
||||
materials: &mut ResMut<Assets<ColorMaterial>>,
|
||||
audio: &Res<crossbeam_channel::Sender<AudioMsg>>,
|
||||
) {
|
||||
commands
|
||||
.spawn_bundle(TransformBundle::from(Transform::from_xyz(0.0, -256.0, 0.0)))
|
||||
.insert(Collider::cuboid(400., 10.))
|
||||
.insert(Level);
|
||||
commands
|
||||
.spawn_bundle(TransformBundle::from(Transform::from_xyz(
|
||||
256.0, -128.0, 0.0,
|
||||
)))
|
||||
.insert(Collider::cuboid(200., 10.))
|
||||
.insert(Level);
|
||||
|
||||
spawn_character(
|
||||
commands,
|
||||
character_meshes,
|
||||
materials,
|
||||
audio,
|
||||
Transform::from_xyz(128., 64., 0.),
|
||||
Color::BLUE,
|
||||
true,
|
||||
);
|
||||
spawn_character(
|
||||
commands,
|
||||
character_meshes,
|
||||
materials,
|
||||
audio,
|
||||
Transform::from_xyz(-128., -128., 0.),
|
||||
Color::RED,
|
||||
false,
|
||||
);
|
||||
spawn_character(
|
||||
commands,
|
||||
character_meshes,
|
||||
materials,
|
||||
audio,
|
||||
Transform::from_xyz(0., -128., 0.),
|
||||
Color::GREEN,
|
||||
false,
|
||||
);
|
||||
}
|
66
src/main.rs
66
src/main.rs
|
@ -1,16 +1,11 @@
|
|||
#[cfg(not(target_arch = "wasm32"))]
|
||||
mod audio;
|
||||
mod filters;
|
||||
mod game;
|
||||
mod levels;
|
||||
mod menu;
|
||||
mod particle_effect;
|
||||
|
||||
use bevy::{
|
||||
prelude::*,
|
||||
window::{WindowId, WindowMode},
|
||||
};
|
||||
use bevy_common_assets::json::JsonAssetPlugin;
|
||||
use bevy::{core_pipeline::clear_color::ClearColorConfig, prelude::*};
|
||||
use bevy_rapier2d::prelude::*;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||
|
@ -27,66 +22,35 @@ fn main() {
|
|||
#[cfg(not(target_arch = "wasm32"))]
|
||||
std::thread::spawn(move || audio::setup(audio_event_receiver));
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
let first_level = game::LevelId(
|
||||
std::env::args()
|
||||
.nth(1)
|
||||
.map_or(0, |s| s.parse().unwrap_or(0)),
|
||||
);
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
let first_level = game::LevelId(0);
|
||||
|
||||
App::new()
|
||||
.insert_resource(Msaa { samples: 4 })
|
||||
.insert_resource(audio_event_sender)
|
||||
.add_state(AppState::Menu)
|
||||
.insert_resource(game::FirstLevel(first_level))
|
||||
.insert_resource(ClearColor(Color::BLACK))
|
||||
.add_plugins(DefaultPlugins)
|
||||
.add_plugin(JsonAssetPlugin::<levels::StoredLevels>::new(&[
|
||||
"levels.json",
|
||||
]))
|
||||
.add_plugin(RapierPhysicsPlugin::<NoUserData>::pixels_per_meter(64.0))
|
||||
//.add_plugin(RapierDebugRenderPlugin::default())
|
||||
.add_plugin(RapierDebugRenderPlugin::default())
|
||||
.add_plugin(menu::MenuPlugin)
|
||||
.add_plugin(game::GamePlugin)
|
||||
.add_plugin(particle_effect::ParticleEffectPlugin)
|
||||
//.add_plugin(bevy_inspector_egui::WorldInspectorPlugin::new())
|
||||
.add_system(keyboard_util_system)
|
||||
.add_plugin(bevy_inspector_egui::WorldInspectorPlugin::new())
|
||||
.add_startup_system(setup)
|
||||
.run();
|
||||
}
|
||||
|
||||
fn setup(mut commands: Commands, mut windows: ResMut<Windows>, asset_server: Res<AssetServer>) {
|
||||
windows
|
||||
.get_mut(WindowId::primary())
|
||||
.unwrap()
|
||||
.set_title(String::from("Bevyjam"));
|
||||
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
let font: Handle<Font> = asset_server.load("UacariLegacy-Thin.ttf");
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
let font: Handle<Font> = asset_server.load("UacariLegacy-Thin.ttf");
|
||||
commands.insert_resource(font);
|
||||
|
||||
commands.insert_resource(asset_server.load::<levels::StoredLevels, _>("game.levels.json"));
|
||||
commands.insert_resource(asset_server.load::<Font, _>("UacariLegacy-Thin.ttf"));
|
||||
commands.insert_resource(asset_server.load::<Image, _>("bevy.png"));
|
||||
|
||||
commands.spawn_bundle(Camera2dBundle::default());
|
||||
commands.spawn_bundle(Camera2dBundle {
|
||||
camera_2d: Camera2d {
|
||||
clear_color: ClearColorConfig::Custom(Color::BLACK),
|
||||
},
|
||||
..Default::default()
|
||||
});
|
||||
commands.insert_resource(AmbientLight {
|
||||
color: Color::WHITE,
|
||||
brightness: 0.6,
|
||||
});
|
||||
}
|
||||
|
||||
fn keyboard_util_system(keyboard_input: Res<Input<KeyCode>>, mut windows: ResMut<Windows>) {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
{
|
||||
if keyboard_input.just_released(KeyCode::Escape) {
|
||||
std::process::exit(0);
|
||||
}
|
||||
if keyboard_input.just_pressed(KeyCode::F11) {
|
||||
if let Some(window) = windows.get_primary_mut() {
|
||||
window.set_mode(match window.mode() {
|
||||
WindowMode::Windowed => WindowMode::Fullscreen,
|
||||
_ => WindowMode::Windowed,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
"BEVYJAM",
|
||||
TextStyle {
|
||||
font: font.clone(),
|
||||
font_size: 96.0,
|
||||
font_size: 48.0,
|
||||
color: Color::WHITE,
|
||||
},
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue