Merge branch 'feat/fully-skinned-3rd-person-character' into 'develop'

Fully skinned 3rd person character, aim IK basic setup

See merge request open-fpsz/open-fpsz!29
This commit is contained in:
anyreso 2024-04-13 20:18:32 +00:00
commit c76c149302
13 changed files with 14600 additions and 20 deletions

View file

@ -0,0 +1,27 @@
class_name Vanguard extends Node
@export var spine_ik_target_attachment : Node3D
@onready var animation_tree : AnimationTree = $AnimationTree
@onready var spine_ik = $Node/Skeleton3D/SpineIK
@onready var spine_ik_target = $SpineIKTarget
enum GroundState { GROUND_STATE_GROUNDED, GROUND_STATE_MID_AIR, GROUND_STATE_DEAD }
func _ready():
spine_ik.start()
func _process(_delta):
spine_ik_target.global_transform = spine_ik_target_attachment.global_transform
func set_locomotion(locomotion : Vector2, ground_speed_factor : float) -> void:
animation_tree.set("parameters/Locomotion/blend_position", locomotion)
animation_tree.set("parameters/GroundSpeed/scale", ground_speed_factor)
func set_ground_state(ground_state : GroundState):
var transition_name = "grounded"
if ground_state == GroundState.GROUND_STATE_MID_AIR:
transition_name = "mid_air"
if ground_state == GroundState.GROUND_STATE_DEAD:
transition_name = "dead"
animation_tree.set("parameters/Transition/transition_request", transition_name)

Binary file not shown.

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

View file

@ -0,0 +1,36 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://ia3bdpe4rm1m"
path.s3tc="res://.godot/imported/vanguard_0.png-601f36bc664114e126d425d5f45085ef.s3tc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
generator_parameters={}
[deps]
source_file="res://entities/player/assets/vanguard_0.png"
dest_files=["res://.godot/imported/vanguard_0.png-601f36bc664114e126d425d5f45085ef.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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

View file

@ -0,0 +1,36 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bvgfmpb2l1juf"
path.s3tc="res://.godot/imported/vanguard_1.png-39b5712c4c4119a42b3540a159f8b3f2.s3tc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
generator_parameters={}
[deps]
source_file="res://entities/player/assets/vanguard_1.png"
dest_files=["res://.godot/imported/vanguard_1.png-39b5712c4c4119a42b3540a159f8b3f2.s3tc.ctex"]
[params]
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=1
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=1
roughness/src_normal="res://entities/player/assets/vanguard_1.png"
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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

View file

@ -0,0 +1,36 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://vtrbc3eja3df"
path.s3tc="res://.godot/imported/vanguard_2.png-986e3665904b0d4758f584d5d3b7b726.s3tc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
generator_parameters={}
[deps]
source_file="res://entities/player/assets/vanguard_2.png"
dest_files=["res://.godot/imported/vanguard_2.png-986e3665904b0d4758f584d5d3b7b726.s3tc.ctex"]
[params]
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=1
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=1
roughness/src_normal="res://entities/player/assets/vanguard_2.png"
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

View file

@ -50,16 +50,20 @@ func _ready():
health_component.health_changed.connect(iff._on_health_changed)
health_component.health_changed.emit(health_component.health)
health_component.health_zeroed.connect(_die)
if player_id == multiplayer.get_unique_id():
if _is_first_person():
camera.current = true
remove_child($ThirdPerson)
else:
remove_child($HUD)
weapon.hide()
input.fired_primary.connect(_fire_primary)
input.jumped.connect(_jump)
func _is_first_person():
return player_id == multiplayer.get_unique_id()
func _fire_primary():
if player_state == PlayerState.PLAYER_DEAD:
if _is_player_dead():
return
if not weapon.can_fire():
return
@ -67,11 +71,12 @@ func _fire_primary():
weapon.transform = _original_weapon_transform
weapon.fire_primary()
weapon.transform = current_weapon_transform
animation_player.stop()
animation_player.play("shoot")
if _is_first_person():
animation_player.stop()
animation_player.play("shoot")
func _jump():
if player_state == PlayerState.PLAYER_DEAD:
if _is_player_dead():
return
_jumping = true
@ -95,26 +100,30 @@ func _handle_jetpack(delta, direction):
energy_changed.emit(energy)
func _process(_delta):
if player_state == PlayerState.PLAYER_DEAD:
if _is_player_dead():
iff.hide()
return
else:
iff.show()
if not _is_first_person():
$ThirdPerson/PlayerMesh.global_transform.basis = Basis.from_euler(Vector3(0.0, input.camera_rotation.x + PI, 0.0))
else:
if animation_player.current_animation == "shoot":
pass
else:
animation_player.play("idle")
%SpringArm3D.global_transform.basis = Basis.from_euler(Vector3(input.camera_rotation.y, input.camera_rotation.x, 0.0))
if animation_player.current_animation == "shoot":
pass
else:
animation_player.play("idle")
func _physics_process(delta):
if player_state == PlayerState.PLAYER_DEAD:
return
# retrieve user's direction vector
var _input_dir = input.direction
# compute direction in local space
var _direction = (transform.basis * Vector3(_input_dir.x, 0, _input_dir.y)).normalized()
_update_third_person_animations()
if _is_player_dead():
return
# adjust direction based on spring arm rotation
_direction = _direction.rotated(Vector3.UP, $SpringArm3D.rotation.y)
@ -144,14 +153,39 @@ func _physics_process(delta):
_jumping = false
func _update_third_person_animations():
if _is_first_person():
return
var tp_player : Vanguard = $ThirdPerson/PlayerMesh
if _is_player_dead():
tp_player.set_ground_state(Vanguard.GroundState.GROUND_STATE_DEAD)
return
if _is_on_floor():
tp_player.set_ground_state(Vanguard.GroundState.GROUND_STATE_GROUNDED)
else:
tp_player.set_ground_state(Vanguard.GroundState.GROUND_STATE_MID_AIR)
var local_velocity = (tp_player.global_basis.inverse() * linear_velocity)
const bias : float = 1.2 # Basically match feet speed with ground speed
tp_player.set_locomotion(Vector2(local_velocity.x, local_velocity.z), bias)
func _is_player_dead():
return player_state == PlayerState.PLAYER_DEAD
func _die():
player_state = PlayerState.PLAYER_DEAD
animation_player.stop()
animation_player.play("death")
if _is_first_person():
animation_player.stop()
animation_player.play("death")
var tween = create_tween()
tween.tween_interval(2)
tween.tween_interval(4)
tween.tween_callback(func(): died.emit(self))
tween.tween_callback(func(): animation_player.stop())
tween.tween_callback(func():
if _is_first_person():
animation_player.stop()
)
func respawn(location):
linear_velocity = Vector3()

View file

@ -1,7 +1,8 @@
[gd_scene load_steps=18 format=3 uid="uid://cbhx1xme0sb7k"]
[gd_scene load_steps=20 format=3 uid="uid://cbhx1xme0sb7k"]
[ext_resource type="Script" path="res://entities/player/player.gd" id="1_mk68k"]
[ext_resource type="Shape3D" uid="uid://dkwljsgaflf31" path="res://entities/player/collision_shape.res" id="2_8rtw3"]
[ext_resource type="PackedScene" uid="uid://drbefw6akui2v" path="res://entities/player/assets/vanguard.tscn" id="2_beyex"]
[ext_resource type="PackedScene" uid="uid://bcv81ku26xo" path="res://interfaces/hud/hud.tscn" id="3_ccety"]
[ext_resource type="PackedScene" uid="uid://c8co0qa2omjmh" path="res://weapons/space_gun/space_gun.tscn" id="4_lhn5w"]
[ext_resource type="PackedScene" uid="uid://dn1tcakam5egs" path="res://weapons/space_gun/projectile.tscn" id="5_lvaut"]
@ -203,6 +204,7 @@ continuous_cd = true
script = ExtResource("1_mk68k")
[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
visible = false
mesh = SubResource("CapsuleMesh_vmqfq")
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
@ -231,6 +233,9 @@ near = 0.1
transform = Transform3D(-1, 0, 2.53518e-06, 0, 1, 0, -2.53518e-06, 0, -1, 0.244668, -0.229311, -0.30332)
PROJECTILE = ExtResource("5_lvaut")
[node name="SpineIKTarget" type="Node3D" parent="SpringArm3D"]
transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 0, 0, 0)
[node name="HealthComponent" parent="." instance=ExtResource("5_t6i6e")]
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
@ -250,6 +255,10 @@ script = ExtResource("6_ymcrr")
[node name="ThirdPerson" type="Node3D" parent="."]
[node name="PlayerMesh" parent="ThirdPerson" node_paths=PackedStringArray("spine_ik_target_attachment") instance=ExtResource("2_beyex")]
transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 0, 0, 0)
spine_ik_target_attachment = NodePath("../../SpringArm3D/SpineIKTarget")
[node name="IFFAttachment" type="Node3D" parent="ThirdPerson"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.27457, 0)

View file

@ -4,4 +4,4 @@ func _test_projectile_class():
var projectile = Projectile.new()
assert(projectile != null, "Projectile class should be instantiated")
assert(projectile.speed == 78.4, "Projectile damage should be initialized to 78.4")