Moving Physics

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

Iam new to programming and I am trying to make a 2D RPG farming game and i made some coding for player movement but when you run to a side and forexample click down, it starts drifting like a car and won’t change it’s position and will keep drifting slowly. I don’t know how to fix it, is it because of godot or something i need to code? If it is something i need to code, i might need some help.

How does your scene tree look like? Which node-types are you using? How do your scripts look like? Just from that description alone nobody will be able to help you…

njamster | 2020-05-08 16:20

As i said, i am new and i looked from a few videos and wanted to play with a bit, please don’t judge me
these are my nodes : Screenshot by Lightshot

extends KinematicBody2D

export (int) var speed = 20
var motion = Vector2(0, 0)

var moving = false
var animPlayer
var movement
var speedMultiplier = 8

func runleft(delta):
    motion.x -= speed * delta

func runright(delta):
    motion.x += speed * delta

func runup(delta):
    motion.y -= speed * delta

func rundown(delta):
    motion.y += speed * delta



func _ready():
    animPlayer = get_node("AnimationPlayer")
    set_physics_process(true)


func _physics_process(delta):
    ApplyMovement(delta)

func ApplyMovement(deltaTime):
    var LEFT = Input.is_action_pressed("ui_left")
    var RIGHT = Input.is_action_pressed("ui_right")
    var UP = Input.is_action_pressed("ui_up")
    var DOWN = Input.is_action_pressed("ui_down")
    if LEFT:
       	runleft(deltaTime)
       	moving = true
	       CheckMovementLoop()
    
elif RIGHT: 
	runright(deltaTime)
	moving = true
	CheckMovementLoop()

elif UP:
	runup(deltaTime)
	moving = true
	CheckMovementLoop()
	
elif DOWN: 
	rundown(deltaTime)
	moving = true
	CheckMovementLoop()
	
elif !LEFT or !RIGHT or !UP or !DOWN:
	moving = false
	CheckMovementLoop()
	
    move_and_collide(motion.normalized() * speed * speedMultiplier * deltaTime)

func CheckMovementLoop():
    if moving:
	    if !motion.is_normalized():
		    match motion.normalized():
			    Vector2.LEFT:
				    movement = "walk_left"
				    animPlayer.play(movement, -speedMultiplier)
			    Vector2.RIGHT:
				    movement = "walk_right"
				    animPlayer.play(movement, -speedMultiplier)
			    Vector2.UP:
				    movement = "walk_up"
				    animPlayer.play(movement, -speedMultiplier)
			    Vector2.DOWN:
				    movement = "walk_down"
				    animPlayer.play(movement, -speedMultiplier)
    elif !moving:
	    motion.x = 0
	    motion.y = 0
	    match movement:
		    "walk_left":
		    	animPlayer.play("idle_left")
		    "walk_right":
			    animPlayer.play("idle_right")
		    "walk_up":
			    animPlayer.play("idle_up")
    		    "walk_down":
	            animPlayer.play("idle_down")

Buffyz | 2020-05-08 18:48

:bust_in_silhouette: Reply From: njamster

In your ApplyMovement- method you first check if the player is pressing “ui_left|right” and only when that’s not the case you check if the player is pressing “ui_up|down”. So if you press and hold “ui_right” your KinematicBody2D will move to the right, so far so good! If you now start holding down “ui_up” as well nothing will change, the body still moves to the right as you check that first. However, if you now release “ui_right”, the character will not stop moving to the right but instead will move right and down now. I assume that’s what you mean by “drifting like a car”. Why? Because you never reset motion.x to 0! That only happens in CheckMovementLoop if none of the arrow keys is pressed. That never happened though: first we pressed “ui_right”, then “ui_right” and “ui_up” at once, then only “ui_up”. Now that we know what’s happening, let’s fix it:

if LEFT:
    ...
    motion.y = 0
elif RIGHT: 
    ...
    motion.y = 0
elif UP:
    ...
    motion.x = 0
elif DOWN: 
    ...
    motion.x = 0
else:
    ...

This preserves the importance of inputs (LEFT > RIGHT > UP > DOWN), but fixes the “drifting” by resetting the motion on the axis not concerned by the current input. Note that one cannot move diagonally with that, if you want to you’d need to do this:

if LEFT:
    ...
elif RIGHT: 
    ...
else:
    motion.x = 0

if UP:
    ...
elif DOWN: 
    ...
else:
    motion.y = 0