Merge branch 'dev-kinematic' of ssh://git@129.151.217.187:23/MikolajG/ttt-ce.git into dev-kinematic
# Conflicts: # .vscode/settings.json # src/player_utils/character_controller.rs
This commit is contained in:
commit
24bf13666f
5 changed files with 252 additions and 29 deletions
|
|
@ -1,29 +0,0 @@
|
||||||
# The run config is used for both run mode and debug mode
|
|
||||||
|
|
||||||
[[configs]]
|
|
||||||
# the name of this task
|
|
||||||
name = "[Dev] Build and run"
|
|
||||||
|
|
||||||
# the type of the debugger. If not set, it can't be debugged but can still be run
|
|
||||||
# type = "lldb"
|
|
||||||
|
|
||||||
# the program to run
|
|
||||||
program = "nix-shell"
|
|
||||||
|
|
||||||
# the program arguments, e.g. args = ["arg1", "arg2"], optional
|
|
||||||
args = ["--run"]
|
|
||||||
|
|
||||||
# current working directory, optional
|
|
||||||
# cwd = "${workspace}"
|
|
||||||
|
|
||||||
# enviroment variables, optional
|
|
||||||
# [configs.env]
|
|
||||||
# VAR1 = "VAL1"
|
|
||||||
# VAR2 = "VAL2"
|
|
||||||
|
|
||||||
# task to run before the run/debug session is started, optional
|
|
||||||
# [configs.prelaunch]
|
|
||||||
# program = "cargo"
|
|
||||||
# args = [
|
|
||||||
# "build",
|
|
||||||
# ]
|
|
||||||
6
.vscode/launch.json
vendored
6
.vscode/launch.json
vendored
|
|
@ -17,6 +17,12 @@
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"type": "node-terminal"
|
"type": "node-terminal"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"command": "nix-shell --run 'cargo check'",
|
||||||
|
"name": "Check for errors",
|
||||||
|
"request": "launch",
|
||||||
|
"type": "node-terminal"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "lldb",
|
"type": "lldb",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
|
|
|
||||||
4
.vscode/settings.json
vendored
4
.vscode/settings.json
vendored
|
|
@ -5,5 +5,9 @@
|
||||||
"Substep",
|
"Substep",
|
||||||
"xpbd"
|
"xpbd"
|
||||||
],
|
],
|
||||||
|
<<<<<<< HEAD
|
||||||
"rust-analyzer.checkOnSave": false
|
"rust-analyzer.checkOnSave": false
|
||||||
|
=======
|
||||||
|
"rust-analyzer.checkOnSave": false,
|
||||||
|
>>>>>>> branch 'dev-kinematic' of ssh://git@129.151.217.187:23/MikolajG/ttt-ce.git
|
||||||
}
|
}
|
||||||
|
|
@ -31,6 +31,11 @@ lto = true
|
||||||
codegen-units = 1
|
codegen-units = 1
|
||||||
strip = true
|
strip = true
|
||||||
|
|
||||||
|
|
||||||
|
[build]
|
||||||
|
rustflags = ["-Z", "threads=7"]
|
||||||
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
dev = [
|
dev = [
|
||||||
"bevy/dynamic_linking",
|
"bevy/dynamic_linking",
|
||||||
|
|
|
||||||
|
|
@ -175,6 +175,7 @@ fn new_fall_velocity(initial_velocity: LinearVelocity, gravity: Vec3, delta_time
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
// fn move_character(
|
// fn move_character(
|
||||||
// time: Res<Time>,
|
// time: Res<Time>,
|
||||||
// mut movement_event_reader: EventReader<MovementAction>,
|
// mut movement_event_reader: EventReader<MovementAction>,
|
||||||
|
|
@ -394,6 +395,242 @@ fn move_character(
|
||||||
velocity.y = character_controller.jump_impulse;
|
velocity.y = character_controller.jump_impulse;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
=======
|
||||||
|
fn apply_gravity(
|
||||||
|
time: Res<Time>,
|
||||||
|
mut controllers: Query<(&CharacterController, &mut LinearVelocity)>,
|
||||||
|
) {
|
||||||
|
// Precision is adjusted so that the example works with
|
||||||
|
// both the `f32` and `f64` features. Otherwise you don't need this.
|
||||||
|
let delta_time = time.delta_seconds_f64().adjust_precision();
|
||||||
|
|
||||||
|
for (character_controller, mut linear_velocity) in &mut controllers {
|
||||||
|
|
||||||
|
let mut fall_acceleration: Vec3 = get_lateral_acceleration(character_controller, delta_time, linear_velocity.0);
|
||||||
|
fall_acceleration.y = 0.0;
|
||||||
|
let has_limited_air_control: bool = false;
|
||||||
|
|
||||||
|
|
||||||
|
// Ugly fix for mismatch types, find a proper solution later
|
||||||
|
let new_velocity: Vec3 = new_fall_velocity(linear_velocity.clone(), character_controller.gravity, delta_time, character_controller.axis_speed_limit);
|
||||||
|
linear_velocity.x = new_velocity.x;
|
||||||
|
linear_velocity.y = new_velocity.y;
|
||||||
|
linear_velocity.z = new_velocity.z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn move_character(
|
||||||
|
time: Res<Time>,
|
||||||
|
mut movement_event_reader: EventReader<MovementAction>,
|
||||||
|
mut query: Query<(
|
||||||
|
&mut LinearVelocity,
|
||||||
|
&CharacterController,
|
||||||
|
Has<Grounded>,
|
||||||
|
&Rotation,
|
||||||
|
&ShapeHits,
|
||||||
|
&Transform,
|
||||||
|
)>,
|
||||||
|
) {
|
||||||
|
let delta_time = time.delta_seconds_f64().adjust_precision();
|
||||||
|
|
||||||
|
for event in movement_event_reader.read() {
|
||||||
|
for (
|
||||||
|
mut velocity,
|
||||||
|
character_controller,
|
||||||
|
is_grounded,
|
||||||
|
rotation,
|
||||||
|
shape_hits,
|
||||||
|
character_transform,
|
||||||
|
) in &mut query
|
||||||
|
{
|
||||||
|
//character_controller.friction = f32::max(0.0, character_controller.friction);
|
||||||
|
let forward = character_transform.forward().xyz().normalize();
|
||||||
|
|
||||||
|
match event {
|
||||||
|
MovementAction::Move(direction) => {
|
||||||
|
if is_grounded {
|
||||||
|
velocity.x = f32::clamp(velocity.x, -character_controller.axis_speed_limit, character_controller.axis_speed_limit);
|
||||||
|
velocity.y = f32::clamp(velocity.y, -character_controller.axis_speed_limit, character_controller.axis_speed_limit);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MovementAction::Jump => {
|
||||||
|
if is_grounded {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn move_character(
|
||||||
|
time: Res<Time>,
|
||||||
|
mut movement_event_reader: EventReader<MovementAction>,
|
||||||
|
mut query: Query<(
|
||||||
|
&mut LinearVelocity,
|
||||||
|
&CharacterController,
|
||||||
|
Has<Grounded>,
|
||||||
|
&Rotation,
|
||||||
|
&ShapeHits,
|
||||||
|
&Transform,
|
||||||
|
)>,
|
||||||
|
) {
|
||||||
|
let delta_time = time.delta_seconds_f64().adjust_precision();
|
||||||
|
|
||||||
|
for event in movement_event_reader.read() {
|
||||||
|
for (
|
||||||
|
mut velocity,
|
||||||
|
character_controller,
|
||||||
|
is_grounded,
|
||||||
|
rotation,
|
||||||
|
shape_hits,
|
||||||
|
character_transform,
|
||||||
|
) in &mut query
|
||||||
|
{
|
||||||
|
match event {
|
||||||
|
MovementAction::Move(direction) => {
|
||||||
|
// Get the forward direction of the character in the local coordinate system
|
||||||
|
let forward = character_transform.forward().xyz().normalize();
|
||||||
|
|
||||||
|
// Calculate the movement in the local coordinate system
|
||||||
|
let local_movement = forward
|
||||||
|
* direction.y
|
||||||
|
* character_controller.movement_acceleration
|
||||||
|
* delta_time
|
||||||
|
+ character_transform
|
||||||
|
.rotation
|
||||||
|
.mul_vec3(Vec3::new(direction.x, 0.0, 0.0))
|
||||||
|
* character_controller.movement_acceleration
|
||||||
|
* delta_time;
|
||||||
|
|
||||||
|
if is_grounded {
|
||||||
|
let mut slope_factor = 1.0;
|
||||||
|
for hit in shape_hits.iter() {
|
||||||
|
let angle =
|
||||||
|
rotation.rotate(-hit.normal2).angle_between(Vector::Y).abs();
|
||||||
|
if angle <= character_controller.max_slope_angle {
|
||||||
|
slope_factor *=
|
||||||
|
(angle / character_controller.max_slope_angle).cos();
|
||||||
|
|
||||||
|
// Update linear velocity
|
||||||
|
velocity.x += local_movement.x * slope_factor;
|
||||||
|
velocity.z += local_movement.z * slope_factor;
|
||||||
|
} else {
|
||||||
|
velocity.x = 0.0;
|
||||||
|
velocity.z = 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
velocity.x += local_movement.x * character_controller.air_control_factor;
|
||||||
|
velocity.z += local_movement.z * character_controller.air_control_factor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MovementAction::Jump => {
|
||||||
|
if is_grounded {
|
||||||
|
velocity.y = character_controller.jump_impulse;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_grounded(
|
||||||
|
mut commands: Commands,
|
||||||
|
mut query: Query<(Entity, &CharacterController, &Rotation, &ShapeHits)>,
|
||||||
|
) {
|
||||||
|
for (entity, character_controller, rotation, hits) in &mut query {
|
||||||
|
let is_grounded = hits.iter().any(|hit| {
|
||||||
|
let angle = rotation.rotate(-hit.normal2).angle_between(Vector::Y).abs();
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"slope angle: {} / {}",
|
||||||
|
angle, character_controller.max_slope_angle
|
||||||
|
);
|
||||||
|
|
||||||
|
angle <= character_controller.max_slope_angle
|
||||||
|
});
|
||||||
|
|
||||||
|
//println!("is grounded: {}", is_grounded);
|
||||||
|
|
||||||
|
if is_grounded {
|
||||||
|
commands.entity(entity).insert(Grounded);
|
||||||
|
} else {
|
||||||
|
commands.entity(entity).remove::<Grounded>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
|
fn kinematic_controller_collisions(
|
||||||
|
collisions: Res<Collisions>,
|
||||||
|
collider_parents: Query<&ColliderParent, Without<Sensor>>,
|
||||||
|
mut character_controllers: Query<
|
||||||
|
(
|
||||||
|
&RigidBody,
|
||||||
|
&mut Position,
|
||||||
|
&Rotation,
|
||||||
|
&mut LinearVelocity,
|
||||||
|
&CharacterController,
|
||||||
|
)
|
||||||
|
>,
|
||||||
|
) {
|
||||||
|
// Iterate through collisions and move the kinematic body to resolve penetration
|
||||||
|
for contacts in collisions.iter() {
|
||||||
|
// If the collision didn't happen during this substep, skip the collision
|
||||||
|
if !contacts.during_current_substep {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the rigid body entities of the colliders (colliders could be children)
|
||||||
|
let Ok([collider_parent1, collider_parent2]) =
|
||||||
|
collider_parents.get_many([contacts.entity1, contacts.entity2])
|
||||||
|
else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get the body of the character controller and whether it is the first
|
||||||
|
// or second entity in the collision.
|
||||||
|
let is_first: bool;
|
||||||
|
let (rb, mut position, rotation, mut linear_velocity, character_controller) =
|
||||||
|
if let Ok(character) = character_controllers.get_mut(collider_parent1.get()) {
|
||||||
|
is_first = true;
|
||||||
|
character
|
||||||
|
} else if let Ok(character) = character_controllers.get_mut(collider_parent2.get()) {
|
||||||
|
is_first = false;
|
||||||
|
character
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
// This system only handles collision response for kinematic character controllers
|
||||||
|
if !rb.is_kinematic() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterate through contact manifolds and their contacts.
|
||||||
|
// Each contact in a single manifold shares the same contact normal.
|
||||||
|
for manifold in contacts.manifolds.iter() {
|
||||||
|
let normal = if is_first {
|
||||||
|
-manifold.global_normal1(rotation)
|
||||||
|
} else {
|
||||||
|
-manifold.global_normal2(rotation)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Solve each penetrating contact in the manifold
|
||||||
|
for contact in manifold.contacts.iter().filter(|c| c.penetration > 0.0) {
|
||||||
|
position.0 += normal * contact.penetration;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the slope isn't too steep to walk on but the character
|
||||||
|
// is falling, reset vertical velocity.
|
||||||
|
if normal.angle_between(Vector::Y).abs() <= character_controller.max_slope_angle
|
||||||
|
&& linear_velocity.y < 0.0
|
||||||
|
{
|
||||||
|
linear_velocity.y = linear_velocity.y.max(0.0);
|
||||||
|
>>>>>>> branch 'dev-kinematic' of ssh://git@129.151.217.187:23/MikolajG/ttt-ce.git
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue