Birdseye View (or GTA style camera)

Trying to get the game camera to be a birds eye view and the player faces/turns where the cursor is. (sort of like Diablo or similar RPG games.

I tried CalcView but that just offset the camera like I had a stretched neck.

I’m fairly new to trying lua so don’t know what I should be looking for. I’ve looked in gamemodes with similar camera styles but I can’t find what I should be looking for. I’ve spent many hours now trying to find this in gamemodes and google. Please point me in the right direction and/or give examples.


In your CalcView, just change the angles as well as the position. Set the position high above the player, and set the angle’s pitch to 90 (or -90?).

I had a BITCH of a time getting this to work for a gamemode that I kinda gave up on. I’ll spread the wealth, all I ask is if you release you give credit.

PLEASE keep in mind that this was implemented in a FRETTA player class - it shouldn’t be too much work to switch it out of that but thats what I’m giving ya.

–These are simply functions to store the values for the traces calculated in calcview
–Makes it easier to access the tracepos in other files/functions
–To access a player use the following (example
–player:GetPlayerClass():GetData(player, “MPos”)
function CLASS:SetData( ply, key, val )
self.Data[ply] = self.Data[ply] or {}
self.Data[ply][key] = val

if CLIENT then
	RunConsoleCommand( "setdata", key, val )


function CLASS:GetData( ply, key )
if not CLASS.Data[ply] then return nil end
return CLASS.Data[ply][key] or 0

–This function is needed to adjust the angle for CalcView for widescreen resolutions
local function MPosAimVec(iScreenX,iScreenY,iScreenW,iScreenH,aCamRot,fFoV)
local fHalfWidth = iScreenW0.5;
local fHalfHeight = iScreenH
local d = fHalfWidth/math.tan(fFoV*0.5);

local vForward=aCamRot:Forward();
local vRight=aCamRot:Right();
local vUp=aCamRot:Up();

return (vForward*d + vRight*(iScreenX-fHalfWidth) + vUp*(fHalfHeight-iScreenY)):Normalize();


local view = { angles = Angle(45,180,0) }
local trace = {}
local angFixTrace = {}
function CLASS:CalcView( ply, pos, angles, fov )
local x, y, ang, sw, sh, hw, hh, mposx, mposy, ratio
mposx = gui.MouseX()
mposy = gui.MouseY()
sw = ScrW()
sh = ScrH()
ratio = sw/sh
hw = sw / 2
hh = sh / 2
x = hw - mposx
y = hh - mposy
ang = Angle( 0, math.deg( math.atan2( -y, x ) ) - 90, 0 )
ang:RotateAroundAxis(ang:Forward(), 45)

view.fov = fov

local fovFix = (math.atan(math.tan((fov * math.pi) / 360) * (ratio / (4/3) )) * 360) / math.pi
trace.start = view.origin
trace.endpos = trace.start + MPosAimVec(mposx, mposy, sw, sh, view.angles, math.rad(fovFix)) * 5000
trace.filter = ply
local tr = util.TraceLine(trace)
if not tr.Hit then return end
CLASS:SetData(ply, "MPos", tostring(tr.HitPos)) --The hitpos of the trace on the world
CLASS:SetData(ply, "MAimVec", tostring(tr.HitPos-ply:EyePos())) --AimVector from the player to the trace

return view


This might not be the best/easiest way to do it, but it works for me.

The only things wrong with it are the trace will hit things in between the “camera” and the player, so your trace can get mucked up if you don’t filter certain things.

[editline]19th February 2011[/editline]

That works for moving the camera but getting the player to aim where the mouse is pointing is a whole 'nother story xD