2d sprite point towards player

Godot Version



Hi! I’m trying to get a 2d enemy face the player at all times. I’m using a 2d sprite that changes frame depending on where the player is.


So far so good - only there should be a straight invisible line between the center of the player (good old Godot icon) and the centre of the black circle via the red dot. Think of the red dot as an eye looking at the player.

For the most part it’s nearly there. However, the upper right quadrant (12 to 3 on a clockface) is not right at all.

Here’s the enemy.gd script

class_name Enemy_test extends Area2D

@onready var p = get_node("/root/main/player")

func _process(_delta):
	var numFrames = 16
	var angle = rotate_to_target(p)

	var f = int(angle/numFrames) +4 
	# +4 to offset the rotation not starting at 0° = Up, 90° = East

	if f >= numFrames or f <= 0:
		f = int( f % numFrames)
	print(str(int(angle))  + "° Frame: " + str(f)) 
	$Sprite2D.frame = f

func rotate_to_target (target):
	var dir = (target.global_position - global_position)
	var angle = rad_to_deg($Sprite2D.transform.x.angle_to(dir))
	if angle >= 360 or angle <= 0: 
		angle = fposmod(angle,360.0) 
	return angle

I can include the project if needed.

Thanks for any help.

I believe you could use helper functions more effectively, like angle_to_point, and I believe your angle to frame range is off. to convert from angle we need to divide by 360° (or TAU) and multiply by our maximum frames.

func _process(_delta):
	var numFrames = 16
	var angle = global_position.angle_to_point(target.global_position)
	var f = int(angle * numFrame / TAU) +4 
	f %= numFrames # no need to if modulus

Of course rotating the sprite also seems like a good idea, but I suppose you have your reasons for using frames instead.

Angle to point works like a dream, but sadly f goes negative with that so I fixed it with

f = (f % numFrames + numFrames) % numFrames

Thanks for your help!

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.