This commit is contained in:
2026-09-10 07:47:15 -04:00
parent 1f555ed3e4
commit 1c4d0ecbfe
39 changed files with 1499 additions and 2357 deletions
+128 -64
View File
@@ -1,97 +1,161 @@
extends CharacterBody3D
const SPEED := 5.0
const JUMP_VELOCITY := 4.5
const MOUSE_SENSITIVITY := 0.003
# Acceleration and deceleration are m/s².
# max_speed is m/s.
@export var accel := 6.7
@export var deccel := 8.5
@export var max_speed := 6.2
const ACCEL := 20.0
const DECEL := 15.0
@export var has_suit := true
@export var has_hvms2 := true
@export var gravity := 9.8
@export var jump_velocity := 4.5
# Mouse sensitivity
@export var mouse_sensitivity := 0.003
# Maximum camera pitch in degrees
@export var max_pitch := 89.0
var movement_vec := Vector3.ZERO
var input_vec := Vector4.ZERO
var jump := false
var air_jumps := 0
func _ready() -> void:
if not has_suit:
$yaw/pitch/Camera/Hud.visible = false
if has_hvms2:
max_speed = 30.0
accel = 10
deccel = 20
jump_velocity = 10
# Capture the mouse when the game starts
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
func _input(event: InputEvent) -> void:
# Mouse-look
if event is InputEventMouseMotion:
if Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:
# Horizontal rotation: rotate the player
$yaw.rotate_y(-event.relative.x * mouse_sensitivity)
# Vertical rotation: rotate the camera
$yaw/pitch.rotate_x(-event.relative.y * mouse_sensitivity)
# Clamp pitch so the camera cannot flip upside down
$yaw/pitch.rotation.x = clamp(
$yaw/pitch.rotation.x,
deg_to_rad(-max_pitch),
deg_to_rad(max_pitch)
)
return
# Mouse click captures the mouse again
if event is InputEventMouseButton:
if event.button_index == MOUSE_BUTTON_LEFT and event.pressed:
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
return
# Keyboard input
if event is InputEventKey:
if event.keycode == KEY_ESCAPE and event.pressed:
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
return
var pressed: bool = event.pressed
if event.keycode == KEY_SPACE and event.pressed and is_on_floor():
velocity.y = JUMP_VELOCITY
match event.keycode:
KEY_W:
input_vec.w = 1.0 if pressed else 0.0
if event.keycode == KEY_E and event.pressed and not event.echo:
var node = $yaw/pitch/Facing.get_collider()
KEY_S:
input_vec.x = 1.0 if pressed else 0.0
if node and node.has_method("interact"):
node.interact(self)
KEY_A:
input_vec.y = 1.0 if pressed else 0.0
if event is InputEventMouseMotion and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:
$yaw.rotate_y(-event.relative.x * MOUSE_SENSITIVITY)
KEY_D:
input_vec.z = 1.0 if pressed else 0.0
$yaw/pitch.rotate_x(-event.relative.y * MOUSE_SENSITIVITY)
KEY_SPACE:
if pressed and is_on_floor():
jump=true
$yaw/pitch.rotation.x = clamp(
$yaw/pitch.rotation.x,
deg_to_rad(-89.0),
deg_to_rad(89.0)
)
KEY_ESCAPE:
if pressed:
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
KEY_SHIFT:
if has_hvms2:
velocity.y = max(velocity.y, -3) if pressed else velocity.y
gravity = 3 if pressed else 9.8
if is_on_floor():
velocity=$yaw/pitch/Camera.basis*Vector3(0,0,50)
func _physics_process(delta: float) -> void:
# Gravity
if not is_on_floor():
velocity += get_gravity() * delta
# W/S/A/D input
var input_direction := Vector2(
input_vec.z - input_vec.y,
input_vec.w - input_vec.x
)
# Read keyboard state directly
var input_x := 0.0
var input_z := 0.0
if Input.is_key_pressed(KEY_A):
input_x -= 1.0
if Input.is_key_pressed(KEY_D):
input_x += 1.0
if Input.is_key_pressed(KEY_W):
input_z -= 1.0
if Input.is_key_pressed(KEY_S):
input_z += 1.0
# Create movement vector
var input_direction := Vector3(input_x, 0.0, input_z)
# Prevent diagonal movement from being faster
if input_direction.length_squared() > 0.0:
if input_direction.length() > 1.0:
input_direction = input_direction.normalized()
# Rotate movement relative to yaw
var direction : Vector3 = $yaw.global_transform.basis * input_direction
direction.y = 0.0
# Camera yaw only
var yaw_basis: Basis = $yaw.global_transform.basis
if direction.length_squared() > 0.0:
direction = direction.normalized()
var forward := -yaw_basis.z
var right := yaw_basis.x
# Target velocity
var target := direction * SPEED
forward.y = 0.0
right.y = 0.0
var acceleration := ACCEL
if direction.length_squared() == 0.0:
acceleration = DECEL
forward = forward.normalized()
right = right.normalized()
# Smooth movement toward target
velocity.x = move_toward(
var target_direction := (
right * input_direction.x
+ forward * input_direction.y
)
# Target horizontal velocity in m/s
var target_velocity := target_direction * max_speed
# Current horizontal velocity in m/s
var current_velocity := Vector3(
velocity.x,
target.x,
0.0,
velocity.z
)
# Acceleration/deceleration in m/s²
var acceleration := accel if target_direction != Vector3.ZERO else deccel
current_velocity = current_velocity.move_toward(
target_velocity,
acceleration * delta
)
velocity.z = move_toward(
velocity.z,
target.z,
acceleration * delta
)
velocity.x = current_velocity.x
velocity.z = current_velocity.z
# Gravity
if not is_on_floor():
velocity.y -= gravity * delta
else:
if jump:
velocity.y=jump_velocity
jump=false
else:
velocity.y=0.0
if global_position.y<=-1000:
get_tree().reload_current_scene()
move_and_slide()
+4 -1
View File
@@ -1,4 +1,7 @@
extends Node2D
func _ready() -> void:
$Container.size=get_viewport_rect().size
func set_tooltip(text: String) -> void:
$Tooltip.text=text
$Container/Tooltip.text=text
Binary file not shown.
Binary file not shown.
+72
View File
@@ -0,0 +1,72 @@
extends MeshInstance3D
@export var max_lights := 256
@export var camera: Camera3D
var lights: Array[Light3D] = []
func _ready() -> void:
find_lights(get_tree().current_scene)
func find_lights(node: Node) -> void:
if node is Light3D:
lights.append(node)
for child in node.get_children():
find_lights(child)
func _process(_delta: float) -> void:
var mat := material_override as ShaderMaterial
if mat == null:
return
if camera == null:
camera = get_viewport().get_camera_3d()
if camera == null:
return
mat.set_shader_parameter(
"inv_projection",
camera.get_camera_projection().inverse()
)
mat.set_shader_parameter(
"inv_view",
camera.global_transform
)
if mat == null:
return
var positions := PackedVector3Array()
var colors := PackedColorArray()
var energies := PackedFloat32Array()
var ranges := PackedFloat32Array()
for light in lights:
if not is_instance_valid(light):
continue
if not light.visible:
continue
positions.append(light.global_position)
colors.append(light.light_color)
energies.append(light.light_energy)
if light is OmniLight3D:
ranges.append(light.omni_range)
elif light is SpotLight3D:
ranges.append(light.spot_range)
else:
ranges.append(100.0)
if positions.size() >= max_lights:
break
mat.set_shader_parameter("light_positions", positions)
mat.set_shader_parameter("light_colors", colors)
mat.set_shader_parameter("light_energies", energies)
mat.set_shader_parameter("light_ranges", ranges)
mat.set_shader_parameter("light_count", positions.size())
+1
View File
@@ -0,0 +1 @@
uid://blvu4cfl61262