mirror of
https://github.com/thegatesbrowser/godot-multiplayer.git
synced 2025-09-06 14:25:52 -04:00
copy from thegates-jam repo
This commit is contained in:
parent
c1a7ad74e1
commit
1a335de566
523 changed files with 22408 additions and 0 deletions
15
player/audio_listener.gd
Normal file
15
player/audio_listener.gd
Normal 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
8
player/camera.gd
Normal file
|
@ -0,0 +1,8 @@
|
|||
extends Camera3D
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
if is_multiplayer_authority():
|
||||
make_current()
|
||||
else:
|
||||
clear_current(false)
|
72
player/camera_controller.gd
Normal file
72
player/camera_controller.gd
Normal 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())
|
108
player/model/character_blend_tree.tres
Normal file
108
player/model/character_blend_tree.tres
Normal 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"]
|
58
player/model/character_skin.gd
Normal file
58
player/model/character_skin.gd
Normal 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()
|
2701
player/model/character_skin.tscn
Normal file
2701
player/model/character_skin.tscn
Normal file
File diff suppressed because one or more lines are too long
17
player/model/custom_animations/default_heartbeat.tres
Normal file
17
player/model/custom_animations/default_heartbeat.tres
Normal 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]
|
||||
}
|
20
player/model/custom_animations/simple_blink.tres
Normal file
20
player/model/custom_animations/simple_blink.tres
Normal 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")]
|
||||
}
|
3
player/model/default_state_machine.tres
Normal file
3
player/model/default_state_machine.tres
Normal file
|
@ -0,0 +1,3 @@
|
|||
[gd_resource type="AnimationNodeStateMachinePlayback" format=3 uid="uid://uhx6kfu45rrc"]
|
||||
|
||||
[resource]
|
BIN
player/model/faces/closed.png
Normal file
BIN
player/model/faces/closed.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.6 KiB |
35
player/model/faces/closed.png.import
Normal file
35
player/model/faces/closed.png.import
Normal 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
BIN
player/model/faces/open.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.3 KiB |
35
player/model/faces/open.png.import
Normal file
35
player/model/faces/open.png.import
Normal 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
BIN
player/model/gdbot.glb
Normal file
Binary file not shown.
9032
player/model/gdbot.glb.import
Normal file
9032
player/model/gdbot.glb.import
Normal file
File diff suppressed because it is too large
Load diff
40
player/model/materials/face_mat.gdshader
Normal file
40
player/model/materials/face_mat.gdshader
Normal 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;
|
||||
|
||||
}
|
15
player/model/materials/face_mat.tres
Normal file
15
player/model/materials/face_mat.tres
Normal 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")
|
7
player/model/materials/glass_mat.tres
Normal file
7
player/model/materials/glass_mat.tres
Normal 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
|
7
player/model/materials/heart_core_mat.tres
Normal file
7
player/model/materials/heart_core_mat.tres
Normal 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
|
BIN
player/model/sounds/landing.wav
Normal file
BIN
player/model/sounds/landing.wav
Normal file
Binary file not shown.
24
player/model/sounds/landing.wav.import
Normal file
24
player/model/sounds/landing.wav.import
Normal 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
|
BIN
player/model/sounds/step.wav
Normal file
BIN
player/model/sounds/step.wav
Normal file
Binary file not shown.
24
player/model/sounds/step.wav.import
Normal file
24
player/model/sounds/step.wav.import
Normal 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
191
player/player.gd
Normal 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
173
player/player.tscn
Normal 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")
|
Loading…
Add table
Add a link
Reference in a new issue