Weird Centripetal Force on KinematicBody2D during Circular Movement

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By scrubswithnosleeves

Hi All!

I am trying to write a script for player movement “orbiting” around a central point where left/right corresponds to orbiting around the point and up/down corresponds to moving towards/away from the point respectively. The following script mostly works, except there is some kind of centripetal force that pushes on the KinematicBody2D away from the point when orbiting (moving L/R). ie the force is perpendicular to the L/R movement. any ideas on what is causing this?

extends KinematicBody2D

var speed = 200

var velocity = Vector2.ZERO

func get_input():
	look_at(Vector2(144,144))
	velocity = Vector2()
	if Input.is_action_pressed("ui_left"):
		velocity = Vector2(0, -speed).rotated(rotation)
	if Input.is_action_pressed('ui_right'):
		velocity = Vector2(0, speed).rotated(rotation)
	if Input.is_action_pressed("ui_down"):
		velocity = Vector2(-speed, 0).rotated(rotation)
	if Input.is_action_pressed('ui_up'):
		velocity = Vector2(speed, 0).rotated(rotation)

func _physics_process(delta):
	get_input()
	move_and_slide(velocity)
:bust_in_silhouette: Reply From: p7f

you are aplying tangencial movement… Imagine you are on the edge of a circle, then you press left. So you will move speed*delta (because move_and_slide) in a linear direction tangencial to that circle. If you where just standing on the circle, that would mean that the next position must be off the circle, as you are moving in a linear direction.

If you want to move in orbit, you should change the angle with left/right, and change the length with up/down, and make a vector out of it.

extends KinematicBody2D

var angular_speed = 1
var normal_speed = 200

var angle = 0
var length = 500

var movement = Vector2.ZERO

func get_input(delta):
	look_at(Vector2(144,144))
	if Input.is_action_pressed("ui_left"):
		angle += angular_speed*delta
	if Input.is_action_pressed('ui_right'):
		angle -= angular_speed*delta
	if Input.is_action_pressed("ui_down"):
		length -= normal_speed*delta
	if Input.is_action_pressed('ui_up'):
		length += normal_speed*delta
	
	movement = Vector2.RIGHT.rotated(angle)*length

func _physics_process(delta):
	get_input(delta)
	global_position = movement

Or you could correct the position after moving, if you still want to use move_and_slide for collisions:

extends KinematicBody2D

var speed = 200

var velocity = Vector2.ZERO
var speed_vector = Vector2()

var previous_length = Vector2.ZERO

func get_input():
    look_at(Vector2(0,0))
    velocity = Vector2()
    speed_vector = Vector2()
    var previous_length = global_position.length()
    if Input.is_action_pressed("ui_left"):
   	    speed_vector = Vector2(0, -speed)
    if Input.is_action_pressed('ui_right'):
	    speed_vector = Vector2(0, speed)
    if Input.is_action_pressed("ui_down"):
	    speed_vector = Vector2(-speed, 0)
    if Input.is_action_pressed('ui_up'):
	    speed_vector = Vector2(speed, 0)
	
    velocity = speed_vector.rotated(rotation)

 func _physics_process(delta):
     get_input()
     move_and_slide(velocity)
     if speed_vector.x != 0:
	    previous_length = global_position.length()
     else:
       	global_position = global_position.normalized()*previous_length