FreeFlyCameraController

A reusable free-fly camera control scheme: yaw/pitch relative to the camera's current (roll-adjusted) orientation, strafe/drive, roll, and a ground-plane clamp so driving forward can't cross the ground. Not a GameEntity - a GameScene (or any owner) constructs one and forwards its own onInput/onUpdate calls to it. Extracted from examples/terrain's original FreeFlyCameraController (issue #148); that example now layers its own scene-switching/debug-toggle/hint-text glue on top of this.

Movement/look are read each frame from a BGE.Controller.ControlMap's move/look axes (see update()), not from onInput() - a connected dual-stick controller drives full strafe+drive / yaw+pitch, and with no real second stick, both axes fall back to the same remote/simulator source, so the single physical d-pad turns and drives exactly as it always has (see update()'s regime check).

Properties

  • camera (BGE.Camera3d)
  • groundPlane (BGE.Math.Plane)
  • turnSpeed (float)
  • driveSpeed (integer) — radians/sec
  • rollSpeed (integer) — units/sec
  • pitchSpeed (float) — degrees/sec
  • maxDownwardTilt (float) — radians/sec
  • minHeightAboveGround (float) — radians (~69 degrees)
  • lastInput (BGE.GameInput) — 1 = pitching up, 1 = pitching down, 0 = not pitching

Constructor

new FreeFlyCameraController( camera: BGE.Camera3d, groundPlane: BGE.Math.Plane, controls: BGE.Controller.ControlMap, moveAxis?: string, lookAxis?: string, ): FreeFlyCameraController

Binds to this specific camera instance for its lifetime - it does not re-resolve the active camera from Game/Renderer each frame like some example code does. If the consumer later calls Game.setCamera() with a different camera, this controller keeps driving the one it was built with; construct a new controller for the new camera.

Parameters

  • camera (BGE.Camera3d) — the camera to drive
  • groundPlane (BGE.Math.Plane) — the plane clampAboveGround() keeps the camera above
  • controls (BGE.Controller.ControlMap) — read each update() for the move/look axes
  • moveAxis (string, optional, default: "\"move\"") — axis name bound (via controls.bindAxis()) to the left/drive stick
  • lookAxis (string, optional, default: "\"look\"") — axis name bound (via controls.bindAxis()) to the right/look stick

Instance Methods

onInput(input: BGE.GameInput): void

Forward a GameScene/GameEntity's own onInput() call here. Tracks roll/pitch direction from the "replay"/"l1" (roll left), "options"/"r1" (roll right) and "rewind"/"fastforward" (pitch) buttons, and resets roll/pitch to their initial values on "play". Movement/turning is not read here - see update().

Parameters

Returns

  • void

update(dt: float): void

Forward a GameScene/GameEntity's own onUpdate() call here. Reads the move/look axes (see class doc comment for the dual-stick-vs-fallback regime), applies strafe/drive/yaw/pitch to the camera, plus any active roll and button-driven pitch.

Parameters

  • dt (float) — seconds since the last frame

Returns

  • void

setInitialPitch(radians: float): void

Sets the controller's starting pitch (radians, same sign convention as the internal pitch accumulator) and resets the camera to face straight down -z before applying it - both an initial setup call and the "play" button's reset use this, so the internal accumulator and the actually-applied rotation never drift apart the way they would if a caller rotated camera.orientation directly without seeding the accumulator to match (the pitch clamp would then only bound input on top of an untracked offset, and "play" would reset to level instead of back to this default).

Parameters

  • radians (float)

Returns

  • void

clampAboveGround(candidate: BGE.Math.Vector): BGE.Math.Vector

Pushes a candidate camera position back above the ground plane by at least minHeightAboveGround, along the plane's own normal - keeps the camera from flying through the ground regardless of the plane's orientation.

Parameters

  • candidate (BGE.Math.Vector)

Returns

  • BGE.Math.Vector