wip: jumping physics

fix/collision-refresh
hheik 2022-11-30 01:48:42 +02:00
parent 6732618773
commit 954ac51bd6
4 changed files with 101 additions and 9 deletions

View File

@ -33,7 +33,7 @@ fn setup(mut commands: Commands) {
custom_size: Some(Vec2::new(80.0, 50.0)), custom_size: Some(Vec2::new(80.0, 50.0)),
..default() ..default()
}, },
transform: Transform::from_xyz(0.0, -100.0, 0.0), transform: Transform::from_xyz(-100.0, -250.0, 0.0),
..default() ..default()
}); });
commands commands

View File

@ -9,7 +9,7 @@ impl Plugin for GameCameraPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.register_inspectable::<CameraFollow>() app.register_inspectable::<CameraFollow>()
.add_startup_system(camera_setup) .add_startup_system(camera_setup)
.add_system(camera_system); .add_system_to_stage(CoreStage::PostUpdate, camera_system);
} }
} }

View File

@ -9,7 +9,8 @@ pub struct KinematicPlugin;
impl Plugin for KinematicPlugin { impl Plugin for KinematicPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.register_type::<KinematicProperties>() app.register_type::<KinematicState>()
.register_type::<KinematicProperties>()
.register_type::<KinematicInput>() .register_type::<KinematicInput>()
.add_system(kinematic_movement); .add_system(kinematic_movement);
} }
@ -17,6 +18,7 @@ impl Plugin for KinematicPlugin {
#[derive(Bundle)] #[derive(Bundle)]
pub struct KinematicBundle { pub struct KinematicBundle {
pub kinematic: KinematicState,
pub rigidbody: RigidBody, pub rigidbody: RigidBody,
pub velocity: Velocity, pub velocity: Velocity,
pub gravity_scale: GravityScale, pub gravity_scale: GravityScale,
@ -32,8 +34,9 @@ pub struct KinematicBundle {
impl Default for KinematicBundle { impl Default for KinematicBundle {
fn default() -> Self { fn default() -> Self {
KinematicBundle { KinematicBundle {
kinematic: KinematicState::default(),
rigidbody: RigidBody::Dynamic, rigidbody: RigidBody::Dynamic,
gravity_scale: GravityScale(4.0), gravity_scale: GravityScale(3.0),
locked_axes: LockedAxes::ROTATION_LOCKED, locked_axes: LockedAxes::ROTATION_LOCKED,
events: ActiveEvents::COLLISION_EVENTS, events: ActiveEvents::COLLISION_EVENTS,
collisions: ActiveCollisionTypes::all(), collisions: ActiveCollisionTypes::all(),
@ -45,6 +48,36 @@ impl Default for KinematicBundle {
} }
} }
#[derive(Component, Reflect, Default)]
#[reflect(Component)]
pub struct KinematicState {
on_ground: bool,
did_jump: bool,
air_jump_counter: u8,
}
impl KinematicState {
#[inline]
pub fn on_ground(&self) -> bool {
self.on_ground
}
#[inline]
pub fn did_jump(&self) -> bool {
self.did_jump
}
#[inline]
pub fn air_jump_counter(&self) -> u8 {
self.air_jump_counter
}
pub fn can_jump(&self) -> bool {
if self.on_ground && !self.did_jump {
return true;
}
false
}
}
#[derive(Component, Reflect)] #[derive(Component, Reflect)]
#[reflect(Component)] #[reflect(Component)]
pub struct KinematicProperties { pub struct KinematicProperties {
@ -54,6 +87,8 @@ pub struct KinematicProperties {
pub air_speed: f32, pub air_speed: f32,
pub air_acceleration: f32, pub air_acceleration: f32,
pub air_friction: f32, pub air_friction: f32,
pub jump_height: f32,
pub air_jumps: u8,
} }
impl Default for KinematicProperties { impl Default for KinematicProperties {
@ -65,6 +100,8 @@ impl Default for KinematicProperties {
air_speed: 100.0, air_speed: 100.0,
air_acceleration: 10.0, air_acceleration: 10.0,
air_friction: 10.0, air_friction: 10.0,
jump_height: 150.0,
air_jumps: 1,
} }
} }
} }
@ -73,29 +110,44 @@ impl Default for KinematicProperties {
#[reflect(Component)] #[reflect(Component)]
pub struct KinematicInput { pub struct KinematicInput {
pub movement: Vec2, pub movement: Vec2,
pub want_jump: bool,
} }
fn kinematic_movement( fn kinematic_movement(
time: Res<Time>, time: Res<Time>,
mut query: Query<( mut query: Query<(
Entity,
&mut Velocity, &mut Velocity,
&mut KinematicState,
&KinematicProperties, &KinematicProperties,
&GlobalTransform,
Option<&KinematicInput>, Option<&KinematicInput>,
Option<&GravityScale>, Option<&GravityScale>,
Option<&Collider>,
)>, )>,
rapier_context: Res<RapierContext>,
) { ) {
for (mut velocity, props, input, gravity) in query.iter_mut() { for (
entity,
mut velocity,
mut kinematic_state,
props,
global_transform,
input,
gravity,
collider,
) in query.iter_mut()
{
let default = &KinematicInput::default(); let default = &KinematicInput::default();
let input = input.unwrap_or(default); let input = input.unwrap_or(default);
let has_gravity = if let Some(gravity) = gravity { let has_gravity = if let Some(gravity) = gravity {
gravity.0.abs() < f32::EPSILON gravity.0.abs() > f32::EPSILON
} else { } else {
false false
}; };
let on_ground = if has_gravity { true } else { false };
let (speed, acceleration, friction) = if on_ground { let (speed, acceleration, friction) = if kinematic_state.on_ground {
( (
props.ground_speed, props.ground_speed,
props.ground_acceleration, props.ground_acceleration,
@ -135,5 +187,44 @@ fn kinematic_movement(
target_velocity, target_velocity,
velocity_change_speed * time.delta_seconds(), velocity_change_speed * time.delta_seconds(),
); );
if input.want_jump && kinematic_state.can_jump() {
velocity.linvel = Vec2 {
y: props.jump_height,
..velocity.linvel
};
kinematic_state.did_jump = true;
}
if has_gravity {
// Reset any possible jump snapping and stuff after the peak of jump
if velocity.linvel.y <= 0.0 {
kinematic_state.did_jump = false;
}
if let Some(collider) = collider {
let (_, rot, pos) = global_transform.to_scale_rotation_translation();
// println!("{pos}");
let angle = rot.to_euler(EulerRot::YXZ).2;
let mut shape = collider.clone();
shape.set_scale(Vec2::ONE * 0.9, 1);
if let Some((_coll_entity, _hit)) = rapier_context.cast_shape(
Vec2::new(pos.x, pos.y),
angle,
Vec2::NEG_Y,
&shape,
2.0,
QueryFilter::new().exclude_collider(entity),
) {
// println!(
// "Collision!\n\t{id:?} {name}\n\t{hit:?}",
// id = coll_entity,
// name = name_query.get(coll_entity).unwrap(),
// );
kinematic_state.on_ground = true;
} else {
kinematic_state.on_ground = false;
}
}
}
} }
} }

View File

@ -43,6 +43,7 @@ pub fn player_system(
}; };
kinematic_input.movement = movement; kinematic_input.movement = movement;
kinematic_input.want_jump = input.pressed(KeyCode::Space)
} }
fn input_to_axis(negative: bool, positive: bool) -> f32 { fn input_to_axis(negative: bool, positive: bool) -> f32 {
@ -58,7 +59,7 @@ fn input_to_axis(negative: bool, positive: bool) -> f32 {
pub fn player_spawn(mut commands: Commands) { pub fn player_spawn(mut commands: Commands) {
let kinematic = KinematicBundle { let kinematic = KinematicBundle {
collider: Collider::round_cuboid(8.0, 16.0, 2.0), collider: Collider::cuboid(8.0, 16.0),
transform: TransformBundle::default(), transform: TransformBundle::default(),
..default() ..default()
}; };