extends Spatial # Lets the user drive the node it's added to with typical flycam controls # # This script should be used on the camera node (or a parent of it) and # allows the player to fly around the scene. Good for debugging and # for graphics demos. # ----------------------------------------------------------------------------- # Limits within which the camera can be moved # Can be set to null to remove all limits export var Boundaries = AABB( Vector3(-10.0, -10.0, -10.0), # Minimum corner Vector3(20.0, 20.0, 20.0) # Size ) # How quickly the camera will move in units per second export var MovementUnitsPerSecond = 3.0 # How quickly the camera will rotate in degrees per mouse mickey # (a mickey being the smallest position change the mouse will report) export var RotationDegreesPerMickey = 0.1 # Whether the player can exit the game by hitting escape # (convenience feature since this script is likely to be used just to view scenes) export var AllowQuitByEscape = true # ----------------------------------------------------------------------------- # Called every frame to advance the simulation by the amount of time passed # @param delta Time that has passed since the last frame in seconds func _process(delta): var movementInput = getMovementInput() movementInput *= delta #translate(currentTransform.basis.xform(movementInput)) translate(movementInput) # it's already doing local translation! limitMovementToBoundaries() # ----------------------------------------------------------------------------- # Called whenever an input event occurs # @param event Details about the input the player has performed func _input(event): if event is InputEventMouseMotion: var eulerAngles = get_rotation() var yawRotation = deg2rad( event.relative.x * -self.RotationDegreesPerMickey ) var pitchRotation = deg2rad( event.relative.y * -self.RotationDegreesPerMickey ) # Apply yaw rotation, unroll into 0 .. 2PI (360 degree) range eulerAngles.y = fmod(eulerAngles.y + yawRotation, PI * 2.0) # Apply pitch rotation, clamp at straight up / straight down # (I stay 0.01 units from the limits because flipping over would # make get_rotation() return 180 degree yaw, i.e. sudden spin) eulerAngles.x = clamp( eulerAngles.x + pitchRotation, -PI / 2.0 + 0.01, +PI / 2.0 - 0.01 ) set_rotation(eulerAngles) if self.AllowQuitByEscape: if event is InputEventKey: if event.pressed && (event.scancode == KEY_ESCAPE): get_tree().quit() # ----------------------------------------------------------------------------- # Called when the scene tree is entered func _enter_tree(): Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED); # ----------------------------------------------------------------------------- # Called when the scene tree is exited func _exit_tree(): Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE); # ----------------------------------------------------------------------------- # Restricts the position of the node to the configured boundaries func limitMovementToBoundaries(): var position = transform.origin var boundsMin = self.Boundaries.position var boundsMax = self.Boundaries.end position.x = clamp(position.x, boundsMin.x, boundsMax.x) position.y = clamp(position.y, boundsMin.y, boundsMax.y) position.z = clamp(position.z, boundsMin.z, boundsMax.z) transform.origin = position # ----------------------------------------------------------------------------- # Reads the movement keys to build the user's desired movement vector # @returns The movement desired by the user func getMovementInput(): var movementInput = Vector3(0.0, 0.0, 0.0) if Input.is_key_pressed(KEY_W): movementInput.z -= self.MovementUnitsPerSecond if Input.is_key_pressed(KEY_S): movementInput.z += self.MovementUnitsPerSecond if Input.is_key_pressed(KEY_A): movementInput.x -= self.MovementUnitsPerSecond if Input.is_key_pressed(KEY_D): movementInput.x += self.MovementUnitsPerSecond if Input.is_key_pressed(KEY_Q): movementInput.y -= self.MovementUnitsPerSecond if Input.is_key_pressed(KEY_E): movementInput.y += self.MovementUnitsPerSecond return movementInput