Castle Game Engine: CastleCameras: Class TWalkCamera

# Class TWalkCamera
Description | Hierarchy | Fields | Methods | Properties
## Unit CastleCameras ## Declaration `type TWalkCamera = class(TCamera)` ## Description Navigation by walking (first-person-shooter-like moving) in 3D scene. Camera is defined by it's position, looking direction and up vector, user can rotate and move camera using various keys. ## Hierarchy TComponent TInputListener TCamera TWalkCamera ## Overview ### Fields
| `internal const DefaultFallSpeedStart = 0.5;`
| `internal const DefaultGrowSpeed = 1.0;`
| `internal const DefaultHeadBobbing = 0.02;`
| `internal const DefaultCrouchHeight = 0.5;`
| `internal const DefaultJumpMaxHeight = 1.0;`
| `internal const DefaultMinAngleRadFromGravityUp = Pi / 18;`
| `internal const DefaultRotationHorizontalSpeed = 150;`
| `internal const DefaultRotationVerticalSpeed = 100;`
| `internal const DefaultFallSpeedIncrease = 13/12;`
| `internal const DefaultMouseLookHorizontalSensitivity = 0.09;`
| `internal const DefaultMouseLookVerticalSensitivity = 0.09;`
| `internal const DefaultHeadBobbingTime = 0.5;`
| `internal const DefaultJumpHorizontalSpeedMultiply = 2.0;`
| `internal const DefaultJumpTime = 1.0 / 8.0;`
| `internal const DefaultMouseDraggingHorizontalRotationSpeed = 0.1;`
| `internal const DefaultMouseDraggingVerticalRotationSpeed = 0.1;`
### Methods
| `procedure Height(const APosition: TVector3Single; out AIsAbove: boolean; out AnAboveHeight: Single; out AnAboveGround: P3DTriangle); virtual;`
| `constructor Create(AOwner: TComponent); override;`
| `destructor Destroy; override;`
| `function Matrix: TMatrix4Single; override;`
| `function RotationMatrix: TMatrix4Single; override;`
| `procedure Update(const SecondsPassed: Single; var HandleInput: boolean); override;`
| `function AllowSuspendForInput: boolean; override;`
| `function Press(const Event: TInputPressRelease): boolean; override;`
| `function SensorTranslation(const X, Y, Z, Length: Double; const SecondsPassed: Single): boolean; override;`
| `function SensorRotation(const X, Y, Z, Angle: Double; const SecondsPassed: Single): boolean; override;`
| `function DoMoveAllowed(const ProposedNewPos: TVector3Single; out NewPos: TVector3Single; const BecauseOfGravity: boolean): boolean; virtual;`
| `function DirectionInGravityPlane: TVector3Single;`
| `procedure Init(const AInitialPosition, AInitialDirection, AInitialUp: TVector3Single; const AGravityUp: TVector3Single; const APreferredHeight: Single; const ARadius: Single); overload;`
| `procedure Init(const box: TBox3D; const ARadius: Single); overload;`
| `function Motion(const Event: TInputMotion): boolean; override;`
| `procedure CorrectPreferredHeight;`
| `procedure CancelFalling;`
| `function MaxJumpDistance: Single;`
| `function RealPreferredHeight: Single;`
| `procedure FallOnTheGround;`
| `procedure GetView(out APos, ADir, AUp: TVector3Single); override;`
| `procedure GetView(out APos, ADir, AUp, AGravityUp: TVector3Single); override;`
| `function GetPosition: TVector3Single; override;`
| `function GetGravityUp: TVector3Single; override;`
| `procedure SetView(const ADir, AUp: TVector3Single; const AdjustUp: boolean = true);`
| `procedure SetView(const APos, ADir, AUp: TVector3Single; const AdjustUp: boolean = true); override;`
| `procedure SetView(const APos, ADir, AUp, AGravityUp: TVector3Single; const AdjustUp: boolean = true); override;`
| `function GetNavigationType: TNavigationType; override;`
| `procedure UpPrefer(const AUp: TVector3Single);`
### Properties
| `property OnMoveAllowed: TMoveAllowedFunc read FOnMoveAllowed write FOnMoveAllowed;`
| `property Position : TVector3Single read FPosition write SetPosition;`
| `property Direction: TVector3Single read FDirection write SetDirection;`
| `property Up : TVector3Single read FUp write SetUp;`
| `property GravityUp: TVector3Single read FGravityUp write SetGravityUp;`
| `property PreferGravityUpForRotations: boolean read FPreferGravityUpForRotations write FPreferGravityUpForRotations default true;`
| `property PreferGravityUpForMoving: boolean read FPreferGravityUpForMoving write FPreferGravityUpForMoving default true;`
| `property MinAngleRadFromGravityUp: Single read FMinAngleRadFromGravityUp write FMinAngleRadFromGravityUp default DefaultMinAngleRadFromGravityUp;`
| `property MouseLook: boolean read FMouseLook write SetMouseLook default false;`
| `property MouseLookHorizontalSensitivity: Single read FMouseLookHorizontalSensitivity write FMouseLookHorizontalSensitivity default DefaultMouseLookHorizontalSensitivity;`
| `property MouseLookVerticalSensitivity: Single read FMouseLookVerticalSensitivity write FMouseLookVerticalSensitivity default DefaultMouseLookVerticalSensitivity;`
| `property InvertVerticalMouseLook: boolean read FInvertVerticalMouseLook write FInvertVerticalMouseLook default false;`
| `property MouseDragMode: TMouseDragMode read FMouseDragMode write FMouseDragMode default mdWalk;`
| `property Gravity: boolean read FGravity write FGravity default false;`
| `property PreferredHeight: Single read FPreferredHeight write FPreferredHeight default 0.0;`
| `property ClimbHeight: Single read FClimbHeight write FClimbHeight;`
| `property OnHeight: THeightEvent read FOnHeight write FOnHeight;`
| `property OnFall: TFallNotifyFunc read FOnFall write FOnFall;`
| `property FallSpeedStart: Single read FFallSpeedStart write FFallSpeedStart default DefaultFallSpeedStart;`
| `property FallSpeedIncrease: Single read FFallSpeedIncrease write FFallSpeedIncrease default DefaultFallSpeedIncrease;`
| `property Falling: boolean read FFalling write FFalling;`
| `property FallingEffect: boolean read FFallingEffect write FFallingEffect default true;`
| `property GrowSpeed: Single read FGrowSpeed write FGrowSpeed default DefaultGrowSpeed;`
| `property JumpMaxHeight: Single read FJumpMaxHeight write FJumpMaxHeight default DefaultJumpMaxHeight;`
| `property IsJumping: boolean read FIsJumping;`
| `property JumpHorizontalSpeedMultiply: Single read FJumpHorizontalSpeedMultiply write FJumpHorizontalSpeedMultiply default DefaultJumpHorizontalSpeedMultiply;`
| `property JumpTime: Single read FJumpTime write FJumpTime default DefaultJumpTime;`
| `property HeadBobbing: Single read FHeadBobbing write FHeadBobbing default DefaultHeadBobbing;`
| `property HeadBobbingTime: Single read FHeadBobbingTime write FHeadBobbingTime default DefaultHeadBobbingTime;`
| `property CrouchHeight: Single read FCrouchHeight write FCrouchHeight default DefaultCrouchHeight;`
| `property IsCrouching: boolean read FIsCrouching;`
| `property FallingOnTheGround: boolean read FFallingOnTheGround;`
| `property IsOnTheGround: boolean read FIsOnTheGround;`
| `property IsWalkingOnTheGround: boolean read FIsWalkingOnTheGround;`
| `property IsAbove: boolean read FIsAbove;`
| `property AboveHeight: Single read FAboveHeight;`
| `property AboveGround: P3DTriangle read FAboveGround write FAboveGround;`
| `property Input_Forward: TInputShortcut read FInput_Forward;`
| `property Input_Backward: TInputShortcut read FInput_Backward;`
| `property Input_LeftRot: TInputShortcut read FInput_LeftRot;`
| `property Input_RightRot: TInputShortcut read FInput_RightRot;`
| `property Input_LeftStrafe: TInputShortcut read FInput_LeftStrafe;`
| `property Input_RightStrafe: TInputShortcut read FInput_RightStrafe;`
| `property Input_UpRotate: TInputShortcut read FInput_UpRotate;`
| `property Input_DownRotate: TInputShortcut read FInput_DownRotate;`
| `property Input_IncreasePreferredHeight: TInputShortcut read FInput_IncreasePreferredHeight;`
| `property Input_DecreasePreferredHeight: TInputShortcut read FInput_DecreasePreferredHeight;`
| `property Input_GravityUp: TInputShortcut read FInput_GravityUp;`
| `property Input_Run: TInputShortcut read FInput_Run;`
| `property Input_MoveSpeedInc: TInputShortcut read FInput_MoveSpeedInc;`
| `property Input_MoveSpeedDec: TInputShortcut read FInput_MoveSpeedDec;`
| `property Input_Jump: TInputShortcut read FInput_Jump;`
| `property Input_Crouch: TInputShortcut read FInput_Crouch;`
| `property MoveForward: boolean read FMoveForward write FMoveForward;`
| `property MoveBackward: boolean read FMoveBackward write FMoveBackward;`
| `property AllowSlowerRotations: boolean read FAllowSlowerRotations write FAllowSlowerRotations default true;`
| `property CheckModsDown: boolean read FCheckModsDown write FCheckModsDown default true;`
| `property MoveHorizontalSpeed: Single read FMoveHorizontalSpeed write FMoveHorizontalSpeed default 1.0;`
| `property MoveVerticalSpeed: Single read FMoveVerticalSpeed write FMoveVerticalSpeed default 1.0;`
| `property MoveSpeed: Single read FMoveSpeed write FMoveSpeed default 1.0;`
| `property RotationHorizontalSpeed: Single read FRotationHorizontalSpeed write FRotationHorizontalSpeed default DefaultRotationHorizontalSpeed;`
| `property RotationVerticalSpeed: Single read FRotationVerticalSpeed write FRotationVerticalSpeed default DefaultRotationVerticalSpeed;`
| `property MouseDraggingHorizontalRotationSpeed: Single read FMouseDraggingHorizontalRotationSpeed write FMouseDraggingHorizontalRotationSpeed default DefaultMouseDraggingHorizontalRotationSpeed;`
| `property MouseDraggingVerticalRotationSpeed: Single read FMouseDraggingVerticalRotationSpeed write FMouseDraggingVerticalRotationSpeed default DefaultMouseDraggingVerticalRotationSpeed;`
| `property RotationHorizontalPivot: Single read FRotationHorizontalPivot write FRotationHorizontalPivot default 0;`
## Description ### Fields
| `internal const DefaultFallSpeedStart = 0.5;`
| `internal const DefaultGrowSpeed = 1.0;`
| `internal const DefaultHeadBobbing = 0.02;`
| `internal const DefaultCrouchHeight = 0.5;`
| `internal const DefaultJumpMaxHeight = 1.0;`
| `internal const DefaultMinAngleRadFromGravityUp = Pi / 18;`
| `internal const DefaultRotationHorizontalSpeed = 150;`
| `internal const DefaultRotationVerticalSpeed = 100;`
| `internal const DefaultFallSpeedIncrease = 13/12;`
| `internal const DefaultMouseLookHorizontalSensitivity = 0.09;`
| `internal const DefaultMouseLookVerticalSensitivity = 0.09;`
| `internal const DefaultHeadBobbingTime = 0.5;`
| `internal const DefaultJumpHorizontalSpeedMultiply = 2.0;`
| `internal const DefaultJumpTime = 1.0 / 8.0;`
| `internal const DefaultMouseDraggingHorizontalRotationSpeed = 0.1;`
| `internal const DefaultMouseDraggingVerticalRotationSpeed = 0.1;`
### Methods
| `procedure Height(const APosition: TVector3Single; out AIsAbove: boolean; out AnAboveHeight: Single; out AnAboveGround: P3DTriangle); virtual;`
Call OnHeight callback.
| `constructor Create(AOwner: TComponent); override;`
| `destructor Destroy; override;`
| `function Matrix: TMatrix4Single; override;`
| `function RotationMatrix: TMatrix4Single; override;`
| `procedure Update(const SecondsPassed: Single; var HandleInput: boolean); override;`
| `function AllowSuspendForInput: boolean; override;`
| `function Press(const Event: TInputPressRelease): boolean; override;`
| `function SensorTranslation(const X, Y, Z, Length: Double; const SecondsPassed: Single): boolean; override;`
| `function SensorRotation(const X, Y, Z, Angle: Double; const SecondsPassed: Single): boolean; override;`
| `function DoMoveAllowed(const ProposedNewPos: TVector3Single; out NewPos: TVector3Single; const BecauseOfGravity: boolean): boolean; virtual;`
`DoMoveAllowed` will be used when user will move in the scene, i.e. when user will want to change Position. ProposedNewPos is the position where the user wants to move (current user position is always stored in Position, so you can calculate move direction by ProposedNewPos - Position). This is the place to "plug in" your collision detection into camera. Returns false if no move is allowed. Otherwise returns true and sets NewPos to the position where user should be moved. E.g. if you're doing a simple test for collisions (with yes/no results), you will always want to set NewPos to ProposedNewPos when returning true. But you can also do more sophisticated calculations and sometimes not allow user to move to ProposedNewPos, but allow him to move instead to some other close position. E.g. look what's happening in quake (or just any first-person 3d game) when you're trying to walk "into the wall" at angle like 30 degrees: you're blocked, i.e. you obviously can't walk into the wall, but your position changes a bit and you're slowly moving alongside the wall. That's how you can use NewPos: you can return true and set NewPos to something that is not exactly ProposedNewPos (but is close to ProposedNewPos). Note that it's allowed to modify NewPos when returning false. This is meaningless, but may be comfortable for implementor of `DoMoveAllowed`. BecauseOfGravity says whether this move is caused by gravity dragging the camera down. Can happen only if Gravity is `True`. You can use BecauseOfGravity to control `DoMoveAllowed` behavior — e.g. view3dscene will not allow camera to move lower that some minimal plane when BecauseOfGravity (because this would mean that camera falls down infinitely), on the other hand when BecauseOfGravity is `False` moving outside bounding box is allowed (to allow camera to look at the scene from "the outside"). Basic implementation of `DoMoveAllowed` in this class: If OnMoveAllowed = nil then returns true and sets NewPos to ProposedNewPos (so move is always allowed). Else calls OnMoveAllowed.
| `function DirectionInGravityPlane: TVector3Single;`
Return Direction vector rotated such that it is orthogonal to GravityUp. This way it returns Direction projected on the gravity horizontal plane, which neutralizes such things like raising / bowing your head. Result is always normalized (length 1). Note that when Direction and GravityUp are parallel, this just returns current Direction — because in such case we can't project Direction on the horizontal plane.
| `procedure Init(const AInitialPosition, AInitialDirection, AInitialUp: TVector3Single; const AGravityUp: TVector3Single; const APreferredHeight: Single; const ARadius: Single); overload;`
Set the most important properties of this camera, in one call. Sets initial camera properties (InitialPosition, InitialDirection, InitialUp), sets current camera properties to them (Position := InitialPosition and so on). Given here AInitialDirection, AInitialUp, AGravityUp will be normalized, and AInitialUp will be adjusted to be orthogonal to AInitialDirection (see SetInitialView). Sets also PreferredHeight and Radius. PreferredHeight may be adjusted to be sensible (by calling CorrectPreferredHeight(ARadius)). You can pass ARadius = 0.0 if you really don't want this PreferredHeight adjustment.
| `procedure Init(const box: TBox3D; const ARadius: Single); overload;`
Alternative Init that sets camera properties such that an object inside Box is more or less "visible good". Sets InitialCameraXxx properties to make it look right, sets current CameraXxx properties to InitialCameraXxx. Sets GravityUp to the same thing as InitialUp. Sets also PreferredHeight to make it behave "sensibly".
| `function Motion(const Event: TInputMotion): boolean; override;`
| `procedure CorrectPreferredHeight;`
This procedure corrects PreferredHeight based on your Radius and on current HeadBobbing. Exactly what and why is done: if you do any kind of collision detection with some Radius, then you should make sure that RealPreferredHeight is always >= of your Radius, otherwise strange effects may happen when crouching or when head bobbing forces camera to go down. Exactly, the required equation is
      MinimumRealPreferredHeight :=
        PreferredHeight * CrouchHeight * (1 - HeadBobbing);
and always must be
      MinimumRealPreferredHeight >= RealPreferredHeight
Reasoning: otherwise this class would "want camera to fall down" (because we will always be higher than RealPreferredHeight) but your OnMoveAllowed would not allow it (because Radius would not allow it). Note that this class doesn't keep value of your Radius, because collision detection is (by design) never done by this class — it's always delegated to OnHeight and OnMoveAllowed. Also, it's not exactly forced how you should force this condition to hold. Sometimes the good solution is to adjust Radius, not to adjust PreferredHeight. Anyway, this method will make sure that this condition holds by eventually adjusting (making larger) PreferredHeight. Note that for Radius = 0.0 this will always leave PreferredHeight as it is.
| `procedure CancelFalling;`
If Falling, then this will force Falling to false without calling OnFallenDown. It's much like forcing the opinion that "camera is not falling down right now". Of course, if in the nearest Update we will find out (using OnHeight) that camera is too high above the ground, then we will start falling down again, setting Falling back to true. (but then we will start falling down from the beginning, starting at given Position and with initial falling down speed). This is useful to call if you just changed Position because e.g. the player teleported somewhere (or e.g. game levels changed). In this case you just want to forget the fact that camera was falling down — no consequences (like lowering player's health, fadeout etc.).
| `function MaxJumpDistance: Single;`
Returns just JumpMaxHeight * PreferredHeight, see JumpMaxHeight for explanation.
| `function RealPreferredHeight: Single;`
This is PreferredHeight slightly modified by head bobbing and crouch. It can be useful for collision detection between camera and something.
| `procedure FallOnTheGround;`
This makes a visual effect of camera falling down horizontally on the ground. Nice to use when player died, and you want to show that it's body falled on the ground. This works by gradually changing Up such that it gets orthogonal to GravityUp.
| `procedure GetView(out APos, ADir, AUp: TVector3Single); override;`
| `procedure GetView(out APos, ADir, AUp, AGravityUp: TVector3Single); override;`
| `function GetPosition: TVector3Single; override;`
| `function GetGravityUp: TVector3Single; override;`
| `procedure SetView(const ADir, AUp: TVector3Single; const AdjustUp: boolean = true);`
| `procedure SetView(const APos, ADir, AUp: TVector3Single; const AdjustUp: boolean = true); override;`
| `procedure SetView(const APos, ADir, AUp, AGravityUp: TVector3Single; const AdjustUp: boolean = true); override;`
| `function GetNavigationType: TNavigationType; override;`
| `procedure UpPrefer(const AUp: TVector3Single);`
Change up vector, keeping the direction unchanged. If necessary, the up vector provided here will be fixed to be orthogonal to direction. See T3DOrient.UpPrefer for detailed documentation what this does.
### Properties
| `property OnMoveAllowed: TMoveAllowedFunc read FOnMoveAllowed write FOnMoveAllowed;`
This is used by DoMoveAllowed, see there for description.
| `property Position : TVector3Single read FPosition write SetPosition;`
Camera position, looking direction and up vector. Initially (after creating this object) they are equal to InitialPosition, InitialDirection, InitialUp. Also Init and GoToInitial methods reset them to these initial values. The Direction and Up vectors should always be normalized (have length 1). When setting them by these properties, we will normalize them automatically. Note that since engine >= 2.2.0 the Direction vector should always be normalized (length 1), and so you cannot change move speed by scaling this vector. Use MoveSpeed, MoveHorizontalSpeed, MoveVerticalSpeed instead. When setting Direction, Up will always be automatically adjusted to be orthogonal to Direction. And vice versa — when setting Up, Direction will be adjusted.
| `property Direction: TVector3Single read FDirection write SetDirection;`
| `property Up : TVector3Single read FUp write SetUp;`
| `property GravityUp: TVector3Single read FGravityUp write SetGravityUp;`
This is the upward direction of the world in which player moves. Must be always normalized (when setting this property, we take care to normalize it). This indicates how Gravity works. This is also the "normal" value for both Up and InitialUp — one that means that player is looking straight foward. This is used for features like PreferGravityUpForRotations and/or PreferGravityUpForMoving. The default value of this vector is (0, 1, 0) (same as the default InitialUp and Up vectors).
| `property PreferGravityUpForRotations: boolean read FPreferGravityUpForRotations write FPreferGravityUpForRotations default true;`
If `PreferGravityUpForRotations` or PreferGravityUpForMoving then various operations are done with respect to GravityUp, otherwise they are done with respect to current Up. With `PreferGravityUpForRotations`, this affects rotations: horizontal rotations (Input_LeftRot and Input_RightRot) and rotations caused by MouseLook. Also vertical rotations are bounded by MinAngleRadFromGravityUp when `PreferGravityUpForRotations`. Note that you can change it freely at runtime, and when you set `PreferGravityUpForRotations` from `False` to `True` then in nearest Update calls Up will be gradually fixed, so that Direction and Up and GravityUp are on the same plane. Also Direction may be adjusted to honour MinAngleRadFromGravityUp. With PreferGravityUpForMoving, this affects moving: horizontal moving (forward, backward, strafe), and vertical moving (Input_Jump and Input_Crouch when Gravity is `False`). E.g. when PreferGravityUpForMoving then forward/backward keys are tied to horizontal plane defined by GravityUp. When not PreferGravityUpForMoving then forward/backward try to move you just in the Direction. Which is usually more handy when e.g. simulating flying. It's a delicate decision how to set them, because generally all the decisions are "somewhat correct" — they just sometimes "feel incorrect" for player. First of all, if the scene is not "naturally oriented" around GravityUp, then you may set `PreferGravityUpForRotations` as `False` and you should leave PreferGravityUpForMoving and Gravity to `False`. By the scene "naturally oriented around GravityUp" I mean that we have some proper GravityUp, not just some guessed GravityUp that may be incorrect. For example when view3dscene loads a VRML model without any camera definition then it assumes that "up vector" is (0, 1, 0), because this is more-or-less VRML standard suggested by VRML spec. But this may be very inappopriate, for example the scene may be actually oriented with (0, 0, 1) up vector in mind. Other examples of the scenes without any "naturally oriented around GravityUp" may be some "outer space" scene without any gravity. With `PreferGravityUpForRotations` the "feeling" of GravityUp is stronger for user, because GravityUp, Up and Direction always define the same plane in 3D space (i.e. along with the 4th point, (0, 0, 0), for camera eye). Raising/bowing the head doesn't break this assumption. Without `PreferGravityUpForRotations`, we quickly start to do rotations in an awkward way — once you do some vertical rotation, you changed Up, and next horizontal rotation will be done versus new Up. If your GravityUp is good, then you generally should leave `PreferGravityUpForRotations` to `True`. Unless you really want the player to feel movements as "awkward", e.g. when you want to simulate this "outer space without any gravity" feeling. If your GravityUp is good, then you generally should set PreferGravityUpForMoving just like Gravity. E.g. when the player is flying / swimming etc. he will probably prefer PreferGravityUpForMoving = `False`, because this way he will not have to press Input_Jump and Input_Crouch. Simply pressing Input_Forward and Input_Backward and doing rotations will be enough to move freely in 3D space. When gravity works, PreferGravityUpForMoving = `True` is better, otherwise player would unnecessarily try to jump when looking up.
| `property PreferGravityUpForMoving: boolean read FPreferGravityUpForMoving write FPreferGravityUpForMoving default true;`
| `property MinAngleRadFromGravityUp: Single read FMinAngleRadFromGravityUp write FMinAngleRadFromGravityUp default DefaultMinAngleRadFromGravityUp;`
This sets the minimal angle (in radians) between GravityUp and Direction, and also between -GravityUp and Direction. This way vertical rotations (like Input_UpRotate, Input_DownRotate) are "bounded" to not allow player to do something strange, i.e. bow your head too much and raise your head too much. This is used only when PreferGravityUpForRotations is `True` and when it's <> 0.0. This must be always between 0 and Pi/2. Value of Pi/2 will effectively disallow vertical rotations (although you should rather do this in a "cleaner way" by calling MakeClear on Input_UpRotate and Input_DownRotate).
| `property MouseLook: boolean read FMouseLook write SetMouseLook default false;`
Use mouse look to navigate (rotate the camera). This also makes mouse cursor of Container hidden, and forces mouse position to the middle of the window (to avoid the situation when mouse movement is blocked by screen borders).
| `property MouseLookHorizontalSensitivity: Single read FMouseLookHorizontalSensitivity write FMouseLookHorizontalSensitivity default DefaultMouseLookHorizontalSensitivity;`
These control mouse look sensitivity. They say how much angle change is produced by moving mouse by 1 pixel. You can change this, to better adjust to user.
| `property MouseLookVerticalSensitivity: Single read FMouseLookVerticalSensitivity write FMouseLookVerticalSensitivity default DefaultMouseLookVerticalSensitivity;`
| `property InvertVerticalMouseLook: boolean read FInvertVerticalMouseLook write FInvertVerticalMouseLook default false;`
If this is `True` and MouseLook works, then the meaning of vertical mouse movement is inverted: when user moves mouse up, he looks down. Many players are more comfortable with such configuration, and many games implement it (usually by calling it "Invert mouse" for short).
| `property MouseDragMode: TMouseDragMode read FMouseDragMode write FMouseDragMode default mdWalk;`
What mouse dragging does. Used only when ciMouseDragging in Input.
| `property Gravity: boolean read FGravity write FGravity default false;`
This unlocks a couple of features and automatic behaviors related to gravity. Gravity always drags the camera down to -GravityUp. Summary of things done by gravity: It uses OnHeight to get camera height above the ground. It allows player to jump. See Input_Jump, IsJumping, JumpMaxHeight, JumpHorizontalSpeedMultiply. It allows player to crouch. See Input_Crouch, CrouchHeight. It tries to keep Position above the ground on PreferredHeight height. When current height is too small — Position is moved up. See GrowSpeed. When current height is too large — we're falling down. See Falling, OnFall, FallSpeedStart, FallSpeedIncrease, FallingEffect. It does head bobbing. See HeadBobbing, HeadBobbingTime. While there are many properties allowing you to control gravity behavior, most of them have initial values that should be sensible in all cases. The only things that you really want to take care of are: OnHeight and PreferredHeight. Everything else should basically work auto-magically. Note that Gravity setting is independent from PreferGravityUpForRotations or PreferGravityUpForMoving settings — PreferGravityUpXxx say how the player controls work, Gravity says what happens to player due to ... well, due to gravity.
| `property PreferredHeight: Single read FPreferredHeight write FPreferredHeight default 0.0;`
When Gravity is on, Position tries to stay `PreferredHeight` above the ground. Temporary it may be lower (player can shortly "duck" when he falls from high). This must always be >= 0. You should set this to something greater than zero to get sensible behavior of some things related to Gravity, and also you should set OnHeight. See CorrectPreferredHeight for important property of `PreferredHeight` that you should keep.
| `property ClimbHeight: Single read FClimbHeight write FClimbHeight;`
The tallest height that you can climb. This is checked in each single horizontal move when Gravity works. Must be >= 0. Value 0 means there is no limit (and makes a small speedup). This is reliable to prevent user from climbing stairs and such, when vertical walls are really vertical (not just steep-almost-vertical). It's not 100% reliable to prevent player from climbing steep hills. That's because, depending on how often an event processing occurs, you actually climb using less or more steps. So even a very steep hill can be always climbed on a computer with very fast speed, because with large FPS you effectively climb it using a lot of very small steps (assuming that FPS limit is not enabled, that is CastleWindow.TCastleApplication.LimitFPS or CastleControl.LimitFPS is zero). Remember that user can still try jumping to climb on high obstactes. See JumpMaxHeight for a way to control jumping. For a 100% reliable way to prevent user from reaching some point, that does not rely on specific camera/gravity settings, you should build actual walls in 3D (invisible walls can be created by Collision.proxy in VRML/X3D).
| `property OnHeight: THeightEvent read FOnHeight write FOnHeight;`
Assign here the callback (or override Height) to say what is the current height of camera above the ground. This should be calculated like collision of ray from Position in direction -GravityUp with the scene. See T3D.Height for specification what returned parameters mean. Implementation of Height in this class calls `OnHeight`, if assigned. (If not assigned, we assume no collision: IsAbove = `False`, AboveHeight = MaxSingle, AboveGround = `Nil`).
| `property OnFall: TFallNotifyFunc read FOnFall write FOnFall;`
Notification that we have been falling down for some time, and suddenly stopped (which means we "hit the ground"). Of course this is used only when Gravity is `True` (it can also be called shortly after you changed Gravity from `True` to `False`, so don't simply assert here that Gravity is `True`). This event can be useful in games, for example to lower player's health, and/or make a visual effect (like a "red out" indicating pain) and/or make a sound effect ("Ouch!" or "Thud!" or such sounds). You can look at FallHeight parameter, given to the callback, e.g. to gauge how much health decreases.
| `property FallSpeedStart: Single read FFallSpeedStart write FFallSpeedStart default DefaultFallSpeedStart;`
Initial speed of falling down. Of course this is used only when Gravity is true. Note that while falling down, the camera will actually fall with greater and greated speed (this adds more realism to the gravity effect...). Note that this is always relative to Direction length. Direction determines moving speed — and so it determines also falling speed. The default DefaultFallSpeedStart is chosen to be something sensible, to usually get nice effect of falling. You can change it at any time, but note that if you change this while Falling is `True`, then you will not change the "current falling down speed". You will change only the falling down speed used the next time.
| `property FallSpeedIncrease: Single read FFallSpeedIncrease write FFallSpeedIncrease default DefaultFallSpeedIncrease;`
When falling down, the speed increases. Set this to 1.0 to fall down with constant speed (taken from FallSpeedStart).
| `property Falling: boolean read FFalling write FFalling;`
Are we currently falling down because of gravity.
| `property FallingEffect: boolean read FFallingEffect write FFallingEffect default true;`
Make a nice dizzying camera effect when falling down. This adds temporary camera rotations simulating that you rotate randomly and helplessly when falling down. Of course this is meaningfull only when Gravity works. Note that changing it from `True` to `False` doesn't immediately "cancel out" this effect if it's currently in progress. It only prevents this effect from starting again.
| `property GrowSpeed: Single read FGrowSpeed write FGrowSpeed default DefaultGrowSpeed;`
When Gravity works and camera height above the ground is less than PreferredHeight, then we try to "grow", i.e. camera position increases along the GravityUp so that camera height above the ground is closer to PreferredHeight. This property (together with length of Direction, that always determines every moving speed) determines the speed of this growth.
| `property JumpMaxHeight: Single read FJumpMaxHeight write FJumpMaxHeight default DefaultJumpMaxHeight;`
How high can you jump ? The max jump distance is calculated as `JumpMaxHeight` * PreferredHeight, see MaxJumpDistance.
| `property IsJumping: boolean read FIsJumping;`
Camera is in the middle of a "jump" move right now.
| `property JumpHorizontalSpeedMultiply: Single read FJumpHorizontalSpeedMultiply write FJumpHorizontalSpeedMultiply default DefaultJumpHorizontalSpeedMultiply;`
Scales the speed of horizontal moving during jump.
| `property JumpTime: Single read FJumpTime write FJumpTime default DefaultJumpTime;`
How fast do you jump up. This is the time, in seconds, in takes to reach MaxJumpDistance height when jumping.
| `property HeadBobbing: Single read FHeadBobbing write FHeadBobbing default DefaultHeadBobbing;`
When you move horizontally, you get "head bobbing" effect — camera position slightly changes it's vertical position, going a little up, then a little down, then a little up again etc. This property mutiplied by PreferredHeight says how much head bobbing can move you along GravityUp. Set this to 0 to disable head bobbing. This must always be < 1.0. For sensible effects, this should be rather close to 0.0. Of course this is meaningfull only when Gravity works.
| `property HeadBobbingTime: Single read FHeadBobbingTime write FHeadBobbingTime default DefaultHeadBobbingTime;`
Controls head bobbing frequency. In the time of `HeadBobbingTime` seconds, we do full head bobbing sequence (camera swing up, then down again). Note that if you do a footsteps sound in your game (see stPlayerFootstepsDefault or TMaterialProperty.FootstepsSound) then you will want this property to match your footsteps sound length, things feel and sound natural then. Also, often it sounds better to record two footsteps inside a single sound file, in which case the footstep sound length should be twice as long as this property. For example, record 2 steps inside a 1-second long footstep sound, and set this property to 0.5 a second (which is a default in fact).
| `property CrouchHeight: Single read FCrouchHeight write FCrouchHeight default DefaultCrouchHeight;`
This defines the preferred height of camera when crouching. This is always mutiplied to PreferredHeight. This should always be <= 1 (`CrouchHeight` = 1 effectively disables crouching, although it's better to do this by calling MakeClear on Input_Crouch).
| `property IsCrouching: boolean read FIsCrouching;`
Is player crouching right now.
| `property FallingOnTheGround: boolean read FFallingOnTheGround;`
`True` when the effect caused by FallOnTheGround is stil in motion.
| `property IsOnTheGround: boolean read FIsOnTheGround;`
This is `True` when gravity works (that is Gravity is `True`), and player is standing stable on the ground. This is set in every Update. You can use this e.g. to make some effects when player is on some special ground (standing or walking), e.g. hurt player when he's standing on some toxical ground. ###### See also IsWalkingOnTheGround This is `True` when gravity works (that is Gravity is `True`), and player is standing stable on the ground, and player is moving horizontally.
| `property IsWalkingOnTheGround: boolean read FIsWalkingOnTheGround;`
This is `True` when gravity works (that is Gravity is `True`), and player is standing stable on the ground, and player is moving horizontally. In other words, this is like "IsOnTheGround and (s)he's walking". This is set in every Update. The intention is that you can use this to make some "footsteps" sound for the player.
| `property IsAbove: boolean read FIsAbove;`
Last known information about whether camera is over the ground. Updated by using Height call. For normal TCamera descendants, this means using OnHeight callback. These are updated only when Height is continously called, which in practice means: only when Gravity is `True`. We do not (and, currently, cannot) track here if AboveGround pointer will be eventually released (which may happen if you release your 3D scene, or rebuild scene causing octree rebuild). This is not a problem for camera class, since we do not use this pointer for anything. But if you use this pointer, then you may want to take care to eventually set it to `Nil` when your octree or such is released.
| `property AboveHeight: Single read FAboveHeight;`
| `property AboveGround: P3DTriangle read FAboveGround write FAboveGround;`
| `property Input_Forward: TInputShortcut read FInput_Forward;`
| `property Input_Backward: TInputShortcut read FInput_Backward;`
| `property Input_LeftRot: TInputShortcut read FInput_LeftRot;`
| `property Input_RightRot: TInputShortcut read FInput_RightRot;`
| `property Input_LeftStrafe: TInputShortcut read FInput_LeftStrafe;`
| `property Input_RightStrafe: TInputShortcut read FInput_RightStrafe;`
| `property Input_UpRotate: TInputShortcut read FInput_UpRotate;`
| `property Input_DownRotate: TInputShortcut read FInput_DownRotate;`
| `property Input_IncreasePreferredHeight: TInputShortcut read FInput_IncreasePreferredHeight;`
| `property Input_DecreasePreferredHeight: TInputShortcut read FInput_DecreasePreferredHeight;`
| `property Input_GravityUp: TInputShortcut read FInput_GravityUp;`
| `property Input_Run: TInputShortcut read FInput_Run;`
| `property Input_MoveSpeedInc: TInputShortcut read FInput_MoveSpeedInc;`
Change the MoveSpeed.
| `property Input_MoveSpeedDec: TInputShortcut read FInput_MoveSpeedDec;`
| `property Input_Jump: TInputShortcut read FInput_Jump;`
Jumping and crouching (when Gravity = `True`) or flying up / down (when Gravity = `False`).
| `property Input_Crouch: TInputShortcut read FInput_Crouch;`
| `property MoveForward: boolean read FMoveForward write FMoveForward;`
Move forward, just like Input_Forward would be pressed.
| `property MoveBackward: boolean read FMoveBackward write FMoveBackward;`
Move backward, just like Input_Backward would be pressed.
| `property AllowSlowerRotations: boolean read FAllowSlowerRotations write FAllowSlowerRotations default true;`
If `True` then all rotation keys (Input_RightRot, Input_LeftRot, Input_UpRotate, Input_DownRotate) will work 10x slower when Ctrl modified is pressed.
| `property CheckModsDown: boolean read FCheckModsDown write FCheckModsDown default true;`
Do we check what key modifiers are pressed and do something differently based on it? If `True` then all keys work only when no modifiers or only shift are pressed. Additionally when Ctrl is pressed (and AllowSlowerRotations) then rotation keys work 10x slower. Also Increase/DecreasePreferredHeight work only when Ctrl pressed. Other keys with other modifiers don't work. We allow shift, because to press character "+" on non-numpad keyboard (useful on laptops, where numpad is difficult) you probably need to press shift. If `False` then all keys work as usual, no matter what modifiers are pressed. And rotation keys never work 10x slower (AllowSlowerRotations is ignored), also Increase/DecreasePreferredHeight are ignored.
| `property MoveHorizontalSpeed: Single read FMoveHorizontalSpeed write FMoveHorizontalSpeed default 1.0;`
Moving speeds. `MoveHorizontalSpeed` is only for horizontal movement, MoveVerticalSpeed is only for vertical, and MoveSpeed simply affects both types of movement. Effectively, we always scale the speed of movement by either ``MoveHorizontalSpeed` * MoveSpeed` or `MoveVerticalSpeed * MoveSpeed`. We move by distance `MoveSpeed * `MoveHorizontalSpeed` (or MoveVerticalSpeed)` during one second. Assuming "normal circumstances", namely that SecondsPassed provided to Update method is expressed in seconds (which is the case, when you use camera as TCastleSceneManager.Camera). So if you leave `MoveHorizontalSpeed` = MoveVerticalSpeed = 1 (as default), MoveSpeed expresses the speed in nice units / per second. Default values for all these speed properties is 1.0, so you simply move by 1 unit per second.
| `property MoveVerticalSpeed: Single read FMoveVerticalSpeed write FMoveVerticalSpeed default 1.0;`
| `property MoveSpeed: Single read FMoveSpeed write FMoveSpeed default 1.0;`
| `property RotationHorizontalSpeed: Single read FRotationHorizontalSpeed write FRotationHorizontalSpeed default DefaultRotationHorizontalSpeed;`
Rotation keys speed, in degrees per second.
| `property RotationVerticalSpeed: Single read FRotationVerticalSpeed write FRotationVerticalSpeed default DefaultRotationVerticalSpeed;`
| `property MouseDraggingHorizontalRotationSpeed: Single read FMouseDraggingHorizontalRotationSpeed write FMouseDraggingHorizontalRotationSpeed default DefaultMouseDraggingHorizontalRotationSpeed;`
Speed (degrees per pixel delta) of rotations by mouse dragging. Relevant only if ciMouseDragging in Input, and MouseDragMode is mdRotate. Separate for horizontal and vertical, this way you can e.g. limit (or disable) vertical rotations, useful for games where you mostly look horizontally and accidentally looking up/down is more confusing than useful.
| `property MouseDraggingVerticalRotationSpeed: Single read FMouseDraggingVerticalRotationSpeed write FMouseDraggingVerticalRotationSpeed default DefaultMouseDraggingVerticalRotationSpeed;`
| `property RotationHorizontalPivot: Single read FRotationHorizontalPivot write FRotationHorizontalPivot default 0;`
Horizontal rotation can rotate around a vector that is `RotationHorizontalPivot` units forward before the camera. This is a poor-mans way to implement some 3rd camera game. Note that when non-zero this may (for now) move the camera without actually checking OnMoveAllowed.
Generated by PasDoc 0.13.0 on 2015-06-15 04:43:09