diff --git a/Game/Classes/Player/CollisionShapeBody.gd b/Game/Classes/Player/CollisionShapeBody.gd new file mode 100644 index 0000000..c82e832 --- /dev/null +++ b/Game/Classes/Player/CollisionShapeBody.gd @@ -0,0 +1,51 @@ +# This script moves the shape up half the amount it shrinks when crouching +# This way the top of the capsule keeps the same relative position to the camera +# Moving the camera instead would cause a camera move when crouching in the air +# which is weird (I tested it). +# +# It also acts as a middleman to ensure crouching will work with all shape types + +extends CollisionShape + +var height: = 1.0 setget set_height, get_height + +var _normal_height: float +var _normal_y: float + +func _ready() -> void: + _normal_y = translation.y + + match shape.get_class(): + "CapsuleShape": + _normal_height = shape.height + + "BoxShape": + _normal_height = shape.extents.z + + var another_class: + push_error("Height logic not implemented for shape %s" % another_class) + +func _process(delta: float) -> void: + if _normal_height: + # Using self. make so we call the setter even though we're inside the objecr + translation.y = _normal_y + (_normal_height - self.height) / 2.0 + +func set_height(value: float) -> void: + match shape.get_class(): + "CapsuleShape": + shape.height = value + + "BoxShape": + shape.extents.z = value + +func get_height() -> float: + match shape.get_class(): + "CapsuleShape": + return shape.height + + "BoxShape": + return shape.extents.z + + var _: + return 0.0 + diff --git a/Game/Classes/Player/Player.gd b/Game/Classes/Player/Player.gd index bcb3cdc..cca69e2 100644 --- a/Game/Classes/Player/Player.gd +++ b/Game/Classes/Player/Player.gd @@ -2,8 +2,13 @@ class_name Player extends KinematicBody const GRAVITY = Vector3.DOWN * 9.8 * 1.5 +const UP = Vector3.UP const JUMP_VELOCITY = 8 const WALK_VELOCITY = 8 +const CROUCH_WALK_VELOCITY = 2 +const CROUCH_VELOCITY = 5 +const HEIGHT = 1.1 +const CROUCH_HEIGHT = 0.55 const AIR_CONTROL = 0.1 @@ -16,6 +21,7 @@ const MOUSE_SENSITIVITY = 1.0 / 1000 export var show_healthbar = true export var max_health = 150 onready var health = max_health setget set_health +onready var collision_shape: = $CollisionShapeBody onready var camera = $Camera onready var debug = $Debug @@ -102,7 +108,7 @@ func on_bullet_flyby(from, to): get_tree().root.call_deferred("add_child", flyby_noise) remote func jump(): - if is_on_floor: + if is_on_floor(): velocity.y = JUMP_VELOCITY jump_timeout = 0.2 $Sounds/Jump.play() @@ -160,7 +166,7 @@ func jetpack_grounded(delta): ] # Only charge when grounded. - if is_on_floor: + if is_on_floor(): jetpack_fuel = clamp( jetpack_fuel + JETPACK_REFILL_RATE * delta, 0.0, @@ -194,8 +200,6 @@ func _physics_process(delta): if get_parent().name != "Players": return - check_floor_collision() - walk(delta) fall(delta) jetpack_grounded(delta) @@ -208,30 +212,16 @@ func _physics_process(delta): if jump_timeout > 0: movement_vector = move_and_slide(velocity, Vector3.UP) else: - var upvector = floor_normal - movement_vector = move_and_slide_with_snap(velocity, Vector3.DOWN, upvector, true) + movement_vector = move_and_slide_with_snap(velocity, Vector3.DOWN, UP, true) velocity = movement_vector rset("translation", translation) -func check_floor_collision(): - var space_state = get_world().direct_space_state - - var from = global_transform.xform(Vector3(0, 0.0, 0)) - var to = global_transform.xform(Vector3(0, -0.3, 0.0)) - - var result = space_state.intersect_ray(from, to) - - if jump_timeout > 0: - is_on_floor = false - elif result: - is_on_floor = true - floor_normal = result.normal - else: - is_on_floor = false - func walk(delta): + var floor_normal = get_floor_normal() + var is_on_floor = is_on_floor() + jump_timeout -= delta # Walk @@ -254,7 +244,8 @@ func walk(delta): walking_speed = walking_speed.rotated(rotation.y) if is_on_floor: - walking_speed = lerp(walking_speed, walk_direction * WALK_VELOCITY, delta * WALK_ACCEL) + var target_velocity: = WALK_VELOCITY if not Input.is_action_pressed("Crouch") else CROUCH_WALK_VELOCITY + walking_speed = lerp(walking_speed, walk_direction * target_velocity, delta * WALK_ACCEL) else: walking_speed = lerp(walking_speed, walk_direction * JUMP_VELOCITY, delta * JUMP_ACCEL) walking_speed = walking_speed.rotated(-rotation.y) @@ -263,7 +254,7 @@ func walk(delta): velocity.z = walking_speed.y # Make walking perpendicular to the floor - if is_on_floor: + if is_on_floor and not Input.is_action_pressed("MoveJump") and floor_normal.y: velocity.y -= velocity.dot(floor_normal) / floor_normal.y if walking_speed.length() > 0 and is_on_floor: @@ -271,16 +262,25 @@ func walk(delta): elif walking_speed.length() == 0 and is_on_floor: weapon_bob_anim.travel("Idle") + # Crouch + if not get_tree().is_input_handled(): + if Input.is_action_pressed("Crouch"): + collision_shape.height = move_toward(collision_shape.height, CROUCH_HEIGHT, CROUCH_VELOCITY * delta) + else: + collision_shape.height = move_toward(collision_shape.height, HEIGHT, CROUCH_VELOCITY * delta) +# collision_shape.shape.height = move_toward(collision_shape.shape.height, HEIGHT, CROUCH_VELOCITY * delta) + + collision_shape.height = stepify(collision_shape.height, 0.01) + func fall(delta): - if is_on_floor: + if is_on_floor(): if not was_on_floor: # if this is the first frame of ground conotact after a frame of no ground contact - we've just ended a fall weapon_bob_anim.travel("Land") - else: velocity += delta * GRAVITY - was_on_floor = is_on_floor + was_on_floor = is_on_floor() master func on_hit(damage, location): diff --git a/Game/Classes/Player/Player.tscn b/Game/Classes/Player/Player.tscn index a944b4c..cb478af 100644 --- a/Game/Classes/Player/Player.tscn +++ b/Game/Classes/Player/Player.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=44 format=2] +[gd_scene load_steps=45 format=2] [ext_resource path="res://Classes/UI/Health.tscn" type="PackedScene" id=1] [ext_resource path="res://Classes/UI/Billboard.gd" type="Script" id=2] @@ -12,6 +12,7 @@ [ext_resource path="res://Assets/Weapons/GrenadeLauncher/GrenadeLauncher.tscn" type="PackedScene" id=10] [ext_resource path="res://Assets/Effects/CircleSoft.svg" type="Texture" id=11] [ext_resource path="res://Assets/Maps/DM1/OmniFlicker.gd" type="Script" id=12] +[ext_resource path="res://Classes/Player/CollisionShapeBody.gd" type="Script" id=14] [sub_resource type="AnimationNodeAnimation" id=1] animation = "Idle" @@ -220,7 +221,7 @@ script = ExtResource( 8 ) transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.53592, -0.0651628 ) [node name="Hand" type="Spatial" parent="Camera"] -transform = Transform( -4.37114e-08, 0, -1, 0, 1, 0, 1, 0, -4.37114e-08, 0.335, -0.390282, -0.559 ) +transform = Transform( -4.37114e-08, 0, -1, 0, 1, 0, 1, 0, -4.37114e-08, 0.335, -0.391038, -0.559 ) [node name="WeaponBobAnimationTree" type="AnimationTree" parent="Camera/Hand"] tree_root = SubResource( 12 ) @@ -286,6 +287,7 @@ margin_bottom = 104.0 [node name="CollisionShapeBody" type="CollisionShape" parent="."] transform = Transform( 1, 0, 0, 0, -1.62921e-07, 1, 0, -1, -1.62921e-07, 0, 0.882822, 0 ) shape = SubResource( 19 ) +script = ExtResource( 14 ) [node name="Debug" type="Label" parent="."] margin_right = 41.0 diff --git a/Game/Classes/UI/TextChat.tscn b/Game/Classes/UI/TextChat.tscn index f151358..ce0e620 100644 --- a/Game/Classes/UI/TextChat.tscn +++ b/Game/Classes/UI/TextChat.tscn @@ -30,6 +30,7 @@ margin_left = 8.0 margin_top = 8.0 margin_right = -8.0 margin_bottom = -8.0 +focus_mode = 2 text = " " scroll_following = true diff --git a/Game/project.godot b/Game/project.godot index a6119d1..19eb6c7 100644 --- a/Game/project.godot +++ b/Game/project.godot @@ -114,6 +114,11 @@ ToggleChatVisibility={ "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":89,"unicode":0,"echo":false,"script":null) ] } +Crouch={ +"deadzone": 0.5, +"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777238,"unicode":0,"echo":false,"script":null) + ] +} [rendering]