Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Difficulty with Implementing Damping and Movement in Spacecraft Using Avian #498

Open
JustKira opened this issue Aug 23, 2024 · 0 comments

Comments

@JustKira
Copy link

JustKira commented Aug 23, 2024

Hello everyone,

I've recently started using Avian, and I'm still relatively new to Bevy as well. I've been trying to create a spacecraft system where the player can control the spacecraft's rotation and forward/backward movement based on its current orientation.

Previously my spacecraft uses a combination of Transform and my own acceleration and velocity system. i used transform.up() for direction-based movement, which worked well. However, since I want to add raycasting and colliders, I decided to rewrite the movement logic using Avian's components.

You can see the current state of my code in this GitHub commit.

Here is old System commit for reference what i am trying to do commit.

The Problems I'm Facing

Damping and Cruising Speed: I want to implement a damping system that prevents the spacecraft from stopping completely. Instead, it should slow down to a certain cruising speed (which you can think of is the avg_speed or something on those lines). However, I'm struggling to figure out how to apply damping in Avian so that it reduces the velocity to this cruising speed rather than zero when there’s no input.
Deceleration to Minimum Speed: When the player presses the "S" key or the down arrow, the spacecraft should decelerate to a defined min_speed. This means that even when decelerating, the spacecraft should never reach a complete stop but rather slow down to this minimum threshold.

Slippery Movement: Currently, the spacecraft feels very slippery, which is odd because the movement was much more precise in my old system. I'm not sure if this is due to the speed calculations or some other factor, but the movement doesn't feel right.
this while i ignore damping i just testing movement with current setup it feels unresponsive.

Also one more is there a Avian way to limit max and min velocity or do just use Clamp or something similar i want to limit angular_velocity and also add min_velocity for linear_velocity

What I've Tried

I attempted to use Avian's damping components, but they didn't seem to work as expected. I applied them to both linear and angular velocities, hoping to achieve a gradual reduction to cruising speed and to allow angular velocity to decrease to zero, but the results weren't satisfactory.
I also tried to adjust other parameters and settings but couldn't achieve the desired effect.

What I Need Help With

I'm looking for advice on how to:
Properly implement a damping system in Avian that allows for movement to slow down to a cruising speed rather than stopping completely.
Adjust the deceleration logic so that pressing "S" or the down arrow key causes the spacecraft to slow down to a predefined minimum speed, but never stops entirely.
Improve the overall feel of the movement to make it less slippery and more responsive.

Any insights or suggestions would be greatly appreciated!

Also here Specific rs file that has all logic

use avian2d::{math::Scalar, prelude::*};
use bevy::prelude::*;
pub struct SpaceCraftPlugin;

#[derive(Event)]
pub enum SpaceCraftVerticalAction {
    VerticalMove(Scalar),
}

#[derive(Event)]
pub enum SpaceCraftHorizontalAction {
    HorizontalMove(Scalar),
}

#[derive(Component)]
pub struct SpaceCraft {}

// #[derive(Component)]
// pub struct SpaceCraftHorizontalMovement {}

// #[derive(Component)]
// pub struct SpaceCraftLinearAcceleration(Scalar);

// #[derive(Component)]
// pub struct SpaceCraftAngularAcceleration(Scalar);
#[derive(Component)]
pub struct MaxSpeed {
    pub value: f32,
}

#[derive(Component)]
pub struct MaxRotationSpeed {
    pub value: f32,
}

impl Plugin for SpaceCraftPlugin {
    fn build(&self, app: &mut App) {
        app.add_event::<SpaceCraftVerticalAction>()
            .add_event::<SpaceCraftHorizontalAction>()
            .add_systems(Startup, spawn_spacecraft)
            .add_systems(
                Update,
                (
                    spacecraft_vertical_input,
                    spacecraft_horizontal_input,
                    spacecraft_local_vertical_movement,
                    spacecraft_rotation,
                )
                    .chain(),
            );
    }
}

fn spacecraft_vertical_input(
    mut event_writer: EventWriter<SpaceCraftVerticalAction>,
    keyboard_input: Res<ButtonInput<KeyCode>>,
) {
    let up: bool = keyboard_input.any_pressed([KeyCode::KeyW, KeyCode::ArrowUp]);
    let down = keyboard_input.any_pressed([KeyCode::KeyS, KeyCode::ArrowDown]);

    let vertical = up as i8 - down as i8;
    let vertical_direction = vertical as Scalar;

    if vertical_direction != 0.0 {
        event_writer.send(SpaceCraftVerticalAction::VerticalMove(vertical_direction));
    }
}

fn spacecraft_horizontal_input(
    mut event_writer: EventWriter<SpaceCraftHorizontalAction>,
    keyboard_input: Res<ButtonInput<KeyCode>>,
) {
    let left = keyboard_input.any_pressed([KeyCode::KeyA, KeyCode::ArrowLeft]);
    let right = keyboard_input.any_pressed([KeyCode::KeyD, KeyCode::ArrowRight]);

    let horizontal = left as i8 - right as i8;
    let horizontal_direction = horizontal as Scalar;

    if horizontal_direction != 0.0 {
        event_writer.send(SpaceCraftHorizontalAction::HorizontalMove(
            horizontal_direction,
        ));
    }
}

fn spawn_spacecraft(mut commands: Commands, asset_server: Res<AssetServer>) {
    commands.spawn((
        RigidBody::Kinematic,
        SpriteBundle {
            texture: asset_server.load("ship_B.png"),
            ..default()
        },
        GravityScale(0.0),
        Collider::circle(10.0),
        MaxSpeed { value: 100.0 },
        MaxRotationSpeed { value: 5.0 },
        LinearDamping::from(0.9),
        AngularDamping::from(0.9),
        SpaceCraft {},
    ));
}

fn spacecraft_local_vertical_movement(
    mut query: Query<(&mut LinearVelocity, &Transform, &MaxSpeed), With<SpaceCraft>>,
    mut spacecraft_action_reader: EventReader<SpaceCraftVerticalAction>,
    time: Res<Time>,
) {
    for event in spacecraft_action_reader.read() {
        for (mut linear_velocity, transform, max_speed) in query.iter_mut() {
            match event {
                SpaceCraftVerticalAction::VerticalMove(direction) => {
                    let spacecraft_direction = transform.up().normalize();
                    let spacecraft_direction2d =
                        Vec2::new(spacecraft_direction.x, spacecraft_direction.y);

                    linear_velocity.0 +=
                        spacecraft_direction2d * *direction * 20.0 * time.delta_seconds();
                }
            }
        }
    }
}

fn spacecraft_rotation(
    mut query: Query<(&mut AngularVelocity, &Transform, &MaxRotationSpeed), With<SpaceCraft>>,
    mut spacecraft_action_reader: EventReader<SpaceCraftHorizontalAction>,
    time: Res<Time>,
) {
    for event in spacecraft_action_reader.read() {
        for (mut angular_velocity, transform, max_rotation_speed) in query.iter_mut() {
            match event {
                SpaceCraftHorizontalAction::HorizontalMove(direction) => {
                    angular_velocity.0 +=
                        *direction * max_rotation_speed.value * time.delta_seconds();
                }
            }
        }
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant