Newer
Older
use bevy::prelude::*;
use bevy_rapier2d::prelude::KinematicCharacterController;
pub const GRAVITY_ACC: f32 = -150.0;
pub const GRAVITY_VEC: Vec2 = Vec2::new(0.0, GRAVITY_ACC);
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, SystemSet)]
pub struct PhysicsSet;
#[derive(Component, Clone, Copy, Debug)]
pub struct HasGravity;
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#[derive(Component, Clone, Copy, Debug, Default, Deref, DerefMut)]
pub struct Velocity(Vec2);
#[derive(Component, Clone, Copy, Debug, Default, Deref, DerefMut)]
pub struct Acceleration(Vec2);
#[derive(Component, Clone, Copy, Debug, Default)]
pub struct PhysicsLimits {
pub velocity: (Option<Vec2>, Option<Vec2>),
pub acceleration: (Option<Vec2>, Option<Vec2>),
}
impl PhysicsLimits {
pub fn limit_velocity(&self, velocity: Vec2) -> Vec2 {
match self.velocity {
(None, None) => velocity,
(Some(min), None) => velocity.max(min),
(None, Some(max)) => velocity.min(max),
(Some(min), Some(max)) => velocity.min(max).max(min),
}
}
pub fn limit_acceleration(&self, acceleration: Vec2) -> Vec2 {
match self.acceleration {
(None, None) => acceleration,
(Some(min), None) => acceleration.max(min),
(None, Some(max)) => acceleration.min(max),
(Some(min), Some(max)) => acceleration.min(max).max(min),
}
}
}
impl Acceleration {
pub fn gravity() -> Self {
Acceleration(GRAVITY_VEC)
}
pub fn new(val: Vec2) -> Self {
Acceleration(val)
}
}
fn apply_acceleration(
time: Res<Time>,
mut query: Query<(
&mut Velocity,
&Acceleration,
Option<&PhysicsLimits>,
Has<HasGravity>,
)>,
phys_config: FetchPhysicsConfig,
let gravity = phys_config.get().map(|p| p.gravity).unwrap_or_default();
for (mut velocity, acceleration, limits, has_gravity) in &mut query {
if has_gravity {
**velocity += Vec2::new(0.0, gravity) * dt;
}
**velocity = limits
.copied()
.unwrap_or_default()
.limit_velocity(**velocity);
}
}
fn apply_velocity_to_kinematics(
time: Res<Time>,
mut query: Query<(&mut KinematicCharacterController, &Velocity)>,
) {
let dt = time.delta_seconds();
for (mut controller, velocity) in &mut query {
controller.translation = Some(**velocity * dt);
}
}
pub struct PhysicsPlugin;
impl Plugin for PhysicsPlugin {
fn build(&self, app: &mut App) {
app.add_systems(
Update,
(apply_acceleration, apply_velocity_to_kinematics)
.chain()
.in_set(PhysicsSet)
.run_if(run_in_game),
);
}
}