metamorphisis
This commit is contained in:
76
src/colliders.rs
Normal file
76
src/colliders.rs
Normal 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
103
src/ground_detection.rs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user