Gallery/player.gd
2025-05-03 12:00:38 -06:00

174 lines
5.8 KiB
GDScript

extends CharacterBody3D
# Movement settings
@export var speed: float = 5.0
@export var jump_force: float = 10.0
@export var gravity: float = 20.0
@export var push_force: float = 10.0 # Force applied to RigidBody3D
@export var mouse_sensitivity: float = 0.002 # Mouse sensitivity
@export var max_look_angle: float = 90.0 # Maximum vertical look angle
@export var interaction_range: float = 3.0 # Range for interacting with objects
@export var interaction_strenght: int = 10
# Ghost mode settings
@export var ghost_mode: bool = false # Toggle ghost mode
@export var ghost_speed: float = 10.0 # Movement speed in ghost mode
# Collision layers
@export var normal_collision_layer: int = 1 # Layer 1: Normal
@export var ghost_collision_layer: int = 2 # Layer 2: Ghost
# Light flicker settings
@export var flicker_interval: float = 0.1 # Time between flickers
@export var flicker_intensity: float = 0.5 # Intensity of flicker (0 to 1)
@export var flicker_range: float = 10.0 # Range within which lights flicker
var flicker_timer: float = 0.0
func _ready() -> void:
# Capture the mouse so it doesn't leave the game window
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
# Initialize collision layer based on starting mode
update_collision_layer()
func _input(event: InputEvent) -> void:
if event is InputEventMouseMotion:
# Rotate the player horizontally (yaw)
rotate_y(-event.relative.x * mouse_sensitivity)
# Rotate the camera vertically (pitch)
$Camera3D.rotate_x(-event.relative.y * mouse_sensitivity)
$Camera3D.rotation_degrees.x = clamp($Camera3D.rotation_degrees.x, -max_look_angle, max_look_angle)
# Check for interaction input (e.g., pressing "E")
if event.is_action_pressed("interact"):
interact_with_object()
# Toggle ghost mode (e.g., pressing "G")
if event.is_action_pressed("toggle_ghost_mode"):
if ghost_mode:
interaction_strenght=10
else:
interaction_strenght=50
ghost_mode = !ghost_mode
print("Ghost mode: ", ghost_mode)
# Update collision layer when toggling ghost mode
update_collision_layer()
func update_collision_layer() -> void:
if ghost_mode:
# Set collision layer and mask for ghost mode
collision_layer = ghost_collision_layer
collision_mask = ghost_collision_layer
else:
# Set collision layer and mask for normal mode
collision_layer = normal_collision_layer
collision_mask = normal_collision_layer
func _physics_process(delta: float) -> void:
if ghost_mode:
ghost_movement(delta)
flicker_lights(delta)
else:
normal_movement(delta)
func normal_movement(delta: float) -> void:
var input_direction: Vector3 = Vector3.ZERO
# Get input for movement
if Input.is_action_pressed("move_forward"):
input_direction.z -= 1
if Input.is_action_pressed("move_backward"):
input_direction.z += 1
if Input.is_action_pressed("move_left"):
input_direction.x -= 1
if Input.is_action_pressed("move_right"):
input_direction.x += 1
# Normalize input to prevent faster diagonal movement
input_direction = input_direction.normalized()
# Apply movement in the camera's direction
var direction: Vector3 = (transform.basis * input_direction).normalized()
velocity.x = direction.x * speed
velocity.z = direction.z * speed
# Apply gravity
if not is_on_floor():
velocity.y -= gravity * delta
# Jumping
if Input.is_action_just_pressed("jump") and is_on_floor():
velocity.y = jump_force
# Move the player and detect collisions
move_and_slide()
# Apply force to RigidBody3D objects on collision
for index in range(get_slide_collision_count()):
var collision = get_slide_collision(index)
var collider = collision.get_collider()
if collider is RigidBody3D:
# Calculate the direction and force to apply
var force_direction = -collision.get_normal()
var force = force_direction * push_force
# Apply the force to the RigidBody3D
collider.apply_central_impulse(force)
func ghost_movement(delta: float) -> void:
var input_direction: Vector3 = Vector3.ZERO
# Get input for movement
if Input.is_action_pressed("move_forward"):
input_direction.z -= 1 # Forward
if Input.is_action_pressed("move_backward"):
input_direction.z += 1 # Backward
if Input.is_action_pressed("move_left"):
input_direction.x -= 1 # Left
if Input.is_action_pressed("move_right"):
input_direction.x += 1 # Right
# Normalize input to prevent faster diagonal movement
input_direction = input_direction.normalized()
# Calculate movement direction relative to the camera
var camera_basis = $Camera3D.global_transform.basis
var direction: Vector3 = (
camera_basis.z * input_direction.z + # Forward/backward
camera_basis.x * input_direction.x # Left/right
).normalized()
# Apply movement
velocity = direction * ghost_speed
# Move the player
move_and_slide()
func flicker_lights(delta: float) -> void:
flicker_timer += delta
if flicker_timer >= flicker_interval:
flicker_timer = 0.0
# Get all lights in the "flicker_lights" group
var lights = get_tree().get_nodes_in_group("flicker_lights")
for light in lights:
if light is OmniLight3D or light is SpotLight3D:
# Check if the light is within range
if light.global_transform.origin.distance_to(global_transform.origin) <= flicker_range:
# Randomly adjust the light's energy
light.light_energy = randf_range(1.0 - flicker_intensity, 1.0 + flicker_intensity)
func interact_with_object() -> void:
# Raycast to check for interactable objects in front of the player
var raycast = $Camera3D/RayCast3D
if raycast.is_colliding():
var collider = raycast.get_collider()
if collider is RigidBody3D:
# Apply a force or torque to flip the object
collider.freeze = false
var flip_force = Vector3(0, interaction_strenght, 0) # Force to flip the object upward
var flip_torque = Vector3(interaction_strenght, 0, 0) # Torque to rotate the object
collider.apply_central_impulse(flip_force)
collider.apply_torque_impulse(flip_torque)