metamorphisis

This commit is contained in:
2024-11-07 00:01:40 +02:00
parent b85a5463a9
commit 0e862aa71f
2 changed files with 179 additions and 0 deletions

76
src/colliders.rs Normal file
View File

@@ -0,0 +1,76 @@
use bevy::prelude::*;
use bevy_ecs_ldtk::prelude::*;
use bevy_rapier2d::prelude::*;
#[derive(Clone, Default, Bundle, LdtkIntCell)]
pub struct ColliderBundle {
pub collider: Collider,
pub rigid_body: RigidBody,
pub velocity: Velocity,
pub rotation_constraints: LockedAxes,
pub gravity_scale: GravityScale,
pub friction: Friction,
pub density: ColliderMassProperties,
}
impl From<&EntityInstance> for ColliderBundle {
fn from(entity_instance: &EntityInstance) -> ColliderBundle {
let rotation_constraints = LockedAxes::ROTATION_LOCKED;
match entity_instance.identifier.as_ref() {
"Player" => ColliderBundle {
collider: Collider::cuboid(6., 14.),
rigid_body: RigidBody::Dynamic,
friction: Friction {
coefficient: 0.0,
combine_rule: CoefficientCombineRule::Min,
},
rotation_constraints,
..Default::default()
},
"Mob" => ColliderBundle {
collider: Collider::cuboid(5., 5.),
rigid_body: RigidBody::KinematicVelocityBased,
rotation_constraints,
..Default::default()
},
"Chest" => ColliderBundle {
collider: Collider::cuboid(8., 8.),
rigid_body: RigidBody::Dynamic,
rotation_constraints,
gravity_scale: GravityScale(1.0),
friction: Friction::new(0.5),
density: ColliderMassProperties::Density(15.0),
..Default::default()
},
_ => ColliderBundle::default(),
}
}
}
#[derive(Clone, Default, Bundle, LdtkIntCell)]
pub struct SensorBundle {
pub collider: Collider,
pub sensor: Sensor,
pub active_events: ActiveEvents,
pub rotation_constraints: LockedAxes,
}
impl From<IntGridCell> for SensorBundle {
fn from(int_grid_cell: IntGridCell) -> SensorBundle {
let rotation_constraints = LockedAxes::ROTATION_LOCKED;
// ladder
if int_grid_cell.value == 2 {
SensorBundle {
collider: Collider::cuboid(8., 8.),
sensor: Sensor,
rotation_constraints,
active_events: ActiveEvents::COLLISION_EVENTS,
}
} else {
SensorBundle::default()
}
}
}

103
src/ground_detection.rs Normal file
View File

@@ -0,0 +1,103 @@
use std::collections::HashSet;
use bevy::prelude::*;
use bevy_rapier2d::prelude::*;
#[derive(Component)]
pub struct GroundSensor {
pub ground_detection_entity: Entity,
pub intersecting_ground_entities: HashSet<Entity>,
}
#[derive(Clone, Default, Component)]
pub struct GroundDetection {
pub on_ground: bool,
}
pub fn spawn_ground_sensor(
mut commands: Commands,
detect_ground_for: Query<(Entity, &Collider), Added<GroundDetection>>,
) {
for (entity, shape) in &detect_ground_for {
if let Some(cuboid) = shape.as_cuboid() {
let Vec2 {
x: half_extents_x,
y: half_extents_y,
} = cuboid.half_extents();
let detector_shape = Collider::cuboid(half_extents_x / 2.0, 2.);
let sensor_translation = Vec3::new(0., -half_extents_y, 0.);
commands.entity(entity).with_children(|builder| {
builder
.spawn_empty()
.insert(ActiveEvents::COLLISION_EVENTS)
.insert(detector_shape)
.insert(Sensor)
.insert(Transform::from_translation(sensor_translation))
.insert(GlobalTransform::default())
.insert(GroundSensor {
ground_detection_entity: entity,
intersecting_ground_entities: HashSet::new(),
});
});
}
}
}
pub fn ground_detection(
mut ground_sensors: Query<&mut GroundSensor>,
mut collisions: EventReader<CollisionEvent>,
collidables: Query<Entity, (With<Collider>, Without<Sensor>)>,
) {
for collision_event in collisions.read() {
match collision_event {
CollisionEvent::Started(e1, e2, _) => {
if collidables.contains(*e1) {
if let Ok(mut sensor) = ground_sensors.get_mut(*e2) {
sensor.intersecting_ground_entities.insert(*e1);
}
} else if collidables.contains(*e2) {
if let Ok(mut sensor) = ground_sensors.get_mut(*e1) {
sensor.intersecting_ground_entities.insert(*e2);
}
}
}
CollisionEvent::Stopped(e1, e2, _) => {
if collidables.contains(*e1) {
if let Ok(mut sensor) = ground_sensors.get_mut(*e2) {
sensor.intersecting_ground_entities.remove(e1);
}
} else if collidables.contains(*e2) {
if let Ok(mut sensor) = ground_sensors.get_mut(*e1) {
sensor.intersecting_ground_entities.remove(e2);
}
}
}
}
}
}
pub fn update_on_ground(
mut ground_detectors: Query<&mut GroundDetection>,
ground_sensors: Query<&GroundSensor, Changed<GroundSensor>>,
) {
for sensor in &ground_sensors {
if let Ok(mut ground_detection) = ground_detectors.get_mut(sensor.ground_detection_entity) {
ground_detection.on_ground = !sensor.intersecting_ground_entities.is_empty();
}
}
}
/// Handles platformer-specific physics operations, specifically ground detection.
pub struct GroundDetectionPlugin;
impl Plugin for GroundDetectionPlugin {
fn build(&self, app: &mut App) {
app.add_systems(Update, spawn_ground_sensor)
.add_systems(Update, ground_detection)
.add_systems(Update, update_on_ground);
}
}