The smoothing can be done by interpolating between the player y angle and the camera's current y angle each frame before moving the camera back on it's z axis. Here's an example that uses a dummy object as the camera's "parent" (the interpolation is done on this object instead of the camera) and SetCameraLookAt() to point at the player.
type tPlayer
objId
moveSpeed as float
turnSpeed as float
endtype
type tCamera
dummyId
distance as float
height as float
lookHeight as float
smoothing as float
endtype
// display
SetWindowSize(1280, 720, 0)
SetVirtualResolution(1280, 720)
SetSyncRate(0, 1)
UseNewDefaultFonts(1)
// make player
Player as tPlayer
Player.objId = CreateObjectBox(0.5, 2.0, 0.4)
Player.moveSpeed = 2.0
Player.turnSpeed = 90.0
MoveObjectLocalY(Player.objId, 1.0)
FixObjectPivot(Player.objId)
// make camera
Camera as tCamera
Camera.dummyId = CreateObjectBox(1,1,1)
Camera.distance = 5.0
Camera.height = 2.0
Camera.lookHeight = 1.8
Camera.smoothing = 0.1 // this should be set between 0 and 1
SetObjectVisible(Camera.dummyId, 0)
// make ground
oGround = CreateObjectPlane(20, 20)
SetObjectColor(oGround, 64, 128, 64, 255)
RotateObjectGlobalX(oGround, 90)
FixObjectPivot(oGround)
do
delta# = GetFrameTime()
HandlePlayer(Player, delta#)
HandleCamera(Camera, Player.objId, delta#)
print("Move with WASD")
sync()
loop
function HandlePlayer(player ref as tPlayer, delta as float)
// handle rotation
turn# = (GetRawKeyState(68) - GetRawKeyState(65)) * player.turnSpeed * delta
RotateObjectGlobalY(player.objId, turn#)
// handle movement
move# = (GetRawKeyState(87) - GetRawKeyState(83)) * player.moveSpeed * delta
MoveObjectLocalZ(player.objId, move#)
endfunction
function HandleCamera(camera ref as tCamera, targetObject, delta as float)
// set camera dummy to target position
SetObjectPosition(camera.dummyId, GetObjectX(targetObject), GetObjectY(targetObject), GetObjectZ(targetObject))
// lerp the camera dummy y rotation smoothly to target y rotation.
// the 1.0 - pow(smoothing, delta) formula creates framerate indepenence
ylerp# = LerpAngle(GetObjectAngleY(camera.dummyId), GetObjectAngleY(targetObject), 1.0 - pow(camera.smoothing, delta))
SetObjectRotation(camera.dummyId, 0, ylerp#, 0)
// move camera dummy back by distance and up by height
MoveObjectLocalZ(camera.dummyId, -camera.distance)
MoveObjectLocalY(camera.dummyId, camera.height)
// position camera at dummy
SetCameraPosition(1, GetObjectX(camera.dummyId), GetObjectY(camera.dummyId), GetObjectZ(camera.dummyId))
// point camera at target + lookHeight
SetCameraLookAt(1, GetObjectX(targetObject), GetObjectY(targetObject) + camera.lookHeight, GetObjectZ(targetObject), 0)
endfunction
// Lerp between two angles, taking shortest path
function LerpAngle(a as float, b as float, t as float)
if abs(b-a) > 180
if b > a
a = a + 360
else
b = b + 360
endif
endif
l# = a + (b-a) * t
endfunction l#