Originally posted as answers in two other threads.
Simple follow camera with smooth camera panning.
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#
Simple orbit camera with basic camera collision
type tPlayer
objId
moveSpeed as float
endtype
type tCamera
distance as float
currentPitch as float
pitchRange as float
targetHeightOffset as float
collisionRadius as float
mouseSensitivity as float
endtype
// mouse movement vars
global gMouseDeltaX as float
global gMouseDeltaY as float
// create player
Player as tPlayer
Player.objId = CreateObjectBox(0.5,2.0,0.4)
Player.moveSpeed = 4.0
SetObjectPosition(Player.objId, 0, 1.0, 0)
FixObjectPivot(Player.objId)
SetObjectCollisionMode(Player.objId, 0)
// create camera
Camera as tCamera
Camera.distance = 4.0
Camera.pitchRange = 80.0
Camera.targetHeightOffset = 1.8
Camera.collisionRadius = 0.25
Camera.mouseSensitivity = 0.2
// create ground
oGround = CreateObjectPlane(30, 30)
SetObjectColor(oGround, 64, 128, 64, 255)
RotateObjectGlobalX(oGround,90)
FixObjectPivot(oGround)
// create some random boxes to test camera collision
for i = 0 to 10
height# = random(1,2)
b = CreateObjectBox(1, height#, 1)
SetObjectColor(b, 128, 64, 64, 255)
SetObjectPosition(b, random(0,20) - 10, height# / 2, random(0, 20) - 10)
next i
// display
SetWindowSize(1280,720,0)
SetVirtualResolution(1280,720)
SetSyncRate(60,1)
UseNewDefaultFonts(1)
// other setup
SetRawMouseVisible(0)
SetCameraRange(1,0.01,1000)
// main loop
while not GetRawKeyState(27)
delta# = GetFrameTime()
// calculate mouse delta
gMouseDeltaX = GetRawMouseX() - gMouseDeltaX
gMouseDeltaY = GetRawMouseY() - gMouseDeltaY
HandlePlayerMovement(Player, delta#)
HandleCamera(Camera, Player.objId, delta#)
HandlePlayerRotation(Player, delta#)
// re-center the mouse
SetRawMousePosition(GetVirtualWidth()/2, GetVirtualHeight()/2)
gMouseDeltaX = GetRawMouseX()
gMouseDeltaY = GetRawMouseY()
print("Move with WASD")
print("Mouse controls the camera")
sync()
endwhile
function HandlePlayerMovement(player ref as tPlayer, delta as float)
moveV# = GetRawKeyState(87) - GetRawKeyState(83)
moveH# = GetRawKeyState(68) - GetRawKeyState(65)
// normalize the movement vector if needed,
// so that speed is consistent in all directions
mag# = sqrt(moveV# * moveV# + moveH# * moveH#)
if mag# > 1.0
moveV# = moveV# / mag#
moveH# = moveH# / mag#
endif
MoveObjectLocalZ(player.objId, moveV# * player.moveSpeed * delta)
MoveObjectLocalX(player.objId, moveH# * player.moveSpeed * delta)
endfunction
function HandlePlayerRotation(player ref as tPlayer, delta as float)
// get camera forward vector on XZ plane
cOldX# = GetCameraX(1)
cOldY# = GetCameraY(1)
cOldZ# = GetCameraZ(1)
MoveCameraLocalZ(1,1)
cForwardX# = GetCameraX(1) - cOldX#
cForwardZ# = GetCameraZ(1) - cOldZ#
SetCameraPosition(1, cOldX#, cOldY#, cOldZ#)
// rotate player to camera orientation
SetObjectLookAt(player.objId, GetObjectX(player.objId) + cForwardX#, GetObjectY(player.objId), GetObjectZ(player.objId) + cForwardZ#, 0)
endfunction
function HandleCamera(camera ref as tCamera, targetObject, delta as float)
// store the target position
tx# = GetObjectX(targetObject)
ty# = GetObjectY(targetObject) + camera.targetHeightOffset
tz# = GetObjectZ(targetObject)
// position camera at target
SetCameraPosition(1, tx#, ty#, tz#)
// rotate camera on Y axis with mouse X
SetCameraRotation(1, 0, GetCameraAngleY(1) + gMouseDeltaX * camera.mouseSensitivity, 0)
// rotate camera on X axis with mouse Y
camera.currentPitch = camera.currentPitch + gMouseDeltaY * camera.mouseSensitivity
camera.currentPitch = ClampFloat(camera.currentPitch, -camera.pitchRange, camera.pitchRange)
RotateCameraLocalX(1, camera.currentPitch)
// move camera back by distance
MoveCameraLocalZ(1, -camera.distance)
// detect camera collision and move camera forward if needed
hit = ObjectSphereCast(0, tx#, ty#, tz#, GetCameraX(1), GetCameraY(1), GetCameraZ(1), camera.collisionRadius)
if hit
SetCameraPosition(1, GetObjectRayCastX(0), GetObjectRayCastY(0), GetObjectRayCastZ(0))
endif
endfunction
function ClampFloat(in as float, min as float, max as float)
if in < min then exitfunction min
if in > max then exitfunction max
endfunction in