From bb357d8062f2b03fa7ae8d6df3ccf67817fb4f85 Mon Sep 17 00:00:00 2001 From: 2ndbeam <2ndbeam@disroot.org> Date: Wed, 18 Mar 2026 13:29:05 +0300 Subject: [PATCH] feat: Finished door mechanics - Door now has i8 direction (-1 or 1) - Door may be locked with Locked component - Player entity RigidBody now cannot sleep to keep MayInteract when idle --- src/layout.rs | 52 +++++++++++++++++++++++++++++++++++---------------- src/player.rs | 1 + 2 files changed, 37 insertions(+), 16 deletions(-) diff --git a/src/layout.rs b/src/layout.rs index a3ffe61..4a0c24d 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -17,7 +17,10 @@ pub struct Wall; #[derive(Component)] #[require(Sprite, InteractiveObject)] -pub struct Door; +pub struct Door(pub i8); + +#[derive(Component)] +pub struct Locked; #[derive(EntityEvent)] pub struct InteractionEvent { @@ -76,24 +79,35 @@ pub fn detect_interact_collisions( fn on_door_interact( event: On, mut commands: Commands, + locked_query: Query<(), With>, collider_query: Query<(), (With, With)>, no_collider_query: Query<(), (With, Without)>, - mut sprite_query: Query<&mut Sprite, With>, + door_query: Query<(&Door, &Children)>, + mut sprite_query: Query<(&mut Sprite, &mut Transform)>, asset_server: Res, ) { - let was_opened = - if collider_query.get(event.entity).is_ok() { false } + if locked_query.get(event.entity).is_ok() { + return; + } + 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); + error!("on_door_interact fired but entity {} isn't door", event.entity); + return; + }; + let Ok((door, children)) = door_query.get(event.entity) else { + error!("on_door_interact fired but entity {} has no children", 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); + for child in children { + if let Ok((mut sprite, mut transform)) = sprite_query.get_mut(*child) { + let (image, translation) = if was_opened { (DOOR_CLOSED_ASSET, 0.) } + else { (DOOR_OPENED_ASSET, door.0 as f32 * 8.) }; + sprite.image = asset_server.load(image); + transform.translation.x = translation; + break; + } + } if was_opened { commands.entity(event.entity).insert(door_collider()); @@ -103,13 +117,13 @@ fn on_door_interact( } fn door_collider() -> Collider { - Collider::cuboid(PIXELS_PER_METER * 0.125, PIXELS_PER_METER) + Collider::cuboid(PIXELS_PER_METER * 0.06125, PIXELS_PER_METER) } -fn door_bundle(image: Handle, position: Vec2) -> impl Bundle { +fn door_bundle(image: Handle, position: Vec2, facing_left: bool) -> impl Bundle { + let direction = if facing_left { -1 } else { 1 }; ( - Door, - Sprite::from_image(image), + Door(direction), Transform::from_xyz(position.x, position.y, 0.), Name::new(format!("Door ({}, {})", position.x, position.y)), door_collider(), @@ -120,6 +134,10 @@ fn door_bundle(image: Handle, position: Vec2) -> impl Bundle { Sensor, Transform::from_xyz(0., 0., 0.), ), + ( + Sprite::from_image(image), + Transform::from_xyz(0., 0., 0.), + ), ], ) } @@ -138,6 +156,8 @@ pub fn setup_world( asset_server: Res, ) { let door_image = asset_server.load(DOOR_CLOSED_ASSET); - commands.spawn(door_bundle(door_image, vec2(128., 0.))); + commands.spawn(door_bundle(door_image.clone(), vec2(128., 0.), true)); + commands.spawn(door_bundle(door_image.clone(), vec2(160., 0.), false)); + commands.spawn(door_bundle(door_image.clone(), vec2(196., 0.), false)).insert(Locked); commands.spawn(wall_bundle(vec2(-128., 0.))); } diff --git a/src/player.rs b/src/player.rs index f91ea52..a10cdd0 100644 --- a/src/player.rs +++ b/src/player.rs @@ -25,6 +25,7 @@ fn player_bundle(asset_server: &Res) -> impl Bundle { ActiveCollisionTypes::default() | ActiveCollisionTypes::KINEMATIC_STATIC, Collider::cuboid(PIXELS_PER_METER * 0.5, PIXELS_PER_METER), ActiveEvents::COLLISION_EVENTS, + Sleeping::disabled(), children![ (Inventory::new(UVec2::new(6, 2)), ActiveInventory), (Inventory::new(UVec2::new(5, 3)), ActiveInventory),