bevy-expedition-demo/src/layout/stairs.rs
2ndbeam 79fe190b6b feat: Level loading from TOML asset
- Fixed detect_interactions system
- Added test for deserializing asset with plugin
2026-03-28 01:46:27 +03:00

105 lines
3.2 KiB
Rust

use bevy::{ecs::relationship::RelatedSpawner, prelude::*};
use bevy_rapier2d::prelude::*;
use crate::{meters, player::Player};
use super::*;
const STAIRS_SPRITE_PATH: &'static str = "sprites/interactive/stairs.png";
#[derive(Component, Debug, PartialEq, Eq, Default, Clone, Copy, Reflect)]
#[reflect(Component, Debug, PartialEq, Default, Clone)]
#[require(InteractiveObject, Collider, Sensor)]
pub enum StairCollider {
#[default]
Up,
Down,
}
#[derive(Component, Clone, Copy, Default, Reflect, Debug, PartialEq)]
#[reflect(Component, Clone, Default, Debug, PartialEq)]
#[require(Transform)]
pub struct Stairs {
pub up: Option<Vec2>,
pub down: Option<Vec2>,
}
pub fn on_stairs_interact(
event: On<InteractionEvent>,
collider_query: Query<(&ChildOf, &StairCollider)>,
stairs_query: Query<&Stairs>,
mut player_query: Query<&mut Transform, With<Player>>,
) {
let Ok((parent, collider_type)) = collider_query.get(event.entity) else {
return;
};
let Ok(stairs) = stairs_query.get(parent.0) else {
error!("StairCollider does not have Stairs parent");
return;
};
let Ok(mut player_transform) = player_query.single_mut() else {
return;
};
let offset = match collider_type {
StairCollider::Up => {
let Some(offset) = stairs.up else {
error!("StairCollider::Up triggered but Stairs.up is None");
return;
};
offset
},
StairCollider::Down => {
let Some(offset) = stairs.down else {
error!("StairCollider::Down triggered but Stairs.down is None");
return;
};
offset
},
};
player_transform.translation.x += offset.x;
player_transform.translation.y += offset.y;
}
pub fn stairs_bundle(
asset_server: &Res<AssetServer>,
position: Vec2,
up_position: Option<Vec2>,
down_position: Option<Vec2>,
) -> impl Bundle {
let image = asset_server.load(STAIRS_SPRITE_PATH);
let (has_up, has_down) = (up_position.is_some(), down_position.is_some());
(
Stairs {
up: up_position,
down: down_position,
},
Transform::from_xyz(position.x, position.y, -1.),
InheritedVisibility::VISIBLE,
Children::spawn((
SpawnWith(move |parent: &mut RelatedSpawner<ChildOf>| {
if has_up {
parent.spawn((
StairCollider::Up,
Collider::cuboid(meters(1.), meters(1.)),
Transform::from_xyz(meters(-1.), 0., 0.),
));
parent.spawn((
Sprite::from_image(image),
Transform::from_xyz(0., meters(1.5), 0.),
));
}
if has_down {
parent.spawn((
StairCollider::Down,
Collider::cuboid(meters(1.), meters(1.)),
Transform::from_xyz(meters(1.), 0., 0.),
));
}
}),
)),
Name::new(format!("Stairs ({},{})", position.x, position.y))
)
}