copy from thegates-jam repo

This commit is contained in:
Nordup 2024-03-31 09:25:42 +04:00
parent c1a7ad74e1
commit 1a335de566
523 changed files with 22408 additions and 0 deletions

15
player/audio_listener.gd Normal file
View file

@ -0,0 +1,15 @@
extends AudioListener3D
@onready var _pivot: Node3D = $"../CameraController"
func _ready() -> void:
if is_multiplayer_authority():
make_current()
else:
clear_current()
func _process(_delta: float) -> void:
rotation_degrees = _pivot.rotation_degrees
rotation_degrees.y += 180

8
player/camera.gd Normal file
View file

@ -0,0 +1,8 @@
extends Camera3D
func _ready() -> void:
if is_multiplayer_authority():
make_current()
else:
clear_current(false)

View file

@ -0,0 +1,72 @@
class_name CameraController
extends Node3D
@export_node_path var player_path : NodePath
@export var invert_mouse_y := false
@export_range(0.0, 1.0) var mouse_sensitivity := 0.25
@export_range(0.0, 8.0) var joystick_sensitivity := 2.0
@export var tilt_upper_limit := deg_to_rad(-60.0)
@export var tilt_lower_limit := deg_to_rad(60.0)
@onready var camera: Camera3D = $PlayerCamera
@onready var _camera_spring_arm: SpringArm3D = $CameraSpringArm
@onready var _pivot: Node3D = $CameraSpringArm/CameraThirdPersonPivot
var _rotation_input: float
var _tilt_input: float
var _mouse_input := false
var _offset: Vector3
var _anchor: CharacterBody3D
var _euler_rotation: Vector3
func _ready() -> void:
if not is_multiplayer_authority():
set_process_input(false)
set_physics_process(false)
func _unhandled_input(event: InputEvent) -> void:
_mouse_input = event is InputEventMouseMotion and Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED
if _mouse_input:
_rotation_input = -event.relative.x * mouse_sensitivity
_tilt_input = -event.relative.y * mouse_sensitivity
func _physics_process(delta: float) -> void:
if not _anchor: return
_rotation_input += Input.get_action_raw_strength("camera_left") - Input.get_action_raw_strength("camera_right")
_tilt_input += Input.get_action_raw_strength("camera_up") - Input.get_action_raw_strength("camera_down")
if EditMode.is_enabled:
_rotation_input = 0.0
_tilt_input = 0.0
if invert_mouse_y:
_tilt_input *= -1
# Set camera controller to current ground level for the character
var target_position := _anchor.global_position + _offset
target_position.y = lerp(global_position.y, _anchor._ground_height, 0.1)
global_position = target_position
# Rotates camera using euler rotation
_euler_rotation.x += _tilt_input * delta
_euler_rotation.x = clamp(_euler_rotation.x, tilt_lower_limit, tilt_upper_limit)
_euler_rotation.y += _rotation_input * delta
transform.basis = Basis.from_euler(_euler_rotation)
camera.global_transform = _pivot.global_transform
camera.rotation.z = 0
_rotation_input = 0.0
_tilt_input = 0.0
func setup(anchor: CharacterBody3D) -> void:
_anchor = anchor
_offset = global_transform.origin - anchor.global_transform.origin
camera.global_transform = camera.global_transform.interpolate_with(_pivot.global_transform, 0.1)
_camera_spring_arm.add_excluded_object(_anchor.get_rid())

View file

@ -0,0 +1,108 @@
[gd_resource type="AnimationNodeBlendTree" load_steps=24 format=3 uid="uid://ctycm6blx4sw4"]
[sub_resource type="AnimationNodeAdd2" id="AnimationNodeAdd2_dpb3n"]
[sub_resource type="AnimationNodeAdd2" id="AnimationNodeAdd2_766tv"]
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_080es"]
animation = &"Godot Custom Animations/simple_blink"
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_cakye"]
animation = &"simple_punch"
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_u6r87"]
animation = &"Godot Custom Animations/default_heartbeat"
[sub_resource type="AnimationNodeOneShot" id="AnimationNodeOneShot_rfqjk"]
filter_enabled = true
filters = ["Armature/Skeleton3D:finger_1_1.L", "Armature/Skeleton3D:finger_1_2.L", "Armature/Skeleton3D:finger_2_1.L", "Armature/Skeleton3D:finger_2_2.L", "Armature/Skeleton3D:finger_3_1.L", "Armature/Skeleton3D:finger_3_2.L", "Armature/Skeleton3D:finger_4_1.L", "Armature/Skeleton3D:finger_4_2.L", "Armature/Skeleton3D:lowerarm.L", "Armature/Skeleton3D:thumb_1.L", "Armature/Skeleton3D:thumb_2.L", "Armature/Skeleton3D:torso", "Armature/Skeleton3D:upperarm.L"]
sync = true
fadein_time = 0.1
fadeout_time = 0.1
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_pi646"]
animation = &"fall"
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_53liu"]
animation = &"ground_impact"
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_nan6l"]
animation = &"Idle"
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_fy3xa"]
animation = &"jump"
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_qysix"]
animation = &"run"
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_ynydo"]
animation = &"walk"
[sub_resource type="AnimationNodeBlendSpace1D" id="AnimationNodeBlendSpace1D_cfy75"]
blend_point_0/node = SubResource("AnimationNodeAnimation_qysix")
blend_point_0/pos = 1.0
blend_point_1/node = SubResource("AnimationNodeAnimation_ynydo")
blend_point_1/pos = 0.0
min_space = 0.0
[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_5sbif"]
[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_sawiy"]
xfade_time = 0.2
[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_xu61x"]
xfade_time = 0.2
[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_2yld2"]
xfade_time = 0.2
[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_ad878"]
xfade_time = 0.1
[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_63es0"]
xfade_time = 0.1
[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_bsdcg"]
xfade_time = 0.2
switch_mode = 2
[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_rbpx6"]
xfade_time = 0.1
switch_mode = 1
[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_42lpg"]
[sub_resource type="AnimationNodeStateMachine" id="AnimationNodeStateMachine_k7175"]
states/End/position = Vector2(701, 90)
states/Start/position = Vector2(212, 90)
states/fall/node = SubResource("AnimationNodeAnimation_pi646")
states/fall/position = Vector2(342, 207)
states/ground_impact/node = SubResource("AnimationNodeAnimation_53liu")
states/ground_impact/position = Vector2(521, 207)
states/idle/node = SubResource("AnimationNodeAnimation_nan6l")
states/idle/position = Vector2(328, 90)
states/jump/node = SubResource("AnimationNodeAnimation_fy3xa")
states/jump/position = Vector2(179, 207)
states/move/node = SubResource("AnimationNodeBlendSpace1D_cfy75")
states/move/position = Vector2(531, 90)
transitions = ["Start", "idle", SubResource("AnimationNodeStateMachineTransition_5sbif"), "idle", "move", SubResource("AnimationNodeStateMachineTransition_sawiy"), "move", "idle", SubResource("AnimationNodeStateMachineTransition_xu61x"), "jump", "fall", SubResource("AnimationNodeStateMachineTransition_2yld2"), "idle", "jump", SubResource("AnimationNodeStateMachineTransition_ad878"), "fall", "ground_impact", SubResource("AnimationNodeStateMachineTransition_63es0"), "ground_impact", "idle", SubResource("AnimationNodeStateMachineTransition_bsdcg"), "ground_impact", "move", SubResource("AnimationNodeStateMachineTransition_rbpx6"), "move", "jump", SubResource("AnimationNodeStateMachineTransition_42lpg")]
graph_offset = Vector2(4, -47)
[resource]
graph_offset = Vector2(-162.506, 80.4752)
nodes/Add2/node = SubResource("AnimationNodeAdd2_766tv")
nodes/Add2/position = Vector2(260, 80)
"nodes/Add2 2/node" = SubResource("AnimationNodeAdd2_dpb3n")
"nodes/Add2 2/position" = Vector2(540, 80)
nodes/Animation/node = SubResource("AnimationNodeAnimation_u6r87")
nodes/Animation/position = Vector2(-160, 80)
"nodes/Animation 2/node" = SubResource("AnimationNodeAnimation_080es")
"nodes/Animation 2/position" = Vector2(-160, 200)
"nodes/Animation 3/node" = SubResource("AnimationNodeAnimation_cakye")
"nodes/Animation 3/position" = Vector2(20, 520)
nodes/PunchOneShot/node = SubResource("AnimationNodeOneShot_rfqjk")
nodes/PunchOneShot/position = Vector2(300, 380)
nodes/StateMachine/node = SubResource("AnimationNodeStateMachine_k7175")
nodes/StateMachine/position = Vector2(20, 380)
nodes/output/position = Vector2(780, 80)
node_connections = [&"Add2", 0, &"Animation", &"Add2", 1, &"Animation 2", &"Add2 2", 0, &"Add2", &"Add2 2", 1, &"PunchOneShot", &"PunchOneShot", 0, &"StateMachine", &"PunchOneShot", 1, &"Animation 3", &"output", 0, &"Add2 2"]

View file

@ -0,0 +1,58 @@
class_name CharacterSkin
extends Node3D
@export var main_animation_player : AnimationPlayer
var moving_blend_path := "parameters/StateMachine/move/blend_position"
# False : set animation to "idle"
# True : set animation to "move"
@onready var moving : bool = false : set = set_moving
# Blend value between the walk and run cycle
# 0.0 walk - 1.0 run
@onready var move_speed : float = 0.0 : set = set_moving_speed
@onready var animation_tree : AnimationTree = $AnimationTree
@onready var state_machine : AnimationNodeStateMachinePlayback = animation_tree.get("parameters/StateMachine/playback")
@onready var _step_sound: AudioStreamPlayer3D = $StepSound
@onready var _landing_sound: AudioStreamPlayer3D = $LandingSound
func _ready():
animation_tree.active = true
main_animation_player["playback_default_blend_time"] = 0.1
@rpc("authority", "call_local", "unreliable_ordered")
func set_moving(value : bool):
moving = value
if moving:
state_machine.travel("move")
else:
state_machine.travel("idle")
@rpc("authority", "call_local", "unreliable_ordered")
func set_moving_speed(value : float):
move_speed = clamp(value, 0.0, 1.0)
animation_tree.set(moving_blend_path, move_speed)
@rpc("authority", "call_local", "unreliable_ordered")
func jump():
state_machine.travel("jump")
@rpc("authority", "call_local", "unreliable_ordered")
func fall():
state_machine.travel("fall")
func play_step_sound():
_step_sound.pitch_scale = randfn(1.1, 0.05)
_step_sound.play()
func play_landing_sound():
_landing_sound.play()

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,17 @@
[gd_resource type="Animation" format=3 uid="uid://b627b68jhaqwt"]
[resource]
length = 3.0
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Armature/Skeleton3D/gdbot_mesh:surface_material_override/2:emission_energy_multiplier")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 1.5, 3),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 0,
"values": [0.5, 3.0, 0.5]
}

View file

@ -0,0 +1,20 @@
[gd_resource type="Animation" load_steps=3 format=3 uid="uid://diuutac72yquv"]
[ext_resource type="Texture2D" uid="uid://dbag7f8i27ub1" path="res://player/model/faces/open.png" id="1_vbky0"]
[ext_resource type="Texture2D" uid="uid://ci7cn145ld3l5" path="res://player/model/faces/closed.png" id="2_xwfhj"]
[resource]
length = 4.0
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Armature/Skeleton3D/gdbot_mesh:surface_material_override/1:shader_parameter/face_texture")
tracks/0/interp = 0
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(1.5, 1.7, 1.9, 2.1, 2.5),
"transitions": PackedFloat32Array(1, 1, 1, 1, 1),
"update": 1,
"values": [ExtResource("1_vbky0"), ExtResource("2_xwfhj"), ExtResource("1_vbky0"), ExtResource("2_xwfhj"), ExtResource("1_vbky0")]
}

View file

@ -0,0 +1,3 @@
[gd_resource type="AnimationNodeStateMachinePlayback" format=3 uid="uid://uhx6kfu45rrc"]
[resource]

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

View file

@ -0,0 +1,35 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://ci7cn145ld3l5"
path.s3tc="res://.godot/imported/closed.png-3e590ab69a341bea90ae32196457e22a.s3tc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://player/model/faces/closed.png"
dest_files=["res://.godot/imported/closed.png-3e590ab69a341bea90ae32196457e22a.s3tc.ctex"]
[params]
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=0

BIN
player/model/faces/open.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

View file

@ -0,0 +1,35 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dbag7f8i27ub1"
path.s3tc="res://.godot/imported/open.png-5012805d48e71003c4f690b36cedcba1.s3tc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://player/model/faces/open.png"
dest_files=["res://.godot/imported/open.png-5012805d48e71003c4f690b36cedcba1.s3tc.ctex"]
[params]
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=0

BIN
player/model/gdbot.glb Normal file

Binary file not shown.

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,40 @@
shader_type spatial;
uniform sampler2D face_texture : filter_nearest, repeat_disable;
uniform float intensity = 1.5;
uniform vec4 screen_color : source_color = vec4(1.0);
uniform vec2 screen_red_offset = vec2(0.0);
uniform vec2 screen_green_offset = vec2(0.0);
uniform vec2 screen_blue_offset = vec2(0.0);
uniform float pixel_size = 20.0;
void fragment() {
vec2 scaled_uv = round(UV * pixel_size) / pixel_size;
float face_red = 1.0 - texture(face_texture, screen_red_offset + scaled_uv).x;
float face_green = 1.0 - texture(face_texture, screen_green_offset + scaled_uv).x;
float face_blue = 1.0 - texture(face_texture, screen_blue_offset + scaled_uv).x;
vec2 grid_2d = sin(fract(UV * pixel_size + 0.5) * 3.14);
float grid = grid_2d.x * grid_2d.y;
grid = grid * 0.6 + 0.4;
ALBEDO = vec3(0.0);
SPECULAR = 0.25;
ROUGHNESS = 0.45;
vec3 iris = vec3(0.0);
iris.r = ((screen_color.r * face_red) / 3.0);
iris.g = ((screen_color.g * face_green) / 3.0);
iris.b = ((screen_color.b * face_blue) / 3.0);
iris.rgb *= 1.0 - screen_color.a;
vec3 fill = screen_color.rgb * screen_color.a;
EMISSION = (iris + fill) * grid * intensity;
}

View file

@ -0,0 +1,15 @@
[gd_resource type="ShaderMaterial" load_steps=3 format=3 uid="uid://dh42cdejchkr3"]
[ext_resource type="Shader" path="res://player/model/materials/face_mat.gdshader" id="1_u8nh3"]
[ext_resource type="Texture2D" uid="uid://ci7cn145ld3l5" path="res://player/model/faces/closed.png" id="2_r4pvf"]
[resource]
render_priority = 0
shader = ExtResource("1_u8nh3")
shader_parameter/intensity = 4.0
shader_parameter/screen_color = Color(0.0784314, 0.556863, 1, 0.00784314)
shader_parameter/screen_red_offset = Vector2(0, 0)
shader_parameter/screen_green_offset = Vector2(0, 0)
shader_parameter/screen_blue_offset = Vector2(0, 0)
shader_parameter/pixel_size = 44.0
shader_parameter/face_texture = ExtResource("2_r4pvf")

View file

@ -0,0 +1,7 @@
[gd_resource type="StandardMaterial3D" format=3 uid="uid://4ugdxr58llu8"]
[resource]
transparency = 1
albedo_color = Color(1, 1, 1, 0.443137)
metallic_specular = 1.0
roughness = 0.1

View file

@ -0,0 +1,7 @@
[gd_resource type="StandardMaterial3D" format=3 uid="uid://cq6bdna8ieu87"]
[resource]
albedo_color = Color(0, 0, 0, 1)
emission_enabled = true
emission = Color(0, 1, 0.392157, 1)
emission_energy_multiplier = 0.831129

Binary file not shown.

View file

@ -0,0 +1,24 @@
[remap]
importer="wav"
type="AudioStreamWAV"
uid="uid://cbcb2d63weegs"
path="res://.godot/imported/landing.wav-af9f0fb6e2c7495f9e2392633d92b046.sample"
[deps]
source_file="res://player/model/sounds/landing.wav"
dest_files=["res://.godot/imported/landing.wav-af9f0fb6e2c7495f9e2392633d92b046.sample"]
[params]
force/8_bit=false
force/mono=false
force/max_rate=false
force/max_rate_hz=44100
edit/trim=false
edit/normalize=false
edit/loop_mode=0
edit/loop_begin=0
edit/loop_end=-1
compress/mode=0

Binary file not shown.

View file

@ -0,0 +1,24 @@
[remap]
importer="wav"
type="AudioStreamWAV"
uid="uid://bx0t7f2nuk2lr"
path="res://.godot/imported/step.wav-79a20c90fb5056e8188ac1531dfedbf8.sample"
[deps]
source_file="res://player/model/sounds/step.wav"
dest_files=["res://.godot/imported/step.wav-79a20c90fb5056e8188ac1531dfedbf8.sample"]
[params]
force/8_bit=false
force/mono=false
force/max_rate=false
force/max_rate_hz=44100
edit/trim=false
edit/normalize=false
edit/loop_mode=0
edit/loop_begin=0
edit/loop_end=-1
compress/mode=0

191
player/player.gd Normal file
View file

@ -0,0 +1,191 @@
extends CharacterBody3D
class_name Player
## Character maximum run speed on the ground.
@export var move_speed := 8.0
## Forward impulse after a melee attack.
@export var attack_impulse := 10.0
## Movement acceleration (how fast character achieve maximum speed)
@export var acceleration := 6.0
## Jump impulse
@export var jump_initial_impulse := 12.0
## Jump impulse when player keeps pressing jump
@export var jump_additional_force := 4.5
## Player model rotation speed
@export var rotation_speed := 12.0
## Minimum horizontal speed on the ground. This controls when the character's animation tree changes
## between the idle and running states.
@export var stopping_speed := 1.0
## Clamp sync delta for faster interpolation
@export var sync_delta_max := 0.2
@onready var _rotation_root: Node3D = $CharacterRotationRoot
@onready var _camera_controller: CameraController = $CameraController
@onready var _ground_shapecast: ShapeCast3D = $GroundShapeCast
@onready var _character_skin: CharacterSkin = $CharacterRotationRoot/CharacterSkin
@onready var _synchronizer: MultiplayerSynchronizer = $MultiplayerSynchronizer
@onready var _move_direction := Vector3.ZERO
@onready var _last_strong_direction := Vector3.FORWARD
@onready var _gravity: float = -30.0
@onready var _ground_height: float = 0.0
## Sync properties
@export var _position: Vector3
@export var _velocity: Vector3
@export var _direction: Vector3 = Vector3.ZERO
@export var _strong_direction: Vector3 = Vector3.FORWARD
var position_before_sync: Vector3
var last_sync_time_ms: int
var sync_delta: float
func _ready() -> void:
if is_multiplayer_authority():
_camera_controller.setup(self)
else:
rotation_speed /= 1.5
_synchronizer.delta_synchronized.connect(on_synchronized)
_synchronizer.synchronized.connect(on_synchronized)
on_synchronized()
func _physics_process(delta: float) -> void:
if not is_multiplayer_authority(): interpolate_client(delta); return
# Calculate ground height for camera controller
if _ground_shapecast.get_collision_count() > 0:
for collision_result in _ground_shapecast.collision_result:
_ground_height = max(_ground_height, collision_result.point.y)
else:
_ground_height = global_position.y + _ground_shapecast.target_position.y
if global_position.y < _ground_height:
_ground_height = global_position.y
# Get input and movement state
var is_just_jumping := Input.is_action_just_pressed("jump") and is_on_floor()
var is_air_boosting := Input.is_action_pressed("jump") and not is_on_floor() and velocity.y > 0.0
_move_direction = _get_camera_oriented_input()
if EditMode.is_enabled:
is_just_jumping = false
is_air_boosting = false
_move_direction = Vector3.ZERO
# To not orient quickly to the last input, we save a last strong direction,
# this also ensures a good normalized value for the rotation basis.
if _move_direction.length() > 0.2:
_last_strong_direction = _move_direction.normalized()
_orient_character_to_direction(_last_strong_direction, delta)
# We separate out the y velocity to not interpolate on the gravity
var y_velocity := velocity.y
velocity.y = 0.0
velocity = velocity.lerp(_move_direction * move_speed, acceleration * delta)
if _move_direction.length() == 0 and velocity.length() < stopping_speed:
velocity = Vector3.ZERO
velocity.y = y_velocity
# Update position
velocity.y += _gravity * delta
if is_just_jumping:
velocity.y += jump_initial_impulse
elif is_air_boosting:
velocity.y += jump_additional_force * delta
# Set character animation
if is_just_jumping:
_character_skin.jump.rpc()
elif not is_on_floor() and velocity.y < 0:
_character_skin.fall.rpc()
elif is_on_floor():
var xz_velocity := Vector3(velocity.x, 0, velocity.z)
if xz_velocity.length() > stopping_speed:
_character_skin.set_moving.rpc(true)
_character_skin.set_moving_speed.rpc(inverse_lerp(0.0, move_speed, xz_velocity.length()))
else:
_character_skin.set_moving.rpc(false)
var position_before := global_position
move_and_slide()
var position_after := global_position
# If velocity is not 0 but the difference of positions after move_and_slide is,
# character might be stuck somewhere!
var delta_position := position_after - position_before
var epsilon := 0.001
if delta_position.length() < epsilon and velocity.length() > epsilon:
global_position += get_wall_normal() * 0.1
set_sync_properties()
func set_sync_properties() -> void:
_position = position
_velocity = velocity
_direction = _move_direction
_strong_direction = _last_strong_direction
func on_synchronized() -> void:
velocity = _velocity
position_before_sync = position
var sync_time_ms = Time.get_ticks_msec()
sync_delta = clampf(float(sync_time_ms - last_sync_time_ms) / 1000, 0, sync_delta_max)
last_sync_time_ms = sync_time_ms
func interpolate_client(delta: float) -> void:
_orient_character_to_direction(_strong_direction, delta)
if _direction.length() == 0:
# Don't interpolate to avoid small jitter when stopping
if (_position - position).length() > 1.0 and _velocity.is_zero_approx():
position = _position # Fix misplacement
else:
# Interpolate between position_before_sync and _position
# and add to ongoing movement to compensate misplacement
var t = 1.0 if is_zero_approx(sync_delta) else delta / sync_delta
sync_delta = clampf(sync_delta - delta, 0, sync_delta_max)
var less_misplacement = position_before_sync.move_toward(_position, t)
position += less_misplacement - position_before_sync
position_before_sync = less_misplacement
velocity.y += _gravity * delta
move_and_slide()
func _get_camera_oriented_input() -> Vector3:
var raw_input := Input.get_vector("move_left", "move_right", "move_up", "move_down")
var input := Vector3.ZERO
# This is to ensure that diagonal input isn't stronger than axis aligned input
input.x = -raw_input.x * sqrt(1.0 - raw_input.y * raw_input.y / 2.0)
input.z = -raw_input.y * sqrt(1.0 - raw_input.x * raw_input.x / 2.0)
input = _camera_controller.global_transform.basis * input
input.y = 0.0
return input
func _orient_character_to_direction(direction: Vector3, delta: float) -> void:
var left_axis := Vector3.UP.cross(direction)
var rotation_basis := Basis(left_axis, Vector3.UP, direction).get_rotation_quaternion()
var model_scale := _rotation_root.transform.basis.get_scale()
_rotation_root.transform.basis = Basis(_rotation_root.transform.basis.get_rotation_quaternion().slerp(rotation_basis, delta * rotation_speed)).scaled(
model_scale
)
@rpc("any_peer", "call_remote", "reliable")
func respawn(spawn_position: Vector3) -> void:
global_position = spawn_position
velocity = Vector3.ZERO

173
player/player.tscn Normal file
View file

@ -0,0 +1,173 @@
[gd_scene load_steps=19 format=3 uid="uid://ciqrpd5675boy"]
[ext_resource type="Script" path="res://player/player.gd" id="1_pdbxc"]
[ext_resource type="Script" path="res://player/camera_controller.gd" id="2_2fob2"]
[ext_resource type="Script" path="res://player/audio_listener.gd" id="2_4csdy"]
[ext_resource type="Script" path="res://player/camera.gd" id="3_qxleh"]
[ext_resource type="PackedScene" uid="uid://c0mo8tek77du4" path="res://player/model/character_skin.tscn" id="3_ufinh"]
[ext_resource type="Script" path="res://ui/floating_nickname.gd" id="6_f61mk"]
[ext_resource type="Resource" uid="uid://rclnl7v8k722" path="res://user_data/user_data_events.res" id="7_bgpps"]
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_8x2xm"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_g6jd1"]
albedo_color = Color(1, 0, 0, 1)
[sub_resource type="BoxMesh" id="BoxMesh_nd4sr"]
material = SubResource("StandardMaterial3D_g6jd1")
size = Vector3(0.7, 0.3, 0.5)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_wn7lu"]
albedo_color = Color(0, 0, 1, 1)
[sub_resource type="BoxMesh" id="BoxMesh_kin6n"]
material = SubResource("StandardMaterial3D_wn7lu")
size = Vector3(0.7, 0.3, 0.5)
[sub_resource type="SeparationRayShape3D" id="SeparationRayShape3D_gqx4v"]
[sub_resource type="CameraAttributesPractical" id="CameraAttributesPractical_2ooex"]
dof_blur_far_enabled = true
dof_blur_far_distance = 100.0
[sub_resource type="CylinderShape3D" id="CylinderShape3D_s5n07"]
[sub_resource type="LabelSettings" id="LabelSettings_sr337"]
font_size = 24
font_color = Color(1, 1, 1, 0.701961)
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_bjie3"]
bg_color = Color(0.251, 1, 0, 0.7)
corner_radius_top_left = 25
corner_radius_top_right = 25
corner_radius_bottom_right = 25
corner_radius_bottom_left = 25
[sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_g0ye7"]
properties/0/path = NodePath(".:_position")
properties/0/spawn = true
properties/0/replication_mode = 1
properties/1/path = NodePath(".:_velocity")
properties/1/spawn = true
properties/1/replication_mode = 1
properties/2/path = NodePath(".:_direction")
properties/2/spawn = true
properties/2/replication_mode = 1
properties/3/path = NodePath(".:_strong_direction")
properties/3/spawn = true
properties/3/replication_mode = 1
[node name="Player" type="CharacterBody3D" groups=["damageables"]]
top_level = true
axis_lock_angular_x = true
axis_lock_angular_y = true
axis_lock_angular_z = true
script = ExtResource("1_pdbxc")
[node name="CharacterCollisionShape" type="CollisionShape3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
shape = SubResource("CapsuleShape3D_8x2xm")
[node name="AudioListener3D" type="AudioListener3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.8, -0.2)
script = ExtResource("2_4csdy")
[node name="MeshInstance3D" type="MeshInstance3D" parent="AudioListener3D"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.35, 0, 0)
visible = false
mesh = SubResource("BoxMesh_nd4sr")
[node name="MeshInstance3D2" type="MeshInstance3D" parent="AudioListener3D"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.35, 0, 0)
visible = false
mesh = SubResource("BoxMesh_kin6n")
[node name="CameraController" type="Node3D" parent="."]
top_level = true
script = ExtResource("2_2fob2")
invert_mouse_y = true
tilt_upper_limit = 0.48
tilt_lower_limit = -0.8
[node name="CameraSpringArm" type="SpringArm3D" parent="CameraController"]
transform = Transform3D(-1, -5.15034e-15, -8.74228e-08, -3.23484e-08, 0.929023, 0.370022, 8.12178e-08, 0.370022, -0.929023, 0, 2.33984, 0)
shape = SubResource("SeparationRayShape3D_gqx4v")
spring_length = 6.0
[node name="CameraThirdPersonPivot" type="Marker3D" parent="CameraController/CameraSpringArm"]
transform = Transform3D(1, 0, -7.10543e-15, 0, 1, 0, 0, 0, 1, 1.42109e-14, 2.38419e-07, 10)
[node name="PlayerCamera" type="Camera3D" parent="CameraController"]
transform = Transform3D(-1, -3.71248e-14, -8.74228e-08, -3.23484e-08, 0.929023, 0.370022, 8.12178e-08, 0.370022, -0.929023, -8.74228e-07, 6.04006, -9.29023)
top_level = true
attributes = SubResource("CameraAttributesPractical_2ooex")
fov = 50.0
script = ExtResource("3_qxleh")
[node name="GroundShapeCast" type="ShapeCast3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0)
shape = SubResource("CylinderShape3D_s5n07")
target_position = Vector3(0, -2.6, 0)
margin = 0.5
max_results = 1
debug_shape_custom_color = Color(0.658824, 1, 0, 1)
[node name="CharacterRotationRoot" type="Node3D" parent="."]
[node name="CharacterSkin" parent="CharacterRotationRoot" instance=ExtResource("3_ufinh")]
[node name="Nickname" type="Control" parent="." node_paths=PackedStringArray("label", "speaking_indicator", "anchor")]
layout_mode = 3
anchors_preset = 0
mouse_filter = 1
script = ExtResource("6_f61mk")
user_data_events = ExtResource("7_bgpps")
label = NodePath("HBoxContainer/Nickname")
speaking_indicator = NodePath("HBoxContainer/Control/SpeakIndicator")
anchor = NodePath("..")
offset = Vector3(0, 3, 0)
[node name="HBoxContainer" type="HBoxContainer" parent="Nickname"]
layout_mode = 1
anchors_preset = 7
anchor_left = 0.5
anchor_top = 1.0
anchor_right = 0.5
anchor_bottom = 1.0
offset_left = -20.0
offset_top = -40.0
offset_right = 20.0
grow_horizontal = 2
grow_vertical = 0
theme_override_constants/separation = 10
alignment = 1
[node name="Nickname" type="Label" parent="Nickname/HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 4
text = "Player One"
label_settings = SubResource("LabelSettings_sr337")
horizontal_alignment = 1
[node name="Control" type="Control" parent="Nickname/HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 4
size_flags_vertical = 4
mouse_filter = 1
[node name="SpeakIndicator" type="Panel" parent="Nickname/HBoxContainer/Control"]
layout_mode = 1
anchors_preset = 4
anchor_top = 0.5
anchor_bottom = 0.5
offset_top = -4.0
offset_right = 13.0
offset_bottom = 9.0
grow_vertical = 2
size_flags_horizontal = 8
size_flags_vertical = 4
mouse_filter = 1
theme_override_styles/panel = SubResource("StyleBoxFlat_bjie3")
[node name="MultiplayerSynchronizer" type="MultiplayerSynchronizer" parent="."]
replication_config = SubResource("SceneReplicationConfig_g0ye7")