generated from 2ndbeam/bevy-template
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
This commit is contained in:
parent
4c23a38b92
commit
bb357d8062
2 changed files with 37 additions and 16 deletions
|
|
@ -17,7 +17,10 @@ pub struct Wall;
|
||||||
|
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
#[require(Sprite, InteractiveObject)]
|
#[require(Sprite, InteractiveObject)]
|
||||||
pub struct Door;
|
pub struct Door(pub i8);
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
pub struct Locked;
|
||||||
|
|
||||||
#[derive(EntityEvent)]
|
#[derive(EntityEvent)]
|
||||||
pub struct InteractionEvent {
|
pub struct InteractionEvent {
|
||||||
|
|
@ -76,24 +79,35 @@ pub fn detect_interact_collisions(
|
||||||
fn on_door_interact(
|
fn on_door_interact(
|
||||||
event: On<InteractionEvent>,
|
event: On<InteractionEvent>,
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
|
locked_query: Query<(), With<Locked>>,
|
||||||
collider_query: Query<(), (With<Door>, With<Collider>)>,
|
collider_query: Query<(), (With<Door>, With<Collider>)>,
|
||||||
no_collider_query: Query<(), (With<Door>, Without<Collider>)>,
|
no_collider_query: Query<(), (With<Door>, Without<Collider>)>,
|
||||||
mut sprite_query: Query<&mut Sprite, With<Door>>,
|
door_query: Query<(&Door, &Children)>,
|
||||||
|
mut sprite_query: Query<(&mut Sprite, &mut Transform)>,
|
||||||
asset_server: Res<AssetServer>,
|
asset_server: Res<AssetServer>,
|
||||||
) {
|
) {
|
||||||
let was_opened =
|
if locked_query.get(event.entity).is_ok() {
|
||||||
if collider_query.get(event.entity).is_ok() { false }
|
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 if no_collider_query.get(event.entity).is_ok() { true }
|
||||||
else {
|
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;
|
return;
|
||||||
};
|
};
|
||||||
let Ok(mut sprite) = sprite_query.get_mut(event.entity) else {
|
let Ok((door, children)) = door_query.get(event.entity) else {
|
||||||
error!("on_door_interact fired but entity {} has no sprite", event.entity);
|
error!("on_door_interact fired but entity {} has no children", event.entity);
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let asset_path = if was_opened { DOOR_CLOSED_ASSET } else { DOOR_OPENED_ASSET };
|
for child in children {
|
||||||
sprite.image = asset_server.load(asset_path);
|
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 {
|
if was_opened {
|
||||||
commands.entity(event.entity).insert(door_collider());
|
commands.entity(event.entity).insert(door_collider());
|
||||||
|
|
@ -103,13 +117,13 @@ fn on_door_interact(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn door_collider() -> Collider {
|
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<Image>, position: Vec2) -> impl Bundle {
|
fn door_bundle(image: Handle<Image>, position: Vec2, facing_left: bool) -> impl Bundle {
|
||||||
|
let direction = if facing_left { -1 } else { 1 };
|
||||||
(
|
(
|
||||||
Door,
|
Door(direction),
|
||||||
Sprite::from_image(image),
|
|
||||||
Transform::from_xyz(position.x, position.y, 0.),
|
Transform::from_xyz(position.x, position.y, 0.),
|
||||||
Name::new(format!("Door ({}, {})", position.x, position.y)),
|
Name::new(format!("Door ({}, {})", position.x, position.y)),
|
||||||
door_collider(),
|
door_collider(),
|
||||||
|
|
@ -120,6 +134,10 @@ fn door_bundle(image: Handle<Image>, position: Vec2) -> impl Bundle {
|
||||||
Sensor,
|
Sensor,
|
||||||
Transform::from_xyz(0., 0., 0.),
|
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<AssetServer>,
|
asset_server: Res<AssetServer>,
|
||||||
) {
|
) {
|
||||||
let door_image = asset_server.load(DOOR_CLOSED_ASSET);
|
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.)));
|
commands.spawn(wall_bundle(vec2(-128., 0.)));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ fn player_bundle(asset_server: &Res<AssetServer>) -> impl Bundle {
|
||||||
ActiveCollisionTypes::default() | ActiveCollisionTypes::KINEMATIC_STATIC,
|
ActiveCollisionTypes::default() | ActiveCollisionTypes::KINEMATIC_STATIC,
|
||||||
Collider::cuboid(PIXELS_PER_METER * 0.5, PIXELS_PER_METER),
|
Collider::cuboid(PIXELS_PER_METER * 0.5, PIXELS_PER_METER),
|
||||||
ActiveEvents::COLLISION_EVENTS,
|
ActiveEvents::COLLISION_EVENTS,
|
||||||
|
Sleeping::disabled(),
|
||||||
children![
|
children![
|
||||||
(Inventory::new(UVec2::new(6, 2)), ActiveInventory),
|
(Inventory::new(UVec2::new(6, 2)), ActiveInventory),
|
||||||
(Inventory::new(UVec2::new(5, 3)), ActiveInventory),
|
(Inventory::new(UVec2::new(5, 3)), ActiveInventory),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue