Point n Click movement animation not working for negative coordinates

Godot Version

Godot Version 4.6.2

Question

I’m brand new to Godot, just went through the code tutorial program, and did the 2d and 3d game tutorials. Now I decided to try something simple on my own, a little 2 room point n click “game” just to test myself. I have the movement working great, but now I’m trying to animate the walk. Every time there’s a negative coordinate the animation just breaks, either gliding in the idle pose or gliding in the first frame of the animation. I have no idea why. I’m sure there’s something very obvious I’m missing. Also forgive me if the code is a bit sloppy, again brand new.

@export var speed = 100
var target = position
func _ready():
	$Playersprite.show()


func _input(event):
	if event is InputEventMouseButton:
		if event.button_index == MOUSE_BUTTON_LEFT and event.pressed:
			target = get_global_mouse_position()
 
func _physics_process(_delta: float):
	var direction: Vector2 = target - position
	velocity = position.direction_to(target) * speed
	if position.distance_to(target) > 1:
		move_and_slide()
		$Playersprite.hide()
	print (position)

	if direction.x > direction.y:
		moveright()
	else:
		movedown()
	if direction.y > direction.x:
		moveleft()
	else:
		moveup()
		
func movedown(): #function for walking down animation
	if target.y > position.y: 
		$MovementFrames.show()
		$MovementFrames.play("Walk_down", 1.0, false)
func moveup(): #function for walking up animation
		$MovementFrames.show()
		$MovementFrames.play("Walk_up", 1, false)
func moveright(): #function for walking to the right
	if target.x > position.x:
		$MovementFrames.show()
		$MovementFrames.play("Walk_right", 1, false)
func moveleft(): #function for walking to the left
	if position.x > target.x:
		$MovementFrames.show()
		$MovementFrames.play("Walk_left", 1, false)
	if target.y - position.y < 2 and target.x - position.x <2:
		$MovementFrames.hide()
		$Playersprite.show()

Your move functions are certainly strange with variations; I presume that’s left over from attempting fixes, so it’s best to keep them very similar, moveup is the best example I believe.

I’d recommend deducing which axis is greater first, this could be done with absolute values. Then which direction of that axis is moving

if absf(direction.y) > absf(direction.x): # moving up or down
    if direction.y > 0: # moving down (positive y)
        movedown()
    else: # moving up (negative y)
        moveup()
else: # moving left or right
    if direction.x > 0: # moving right
        moveright()
    else: # moving left
        moveleft()
1 Like

I tried copy\pasting that block into my script and now up, down, and right work, and it works for the most part, thank you for that. Is there a reason that both coordinates being negative i.e moving up and to the left together doesn’t call any of those functions?

Did you change your moveleft function to match how moveup works? Currently there are if statements inside of moveleft that would result in no action.

I made all the move functions identical. Now they all just change the sprite and play the animation. I took all the if statements out of those functions. I did just notice that in the script i posted that final if statement is inside the moveleft function, but that’s not the case anymore

What does your full script look like now? Moving up and to the left should call moveup, the sample prioritizes the Y axis first so holding two directions should net a moveup or movedown.

1 Like
extends CharacterBody2D

@export var speed = 100
var target = position
func _ready():
	$Playersprite.show()


func _input(event):
	if event is InputEventMouseButton:
		if event.button_index == MOUSE_BUTTON_LEFT and event.pressed:
			target = get_global_mouse_position()


func _physics_process(_delta: float):
	var direction: Vector2 = target - position
	
	velocity = position.direction_to(target) * speed
	
	if position.distance_to(target) > 1:
		move_and_slide()
		$Playersprite.hide()
	if absf(direction.y) > absf(direction.x): # moving up or down
		if direction.y > 0: # moving down (positive y)
			movedown()
		else: #moving up (negative y)
			moveup()
	else: # moving left or right
		if direction.x > 0: # moving right
			moveright()
		else: # moving left
			moveleft()
	if target.y - position.y < 2 and target.x - position.x < 2:
		$MovementFrames.hide()
		$Playersprite.show()
		
func movedown():
	$MovementFrames.show()
	$MovementFrames.play("Walk_down", 1, false)
func moveup():
	$MovementFrames.show()
	$MovementFrames.play("Walk_up", 1, false)
func moveright():
	$MovementFrames.show()
	$MovementFrames.play("Walk_right", 1, false)
func moveleft():
	$MovementFrames.show()
	$MovementFrames.play("Walk_left", 1, false)

Are there any errors or warnings?

No, everything runs fine except moving up/left. Frankly I’m more frustrated that I don’t know why than anything else

How did you determine the function isn’t being called? Could you add a print statement to moveup to double-check? Maybe it’s an animation problem rather than code

Maybe it is an animation issue. I did what you said, and also added one to moveleft. It does call both correctly, the animations just don’t play. I’ll have a look at the animations and SpriteFrames to see if there’s something there.

I think I found my problem line for the animation.

if target.y - position.y < 2 and target.x - position.x < 2:

I deleted that line, and now all the animations play. Granted, they don’t switch back to the idle sprite anymore but they all work. Now i just need to rephrase this line to accomplish the same thing without using the “<2” I think.

A right, you do have a distance check here, you could use else: or you could check that the distance is low.

1 Like

I tried both an else statement:

if position.distance_to(target) > 1:
		move_and_slide()
...
else:
        $MovementFrames.hide()
        $PlayerSprite.show()

I also tried making an idle function that did the same thing and had the else statement call it. Neither worked, and it just shows both sprites once the character reaches the destination. I did notice that for some reason the program is constantly calling moveleft. I went through all the “move” functions and had it print “1”, and they were all fine, only printing while moving. Except moveleft that prints constantly. All the syntax is identical, so why would it be doing that?

The else statements include when direction is equal to zero, you could wrap the block of code handling move functions in a big if not direction.is_zero_approx()

1 Like

so an elif statement? Or am I still missing something, I didn’t think you could include conditions in just an else statement

if not direction.is_zero_approx():
	if absf(direction.y) > absf(direction.x): # moving up or down
		if direction.y > 0: # moving down (positive y)
			movedown()
		else: #moving up (negative y)
			moveup()
	else: # moving left or right
		if direction.x > 0: # moving right
			moveright()
		else: # moving left
			moveleft()
1 Like

I think it’s working now, turns out I had something indented wrong and it was the root of all my troubles. Thank you so much for your help!

1 Like

Posting the actual functioning script in case anyone else needs it.

extends CharacterBody2D

@export var speed = 100
var target = position
func _ready():
	$Playersprite.show()
func movedown():
	$MovementFrames.show()
	$MovementFrames.play("Walk_down", 1, false)
func moveup():
	$MovementFrames.show()
	$MovementFrames.play("Walk_up", 1, false)
func moveright():
	$MovementFrames.show()
	$MovementFrames.play("Walk_right", 1, false)
func moveleft():
	$MovementFrames.show()
	$MovementFrames.play("Walk_left", 1, false)

func _input(event):
	if event is InputEventMouseButton:
		if event.button_index == MOUSE_BUTTON_LEFT and event.pressed:
			target = get_global_mouse_position()


func _physics_process(_delta: float):
	var direction: Vector2 = target - position
	velocity = position.direction_to(target) * speed
	
	if position.distance_to(target) > 1:
		move_and_slide()
		$Playersprite.hide()

		if absf(direction.y) > absf(direction.x): # moving up or down
			if direction.y > 0: # moving down (positive y)
				movedown()
			else: #moving up (negative y)
				moveup()
		else: # moving left or right
			if direction.x > 0: # moving right
				moveright()
			else:
				moveleft()
	else:
		$MovementFrames.hide()
		$Playersprite.show()