Improved component system

This commit is contained in:
Eduard Urbach 2024-02-07 23:04:19 +01:00
parent 97087ad03e
commit c4a9da0880
Signed by: akyoto
GPG Key ID: C874F672B1AF20C0
22 changed files with 263 additions and 188 deletions

View File

@ -18,7 +18,7 @@
[ext_resource type="PackedScene" uid="uid://cb2t7bvvf3gwh" path="res://enemy/slime/Slime.tscn" id="15_hgl78"] [ext_resource type="PackedScene" uid="uid://cb2t7bvvf3gwh" path="res://enemy/slime/Slime.tscn" id="15_hgl78"]
[ext_resource type="Script" path="res://world/PlayerManager.gd" id="16_dp6bj"] [ext_resource type="Script" path="res://world/PlayerManager.gd" id="16_dp6bj"]
[ext_resource type="PackedScene" uid="uid://dagn5bf7ou3sd" path="res://ui/UI.tscn" id="17_43qhq"] [ext_resource type="PackedScene" uid="uid://dagn5bf7ou3sd" path="res://ui/UI.tscn" id="17_43qhq"]
[ext_resource type="Material" uid="uid://bdsblfaxbipaa" path="res://grass/grass_material.tres" id="18_tja64"] [ext_resource type="Material" uid="uid://bdsblfaxbipaa" path="res://world/grass/grass_material.tres" id="18_tja64"]
[ext_resource type="Script" path="res://camera/Camera.gd" id="18_wogcj"] [ext_resource type="Script" path="res://camera/Camera.gd" id="18_wogcj"]
[ext_resource type="MultiMesh" uid="uid://dog5aq5n2q025" path="res://assets/grass/grass.multimesh" id="19_ae26a"] [ext_resource type="MultiMesh" uid="uid://dog5aq5n2q025" path="res://assets/grass/grass.multimesh" id="19_ae26a"]
@ -74,6 +74,7 @@ packet_type = 11
[node name="PlayerMove" type="Node" parent="Client"] [node name="PlayerMove" type="Node" parent="Client"]
script = ExtResource("8_ke1yy") script = ExtResource("8_ke1yy")
delay = 100
packet_type = 12 packet_type = 12
[node name="PlayerJump" type="Node" parent="Client"] [node name="PlayerJump" type="Node" parent="Client"]

View File

@ -1,48 +1,2 @@
class_name Character class_name Character
extends CharacterBody3D extends CharacterBody3D
signal jumped
@export var model: Node3D
@export var move_speed: float = 4.5
@export var rotation_speed: float = 20.0
const JUMP_VELOCITY := 4.5
const DECELERATE := 0.75
var direction: Vector3
var angle: float
var gravity: float = ProjectSettings.get_setting("physics/3d/default_gravity")
var controller: Node
func _process(delta):
if direction != Vector3.ZERO:
angle = atan2(direction.x, direction.z)
model.rotation.y = lerp_angle(model.rotation.y, angle, rotation_speed * delta)
func _physics_process(delta):
if direction:
velocity.x = direction.x * move_speed
velocity.z = direction.z * move_speed
else:
velocity.x *= DECELERATE
velocity.z *= DECELERATE
if !is_on_floor():
velocity.y -= gravity * delta
move_and_slide()
func jump():
if !is_on_floor():
return
velocity.y = JUMP_VELOCITY
jumped.emit()
func dash():
print("dash")
func attack():
print("attack")

View File

@ -0,0 +1,55 @@
class_name AnimationComponent
extends Node
const RESET = "human/RESET"
var animation_player: AnimationPlayer
var movement: MovementComponent
var next_animation: StringName = RESET
var skip: int
func _ready():
var player := owner as Player
player.dashed.connect(dash)
player.attacked.connect(attack)
movement = player.find_child("Movement")
animation_player = $AnimationPlayer
func _process(_delta):
if skip == 0:
play_movement()
if animation_player.current_animation == next_animation:
return
animation_player.play(next_animation)
func play_movement():
if !movement:
play(RESET)
return
if movement.body.velocity.y > 0:
play("human/jump")
elif movement.body.velocity.y < 0:
play("human/fall")
elif movement.direction != Vector3.ZERO:
play("human/run-fast")
else:
play("human/idle")
func dash():
play_with_duration("human/roll", 1.0)
func attack():
play_with_duration("human/slash", 1.0)
func play(action_name: StringName):
next_animation = action_name
func play_with_duration(action_name: StringName, duration: float):
next_animation = action_name
skip += 1
await get_tree().create_timer(duration).timeout
skip -= 1

View File

@ -0,0 +1,9 @@
[gd_scene load_steps=2 format=3 uid="uid://bivxnxwi863o0"]
[ext_resource type="Script" path="res://character/animation/AnimationComponent.gd" id="1_lenw3"]
[node name="Animation" type="Node"]
script = ExtResource("1_lenw3")
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
playback_default_blend_time = 0.2

View File

@ -2,10 +2,11 @@ class_name HealthComponent
extends Node extends Node
@export var max_health: float @export var max_health: float
var health: float var health: float
func _ready(): func _ready():
pass health = max_health
func take_damage(attack: Attack): func take_damage(attack: Attack):
health -= attack.damage health -= attack.damage

View File

@ -2,5 +2,5 @@
[ext_resource type="Script" path="res://character/health/HealthComponent.gd" id="1_403dm"] [ext_resource type="Script" path="res://character/health/HealthComponent.gd" id="1_403dm"]
[node name="HealthComponent" type="Node"] [node name="Health" type="Node"]
script = ExtResource("1_403dm") script = ExtResource("1_403dm")

View File

@ -0,0 +1,42 @@
class_name MovementComponent
extends Node
@export var move_speed := 4.5
@export var jump_velocity := 4.5
@export var deceleration := 0.75
var body: CharacterBody3D
var direction: Vector3
var gravity: float
func _ready():
if owner.has_signal("direction_changed"):
owner.direction_changed.connect(on_direction_changed)
if owner.has_signal("jumped"):
owner.jumped.connect(jump)
body = owner as CharacterBody3D
gravity = ProjectSettings.get_setting("physics/3d/default_gravity")
func _physics_process(delta):
if direction:
body.velocity.x = direction.x * move_speed
body.velocity.z = direction.z * move_speed
else:
body.velocity.x *= deceleration
body.velocity.z *= deceleration
if !body.is_on_floor():
body.velocity.y -= gravity * delta
body.move_and_slide()
func on_direction_changed(new_direction: Vector3):
direction = new_direction
func can_jump() -> bool:
return body.is_on_floor()
func jump():
body.velocity.y = jump_velocity

View File

@ -0,0 +1,6 @@
[gd_scene load_steps=2 format=3 uid="uid://x102pryt2s5a"]
[ext_resource type="Script" path="res://character/movement/MovementComponent.gd" id="1_2gnmd"]
[node name="Movement" type="Node"]
script = ExtResource("1_2gnmd")

View File

@ -0,0 +1,25 @@
class_name RotationComponent
extends Node
@export var root: Node3D
@export var rotation_speed: float = 20.0
var direction: Vector3
var angle: float
func _ready():
assert(root, "Rotation root needs to be set")
if owner.has_signal("direction_changed"):
owner.direction_changed.connect(on_direction_changed)
update_configuration_warnings()
func _process(delta):
if direction != Vector3.ZERO:
angle = atan2(direction.x, direction.z)
root.rotation.y = lerp_angle(root.rotation.y, angle, rotation_speed * delta)
func on_direction_changed(new_direction: Vector3):
direction = new_direction

View File

@ -0,0 +1,6 @@
[gd_scene load_steps=2 format=3 uid="uid://d0onbq0ad1ap4"]
[ext_resource type="Script" path="res://character/rotation/RotationComponent.gd" id="1_j1874"]
[node name="Rotation" type="Node"]
script = ExtResource("1_j1874")

View File

@ -0,0 +1,2 @@
class_name Controller
extends Node

View File

@ -1,2 +1,2 @@
class_name EnemyController class_name EnemyController
extends Node extends Controller

View File

@ -0,0 +1,34 @@
class_name PlayerController
extends Controller
## The character that we're controlling.
var player: Player
## We need the movement component to check if we can perform certain actions.
var movement: MovementComponent
func _init(new_player: Player):
player = new_player
movement = player.find_child("Movement")
func _unhandled_input(event):
if Global.interacting_with_ui:
return
# Calculate the direction
var move := Input.get_vector("move_left", "move_right", "move_forward", "move_backward")
var direction := (Global.camera.transform.basis * Vector3(move.x, 0, move.y))
direction.y = 0
direction = direction.normalized()
# Notify components
player.set_direction(direction)
if event.is_action_pressed("jump") && movement && movement.can_jump():
player.jump()
if event.is_action_pressed("dash"):
player.dash()
if event.is_action_pressed("attack"):
player.attack()

View File

@ -0,0 +1,25 @@
class_name ProxyController
extends Controller
## The character that we're controlling.
var player: Player
## The authoritative position on the server.
var server_position: Vector3
func _init(new_player: Player):
player = new_player
func _ready():
server_position = player.position
func _process(_delta):
var move := server_position - player.position
move.y = 0.0
if move.length_squared() < 0.01:
player.set_direction(Vector3.ZERO)
return
var direction := Vector3(move.x, 0, move.z).normalized()
player.set_direction(direction)

View File

@ -1,8 +1,9 @@
[gd_scene load_steps=8 format=3 uid="uid://cb2t7bvvf3gwh"] [gd_scene load_steps=9 format=3 uid="uid://cb2t7bvvf3gwh"]
[ext_resource type="PackedScene" uid="uid://b358op5h1y83m" path="res://assets/slime/Slime.blend" id="1_1h1hj"] [ext_resource type="PackedScene" uid="uid://b358op5h1y83m" path="res://assets/slime/Slime.blend" id="1_1h1hj"]
[ext_resource type="Script" path="res://enemy/Enemy.gd" id="1_r5888"] [ext_resource type="Script" path="res://enemy/Enemy.gd" id="1_r5888"]
[ext_resource type="PackedScene" uid="uid://2bbycjulf00g" path="res://character/health/HealthComponent.tscn" id="2_fsqxc"] [ext_resource type="PackedScene" uid="uid://2bbycjulf00g" path="res://character/health/HealthComponent.tscn" id="2_fsqxc"]
[ext_resource type="PackedScene" uid="uid://x102pryt2s5a" path="res://character/movement/MovementComponent.tscn" id="3_2phqx"]
[sub_resource type="BoxShape3D" id="BoxShape3D_x1ppt"] [sub_resource type="BoxShape3D" id="BoxShape3D_x1ppt"]
size = Vector3(0.7, 0.6, 0.7) size = Vector3(0.7, 0.6, 0.7)
@ -35,9 +36,8 @@ _data = {
"slime_idle": SubResource("Animation_mdtm7") "slime_idle": SubResource("Animation_mdtm7")
} }
[node name="Slime" type="CharacterBody3D" node_paths=PackedStringArray("model") groups=["enemy"]] [node name="Slime" type="CharacterBody3D" groups=["enemy"]]
script = ExtResource("1_r5888") script = ExtResource("1_r5888")
model = NodePath("Model")
[node name="Model" parent="." instance=ExtResource("1_1h1hj")] [node name="Model" parent="." instance=ExtResource("1_1h1hj")]
@ -53,3 +53,5 @@ libraries = {
autoplay = "slime_idle" autoplay = "slime_idle"
[node name="Health" parent="." instance=ExtResource("2_fsqxc")] [node name="Health" parent="." instance=ExtResource("2_fsqxc")]
[node name="Movement" parent="." instance=ExtResource("3_2phqx")]

View File

@ -41,12 +41,11 @@ func spawn_player(id: String) -> Player:
player.id = id player.id = id
if id == Global.account_id: if id == Global.account_id:
player.controller = PlayerController.new() player.controller = PlayerController.new(player)
Global.player = player Global.player = player
main_player_spawned.emit(player) main_player_spawned.emit(player)
else: else:
player.controller = ProxyController.new() player.controller = ProxyController.new(player)
player.controller.character = player
player.add_child(player.controller) player.add_child(player.controller)
return player return player

View File

@ -1,64 +0,0 @@
class_name AnimationController
extends Node
@export var character: Character
@export var animation_player: AnimationPlayer
var next_animation: StringName = "RESET"
func _ready():
assert(character)
assert(animation_player)
func _process(_delta):
if character.velocity.y > 0:
play("human/jump")
elif character.velocity.y < 0:
play("human/fall")
elif character.direction != Vector3.ZERO:
play("human/run-fast")
else:
play("human/idle")
if animation_player.current_animation == next_animation:
return
animation_player.play(next_animation)
func play(action_name: StringName):
next_animation = action_name
# func air(y_velocity: float):
# if y_velocity > 0:
# play("rifle_jump")
# else:
# play("falling")
# func aim(move: Vector2, is_shooting: bool):
# if move.x > 0:
# play("rifle_aim_strafe_right")
# elif move.x < 0:
# play("rifle_aim_strafe_left")
# elif move.y < 0:
# play("rifle_aim_walk_forward")
# elif move.y > 0:
# play("rifle_aim_walk_backward")
# else:
# play("rifle_aim")
# if is_shooting:
# play("rifle_shoot")
# func run(move: Vector2, is_shooting: bool):
# if move.y < 0:
# play("rifle_run_forward")
# elif move.y > 0:
# play("rifle_run_backward")
# elif move.x > 0:
# play("rifle_run_right")
# elif move.x < 0:
# play("rifle_run_left")
# elif is_shooting:
# play("rifle_shoot")
# else:
# play("rifle_idle")

View File

@ -1,8 +1,29 @@
class_name Player class_name Player
extends Character extends CharacterBody3D
signal attacked
signal dashed
signal jumped
signal direction_changed
var controller: Controller
func attack():
attacked.emit()
func dash():
dashed.emit()
func jump():
jumped.emit()
func set_direction(direction: Vector3):
direction_changed.emit(direction)
# TODO: Remove this:
var id: String var id: String
func set_character_name(new_name: String): func set_character_name(new_name: String):
name = new_name name = new_name
get_node("Label").text = name $Label.text = name

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=11 format=3 uid="uid://2lcnu3dy54lx"] [gd_scene load_steps=13 format=3 uid="uid://2lcnu3dy54lx"]
[ext_resource type="Script" path="res://player/Player.gd" id="1_8gebs"] [ext_resource type="Script" path="res://player/Player.gd" id="1_8gebs"]
[ext_resource type="PackedScene" uid="uid://c8j7t4yg7anb0" path="res://assets/female/Female.blend" id="2_8nah6"] [ext_resource type="PackedScene" uid="uid://c8j7t4yg7anb0" path="res://assets/female/Female.blend" id="2_8nah6"]
@ -6,17 +6,18 @@
[ext_resource type="PackedScene" uid="uid://cgqbkj8wbcatv" path="res://assets/hair/PonyTail.blend" id="3_umw6q"] [ext_resource type="PackedScene" uid="uid://cgqbkj8wbcatv" path="res://assets/hair/PonyTail.blend" id="3_umw6q"]
[ext_resource type="FontFile" uid="uid://b7mov13kwi8u8" path="res://assets/font/ubuntu_nf_regular.ttf" id="4_76ehj"] [ext_resource type="FontFile" uid="uid://b7mov13kwi8u8" path="res://assets/font/ubuntu_nf_regular.ttf" id="4_76ehj"]
[ext_resource type="Skin" uid="uid://bbqyiue1vj37f" path="res://assets/hoodie/Hoodie_Skin.tres" id="4_b1tg1"] [ext_resource type="Skin" uid="uid://bbqyiue1vj37f" path="res://assets/hoodie/Hoodie_Skin.tres" id="4_b1tg1"]
[ext_resource type="Script" path="res://player/AnimationController.gd" id="4_i2ybk"]
[ext_resource type="ArrayMesh" uid="uid://b3qvgfg41b7jo" path="res://assets/hoodie/Hoodie_Mesh.res" id="5_mkrgn"] [ext_resource type="ArrayMesh" uid="uid://b3qvgfg41b7jo" path="res://assets/hoodie/Hoodie_Mesh.res" id="5_mkrgn"]
[ext_resource type="AnimationLibrary" uid="uid://d4n0puibh4hyt" path="res://assets/animations/human.blend" id="6_fl6or"] [ext_resource type="PackedScene" uid="uid://x102pryt2s5a" path="res://character/movement/MovementComponent.tscn" id="8_25qd0"]
[ext_resource type="PackedScene" uid="uid://d0onbq0ad1ap4" path="res://character/rotation/RotationComponent.tscn" id="9_agxqu"]
[ext_resource type="PackedScene" uid="uid://bivxnxwi863o0" path="res://character/animation/AnimationComponent.tscn" id="10_bcaeg"]
[ext_resource type="AnimationLibrary" uid="uid://d4n0puibh4hyt" path="res://assets/animations/human.blend" id="11_d0e6r"]
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_2f50n"] [sub_resource type="CapsuleShape3D" id="CapsuleShape3D_2f50n"]
radius = 0.25 radius = 0.25
height = 1.6 height = 1.6
[node name="Player" type="CharacterBody3D" node_paths=PackedStringArray("model") groups=["player"]] [node name="Player" type="CharacterBody3D" groups=["player"]]
script = ExtResource("1_8gebs") script = ExtResource("1_8gebs")
model = NodePath("Model")
[node name="Model" type="Node3D" parent="."] [node name="Model" type="Node3D" parent="."]
@ -94,20 +95,6 @@ bone_idx = 12
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.8, 0) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.8, 0)
shape = SubResource("CapsuleShape3D_2f50n") shape = SubResource("CapsuleShape3D_2f50n")
[node name="Animation" type="Node" parent="." node_paths=PackedStringArray("character", "animation_player")]
script = ExtResource("4_i2ybk")
character = NodePath("..")
animation_player = NodePath("../AnimationPlayer")
[node name="Health" parent="." instance=ExtResource("2_np5ag")]
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
root_node = NodePath("../Model/Female")
libraries = {
"human": ExtResource("6_fl6or")
}
playback_default_blend_time = 0.2
[node name="Label" type="Label3D" parent="."] [node name="Label" type="Label3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2, 0) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2, 0)
pixel_size = 0.001 pixel_size = 0.001
@ -119,4 +106,20 @@ font = ExtResource("4_76ehj")
font_size = 128 font_size = 128
outline_size = 32 outline_size = 32
[node name="Health" parent="." instance=ExtResource("2_np5ag")]
[node name="Movement" parent="." instance=ExtResource("8_25qd0")]
[node name="Rotation" parent="." node_paths=PackedStringArray("root") instance=ExtResource("9_agxqu")]
root = NodePath("../Model")
[node name="Animation" parent="." instance=ExtResource("10_bcaeg")]
[node name="AnimationPlayer" parent="Animation" index="0"]
root_node = NodePath("../../Model/Female")
libraries = {
"human": ExtResource("11_d0e6r")
}
[editable path="Model/Female"] [editable path="Model/Female"]
[editable path="Animation"]

View File

@ -1,5 +0,0 @@
class_name Controller
extends Node
## The character that we're controlling.
@export var character: Character

View File

@ -1,22 +0,0 @@
class_name PlayerController
extends Controller
var move: Vector2
func _unhandled_input(event):
if Global.interacting_with_ui:
return
move = Input.get_vector("move_left", "move_right", "move_forward", "move_backward")
character.direction = (Global.camera.transform.basis * Vector3(move.x, 0, move.y))
character.direction.y = 0
character.direction = character.direction.normalized()
if event.is_action_pressed("jump"):
character.jump()
if event.is_action_pressed("dash"):
character.dash()
if event.is_action_pressed("attack"):
character.attack()

View File

@ -1,19 +0,0 @@
class_name ProxyController
extends Controller
## The authoritative position on the server.
var server_position: Vector3
func _ready():
server_position = character.position
func _process(_delta):
var move := server_position - character.position
move.y = 0.0
if move.length_squared() < 0.01:
character.direction = Vector3.ZERO
return
character.direction = Vector3(move.x, 0, move.z)
character.direction = character.direction.normalized()