Compare commits

...

2 commits

Author SHA1 Message Date
f6022d84b2 feat: BpmTimer and AttackArea 2026-04-13 14:24:58 +03:00
e4b1475c48 feat: Basic player implementation 2026-04-10 13:35:44 +03:00
14 changed files with 1026 additions and 54 deletions

611
Cargo.lock generated
View file

@ -23,6 +23,10 @@ name = "accesskit"
version = "0.21.1" version = "0.21.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf203f9d3bd8f29f98833d1fbef628df18f759248a547e7e01cfbf63cda36a99" checksum = "cf203f9d3bd8f29f98833d1fbef628df18f759248a547e7e01cfbf63cda36a99"
dependencies = [
"enumn",
"serde",
]
[[package]] [[package]]
name = "accesskit_consumer" name = "accesskit_consumer"
@ -103,6 +107,12 @@ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "allocator-api2"
version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
[[package]] [[package]]
name = "alsa" name = "alsa"
version = "0.9.1" version = "0.9.1"
@ -357,6 +367,7 @@ dependencies = [
"bevy_derive", "bevy_derive",
"bevy_ecs", "bevy_ecs",
"bevy_reflect", "bevy_reflect",
"serde",
] ]
[[package]] [[package]]
@ -577,6 +588,8 @@ name = "bevy_combat_proto"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"bevy", "bevy",
"bevy_rapier2d",
"leafwing-input-manager",
"petgraph", "petgraph",
] ]
@ -898,6 +911,7 @@ dependencies = [
"bevy_reflect", "bevy_reflect",
"derive_more", "derive_more",
"log", "log",
"serde",
"smol_str", "smol_str",
"thiserror 2.0.18", "thiserror 2.0.18",
] ]
@ -957,6 +971,7 @@ dependencies = [
"bevy_post_process", "bevy_post_process",
"bevy_ptr", "bevy_ptr",
"bevy_reflect", "bevy_reflect",
"bevy_remote",
"bevy_render", "bevy_render",
"bevy_scene", "bevy_scene",
"bevy_shader", "bevy_shader",
@ -1035,7 +1050,7 @@ dependencies = [
"arrayvec", "arrayvec",
"bevy_reflect", "bevy_reflect",
"derive_more", "derive_more",
"glam", "glam 0.30.10",
"itertools 0.14.0", "itertools 0.14.0",
"libm", "libm",
"rand", "rand",
@ -1065,6 +1080,7 @@ dependencies = [
"bytemuck", "bytemuck",
"derive_more", "derive_more",
"hexasphere", "hexasphere",
"serde",
"thiserror 2.0.18", "thiserror 2.0.18",
"tracing", "tracing",
"wgpu-types", "wgpu-types",
@ -1193,6 +1209,19 @@ version = "0.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7a9329e8dc4e01ced480eeec4902e6d7cb56e56ec37f6fbc4323e5c937290a7" checksum = "c7a9329e8dc4e01ced480eeec4902e6d7cb56e56ec37f6fbc4323e5c937290a7"
[[package]]
name = "bevy_rapier2d"
version = "0.33.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0b8ac06b0333af78e706982e13a33cfbacb9225d735a33ae8130a4d735bdfc5"
dependencies = [
"bevy",
"bitflags 2.11.0",
"log",
"nalgebra",
"rapier2d",
]
[[package]] [[package]]
name = "bevy_reflect" name = "bevy_reflect"
version = "0.18.1" version = "0.18.1"
@ -1209,7 +1238,7 @@ dependencies = [
"downcast-rs 2.0.2", "downcast-rs 2.0.2",
"erased-serde", "erased-serde",
"foldhash 0.2.0", "foldhash 0.2.0",
"glam", "glam 0.30.10",
"indexmap", "indexmap",
"inventory", "inventory",
"petgraph", "petgraph",
@ -1236,6 +1265,31 @@ dependencies = [
"uuid", "uuid",
] ]
[[package]]
name = "bevy_remote"
version = "0.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0129e24bf3e281dd52996a9290c35f8c4821ca09e1ce8b8b222671e1ad9da0c"
dependencies = [
"anyhow",
"async-channel",
"async-io",
"bevy_app",
"bevy_asset",
"bevy_derive",
"bevy_ecs",
"bevy_log",
"bevy_platform",
"bevy_reflect",
"bevy_tasks",
"bevy_utils",
"http-body-util",
"hyper",
"serde",
"serde_json",
"smol-hyper",
]
[[package]] [[package]]
name = "bevy_render" name = "bevy_render"
version = "0.18.1" version = "0.18.1"
@ -1269,7 +1323,7 @@ dependencies = [
"downcast-rs 2.0.2", "downcast-rs 2.0.2",
"encase", "encase",
"fixedbitset", "fixedbitset",
"glam", "glam 0.30.10",
"image", "image",
"indexmap", "indexmap",
"js-sys", "js-sys",
@ -1429,6 +1483,7 @@ checksum = "384eb04d80aa38664d69988fd30cbbe03e937ecb65c66aa6abe60ce0bca826aa"
dependencies = [ dependencies = [
"async-channel", "async-channel",
"async-executor", "async-executor",
"async-io",
"async-task", "async-task",
"atomic-waker", "atomic-waker",
"bevy_platform", "bevy_platform",
@ -1526,6 +1581,7 @@ dependencies = [
"bevy_utils", "bevy_utils",
"bevy_window", "bevy_window",
"derive_more", "derive_more",
"serde",
"smallvec", "smallvec",
"taffy", "taffy",
"thiserror 2.0.18", "thiserror 2.0.18",
@ -2257,12 +2313,39 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76" checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76"
[[package]]
name = "dyn-clone"
version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555"
[[package]]
name = "dyn-eq"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c2d035d21af5cde1a6f5c7b444a5bf963520a9f142e5d06931178433d7d5388"
[[package]]
name = "dyn-hash"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fdab65db9274e0168143841eb8f864a0a21f8b1b8d2ba6812bbe6024346e99e"
[[package]] [[package]]
name = "either" name = "either"
version = "1.15.0" version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
[[package]]
name = "ena"
version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eabffdaee24bd1bf95c5ef7cec31260444317e72ea56c4c91750e8b7ee58d5f1"
dependencies = [
"log",
]
[[package]] [[package]]
name = "encase" name = "encase"
version = "0.12.0" version = "0.12.0"
@ -2294,6 +2377,17 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "enumn"
version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f9ed6b3789237c8a0c1c505af1c7eb2c560df6186f01b098c3a1064ea532f38"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "equivalent" name = "equivalent"
version = "1.0.2" version = "1.0.2"
@ -2618,6 +2712,141 @@ dependencies = [
"xml-rs", "xml-rs",
] ]
[[package]]
name = "glam"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "333928d5eb103c5d4050533cec0384302db6be8ef7d3cebd30ec6a35350353da"
dependencies = [
"num-traits",
]
[[package]]
name = "glam"
version = "0.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3abb554f8ee44336b72d522e0a7fe86a29e09f839a36022fa869a7dfe941a54b"
dependencies = [
"num-traits",
]
[[package]]
name = "glam"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4126c0479ccf7e8664c36a2d719f5f2c140fbb4f9090008098d2c291fa5b3f16"
dependencies = [
"num-traits",
]
[[package]]
name = "glam"
version = "0.17.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e01732b97afd8508eee3333a541b9f7610f454bb818669e66e90f5f57c93a776"
dependencies = [
"num-traits",
]
[[package]]
name = "glam"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "525a3e490ba77b8e326fb67d4b44b4bd2f920f44d4cc73ccec50adc68e3bee34"
dependencies = [
"num-traits",
]
[[package]]
name = "glam"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b8509e6791516e81c1a630d0bd7fbac36d2fa8712a9da8662e716b52d5051ca"
dependencies = [
"num-traits",
]
[[package]]
name = "glam"
version = "0.20.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f43e957e744be03f5801a55472f593d43fabdebf25a4585db250f04d86b1675f"
dependencies = [
"num-traits",
]
[[package]]
name = "glam"
version = "0.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "518faa5064866338b013ff9b2350dc318e14cc4fcd6cb8206d7e7c9886c98815"
dependencies = [
"num-traits",
]
[[package]]
name = "glam"
version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12f597d56c1bd55a811a1be189459e8fad2bbc272616375602443bdfb37fa774"
dependencies = [
"num-traits",
]
[[package]]
name = "glam"
version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e4afd9ad95555081e109fe1d21f2a30c691b5f0919c67dfa690a2e1eb6bd51c"
dependencies = [
"num-traits",
]
[[package]]
name = "glam"
version = "0.24.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5418c17512bdf42730f9032c74e1ae39afc408745ebb2acf72fbc4691c17945"
dependencies = [
"libm",
]
[[package]]
name = "glam"
version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "151665d9be52f9bb40fc7966565d39666f2d1e69233571b71b87791c7e0528b3"
dependencies = [
"libm",
]
[[package]]
name = "glam"
version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e05e7e6723e3455f4818c7b26e855439f7546cf617ef669d1adedb8669e5cb9"
dependencies = [
"libm",
]
[[package]]
name = "glam"
version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "779ae4bf7e8421cf91c0b3b64e7e8b40b862fba4d393f59150042de7c4965a94"
dependencies = [
"libm",
]
[[package]]
name = "glam"
version = "0.29.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8babf46d4c1c9d92deac9f7be466f76dfc4482b6452fc5024b5e8daf6ffeb3ee"
dependencies = [
"libm",
]
[[package]] [[package]]
name = "glam" name = "glam"
version = "0.30.10" version = "0.30.10"
@ -2631,6 +2860,24 @@ dependencies = [
"serde_core", "serde_core",
] ]
[[package]]
name = "glam"
version = "0.31.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "556f6b2ea90b8d15a74e0e7bb41671c9bdf38cd9f78c284d750b9ce58a2b5be7"
dependencies = [
"libm",
]
[[package]]
name = "glam"
version = "0.32.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f70749695b063ecbf6b62949ccccde2e733ec3ecbbd71d467dca4e5c6c97cca0"
dependencies = [
"libm",
]
[[package]] [[package]]
name = "glob" name = "glob"
version = "0.3.3" version = "0.3.3"
@ -2810,6 +3057,7 @@ version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
dependencies = [ dependencies = [
"allocator-api2",
"equivalent", "equivalent",
"foldhash 0.2.0", "foldhash 0.2.0",
"serde", "serde",
@ -2846,7 +3094,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29a164ceff4500f2a72b1d21beaa8aa8ad83aec2b641844c659b190cb3ea2e0b" checksum = "29a164ceff4500f2a72b1d21beaa8aa8ad83aec2b641844c659b190cb3ea2e0b"
dependencies = [ dependencies = [
"constgebra", "constgebra",
"glam", "glam 0.30.10",
"tinyvec", "tinyvec",
] ]
@ -2856,6 +3104,72 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df"
[[package]]
name = "http"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a"
dependencies = [
"bytes",
"itoa",
]
[[package]]
name = "http-body"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184"
dependencies = [
"bytes",
"http",
]
[[package]]
name = "http-body-util"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a"
dependencies = [
"bytes",
"futures-core",
"http",
"http-body",
"pin-project-lite",
]
[[package]]
name = "httparse"
version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
[[package]]
name = "httpdate"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
[[package]]
name = "hyper"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11"
dependencies = [
"atomic-waker",
"bytes",
"futures-channel",
"futures-core",
"http",
"http-body",
"httparse",
"httpdate",
"itoa",
"pin-project-lite",
"pin-utils",
"smallvec",
"tokio",
]
[[package]] [[package]]
name = "id-arena" name = "id-arena"
version = "2.3.0" version = "2.3.0"
@ -3074,6 +3388,34 @@ version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
name = "leafwing-input-manager"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fed83d1d7334e742aab3409782cdbb2bc96cc017df9ff342dd5aeb80eed1b784"
dependencies = [
"bevy",
"dyn-clone",
"dyn-eq",
"dyn-hash",
"itertools 0.14.0",
"leafwing_input_manager_macros",
"serde",
"serde_flexitos",
]
[[package]]
name = "leafwing_input_manager_macros"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2226cb83129176a6c634f2ce0828c2c29896ea0898fc198636f98696b8056890"
dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "leb128fmt" name = "leb128fmt"
version = "0.1.0" version = "0.1.0"
@ -3201,6 +3543,16 @@ dependencies = [
"regex-automata", "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]] [[package]]
name = "memchr" name = "memchr"
version = "2.8.0" version = "2.8.0"
@ -3301,6 +3653,51 @@ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]]
name = "nalgebra"
version = "0.34.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df76ea0ff5c7e6b88689085804d6132ded0ddb9de5ca5b8aeb9eeadc0508a70a"
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",
"glam 0.31.1",
"glam 0.32.1",
"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]] [[package]]
name = "ndk" name = "ndk"
version = "0.8.0" version = "0.8.0"
@ -3412,6 +3809,25 @@ dependencies = [
"windows-sys 0.61.2", "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]] [[package]]
name = "num-derive" name = "num-derive"
version = "0.4.2" version = "0.4.2"
@ -3423,6 +3839,26 @@ dependencies = [
"syn", "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]] [[package]]
name = "num-traits" name = "num-traits"
version = "0.2.19" version = "0.2.19"
@ -3801,6 +4237,32 @@ dependencies = [
"windows-link 0.2.1", "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.11.0",
"downcast-rs 2.0.2",
"either",
"ena",
"foldhash 0.2.0",
"hashbrown 0.16.1",
"log",
"nalgebra",
"num-derive",
"num-traits",
"ordered-float",
"simba",
"slab",
"smallvec",
"spade",
"thiserror 2.0.18",
]
[[package]] [[package]]
name = "paste" name = "paste"
version = "1.0.15" version = "1.0.15"
@ -3852,6 +4314,12 @@ version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
[[package]]
name = "pin-utils"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]] [[package]]
name = "piper" name = "piper"
version = "0.2.5" version = "0.2.5"
@ -3974,6 +4442,19 @@ name = "profiling"
version = "1.0.17" version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3eb8486b569e12e2c32ad3e204dbaba5e4b5b216e9367044f25f1dba42341773" checksum = "3eb8486b569e12e2c32ad3e204dbaba5e4b5b216e9367044f25f1dba42341773"
dependencies = [
"profiling-procmacros",
]
[[package]]
name = "profiling-procmacros"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52717f9a02b6965224f95ca2a81e2e0c5c43baacd28ca057577988930b6c3d5b"
dependencies = [
"quote",
"syn",
]
[[package]] [[package]]
name = "pxfm" name = "pxfm"
@ -4068,12 +4549,43 @@ version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "973443cf09a9c8656b574a866ab68dfa19f0867d0340648c7d2f6a71b8a8ea68" checksum = "973443cf09a9c8656b574a866ab68dfa19f0867d0340648c7d2f6a71b8a8ea68"
[[package]]
name = "rapier2d"
version = "0.31.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dbf9046b02ffdaff5a8b65405e5e557d71dfb13e74d335fcf9fd12ad6c503a7"
dependencies = [
"approx",
"arrayvec",
"bit-vec",
"bitflags 2.11.0",
"downcast-rs 2.0.2",
"log",
"nalgebra",
"num-derive",
"num-traits",
"ordered-float",
"parry2d",
"profiling",
"rustc-hash 2.1.2",
"simba",
"static_assertions",
"thiserror 2.0.18",
"wide",
]
[[package]] [[package]]
name = "raw-window-handle" name = "raw-window-handle"
version = "0.6.2" version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539"
[[package]]
name = "rawpointer"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
[[package]] [[package]]
name = "read-fonts" name = "read-fonts"
version = "0.36.0" version = "0.36.0"
@ -4163,6 +4675,12 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832"
[[package]]
name = "robust"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e27ee8bb91ca0adcf0ecb116293afa12d393f9c2b9b9cd54d33e8078fe19839"
[[package]] [[package]]
name = "rodio" name = "rodio"
version = "0.20.1" version = "0.20.1"
@ -4255,6 +4773,15 @@ dependencies = [
"twox-hash", "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]] [[package]]
name = "same-file" name = "same-file"
version = "1.0.6" version = "1.0.6"
@ -4337,6 +4864,16 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "serde_flexitos"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3323d093d7597660758b742dd7a1525539613f6182b306a4e1dd6e01a89bada9"
dependencies = [
"erased-serde",
"serde",
]
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.149" version = "1.0.149"
@ -4365,6 +4902,19 @@ version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 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]] [[package]]
name = "simd-adler32" name = "simd-adler32"
version = "0.3.9" version = "0.3.9"
@ -4427,6 +4977,9 @@ name = "smallvec"
version = "1.15.1" version = "1.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
dependencies = [
"serde",
]
[[package]] [[package]]
name = "smithay-client-toolkit" name = "smithay-client-toolkit"
@ -4453,6 +5006,19 @@ dependencies = [
"xkeysym", "xkeysym",
] ]
[[package]]
name = "smol-hyper"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7428a49d323867702cd12b97b08a6b0104f39ec13b49117911f101271321bc1a"
dependencies = [
"async-executor",
"async-io",
"futures-io",
"hyper",
"pin-project-lite",
]
[[package]] [[package]]
name = "smol_str" name = "smol_str"
version = "0.2.2" version = "0.2.2"
@ -4462,6 +5028,18 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "spade"
version = "2.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9699399fd9349b00b184f5635b074f9ec93afffef30c853f8c875b32c0f8c7fa"
dependencies = [
"hashbrown 0.16.1",
"num-traits",
"robust",
"smallvec",
]
[[package]] [[package]]
name = "spin" name = "spin"
version = "0.10.0" version = "0.10.0"
@ -4668,6 +5246,15 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "tokio"
version = "1.51.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bd1c4c0fc4a7ab90fc15ef6daaa3ec3b893f004f915f2392557ed23237820cd"
dependencies = [
"pin-project-lite",
]
[[package]] [[package]]
name = "toml_datetime" name = "toml_datetime"
version = "0.7.5+spec-1.1.0" version = "0.7.5+spec-1.1.0"
@ -4824,6 +5411,12 @@ version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c"
[[package]]
name = "typenum"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
[[package]] [[package]]
name = "typewit" name = "typewit"
version = "1.15.1" version = "1.15.1"
@ -5308,6 +5901,16 @@ dependencies = [
"web-sys", "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]] [[package]]
name = "winapi" name = "winapi"
version = "0.3.9" version = "0.3.9"

View file

@ -6,7 +6,9 @@ version = "0.1.0"
edition = "2024" edition = "2024"
[dependencies] [dependencies]
bevy = { version = "0.18.0" } bevy = { version = "0.18.0", features = ["bevy_remote"] }
bevy_rapier2d = "0.33.0"
leafwing-input-manager = "0.20.0"
petgraph = { version = "0.8.3" } petgraph = { version = "0.8.3" }
[profile.dev] [profile.dev]

Binary file not shown.

After

Width:  |  Height:  |  Size: 199 B

75
src/combat/attack.rs Normal file
View file

@ -0,0 +1,75 @@
//! Attack module
use std::time::Duration;
use bevy::prelude::*;
use bevy_rapier2d::prelude::*;
/// Contains logic for attack-related calculations
#[derive(Component, Clone, Debug, Reflect)]
#[reflect(Component, Clone, Debug)]
#[require(Transform, Collider, Sensor)]
pub struct AttackArea {
accuracy: f32,
damage: f32,
timer: Timer,
max_distance: f32,
}
/// Determines [AttackArea] damage based on distance of target from itself
#[derive(Component, Clone, Copy, PartialEq, Eq, Debug, Reflect, Default)]
#[reflect(Component, Clone, PartialEq, Debug, Default)]
#[require(Transform)]
pub struct AttackAreaOrigin;
impl AttackArea {
/// Constructs new attack area
pub fn new(accuracy: f32, damage: f32, duration: Duration, half_area: Vec2) -> Self {
let max_distance = ((half_area.x * 2.).powi(2) + half_area.y.powi(2)).sqrt();
Self {
accuracy,
damage,
timer: Timer::new(duration, TimerMode::Once),
max_distance,
}
}
/// Returns attack area bundle with everything needed
pub fn bundle(
damage: f32,
accuracy: f32,
duration: Duration,
position: Vec2,
half_area: Vec2,
facing_left: bool,
) -> impl Bundle {
let origin_x = if facing_left { position.x - half_area.x } else { position.x + half_area.x };
(
// Basic
AttackArea::new(accuracy, damage, duration, half_area),
// Collision
Transform::from_xyz(position.x, position.y, 0.),
Collider::cuboid(half_area.x, half_area.y),
// AttackAreaOrigin
Children::spawn((
Spawn((
AttackAreaOrigin,
Transform::from_xyz(origin_x, 0., 0.),
)),
)),
)
}
/// Updates timer and returns true if attack has ended
pub fn tick(&mut self, dt: Duration) -> bool {
self.timer.tick(dt).is_finished()
}
/// Returns damage for given distance to origin
pub fn damage(&self, distance_to_origin: f32) -> f32 {
let distance_ratio = 1. - distance_to_origin.min(self.max_distance) / self.max_distance;
let total_multiplier = self.accuracy * distance_ratio;
self.damage * EaseFunction::QuinticOut.sample_unchecked(total_multiplier)
}
}

3
src/combat/mod.rs Normal file
View file

@ -0,0 +1,3 @@
//! This module contains core concepts of the combat system
pub mod attack;

62
src/input.rs Normal file
View file

@ -0,0 +1,62 @@
//! Input module
use bevy::prelude::*;
use leafwing_input_manager::prelude::*;
/// This trait is used to provide uniform way of getting predefined [InputMap]
pub trait DefaultInputMap: Actionlike {
/// Get default input map for the Actionlike
fn input_map() -> InputMap<Self>;
}
/// Input used to control player character
#[derive(Actionlike, Debug, PartialEq, Eq, Hash, Clone, Copy, Reflect)]
#[reflect(Debug, PartialEq, Hash, Clone)]
pub enum PlayerInput {
/// Move character
#[actionlike(Axis)] Move,
/// Dodge with light weapon or block with heavy weapon
DodgeBlock,
/// Perform light attack
LightAttack,
/// Perform heavy attack
HeavyAttack,
}
impl DefaultInputMap for PlayerInput {
fn input_map() -> InputMap<Self> {
InputMap::default()
.with_axis(Self::Move, VirtualAxis::ad())
.with_axis(Self::Move, GamepadAxis::LeftStickX)
.with(Self::DodgeBlock, KeyCode::ShiftLeft)
.with(Self::DodgeBlock, GamepadButton::South)
.with(Self::LightAttack, MouseButton::Left)
.with(Self::HeavyAttack, GamepadButton::North)
.with(Self::LightAttack, MouseButton::Right)
.with(Self::HeavyAttack, GamepadButton::East)
}
}
/// Input used to debug this prototype
#[derive(Actionlike, Debug, PartialEq, Eq, Hash, Clone, Copy, Reflect)]
#[reflect(Debug, PartialEq, Hash, Clone)]
pub enum DebugInput {
/// Reset game state
Reset,
/// Spawn enemy in predefined position
SpawnEnemy,
}
impl DefaultInputMap for DebugInput {
fn input_map() -> InputMap<Self> {
InputMap::default()
.with(Self::Reset, KeyCode::KeyR)
.with(Self::Reset, GamepadButton::Select)
.with(Self::SpawnEnemy, KeyCode::KeyT)
.with(Self::SpawnEnemy, GamepadButton::LeftTrigger)
}
}

View file

@ -5,4 +5,25 @@
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
pub mod combat;
pub mod graph; pub mod graph;
pub mod input;
pub mod player;
pub mod plugin;
pub mod timer;
use bevy::prelude::*;
use crate::{player::Player, timer::BpmTimer};
const PIXELS_PER_METER: f32 = 16.;
/// Returns pixel measurement for given length in meters
#[inline(always)] pub const fn meters(length: f32) -> f32 { PIXELS_PER_METER * length }
// TODO: Replace with proper setting up
/// Temporary function to setup world
pub fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
commands.spawn(Player::bundle(&asset_server, Vec2::ZERO));
commands.spawn(BpmTimer::new(120.));
}

View file

@ -1,54 +1,19 @@
use bevy::prelude::*; use bevy::{
prelude::*,
#[derive(Component)] remote::{
struct Person; RemotePlugin,
http::RemoteHttpPlugin,
#[derive(Component)] },
struct Name(String); };
use bevy_combat_proto::plugin::GamePlugin;
#[derive(Resource)]
struct GreetTimer(Timer);
#[derive(Resource)]
struct UpdateTimer(Timer);
pub struct HelloPlugin;
impl Plugin for HelloPlugin {
fn build(&self, app: &mut App) {
app.insert_resource(GreetTimer(Timer::from_seconds(2.0, TimerMode::Repeating)));
app.insert_resource(UpdateTimer(Timer::from_seconds(10.0, TimerMode::Once)));
app.add_systems(Startup, add_people);
app.add_systems(Update, (update_people, greet_people).chain());
}
}
fn add_people(mut commands: Commands) {
commands.spawn((Person, Name("Alkesey Mirnekov".to_string())));
commands.spawn((Person, Name("Alkesey Mirnekov 2".to_string())));
commands.spawn((Person, Name("Alkesey Mirnekov 3".to_string())));
}
fn greet_people(time: Res<Time>, mut timer: ResMut<GreetTimer>, query: Query<&Name, With<Person>>) {
if timer.0.tick(time.delta()).just_finished() {
for name in &query {
println!("hello {}!", name.0);
}
}
}
fn update_people(time: Res<Time>, mut timer: ResMut<UpdateTimer>, mut query: Query<&mut Name, With<Person>>) {
if timer.0.tick(time.delta()).just_finished() {
for mut name in &mut query {
name.0 = format!("{} II", name.0);
}
}
}
fn main() { fn main() {
App::new() App::new()
.add_plugins(DefaultPlugins) .add_plugins((
.add_plugins(HelloPlugin) DefaultPlugins.set(ImagePlugin::default_nearest()),
GamePlugin,
RemotePlugin::default(),
RemoteHttpPlugin::default(),
))
.run(); .run();
} }

76
src/player/mod.rs Normal file
View file

@ -0,0 +1,76 @@
//! Player module
use bevy::{camera::ScalingMode, prelude::*};
use bevy_rapier2d::prelude::*;
use leafwing_input_manager::prelude::*;
use crate::{
meters,
input::{
DefaultInputMap,
PlayerInput,
}
};
pub mod systems;
/// Player component
#[derive(Component, Clone, Copy, PartialEq, Debug, Reflect)]
#[reflect(Component, Clone, PartialEq, Debug, Default)]
#[require(Transform, InputMap<PlayerInput>)]
pub struct Player {
/// Movement speed in pixels/s
pub speed: f32,
}
impl Default for Player {
fn default() -> Self {
Self {
speed: meters(1.),
}
}
}
impl Player {
/// Returns player bundle with everything needed
pub fn bundle(asset_server: &Res<AssetServer>, position: Vec2) -> impl Bundle {
let image = asset_server.load("sprites/player/placeholder.png");
(
// Basic
Name::new("Player"),
Player::default(),
// Visible
Sprite::from_image(image),
Transform::from_xyz(position.x, position.y, 1.),
// Input
PlayerInput::input_map(),
// Collision
RigidBody::KinematicPositionBased,
KinematicCharacterController::default(),
ActiveCollisionTypes::default() | ActiveCollisionTypes::KINEMATIC_STATIC,
Collider::cuboid(meters(0.3), meters(0.9)),
ActiveEvents::COLLISION_EVENTS,
Sleeping::disabled(),
Children::spawn((
Spawn((
Name::new("Player camera"),
Camera2d,
Camera {
clear_color: ClearColorConfig::Custom(Color::hsl(0.02, 0.67, 0.65)),
..default()
},
Projection::Orthographic(OrthographicProjection {
scaling_mode: ScalingMode::FixedVertical {
viewport_height: meters(24.),
},
..OrthographicProjection::default_2d()
}),
)),
)),
)
}
}

25
src/player/systems.rs Normal file
View file

@ -0,0 +1,25 @@
//! Player systems
use super::*;
/// Do something based on [PlayerInput]
pub fn handle_input(
time: Res<Time>,
player_query: Query<(
&Player,
&ActionState<PlayerInput>,
&mut KinematicCharacterController,
&mut Sprite,
)>,
) {
for (player, action_state, mut controller, mut sprite) in player_query {
let direction = action_state.clamped_value(&PlayerInput::Move);
controller.translation = Some(vec2(direction * player.speed * time.delta_secs(), 0.));
if direction != 0. {
sprite.flip_x = direction < 0.;
}
}
}

28
src/plugin.rs Normal file
View file

@ -0,0 +1,28 @@
//! Plugin module where everything is connected
use bevy::prelude::*;
use bevy_rapier2d::prelude::*;
use leafwing_input_manager::prelude::*;
use crate::*;
/// Plugin that connects everything needed for this prototype
pub struct GamePlugin;
impl Plugin for GamePlugin {
fn build(&self, app: &mut App) {
app.add_plugins((
RapierDebugRenderPlugin::default(),
RapierPhysicsPlugin::<()>::default()
.with_length_unit(meters(1.)),
InputManagerPlugin::<input::PlayerInput>::default(),
InputManagerPlugin::<input::DebugInput>::default(),
))
.add_systems(Startup, setup)
.add_systems(Update, (
player::systems::handle_input,
timer::update_bpm_timers,
));
}
}

26
src/tests/attack.rs Normal file
View file

@ -0,0 +1,26 @@
use std::time::Duration;
use bevy::prelude::*;
use crate::combat::attack::AttackArea;
#[test]
fn attack_deals_max_damage() {
let a = AttackArea::new(1., 1., Duration::from_secs(1), vec2(1., 1.));
assert_eq!(a.damage(0.), 1.);
}
#[test]
fn attack_too_far() {
let a = AttackArea::new(1., 1., Duration::from_secs(1), vec2(1., 1.));
assert_eq!(a.damage(5f32.sqrt()), 0.);
}
#[test]
fn attack_too_inaccurate() {
let a = AttackArea::new(0., 1., Duration::from_secs(1), vec2(1., 1.));
assert_eq!(a.damage(0.), 0.);
}

View file

@ -1 +1,2 @@
mod attack;
mod graph; mod graph;

85
src/timer.rs Normal file
View file

@ -0,0 +1,85 @@
//! Beats per minute based timer module
use std::time::Duration;
use bevy::prelude::*;
/// Calculates [Duration] from BPM
#[inline(always)]
pub fn duration_from_bpm(bpm: f32) -> Duration {
Duration::from_millis((60_000. / bpm) as u64)
}
/// Calculates BPM from [Duration]
#[inline(always)]
pub fn bpm_from_duration(dur: Duration) -> f32 {
60_000. / (dur.as_millis() as f32)
}
/// Event that is triggered when [BpmTimer] just ticked
#[derive(EntityEvent, Clone, Copy, PartialEq, Debug, Reflect)]
#[reflect(Event, Clone, PartialEq, Debug)]
pub struct TickEvent {
/// [BpmTimer] that triggered event
#[event_target] pub timer: Entity,
/// Total elapsed time of that timer in beats
pub elapsed: f32,
}
/// Timer that is based on beats per minute (BPM) value
/// Ticks every beat, counts total ticks and triggers [TickEvent]
#[derive(Component, Clone, PartialEq, Debug, Reflect)]
#[reflect(Component, Clone, PartialEq, Debug)]
pub struct BpmTimer {
timer: Timer,
elapsed: f32,
}
impl BpmTimer {
/// Constructs new BpmTimer from given BPM
pub fn new(bpm: f32) -> Self {
Self {
timer: Timer::new(duration_from_bpm(bpm), TimerMode::Repeating),
elapsed: 0.,
}
}
/// Updates internal timer and returns true if it just ticked
pub fn tick(&mut self, dt: Duration) -> bool {
let ticked = self.timer.tick(dt).just_finished();
if ticked { self.elapsed += 1.; }
ticked
}
/// Returns total elapsed time in beats
#[inline(always)]
pub fn beats_elapsed(&self) -> f32 {
self.elapsed + self.timer.fraction()
}
/// Get beats per minute value of timer
#[inline(always)]
pub fn get_bpm(&self) -> f32 {
bpm_from_duration(self.timer.duration())
}
/// Set new BPM value
pub fn set_bpm(&mut self, new_bpm: f32) {
self.timer.set_duration(duration_from_bpm(new_bpm));
}
/// Resets elapsed beats
pub fn reset(&mut self) {
self.timer.reset();
self.elapsed = 0.;
}
}
/// System that ticks each [BpmTimer] and triggers [TickEvent]s
pub fn update_bpm_timers(mut commands: Commands, time: Res<Time>, timers: Query<(Entity, &mut BpmTimer)>) {
for (timer_id, mut timer) in timers {
if timer.tick(time.delta()) {
commands.trigger(TickEvent { timer: timer_id, elapsed: timer.beats_elapsed() });
}
}
}