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/secrollSpeed(integer) — units/secpitchSpeed(float) — degrees/secmaxDownwardTilt(float) — radians/secminHeightAboveGround(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,
): FreeFlyCameraControllerBinds 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 drivegroundPlane(BGE.Math.Plane) — the plane clampAboveGround() keeps the camera abovecontrols(BGE.Controller.ControlMap) — read each update() for the move/look axesmoveAxis(string, optional, default: "\"move\"") — axis name bound (via controls.bindAxis()) to the left/drive sticklookAxis(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
input(BGE.GameInput)
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