avian start
This commit is contained in:
parent
12eea03a37
commit
42651aa4be
455
Cargo.lock
generated
455
Cargo.lock
generated
@ -103,6 +103,12 @@ dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "allocator-api2"
|
||||
version = "0.2.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
|
||||
|
||||
[[package]]
|
||||
name = "alsa"
|
||||
version = "0.9.1"
|
||||
@ -308,6 +314,45 @@ version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
||||
|
||||
[[package]]
|
||||
name = "avian2d"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "060ae40aced85ed01296f556ed1909fcafe81a5e5059889bed126339ccd55b43"
|
||||
dependencies = [
|
||||
"approx",
|
||||
"arrayvec",
|
||||
"avian_derive",
|
||||
"bevy",
|
||||
"bevy_heavy",
|
||||
"bevy_math",
|
||||
"bevy_transform_interpolation",
|
||||
"bitflags 2.10.0",
|
||||
"derive_more",
|
||||
"disqualified",
|
||||
"glam_matrix_extras",
|
||||
"itertools 0.13.0",
|
||||
"nalgebra",
|
||||
"parry2d",
|
||||
"parry2d-f64",
|
||||
"slab",
|
||||
"smallvec",
|
||||
"thiserror 2.0.17",
|
||||
"thread_local",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "avian_derive"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "12b257f601a1535e0d4a7a7796f535e3a13de62fd422b16dff7c14d27f0d4048"
|
||||
dependencies = [
|
||||
"proc-macro-error2",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.22.1"
|
||||
@ -794,6 +839,17 @@ dependencies = [
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bevy_heavy"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc496d1d43b890896cf561d8ce3dcf7b7b8e4c03c4e837a49a83a530abccbc5e"
|
||||
dependencies = [
|
||||
"bevy_math",
|
||||
"bevy_reflect",
|
||||
"glam_matrix_extras",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bevy_image"
|
||||
version = "0.18.0"
|
||||
@ -972,7 +1028,7 @@ dependencies = [
|
||||
"arrayvec",
|
||||
"bevy_reflect",
|
||||
"derive_more",
|
||||
"glam",
|
||||
"glam 0.30.10",
|
||||
"itertools 0.14.0",
|
||||
"libm",
|
||||
"rand",
|
||||
@ -1146,7 +1202,7 @@ dependencies = [
|
||||
"downcast-rs 2.0.2",
|
||||
"erased-serde",
|
||||
"foldhash 0.2.0",
|
||||
"glam",
|
||||
"glam 0.30.10",
|
||||
"indexmap",
|
||||
"inventory",
|
||||
"petgraph",
|
||||
@ -1206,7 +1262,7 @@ dependencies = [
|
||||
"downcast-rs 2.0.2",
|
||||
"encase",
|
||||
"fixedbitset",
|
||||
"glam",
|
||||
"glam 0.30.10",
|
||||
"image",
|
||||
"indexmap",
|
||||
"js-sys",
|
||||
@ -1436,6 +1492,15 @@ dependencies = [
|
||||
"thiserror 2.0.17",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bevy_transform_interpolation"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "88545c8b0fa8f3502b9a439c71fa6b596ee9e808bfb16f27a51c8c6f7405a657"
|
||||
dependencies = [
|
||||
"bevy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bevy_ui"
|
||||
version = "0.18.0"
|
||||
@ -2041,6 +2106,25 @@ dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
|
||||
dependencies = [
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-queue"
|
||||
version = "0.3.12"
|
||||
@ -2180,6 +2264,15 @@ version = "1.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
|
||||
|
||||
[[package]]
|
||||
name = "ena"
|
||||
version = "0.14.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d248bdd43ce613d87415282f69b9bb99d947d290b10962dd6c56233312c2ad5"
|
||||
dependencies = [
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "encase"
|
||||
version = "0.12.0"
|
||||
@ -2514,12 +2607,103 @@ dependencies = [
|
||||
"xml-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glam"
|
||||
version = "0.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "333928d5eb103c5d4050533cec0384302db6be8ef7d3cebd30ec6a35350353da"
|
||||
|
||||
[[package]]
|
||||
name = "glam"
|
||||
version = "0.15.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3abb554f8ee44336b72d522e0a7fe86a29e09f839a36022fa869a7dfe941a54b"
|
||||
|
||||
[[package]]
|
||||
name = "glam"
|
||||
version = "0.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4126c0479ccf7e8664c36a2d719f5f2c140fbb4f9090008098d2c291fa5b3f16"
|
||||
|
||||
[[package]]
|
||||
name = "glam"
|
||||
version = "0.17.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e01732b97afd8508eee3333a541b9f7610f454bb818669e66e90f5f57c93a776"
|
||||
|
||||
[[package]]
|
||||
name = "glam"
|
||||
version = "0.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "525a3e490ba77b8e326fb67d4b44b4bd2f920f44d4cc73ccec50adc68e3bee34"
|
||||
|
||||
[[package]]
|
||||
name = "glam"
|
||||
version = "0.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b8509e6791516e81c1a630d0bd7fbac36d2fa8712a9da8662e716b52d5051ca"
|
||||
|
||||
[[package]]
|
||||
name = "glam"
|
||||
version = "0.20.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f43e957e744be03f5801a55472f593d43fabdebf25a4585db250f04d86b1675f"
|
||||
|
||||
[[package]]
|
||||
name = "glam"
|
||||
version = "0.21.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "518faa5064866338b013ff9b2350dc318e14cc4fcd6cb8206d7e7c9886c98815"
|
||||
|
||||
[[package]]
|
||||
name = "glam"
|
||||
version = "0.22.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "12f597d56c1bd55a811a1be189459e8fad2bbc272616375602443bdfb37fa774"
|
||||
|
||||
[[package]]
|
||||
name = "glam"
|
||||
version = "0.23.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e4afd9ad95555081e109fe1d21f2a30c691b5f0919c67dfa690a2e1eb6bd51c"
|
||||
|
||||
[[package]]
|
||||
name = "glam"
|
||||
version = "0.24.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5418c17512bdf42730f9032c74e1ae39afc408745ebb2acf72fbc4691c17945"
|
||||
|
||||
[[package]]
|
||||
name = "glam"
|
||||
version = "0.25.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "151665d9be52f9bb40fc7966565d39666f2d1e69233571b71b87791c7e0528b3"
|
||||
|
||||
[[package]]
|
||||
name = "glam"
|
||||
version = "0.27.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e05e7e6723e3455f4818c7b26e855439f7546cf617ef669d1adedb8669e5cb9"
|
||||
|
||||
[[package]]
|
||||
name = "glam"
|
||||
version = "0.28.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "779ae4bf7e8421cf91c0b3b64e7e8b40b862fba4d393f59150042de7c4965a94"
|
||||
|
||||
[[package]]
|
||||
name = "glam"
|
||||
version = "0.29.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8babf46d4c1c9d92deac9f7be466f76dfc4482b6452fc5024b5e8daf6ffeb3ee"
|
||||
|
||||
[[package]]
|
||||
name = "glam"
|
||||
version = "0.30.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19fc433e8437a212d1b6f1e68c7824af3aed907da60afa994e7f542d18d12aa9"
|
||||
dependencies = [
|
||||
"approx",
|
||||
"bytemuck",
|
||||
"encase",
|
||||
"libm",
|
||||
@ -2527,6 +2711,16 @@ dependencies = [
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glam_matrix_extras"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4664468a60479272b880a8bfc00ad2915229b93d2b2d585556fb33f9ba80e72"
|
||||
dependencies = [
|
||||
"bevy_reflect",
|
||||
"glam 0.30.10",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glob"
|
||||
version = "0.3.3"
|
||||
@ -2697,6 +2891,8 @@ version = "0.15.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
|
||||
dependencies = [
|
||||
"allocator-api2",
|
||||
"equivalent",
|
||||
"foldhash 0.1.5",
|
||||
]
|
||||
|
||||
@ -2736,7 +2932,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29a164ceff4500f2a72b1d21beaa8aa8ad83aec2b641844c659b190cb3ea2e0b"
|
||||
dependencies = [
|
||||
"constgebra",
|
||||
"glam",
|
||||
"glam 0.30.10",
|
||||
"tinyvec",
|
||||
]
|
||||
|
||||
@ -3024,6 +3220,16 @@ dependencies = [
|
||||
"regex-automata",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "matrixmultiply"
|
||||
version = "0.3.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a06de3016e9fae57a36fd14dba131fccf49f74b40b7fbdb472f96e361ec71a08"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"rawpointer",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.6"
|
||||
@ -3124,6 +3330,49 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nalgebra"
|
||||
version = "0.34.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4d5b3eff5cd580f93da45e64715e8c20a3996342f1e466599cf7a267a0c2f5f"
|
||||
dependencies = [
|
||||
"approx",
|
||||
"glam 0.14.0",
|
||||
"glam 0.15.2",
|
||||
"glam 0.16.0",
|
||||
"glam 0.17.3",
|
||||
"glam 0.18.0",
|
||||
"glam 0.19.0",
|
||||
"glam 0.20.5",
|
||||
"glam 0.21.3",
|
||||
"glam 0.22.0",
|
||||
"glam 0.23.0",
|
||||
"glam 0.24.2",
|
||||
"glam 0.25.0",
|
||||
"glam 0.27.0",
|
||||
"glam 0.28.0",
|
||||
"glam 0.29.3",
|
||||
"glam 0.30.10",
|
||||
"matrixmultiply",
|
||||
"nalgebra-macros",
|
||||
"num-complex",
|
||||
"num-rational",
|
||||
"num-traits",
|
||||
"simba",
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nalgebra-macros"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "973e7178a678cfd059ccec50887658d482ce16b0aa9da3888ddeab5cd5eb4889"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ndk"
|
||||
version = "0.8.0"
|
||||
@ -3223,6 +3472,25 @@ dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
|
||||
dependencies = [
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-complex"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-derive"
|
||||
version = "0.4.2"
|
||||
@ -3234,6 +3502,26 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.46"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-rational"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.19"
|
||||
@ -3612,6 +3900,60 @@ dependencies = [
|
||||
"windows-link 0.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parry2d"
|
||||
version = "0.25.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef681740349cec3ab9b5996b03b459b383b6998e1ffcb2804e8b57eb1e8491d9"
|
||||
dependencies = [
|
||||
"approx",
|
||||
"arrayvec",
|
||||
"bitflags 2.10.0",
|
||||
"downcast-rs 2.0.2",
|
||||
"either",
|
||||
"ena",
|
||||
"foldhash 0.2.0",
|
||||
"hashbrown 0.16.1",
|
||||
"log",
|
||||
"nalgebra",
|
||||
"num-derive",
|
||||
"num-traits",
|
||||
"ordered-float",
|
||||
"rayon",
|
||||
"simba",
|
||||
"slab",
|
||||
"smallvec",
|
||||
"spade",
|
||||
"thiserror 2.0.17",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parry2d-f64"
|
||||
version = "0.25.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "835d4ca2b68026b04a75ca6196da961d8c0895420eacc9cc2201f7ad54775780"
|
||||
dependencies = [
|
||||
"approx",
|
||||
"arrayvec",
|
||||
"bitflags 2.10.0",
|
||||
"downcast-rs 2.0.2",
|
||||
"either",
|
||||
"ena",
|
||||
"foldhash 0.2.0",
|
||||
"hashbrown 0.16.1",
|
||||
"log",
|
||||
"nalgebra",
|
||||
"num-derive",
|
||||
"num-traits",
|
||||
"ordered-float",
|
||||
"rayon",
|
||||
"simba",
|
||||
"slab",
|
||||
"smallvec",
|
||||
"spade",
|
||||
"thiserror 2.0.17",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "paste"
|
||||
version = "1.0.15"
|
||||
@ -3761,6 +4103,28 @@ dependencies = [
|
||||
"toml_edit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error-attr2"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error2"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802"
|
||||
dependencies = [
|
||||
"proc-macro-error-attr2",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.105"
|
||||
@ -3872,6 +4236,32 @@ version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539"
|
||||
|
||||
[[package]]
|
||||
name = "rawpointer"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f"
|
||||
dependencies = [
|
||||
"either",
|
||||
"rayon-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91"
|
||||
dependencies = [
|
||||
"crossbeam-deque",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "read-fonts"
|
||||
version = "0.35.0"
|
||||
@ -3961,6 +4351,12 @@ version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832"
|
||||
|
||||
[[package]]
|
||||
name = "robust"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e27ee8bb91ca0adcf0ecb116293afa12d393f9c2b9b9cd54d33e8078fe19839"
|
||||
|
||||
[[package]]
|
||||
name = "rodio"
|
||||
version = "0.20.1"
|
||||
@ -4053,6 +4449,15 @@ dependencies = [
|
||||
"twox-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "safe_arch"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96b02de82ddbe1b636e6170c21be622223aea188ef2e139be0a5b219ec215323"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
version = "1.0.6"
|
||||
@ -4163,6 +4568,19 @@ version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "simba"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c99284beb21666094ba2b75bbceda012e610f5479dfcc2d6e2426f53197ffd95"
|
||||
dependencies = [
|
||||
"approx",
|
||||
"num-complex",
|
||||
"num-traits",
|
||||
"paste",
|
||||
"wide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "simd-adler32"
|
||||
version = "0.3.8"
|
||||
@ -4244,6 +4662,18 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spade"
|
||||
version = "2.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb313e1c8afee5b5647e00ee0fe6855e3d529eb863a0fdae1d60006c4d1e9990"
|
||||
dependencies = [
|
||||
"hashbrown 0.15.5",
|
||||
"num-traits",
|
||||
"robust",
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.10.0"
|
||||
@ -4414,6 +4844,7 @@ dependencies = [
|
||||
name = "time_travel"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"avian2d",
|
||||
"bevy",
|
||||
]
|
||||
|
||||
@ -4592,6 +5023,12 @@ version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c"
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
|
||||
|
||||
[[package]]
|
||||
name = "typewit"
|
||||
version = "1.14.2"
|
||||
@ -5037,6 +5474,16 @@ dependencies = [
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wide"
|
||||
version = "0.7.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ce5da8ecb62bcd8ec8b7ea19f69a51275e91299be594ea5cc6ef7819e16cd03"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"safe_arch",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
|
||||
@ -4,4 +4,5 @@ version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
avian2d = "0.5.0"
|
||||
bevy = "0.18.0"
|
||||
|
||||
BIN
assets/player.png
Normal file
BIN
assets/player.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.1 KiB |
357
src/avian.rs
Normal file
357
src/avian.rs
Normal file
@ -0,0 +1,357 @@
|
||||
use avian2d::{math::*, prelude::*};
|
||||
use bevy::prelude::*;
|
||||
|
||||
pub struct CharacterControllerPlugin;
|
||||
|
||||
impl Plugin for CharacterControllerPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.add_message::<MovementAction>()
|
||||
.add_systems(
|
||||
Update,
|
||||
(
|
||||
(keyboard_input, gamepad_input),
|
||||
movement,
|
||||
apply_movement_damping,
|
||||
)
|
||||
.chain(),
|
||||
)
|
||||
.add_systems(
|
||||
// Run collision handling after collision detection.
|
||||
//
|
||||
// NOTE: The collision implementation here is very basic and a bit buggy.
|
||||
// A collide-and-slide algorithm would likely work better.
|
||||
PhysicsSchedule,
|
||||
kinematic_controller_collisions.in_set(NarrowPhaseSystems::Last),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// A [`Message`] written for a movement input action.
|
||||
#[derive(Message)]
|
||||
pub struct MovementAction(Vec2);
|
||||
|
||||
/// A marker component indicating that an entity is using a character controller.
|
||||
#[derive(Component)]
|
||||
pub struct CharacterController;
|
||||
|
||||
/// A marker component indicating that an entity is on the ground.
|
||||
#[derive(Component)]
|
||||
#[component(storage = "SparseSet")]
|
||||
pub struct Grounded;
|
||||
|
||||
/// The acceleration used for character movement.
|
||||
#[derive(Component)]
|
||||
pub struct MovementAcceleration(Scalar);
|
||||
|
||||
/// The damping factor used for slowing down movement.
|
||||
#[derive(Component)]
|
||||
pub struct MovementDampingFactor(Scalar);
|
||||
|
||||
/// The maximum angle a slope can have for a character controller
|
||||
/// to be able to climb and jump. If the slope is steeper than this angle,
|
||||
/// the character will slide down.
|
||||
#[derive(Component)]
|
||||
pub struct MaxSlopeAngle(Scalar);
|
||||
|
||||
/// A bundle that contains the components needed for a basic
|
||||
/// kinematic character controller.
|
||||
#[derive(Bundle)]
|
||||
pub struct CharacterControllerBundle {
|
||||
character_controller: CharacterController,
|
||||
body: RigidBody,
|
||||
collider: Collider,
|
||||
ground_caster: ShapeCaster,
|
||||
movement: MovementBundle,
|
||||
}
|
||||
|
||||
/// A bundle that contains components for character movement.
|
||||
#[derive(Bundle)]
|
||||
pub struct MovementBundle {
|
||||
acceleration: MovementAcceleration,
|
||||
damping: MovementDampingFactor,
|
||||
max_slope_angle: MaxSlopeAngle,
|
||||
}
|
||||
|
||||
impl MovementBundle {
|
||||
pub const fn new(acceleration: Scalar, damping: Scalar, max_slope_angle: Scalar) -> Self {
|
||||
Self {
|
||||
acceleration: MovementAcceleration(acceleration),
|
||||
damping: MovementDampingFactor(damping),
|
||||
max_slope_angle: MaxSlopeAngle(max_slope_angle),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for MovementBundle {
|
||||
fn default() -> Self {
|
||||
Self::new(30.0, 0.99, PI * 0.45)
|
||||
}
|
||||
}
|
||||
|
||||
impl CharacterControllerBundle {
|
||||
pub fn new(collider: Collider) -> Self {
|
||||
// Create shape caster as a slightly smaller version of collider
|
||||
let mut caster_shape = collider.clone();
|
||||
caster_shape.set_scale(Vector::ONE * 0.99, 10);
|
||||
|
||||
Self {
|
||||
character_controller: CharacterController,
|
||||
body: RigidBody::Kinematic,
|
||||
collider,
|
||||
ground_caster: ShapeCaster::new(caster_shape, Vector::ZERO, 0.0, Dir2::NEG_Y)
|
||||
.with_max_distance(10.0),
|
||||
movement: MovementBundle::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_movement(
|
||||
mut self,
|
||||
acceleration: Scalar,
|
||||
damping: Scalar,
|
||||
max_slope_angle: Scalar,
|
||||
) -> Self {
|
||||
self.movement = MovementBundle::new(acceleration, damping, max_slope_angle);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// Sends [`MovementAction`] events based on keyboard input.
|
||||
fn keyboard_input(
|
||||
mut movement_writer: MessageWriter<MovementAction>,
|
||||
keyboard_input: Res<ButtonInput<KeyCode>>,
|
||||
) {
|
||||
let left = keyboard_input.any_pressed([KeyCode::KeyA, KeyCode::ArrowLeft]);
|
||||
let right = keyboard_input.any_pressed([KeyCode::KeyD, KeyCode::ArrowRight]);
|
||||
let up = keyboard_input.any_pressed([KeyCode::KeyW, KeyCode::ArrowUp]);
|
||||
let down = keyboard_input.any_pressed([KeyCode::KeyS, KeyCode::ArrowDown]);
|
||||
|
||||
let x = right as i8 - left as i8;
|
||||
let y = up as i8 - down as i8;
|
||||
let dir = Vec2::new(x as f32, y as f32);
|
||||
|
||||
if let Some(dir) = dir.try_normalize() {
|
||||
movement_writer.write(MovementAction(dir));
|
||||
}
|
||||
}
|
||||
|
||||
/// Sends [`MovementAction`] events based on gamepad input.
|
||||
fn gamepad_input(mut movement_writer: MessageWriter<MovementAction>, gamepads: Query<&Gamepad>) {
|
||||
for gamepad in gamepads.iter() {
|
||||
if let (Some(x), Some(y)) = (
|
||||
gamepad.get(GamepadAxis::LeftStickX),
|
||||
gamepad.get(GamepadAxis::LeftStickY),
|
||||
) {
|
||||
let mut dir = Vec2::new(x, y);
|
||||
let len = dir.length();
|
||||
if len == 0. {
|
||||
continue;
|
||||
}
|
||||
if len > 1. {
|
||||
dir = dir.normalize();
|
||||
}
|
||||
|
||||
movement_writer.write(MovementAction(dir));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Responds to [`MovementAction`] events and moves character controllers accordingly.
|
||||
fn movement(
|
||||
time: Res<Time>,
|
||||
mut movement_reader: MessageReader<MovementAction>,
|
||||
mut controllers: Query<(
|
||||
&MovementAcceleration,
|
||||
&MovementDampingFactor,
|
||||
&mut LinearVelocity,
|
||||
)>,
|
||||
) {
|
||||
// Precision is adjusted so that the example works with
|
||||
// both the `f32` and `f64` features. Otherwise you don't need this.
|
||||
let delta_time = time.delta_secs_f64().adjust_precision();
|
||||
|
||||
for (movement_acceleration, dampening, mut linear_velocity) in &mut controllers {
|
||||
if movement_reader.is_empty() {
|
||||
linear_velocity.x *= 1.0 / (1.0 + damping_factor.0 * delta_time);
|
||||
}
|
||||
for event in movement_reader.read() {
|
||||
match event {
|
||||
MovementAction::Move(direction) => {
|
||||
linear_velocity.x += *direction * movement_acceleration.0 * delta_time;
|
||||
}
|
||||
MovementAction::Jump => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Slows down movement in the X direction.
|
||||
fn apply_movement_damping(
|
||||
time: Res<Time>,
|
||||
mut query: Query<(&MovementDampingFactor, &mut LinearVelocity)>,
|
||||
) {
|
||||
// Precision is adjusted so that the example works with
|
||||
// both the `f32` and `f64` features. Otherwise you don't need this.
|
||||
let delta_time = time.delta_secs_f64().adjust_precision();
|
||||
|
||||
for (damping_factor, mut linear_velocity) in &mut query {
|
||||
// We could use `LinearDamping`, but we don't want to dampen movement along the Y axis
|
||||
linear_velocity.x *= 1.0 / (1.0 + damping_factor.0 * delta_time);
|
||||
}
|
||||
}
|
||||
|
||||
/// Kinematic bodies do not get pushed by collisions by default,
|
||||
/// so it needs to be done manually.
|
||||
///
|
||||
/// This system handles collision response for kinematic character controllers
|
||||
/// by pushing them along their contact normals by the current penetration depth,
|
||||
/// and applying velocity corrections in order to snap to slopes, slide along walls,
|
||||
/// and predict collisions using speculative contacts.
|
||||
#[allow(clippy::type_complexity)]
|
||||
fn kinematic_controller_collisions(
|
||||
collisions: Collisions,
|
||||
bodies: Query<&RigidBody>,
|
||||
collider_rbs: Query<&ColliderOf, Without<Sensor>>,
|
||||
mut character_controllers: Query<
|
||||
(&mut Position, &mut LinearVelocity, Option<&MaxSlopeAngle>),
|
||||
(With<RigidBody>, With<CharacterController>),
|
||||
>,
|
||||
time: Res<Time>,
|
||||
) {
|
||||
// Iterate through collisions and move the kinematic body to resolve penetration
|
||||
for contacts in collisions.iter() {
|
||||
// Get the rigid body entities of the colliders (colliders could be children)
|
||||
let Ok([&ColliderOf { body: rb1 }, &ColliderOf { body: rb2 }]) =
|
||||
collider_rbs.get_many([contacts.collider1, contacts.collider2])
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
|
||||
// Get the body of the character controller and whether it is the first
|
||||
// or second entity in the collision.
|
||||
let is_first: bool;
|
||||
|
||||
let character_rb: RigidBody;
|
||||
let is_other_dynamic: bool;
|
||||
|
||||
let (mut position, mut linear_velocity, max_slope_angle) =
|
||||
if let Ok(character) = character_controllers.get_mut(rb1) {
|
||||
is_first = true;
|
||||
character_rb = *bodies.get(rb1).unwrap();
|
||||
is_other_dynamic = bodies.get(rb2).is_ok_and(|rb| rb.is_dynamic());
|
||||
character
|
||||
} else if let Ok(character) = character_controllers.get_mut(rb2) {
|
||||
is_first = false;
|
||||
character_rb = *bodies.get(rb2).unwrap();
|
||||
is_other_dynamic = bodies.get(rb1).is_ok_and(|rb| rb.is_dynamic());
|
||||
character
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
|
||||
// This system only handles collision response for kinematic character controllers.
|
||||
if !character_rb.is_kinematic() {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Iterate through contact manifolds and their contacts.
|
||||
// Each contact in a single manifold shares the same contact normal.
|
||||
for manifold in contacts.manifolds.iter() {
|
||||
let normal = if is_first {
|
||||
-manifold.normal
|
||||
} else {
|
||||
manifold.normal
|
||||
};
|
||||
|
||||
let mut deepest_penetration: Scalar = Scalar::MIN;
|
||||
|
||||
// Solve each penetrating contact in the manifold.
|
||||
for contact in manifold.points.iter() {
|
||||
if contact.penetration > 0.0 {
|
||||
position.0 += normal * contact.penetration;
|
||||
}
|
||||
deepest_penetration = deepest_penetration.max(contact.penetration);
|
||||
}
|
||||
|
||||
// For now, this system only handles velocity corrections for collisions against static geometry.
|
||||
if is_other_dynamic {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Determine if the slope is climbable or if it's too steep to walk on.
|
||||
let slope_angle = normal.angle_to(Vector::Y);
|
||||
let climbable = max_slope_angle.is_some_and(|angle| slope_angle.abs() <= angle.0);
|
||||
|
||||
if deepest_penetration > 0.0 {
|
||||
// If the slope is climbable, snap the velocity so that the character
|
||||
// up and down the surface smoothly.
|
||||
if climbable {
|
||||
// Points either left or right depending on which side the normal is leaning on.
|
||||
// (This could be simplified for 2D, but this approach is dimension-agnostic)
|
||||
let normal_direction_x =
|
||||
normal.reject_from_normalized(Vector::Y).normalize_or_zero();
|
||||
|
||||
// The movement speed along the direction above.
|
||||
let linear_velocity_x = linear_velocity.dot(normal_direction_x);
|
||||
|
||||
// Snap the Y speed based on the speed at which the character is moving
|
||||
// up or down the slope, and how steep the slope is.
|
||||
//
|
||||
// A 2D visualization of the slope, the contact normal, and the velocity components:
|
||||
//
|
||||
// ╱
|
||||
// normal ╱
|
||||
// * ╱
|
||||
// │ * ╱ velocity_x
|
||||
// │ * - - - - - -
|
||||
// │ * | velocity_y
|
||||
// │ * |
|
||||
// *───────────────────*
|
||||
|
||||
let max_y_speed = -linear_velocity_x * slope_angle.tan();
|
||||
linear_velocity.y = linear_velocity.y.max(max_y_speed);
|
||||
} else {
|
||||
// The character is intersecting an unclimbable object, like a wall.
|
||||
// We want the character to slide along the surface, similarly to
|
||||
// a collide-and-slide algorithm.
|
||||
|
||||
// Don't apply an impulse if the character is moving away from the surface.
|
||||
if linear_velocity.dot(normal) > 0.0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Slide along the surface, rejecting the velocity along the contact normal.
|
||||
let impulse = linear_velocity.reject_from_normalized(normal);
|
||||
linear_velocity.0 = impulse;
|
||||
}
|
||||
} else {
|
||||
// The character is not yet intersecting the other object,
|
||||
// but the narrow phase detected a speculative collision.
|
||||
//
|
||||
// We need to push back the part of the velocity
|
||||
// that would cause penetration within the next frame.
|
||||
|
||||
let normal_speed = linear_velocity.dot(normal);
|
||||
|
||||
// Don't apply an impulse if the character is moving away from the surface.
|
||||
if normal_speed > 0.0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Compute the impulse to apply.
|
||||
let impulse_magnitude =
|
||||
normal_speed - (deepest_penetration / time.delta_secs_f64().adjust_precision());
|
||||
let mut impulse = impulse_magnitude * normal;
|
||||
|
||||
// Apply the impulse differently depending on the slope angle.
|
||||
if climbable {
|
||||
// Avoid sliding down slopes.
|
||||
linear_velocity.y -= impulse.y.min(0.0);
|
||||
} else {
|
||||
// Avoid climbing up walls.
|
||||
impulse.y = impulse.y.max(0.0);
|
||||
linear_velocity.0 -= impulse;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
80
src/main.rs
80
src/main.rs
@ -1,21 +1,35 @@
|
||||
use avian2d::{
|
||||
PhysicsPlugins,
|
||||
math::{Scalar, Vector},
|
||||
prelude::{Collider, Gravity, RigidBody},
|
||||
};
|
||||
use bevy::{camera::ScalingMode, color::palettes::css::GREEN, prelude::*};
|
||||
|
||||
use crate::avian::{CharacterControllerBundle, CharacterControllerPlugin};
|
||||
|
||||
pub mod avian;
|
||||
|
||||
fn main() {
|
||||
App::new()
|
||||
.add_plugins(DefaultPlugins)
|
||||
.add_plugins((
|
||||
DefaultPlugins,
|
||||
// Add physics plugins and specify a units-per-meter scaling factor, 1 meter = 20 pixels.
|
||||
// The unit allows the engine to tune its parameters for the scale of the world, improving stability.
|
||||
PhysicsPlugins::default().with_length_unit(20.0),
|
||||
CharacterControllerPlugin,
|
||||
))
|
||||
.add_systems(Startup, setup)
|
||||
.add_systems(Update, sprite_movement)
|
||||
.add_systems(Update, draw_gizmo)
|
||||
.add_systems(Update, debug_border)
|
||||
.insert_resource(Gravity(Vector::ZERO))
|
||||
.run();
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
enum Direction {
|
||||
Left,
|
||||
Right,
|
||||
}
|
||||
|
||||
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||
fn setup(
|
||||
mut commands: Commands,
|
||||
mut materials: ResMut<Assets<ColorMaterial>>,
|
||||
mut meshes: ResMut<Assets<Mesh>>,
|
||||
asset_server: Res<AssetServer>,
|
||||
) {
|
||||
let mut projection = OrthographicProjection::default_2d();
|
||||
projection.scaling_mode = ScalingMode::AutoMin {
|
||||
min_width: 1920.,
|
||||
@ -23,30 +37,36 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||
};
|
||||
commands.spawn((Camera2d, Projection::Orthographic(projection)));
|
||||
|
||||
// player
|
||||
commands.spawn((
|
||||
Sprite::from_image(asset_server.load("icon.png")),
|
||||
Mesh2d(meshes.add(Capsule2d::new(12.5, 20.0))),
|
||||
MeshMaterial2d(materials.add(Color::srgb(0.2, 0.7, 0.9))),
|
||||
Transform::from_xyz(0.0, -100.0, 0.0),
|
||||
CharacterControllerBundle::new(Collider::capsule(12.5, 20.0)).with_movement(
|
||||
1250.0,
|
||||
10.0,
|
||||
(30.0 as Scalar).to_radians(),
|
||||
),
|
||||
));
|
||||
|
||||
// A cube to move around
|
||||
commands.spawn((
|
||||
Sprite {
|
||||
color: Color::srgb(0.0, 0.4, 0.7),
|
||||
custom_size: Some(Vec2::new(30.0, 30.0)),
|
||||
..default()
|
||||
},
|
||||
Transform::from_xyz(50.0, -100.0, 0.0),
|
||||
RigidBody::Dynamic,
|
||||
Collider::rectangle(30.0, 30.0),
|
||||
));
|
||||
|
||||
commands.spawn((
|
||||
Sprite::from_image(asset_server.load("player.png")),
|
||||
Transform::from_xyz(0., 0., 0.),
|
||||
Direction::Right,
|
||||
));
|
||||
}
|
||||
|
||||
/// The sprite is animated by changing its translation depending on the time that has passed since
|
||||
/// the last frame.
|
||||
fn sprite_movement(time: Res<Time>, mut sprite_position: Query<(&mut Direction, &mut Transform)>) {
|
||||
for (mut logo, mut transform) in &mut sprite_position {
|
||||
match *logo {
|
||||
Direction::Right => transform.translation.x += 150. * time.delta_secs(),
|
||||
Direction::Left => transform.translation.x -= 150. * time.delta_secs(),
|
||||
}
|
||||
|
||||
if transform.translation.x > 200. {
|
||||
*logo = Direction::Left;
|
||||
} else if transform.translation.x < -200. {
|
||||
*logo = Direction::Right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn draw_gizmo(mut gizmos: Gizmos) {
|
||||
fn debug_border(mut gizmos: Gizmos) {
|
||||
gizmos.rect_2d(Isometry2d::IDENTITY, Vec2::new(1920., 1080.), GREEN);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user