Godot Version
4.7
Question
Hello! I was trying out something new (maybe not a great idea because I’m still a little new to programming in gdscript) and was trying to develop a game where the player is stalked by an NPC who follows them. I wanted the game to take place through the NPC’s eyes, making movement more difficult and tense for the player. However I was having trouble trying to make a basic camera which rotates toward the player- it will try to for the most part, but will also have trouble spinning in circles or will even try to look the other way.
I’m hoping to build something more basic, but let me know if this is something i might have to develop like an NPC AI for or something like that.
Most of the main code I put below, it’s attached to a camera on my stalker’s head:
func _process(delta: float) → void:
# the “target” is the player’s current position
# "get_parent() gets the parent node (in this case “watcher”)
# watcher’s XZ + the camera’s Y is the camera’s location
distance = (get_parent().position + position) - Globals.playerLocation
# direction changes whether it turns right or left (+1/-1)
direction.y = distance.x/abs(distance.x)
# there's distance.x, distance.y and distance.z
# use trig to calculate the angle (target) we need to rotate the camera
# calculate target.y (desired rotation around y axis)
if not distance.x == 0 and not distance.z == 0:
# arctangent (atan) of opposite over adjacent
# this is the equation to find the angle we need
# 180 / PI is what you need to multiply it by
# in order to convert angle from RADIANS to DEGREES
target.y = atan((distance.x)/(distance.z)) * (180/PI)
if target.y < 0:
target.y = 360.0 - target.y
# need_to_turn is how many degrees we need to turn
need_to_turn = round(target.y) - round(rotation_degrees.y)
# this alters need_to_turn so that the camera will take
# the shortest path to achieve target
if need_to_turn > 180:
need_to_turn = need_to_turn - 360
if need_to_turn < -180:
need_to_turn = need_to_turn + 360
# begin rotation around axis y
# I set it to the target +-10 so that it looks realistic and hopefully to get rid of more finicky effects that set in if it misses the target. Setting it exactly at the target, I had similar issues anyways
if round(rotation_degrees.y) >= (round(target.y) + 10) or round(rotation_degrees.y) <= (round(target.y) - 10):
# this makes the head turn faster if it's going to rotate further, or at least that's the idea. I haven't had a ton of issues with this part of the code, though I do wonder if there's a better way to write it
if abs(need_to_turn) > 90 and not speed_y >= 5.0:
speed_y += 0.1
if abs(need_to_turn) < 45 and not speed_y == 0.5:
speed_y -= 0.1
# This is to reset the rotation when it goes past 360 degrees. I had MORE issues before I implemented this, where the head would spin forever and hit like 400 degrees rotated... I still have issues after. Namely, I think there's an issue with my equations where the target would be at like 400 degrees needed to rotate, which of course my program can't reach since I disabled it.
if round(rotation_degrees.y) > 360:
rotation_degrees.y = 0.0
if round(rotation_degrees.y) < 0:
rotation_degrees.y = 360
rotation_degrees.y += (direction.y * speed_y)
If anyone knows of perhaps some better equations or shortcuts I could use, maybe something to help with the bugs, I would appreciate it! ![]()