0 votes

Hey guys! I've been trying to figure out how to make a 2d car with a top-down perspective drift, but i can't figure out how... If anyone could give me a hint as of how to do it, it would be very appreciated.

Thanks!

in Engine by (22 points)

1 Answer

+3 votes
Best answer

There are many ways to approach this, depending on how realistic you want to go. The most simple solution seems to be to start with a Rigidbody2D with an Asteroids-style control setup and use a force proportional to the orthogonal velocity to simulate tire friction. I wanted to test this so here's a basic setup:

extends RigidBody2D

var steering_com = 0.0
var force_com = 0.0

func _ready():
    set_process_input(true)
    set_fixed_process(true)
    var shape = RectangleShape2D.new()
    shape.set_extents(Vector2(8, 20))
    add_shape(shape)

func _fixed_process(delta):
    var tf = get_global_transform()
    var vel = get_linear_velocity()
#   get the orthogonal velocity vector
    var right_vel = tf.x * tf.x.dot(vel)
#   decrease the force in proportion to the velocity to stop endless acceleration
    var force = force_com - force_com * clamp(vel.length() / 400.0, 0.0, 1.0)
    var steering_torque = steering_com
    if tf.y.dot(vel) < 0.0:
#   if reversing, reverse the steering
        steering_torque = -steering_com
#   make reversing much slower
        if force_com <= 0.0:
            force *= 0.1
#   apply the side force, the lower this is the more the car slides
#   make the sliding depend on the power command somewhat
    apply_impulse(Vector2(), -right_vel * 0.07 * clamp(1.0 / abs(force), 0.01, 1.0))
#  
    apply_impulse(Vector2(), tf.basis_xform(Vector2(0, force)))
#   scale the steering torque with velocity to prevent turning the car when not moving
    set_applied_torque(steering_torque * vel.length() / 200.0)

I left out the input processing, but I used 8.0 and -12.0 for power (force_com) and -512 and 512 for steering (steering_com). Gravity scale is set to 0. The various constants can be tweaked to change the behavior of the car.
There's of course a lot you could do to make the car more fun/realistic to drive like tweaking the side-force and angular damping, smoothing the throttle when using a keyboard etc. At the very least you'd need to handle different road-surfaces somehow.
Maybe a more realistic approach would be to use one rigidbody for each wheel and one for the chassis, there's some Box2D examples that do this.

by (1,550 points)
selected by

Thank you so much for yout answer! I did indeed based my movement with an asteroid-like movement style, and I've found some info on this site : https://gamedev.stackexchange.com/questions/23093/creating-sideways-friction-in-a-2d-top-down-racer
but I'll look into your methode and try to make my movement feel just right

Hi Sir

can you revise your code to implement for area2d node

Would be great if someone could update this to 3.1, as I'm getting errors:

Method 'add_shape' is not declared in the current class

I also had to remove the set_fixed_process() call.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.