|
use std::collections::HashSet; |
|
use bevy::prelude::*; |
|
use bevy_rapier2d::{ dynamics::GravityScale, pipeline::CollisionEvent }; |
|
|
|
use crate::plugins::rapier_utils::reciprocal_collisions; |
|
|
|
|
|
|
|
#[derive(Copy, Clone, Eq, PartialEq, Debug, Default, Component)] |
|
pub struct Climbable; |
|
|
|
|
|
#[derive(Clone, Eq, PartialEq, Debug, Default, Component)] |
|
pub struct Climber { |
|
pub climbing: bool, |
|
pub intersecting_climbables: HashSet<Entity>, |
|
} |
|
|
|
|
|
|
|
|
|
pub fn detect_climb_range( |
|
mut climbers: Query<&mut Climber>, |
|
climbables: Query<Entity, With<Climbable>>, |
|
mut collisions: EventReader<CollisionEvent> |
|
) { |
|
reciprocal_collisions(&mut collisions, move |collider_a, collider_b, _, start| { |
|
if |
|
let (Ok(mut climber), Ok(climbable)) = ( |
|
climbers.get_mut(*collider_a), |
|
climbables.get(*collider_b), |
|
) |
|
{ |
|
if start { |
|
climber.intersecting_climbables.insert(climbable); |
|
} else { |
|
climber.intersecting_climbables.remove(&climbable); |
|
} |
|
true |
|
} else { |
|
false |
|
} |
|
}); |
|
} |
|
|
|
|
|
|
|
|
|
pub fn ignore_gravity_if_climbing( |
|
mut query: Query<(&Climber, &mut GravityScale), Changed<Climber>> |
|
) { |
|
for (climber, mut gravity_scale) in &mut query { |
|
if climber.climbing { |
|
gravity_scale.0 = 0.0; |
|
} else { |
|
gravity_scale.0 = 1.0; |
|
} |
|
} |
|
} |
|
|