2
\$\begingroup\$

I am trying to code some swooping behavior for a flying enemy in my 2D platformer.

The ideal behavior has the enemy starting from an arbitrary height above the ground, then accelerating downward and horizontally until flush with the ground, after which he slows and comes to a rest.

I would like to code this in such a way that I can adjust a parameter controlling the steepness of the curve.

In other words, I want a kind of asymptotic movement, similar to this:

enter image description here

https://www.mathsisfun.com/algebra/asymptote.html

How can I code this kind of movement in such a way that my enemy can start from any height and smoothly and elegantly accelerates down this kind of curve before gracefully stopping?

I have recourse to all the usual stuff (for example, acceleration, velocity, friction, raycasts, etc.). I would prefer to code the movement using this stuff, rather than hardcoding movement along a curve or path.

I was thinking it might be possible to achieve what I want by raycasting downward and getting the enemy's distance from the ground, and using this distance to adjust accelerations and velocities, but I'm not exactly sure how to go about it.

I work in Godot, but would like an engine-neutral explanation of how to achieve this kind of behavior.

\$\endgroup\$
2
\$\begingroup\$

The easiest way is probably using an exponential filter:

float target_height = 0.0f;
float current_height = 100.0f;
float smoothness = 0.95f;

void update() {
   current_height = smoothness * current_height +
                    (1.0f - smoothness) * target_height;
}

Notice that this is non-physical. If you must make use of physics, you can do this using a PD controller.

// Controls how fast the plant responds to the error.
float proportional_gain = -0.1f;
// Damps the response so that it doesn't overshoot the target.
float derivative_gain = -2.0f;
float current_height = 100.0f;
float target_height = 0.0f;
float prev_error = 0.0f;
float current_velocity = 0.0f;
float mass = 1.0f;

void update(float dt) {
    float error = current_height - target_height;
    float dError = (error - prev_error) / dt;
    float output = proportional_gain * error +
                   derivative_gain * dError;    
    prev_error = error;
    velocity += (output / mass) * dt;
    current_height += velocity * dt;
}

Output of the PD controller: Image of the output of PD control.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.