From 4c23a38b92a469e6bd65d7a0b107d78f49c9bb19 Mon Sep 17 00:00:00 2001 From: 2ndbeam <2ndbeam@disroot.org> Date: Mon, 16 Mar 2026 17:21:10 +0300 Subject: [PATCH] feat: Collision beginning - Added system for detecting collisions with interactive objects - Added interactive doors --- Cargo.lock | 347 +++++++++++++++++++++++++++++++++++++++++++++++++- Cargo.toml | 1 + src/layout.rs | 142 +++++++++++++++++++++ src/lib.rs | 20 ++- src/player.rs | 24 +++- 5 files changed, 524 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fa5ef63..06b99c8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -107,6 +107,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" @@ -1019,7 +1025,7 @@ dependencies = [ "arrayvec", "bevy_reflect", "derive_more", - "glam", + "glam 0.30.10", "itertools 0.14.0", "libm", "rand", @@ -1178,6 +1184,19 @@ version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4f98cbc6d34bbdb58240b72ed1731931b4991a893b3a3238bb7c42ae054aa676" +[[package]] +name = "bevy_rapier2d" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0b8ac06b0333af78e706982e13a33cfbacb9225d735a33ae8130a4d735bdfc5" +dependencies = [ + "bevy", + "bitflags 2.10.0", + "log", + "nalgebra", + "rapier2d", +] + [[package]] name = "bevy_reflect" version = "0.18.0" @@ -1194,7 +1213,7 @@ dependencies = [ "downcast-rs 2.0.2", "erased-serde", "foldhash 0.2.0", - "glam", + "glam 0.30.10", "indexmap", "inventory", "petgraph", @@ -1279,7 +1298,7 @@ dependencies = [ "downcast-rs 2.0.2", "encase", "fixedbitset", - "glam", + "glam 0.30.10", "image", "indexmap", "js-sys", @@ -2293,6 +2312,15 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +[[package]] +name = "ena" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eabffdaee24bd1bf95c5ef7cec31260444317e72ea56c4c91750e8b7ee58d5f1" +dependencies = [ + "log", +] + [[package]] name = "encase" version = "0.12.0" @@ -2399,6 +2427,7 @@ dependencies = [ "bevy", "bevy_common_assets", "bevy_input", + "bevy_rapier2d", "leafwing-input-manager", "serde", "toml 1.0.3+spec-1.1.0", @@ -2650,6 +2679,96 @@ 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" @@ -2833,6 +2952,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", ] @@ -2872,7 +2993,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29a164ceff4500f2a72b1d21beaa8aa8ad83aec2b641844c659b190cb3ea2e0b" dependencies = [ "constgebra", - "glam", + "glam 0.30.10", "tinyvec", ] @@ -3254,6 +3375,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.8.0" @@ -3354,6 +3485,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" @@ -3465,6 +3639,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" @@ -3476,6 +3669,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" @@ -3854,6 +4067,32 @@ 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", + "simba", + "slab", + "smallvec", + "spade", + "thiserror 2.0.18", +] + [[package]] name = "paste" version = "1.0.15" @@ -4017,6 +4256,19 @@ name = "profiling" version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" 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]] name = "pxfm" @@ -4108,12 +4360,43 @@ version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" 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.10.0", + "downcast-rs 2.0.2", + "log", + "nalgebra", + "num-derive", + "num-traits", + "ordered-float", + "parry2d", + "profiling", + "rustc-hash 2.1.1", + "simba", + "static_assertions", + "thiserror 2.0.18", + "wide", +] + [[package]] name = "raw-window-handle" 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 = "read-fonts" version = "0.35.0" @@ -4203,6 +4486,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" @@ -4295,6 +4584,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" @@ -4424,6 +4722,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" @@ -4521,6 +4832,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" @@ -4916,6 +5239,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" @@ -5361,6 +5690,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" diff --git a/Cargo.toml b/Cargo.toml index baca00b..2253d6f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ edition = "2024" bevy = { version = "0.18.0", features = ["bevy_remote", "debug", "experimental_bevy_ui_widgets"] } bevy_common_assets = { version = "0.15.0", features = ["toml"] } bevy_input = { version = "0.18.0", features = ["serde", "serialize"] } +bevy_rapier2d = { version = "0.33.0", features = ["rapier-debug-render"] } leafwing-input-manager = "0.20.0" serde = { version = "1.0.228", features = ["derive"] } toml = "1.0.3" diff --git a/src/layout.rs b/src/layout.rs index 8b13789..a3ffe61 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -1 +1,143 @@ +use bevy::{ecs::query::QueryFilter, prelude::*}; +use bevy_rapier2d::prelude::*; +use crate::{PIXELS_PER_METER, player::Player}; + +const DOOR_OPENED_ASSET: &'static str = "sprites/interactive/door_opened.png"; +const DOOR_CLOSED_ASSET: &'static str = "sprites/interactive/door_closed.png"; + +#[derive(Component)] +pub struct MayInteract; + +#[derive(Component, Default)] +pub struct InteractiveObject; + +#[derive(Component)] +pub struct Wall; + +#[derive(Component)] +#[require(Sprite, InteractiveObject)] +pub struct Door; + +#[derive(EntityEvent)] +pub struct InteractionEvent { + pub entity: Entity, +} + +fn get_interactive_id( + tested_id: Entity, + interactive_query: Query<(), F>, + parent_query: Query<&ChildOf, With>, +) -> Option { + if interactive_query.get(tested_id).is_ok() { + return Some(tested_id); + } + let Ok(parent_id) = parent_query.get(tested_id) else { + return None; + }; + match interactive_query.get(parent_id.0) { + Ok(_) => Some(parent_id.0), + Err(_) => None, + } +} + +pub fn detect_interact_collisions( + mut commands: Commands, + mut collision_events: MessageReader, + player_query: Query<(), With>, + interactive_query1: Query<(), (With, Without)>, + interactive_query2: Query<(), (With, With)>, + parent_query: Query<&ChildOf, With>, +) { + for collision_event in collision_events.read() { + match collision_event { + CollisionEvent::Started(first, second, _) => { + let Some(interactive_id) = get_interactive_id(*first, interactive_query1, parent_query) else { + continue; + }; + if player_query.get(*second).is_err() { + continue; + } + commands.entity(interactive_id).insert(MayInteract); + }, + CollisionEvent::Stopped(first, second, _) => { + let Some(interactive_id) = get_interactive_id(*first, interactive_query2, parent_query) else { + continue; + }; + if player_query.get(*second).is_err() { + continue; + } + commands.entity(interactive_id).remove::(); + }, + } + } +} + +fn on_door_interact( + event: On, + mut commands: Commands, + collider_query: Query<(), (With, With)>, + no_collider_query: Query<(), (With, Without)>, + mut sprite_query: Query<&mut Sprite, With>, + asset_server: Res, +) { + let was_opened = + if collider_query.get(event.entity).is_ok() { false } + else if no_collider_query.get(event.entity).is_ok() { true } + else { + error!("on_door_interact fired but entity {} isn't door", event.entity); + return; + }; + let Ok(mut sprite) = sprite_query.get_mut(event.entity) else { + error!("on_door_interact fired but entity {} has no sprite", event.entity); + return; + }; + let asset_path = if was_opened { DOOR_CLOSED_ASSET } else { DOOR_OPENED_ASSET }; + sprite.image = asset_server.load(asset_path); + + if was_opened { + commands.entity(event.entity).insert(door_collider()); + } else { + commands.entity(event.entity).remove::(); + } +} + +fn door_collider() -> Collider { + Collider::cuboid(PIXELS_PER_METER * 0.125, PIXELS_PER_METER) +} + +fn door_bundle(image: Handle, position: Vec2) -> impl Bundle { + ( + Door, + Sprite::from_image(image), + Transform::from_xyz(position.x, position.y, 0.), + Name::new(format!("Door ({}, {})", position.x, position.y)), + door_collider(), + Observer::new(on_door_interact), + children![ + ( + Collider::cuboid(PIXELS_PER_METER * 0.5, PIXELS_PER_METER), + Sensor, + Transform::from_xyz(0., 0., 0.), + ), + ], + ) +} + +fn wall_bundle(position: Vec2) -> impl Bundle { + ( + Wall, + Transform::from_xyz(position.x, position.y, 0.), + Collider::cuboid(PIXELS_PER_METER * 0.5, PIXELS_PER_METER), + Name::new(format!("Wall ({}, {})", position.x, position.y)), + ) +} + +pub fn setup_world( + mut commands: Commands, + asset_server: Res, +) { + let door_image = asset_server.load(DOOR_CLOSED_ASSET); + commands.spawn(door_bundle(door_image, vec2(128., 0.))); + commands.spawn(wall_bundle(vec2(-128., 0.))); +} diff --git a/src/lib.rs b/src/lib.rs index 190366b..cf4a479 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,9 +7,12 @@ pub mod ui; mod tests; use bevy::{prelude::*, ui_widgets::ScrollbarPlugin}; +use bevy_rapier2d::{prelude::*, rapier::prelude::IntegrationParameters}; use leafwing_input_manager::prelude::*; use serde::{Deserialize, Serialize}; +pub const PIXELS_PER_METER: f32 = 16.0; + pub struct ExpeditionPlugin; #[derive(Actionlike, PartialEq, Eq, Hash, Debug, Clone, Reflect, Serialize, Deserialize)] @@ -87,15 +90,30 @@ impl Plugin for ExpeditionPlugin { input::InputAssetPlugin::::default(), input::InputAssetPlugin::::default(), ScrollbarPlugin, + RapierPhysicsPlugin::<()>::default() + .with_custom_initialization(RapierContextInitialization::InitializeDefaultRapierContext { + integration_parameters: IntegrationParameters { + length_unit: PIXELS_PER_METER, + ..default() + }, + rapier_configuration: RapierConfiguration { + gravity: Vec2::ZERO, + physics_pipeline_active: true, + scaled_shape_subdivision: 10, + force_update_from_transform_changes: false, + }, + }), + RapierDebugRenderPlugin::default(), )) .init_state::() .insert_resource(ui::WindowSize::default()) - .add_systems(Startup, (player::setup_player, setup_global)) + .add_systems(Startup, (player::setup_player, setup_global, layout::setup_world)) .add_systems(Update, ( player::handle_input, ui::update_window_size, ui::handle_input, insert_entity_name, + layout::detect_interact_collisions, )) .add_systems(OnEnter(GameState::Inventory), inventory::ui::setup_ui_inventory) .add_systems(OnExit(GameState::Inventory), inventory::ui::clear_ui_inventory) diff --git a/src/player.rs b/src/player.rs index 9b98d97..f91ea52 100644 --- a/src/player.rs +++ b/src/player.rs @@ -1,7 +1,8 @@ use bevy::prelude::*; +use bevy_rapier2d::prelude::*; use leafwing_input_manager::prelude::*; -use crate::{GameState, InputAction as Action, inventory::{ActiveInventory, Inventory, item::Item}}; +use crate::{GameState, InputAction as Action, PIXELS_PER_METER, inventory::{ActiveInventory, Inventory, item::Item}, layout::{InteractionEvent, MayInteract}}; #[derive(Component, Reflect)] pub struct Player { @@ -19,6 +20,11 @@ fn player_bundle(asset_server: &Res) -> impl Bundle { Transform::from_xyz(0f32, 0f32, 1f32), Action::default_input_map(), Name::new("Player"), + RigidBody::KinematicPositionBased, + KinematicCharacterController::default(), + ActiveCollisionTypes::default() | ActiveCollisionTypes::KINEMATIC_STATIC, + Collider::cuboid(PIXELS_PER_METER * 0.5, PIXELS_PER_METER), + ActiveEvents::COLLISION_EVENTS, children![ (Inventory::new(UVec2::new(6, 2)), ActiveInventory), (Inventory::new(UVec2::new(5, 3)), ActiveInventory), @@ -63,12 +69,13 @@ pub fn handle_input( time: Res