(Yet another) Terrain Algorithm

Don’t know Resident Evil 4, sorry, but this is what I use as camera code most of the time. It’s a combined third-person/first-person camera, with tracking (follows the NP movement, but slightly delayed).

Switching from first-person to third-person mode and back is done by setting the camera distance. If the distance is the minimum distance the code swaps to first-person. SetDistance could be tied e.g. to the mouse wheel.

Oh, and call tracking.updateMethod( ) once a frame to move the camera.

enn0x

class Tracking:

    def __init__( self, np ):
        self.np = np

        self.resilience = 8.0
        self.pitch = 0.0
        self.distance = 10.0

        self.updateMethod = self.updateThirdPerson

        self.target = render.attachNewNode( 'cameraTarget' )
        self.target.reparentTo( self.np )
        self.target.setPos( 0, 0, 0.8 )

        self.tracking = render.attachNewNode( 'cameraTracking' )
        self.tracking.reparentTo( render )
        self.tracking.setPos( self.target, 0, 0, 0 )

        base.camera.reparentTo( self.tracking )
        base.camera.setPos( 0, -self.distance, 0 )
        base.camera.lookAt( 0, 0, 0 )

    def release( self ):
        self.target.removeNode( )
        self.tracking.removeNode( )

        base.camera.reparentTo( render )

    def setPitch( self, delta ):
        self.pitch += delta
        self.pitch = clampScalar( self.pitch, -70.0, 70.0 )

    def setCameraDistance( self, factor ):
        self.distance *= factor
        self.distance = clampScalar( self.distance, 2.0, 400.0 )

        if self.distance == 2.0:
            self.updateMethod = self.updateFirstPerson
            base.camera.setPos( 0, 0, 0 )
            self.np.hide( )
        else:
            self.updateMethod = self.updateThirdPerson
            base.camera.setPos( 0, -self.distance, 0 )
            self.np.show( )

    def updateThirdPerson( self, dt ):
        dt2 = min( dt * self.resilience, 0.4 )
        t = self.target.getTransform( self.tracking )

        deltaPos = t.getPos( ) * dt2
        self.tracking.setPos( self.tracking, deltaPos )

        deltaH = t.getHpr( )[0] * dt2
        self.tracking.setH( self.tracking.getH( ) + deltaH )
        self.tracking.setP( self.pitch )

    def updateFirstPerson( self, dt ):
        self.tracking.setPos( self.target, 0, 0, 0 )

        self.tracking.setH( self.np.getH( ) )
        self.tracking.setP( self.pitch )