How do I do a third person camera in the Game Engine?
# Third Person Camera - Made by Mobious

import bge
import math
import mathutils as mathu

# constants
# Feel free to tweak these.
SENSITIVITY = .003      # mouse sensitivity
S = .8                  # mouse smoothing
INV_X = 1               # invert x-axis
INV_Y = 1               # invert y-axis
MAX_DIST = 25.0         # maximum distance from player
MIN_DIST = 5            # minimum distance to obstacle or player
DRCAP = .5              # distance restore speed cap
RSMOOTH = 20            # camera range smoothing
FSMOOTH = RSMOOTH / 3   # front obstruction smoothing
ZSMOOTH = 13            # zoom smoothing
LRSMOOTH = 10           # camera LR smoothing
ZOOM_STEP = 1.3         # distance to zoom on mousewheel
Z_OFFSET = 1.0          # Z offset from player
HOR_OFFSET = 80.0        # Horizontal offset factor
MIN_ANGLE = math.pi/20  # minimum angle camera can be from verticle
PROP = 'block_camera'   # property that block camera

# Change 'Player' to whatever object you want the camera to track
scene = bge.logic.getCurrentScene()
player = scene.objects['Player']

# controls
ZoomIn = bge.events.WHEELUPMOUSE
ZoomOut = bge.events.WHEELDOWNMOUSE
ToggleLR = bge.events.MIDDLEMOUSE

def main():

    cont = bge.logic.getCurrentController()
    own = cont.owner

    mouse = cont.sensors['Mouse']
    rear = cont.sensors['rear']
    front = cont.sensors['front']

    # initialize vars
    if 'x' not in own:
        own['x'] = 0.0
        own['y'] = math.pi / 3
        own['dist'] = MAX_DIST
        x = bge.render.getWindowWidth() // 2
        y = bge.render.getWindowHeight() // 2
        own['size'] = (x,y)
        bge.render.setMousePosition(x,y)
        own['zoom'] = MAX_DIST
        own['oldx'] = 0.0
        own['oldy'] = 0.0
        rear.range = MAX_DIST
        front.range = MAX_DIST - MIN_DIST
        rear.propName = PROP
        front.propName = PROP
        own['LR'] = HOR_OFFSET
        own['LRinv'] = 1
        return

    # check and correct for camera obstructions using smoothing
    # obstacle in front of camera
    if front.positive:
        dist = own.getDistanceTo(front.hitPosition)
        if (own['dist'] - dist) &gt; MIN_DIST:
            own['dist'] -= (dist + MIN_DIST) / FSMOOTH

    # obstacle behind camera
    elif rear.positive:
        dist = own.getDistanceTo(rear.hitPosition)
        if dist &gt; MIN_DIST:
            if own['dist'] - own['zoom'] &lt; 0:
                own['dist'] += (dist - min(MIN_DIST, own['zoom'])) / RSMOOTH
        elif own.getDistanceTo(player) &gt; MIN_DIST:
            own['dist'] -= min(MIN_DIST - dist, own['dist'] - MIN_DIST) / RSMOOTH
    elif own['dist'] &lt; own['zoom']: # restore max distance
        dist = (own['zoom'] - own['dist'])
        own['dist'] += dist / ZSMOOTH
    if own['dist'] &gt; own['zoom']: # zoom in
        own['dist'] -= (own['dist'] - own['zoom']) / ZSMOOTH
    front.range = own['dist'] - MIN_DIST

    # mouse movement
    xpos = own['size'][0]
    ypos = own['size'][1]
    x = INV_X*(xpos - mouse.position[0])
    y = -INV_Y*(ypos - mouse.position[1])
    x *= SENSITIVITY
    y *= SENSITIVITY

    # smooth movement
    own['oldx'] = (own['oldx']*S + x*(1-S))
    own['oldy'] = (own['oldy']*S + y*(1-S))
    x = own['oldx']
    y = own['oldy']

    # center mouse in game window
    bge.render.setMousePosition(xpos,ypos)

    # zoom controls
    keys = bge.logic.mouse.events
    keys.update(bge.logic.keyboard.events)
    if keys[ZoomIn] and own['zoom'] &gt;= MIN_DIST + ZOOM_STEP:
        own['zoom'] -= ZOOM_STEP
    elif keys[ZoomOut] and own['zoom'] &lt;= MAX_DIST - ZOOM_STEP:
        own['zoom'] += ZOOM_STEP

    # update angles
    inv = False
    own['x'] += x
    own['y'] -= y

    if own['x'] &gt; math.pi:
        own['x'] -= 2*math.pi
        inv = True
    elif own['x'] &lt;= -2*math.pi:
        own['x'] += 2*math.pi
        inv = True
    if own['y'] &gt; math.pi - 2*MIN_ANGLE:
        own['y'] = math.pi - 2*MIN_ANGLE
    elif own['y'] &lt; 0.0 + MIN_ANGLE:
        own['y'] = 0.0 + MIN_ANGLE

    # LR toggling and smoothing
    if keys[ToggleLR] == 1:
        own['LRinv'] *= -1
    dist = own['LRinv']*HOR_OFFSET - own['LR']
    own['LR'] += dist / LRSMOOTH
    dist = own['LR'] / math.pow(own['dist'], 2)

    # calculate and set new camera position
    own['tdist'] = own['dist']*math.fabs(math.cos(math.pi/2 - own['y']))
    zshift = own['dist']*math.sin(math.pi/2 - own['y'])
    z = player.worldPosition[2] + zshift + Z_OFFSET
    yshift = own['tdist']*-math.cos(own['x'])
    y = player.worldPosition[1] + yshift + dist*math.sin(own['x'])
    xshift = own['tdist']*math.sin(own['x'])
    x = player.worldPosition[0] + xshift + dist*math.cos(own['x'])
    own.worldPosition = [x,y,z]

    #set new camera angle
    vec = mathu.Vector((own['y'], 0, own['x']))
    own.localOrientation = vec