Greetings,

I am searching for 2-3 days on internet how to make my ship stop more naturally and every solution that I found didn't work. I know that when keys are released a velocity.length should go to 0 but somehow I can't figure out what formula to put and where.
Here is the code:

``````extends KinematicBody2D
export (int) var speed = 500
export (float) var rotation_speed = 1.5
export (float) var friction = 0.65

var velocity = Vector2()
var rotation_dir = 0
var acc = Vector2()
var pos = Vector2()

pass

func _physics_process(delta):
rotation_dir = 0
velocity = Vector2(0, 0)

if Input.is_action_pressed('right'):
rotation_dir += 1
if Input.is_action_pressed('left'):
rotation_dir -= 1
if Input.is_action_pressed('up'):
acc = Vector2(0, -speed).rotated(rotation)
elif Input.is_action_pressed('down'):
acc = Vector2(0, speed).rotated(rotation)
else:
acc = Vector2(0, 0)

velocity += acc * delta
pos += velocity
rotation += rotation_dir * rotation_speed * delta

move_and_slide(pos, Vector2(0, 0))
``````

I've tried adding after "else:" velocity*= pow(friction, delta) but it only made it faster.
If You could help me I would be very thankful because this is very frustrating not to find a solution for, I believe, very simple problem.

in Engine

Firction is a force that depends on the normal force (gravity * mass if on horizontal plane) multiplied by a friction coefficient. If it's a top-down game, i would directly define the friction acceleration, and each time, i would make the difference between that and the acc you calculated. However, you must have in mind that when the objects slows down too much, the object stops and the friction dissappears, so on each step you could ask if velocity is under some threshold and then set friction to 0. Something like this could work:

``````extends KinematicBody2D
export (int) var speed = 500
export (float) var rotation_speed = 1.5
export (float) var friction = 100

var velocity = Vector2()
var rotation_dir = 0
var speed_thresh = 50
var acc = Vector2()
var pos = Vector2()
pass

func _physics_process(delta):
rotation_dir = 0
# i don't think you should reset velocity if you are trying to get an accelerated movement. I'll comment this ouyt
#velocity = Vector2(0, 0)

if Input.is_action_pressed('right'):
rotation_dir += 1
if Input.is_action_pressed('left'):
friction = 100
rotation_dir -= 1
if Input.is_action_pressed('up'):
friction = 100
acc = Vector2(0, -speed).rotated(rotation)
elif Input.is_action_pressed('down'):
acc = Vector2(0, speed).rotated(rotation)
else:
acc = Vector2(0, 0)

# Difference between acc and friction. Rotate rotation+180 is for making opposite vectors
acc += Vector2(0,friction).rotaed(rotation+180)
velocity += acc * delta
if abs(velocity.y) < speed_thresh and abs(velocity.x) < speed_thresh:
velocity = 0
friction = 0

#Don't know why you accumulate in pos every frame. I would just use velocity
#pos += velocity
rotation += rotation_dir * rotation_speed * delta

move_and_slide(velocity, Vector2(0, 0))
``````

I cannot try this right now cause i'm not at home. But let me know if it does not work and i'll try to make it right

If you put this after your move_ and_ slide the script will work nicely:

``````pos = pos.linear_interpolate(Vector2(0,0), friction * delta)
``````

Funny, huh? The pos variable is doing what your velocity is supposed to do. Here's a corrected script:

``````extends KinematicBody2D
export (int) var speed = 500
export (float) var rotation_speed = 1.5
export (float) var friction = 0.65

var velocity = Vector2()
var rotation_dir = 0
var acc = Vector2()

pass

func _physics_process(delta):
rotation_dir = 0

if Input.is_action_pressed('right'):
rotation_dir += 1
if Input.is_action_pressed('left'):
rotation_dir -= 1
if Input.is_action_pressed('up'):
acc = Vector2(0, -speed).rotated(rotation)
elif Input.is_action_pressed('down'):
acc = Vector2(0, speed).rotated(rotation)
else:
acc = Vector2(0, 0)

velocity += acc * delta
rotation += rotation_dir * rotation_speed * delta

move_and_slide(velocity, Vector2(0, 0))

velocity = velocity.linear_interpolate(Vector2(0,0), friction * delta)
``````

I removed the pos variable since it's not needed, and I removed the part where you set velocity to zero, and I added the last line that does the friction part.

by (154 points)
selected by

I'm sorry for such a late respond but I didn't have time for project because of college duties. This solution is working PERFECTLY, thank You very much. I didn't know such a simple one line of code could be answer to my problem.