Compare commits
10 Commits
e3f652e6b1
...
0c1ded340a
Author | SHA1 | Date |
---|---|---|
Jarrod Doyle | 0c1ded340a | |
Jarrod Doyle | 085118ddfa | |
Jarrod Doyle | 78bca9eafb | |
Jarrod Doyle | eda51bcb50 | |
Jarrod Doyle | bcff3d172e | |
Jarrod Doyle | 9c9a3ecc26 | |
Jarrod Doyle | 2b01dfaeaa | |
Jarrod Doyle | 050a897cad | |
Jarrod Doyle | 89ec939325 | |
Jarrod Doyle | 4d95b7d9d1 |
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "GDScript: Launch Project",
|
||||||
|
"type": "godot",
|
||||||
|
"request": "launch",
|
||||||
|
"project": "${workspaceFolder}",
|
||||||
|
"debug_collisions": false,
|
||||||
|
"debug_paths": false,
|
||||||
|
"debug_navigation": false,
|
||||||
|
"additional_options": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -1,21 +0,0 @@
|
||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2023 Ryan Haskell-Glatz
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
|
@ -1,70 +0,0 @@
|
||||||
@tool
|
|
||||||
class_name FormatOnSave extends EditorPlugin
|
|
||||||
|
|
||||||
const SUCCESS: int = 0
|
|
||||||
const AUTO_RELOAD_SETTING: String = "text_editor/behavior/files/auto_reload_scripts_on_external_change"
|
|
||||||
var original_auto_reload_setting: bool
|
|
||||||
|
|
||||||
|
|
||||||
# LIFECYCLE EVENTS
|
|
||||||
func _enter_tree():
|
|
||||||
activate_auto_reload_setting()
|
|
||||||
resource_saved.connect(on_resource_saved)
|
|
||||||
|
|
||||||
|
|
||||||
func _exit_tree():
|
|
||||||
resource_saved.disconnect(on_resource_saved)
|
|
||||||
restore_original_auto_reload_setting()
|
|
||||||
|
|
||||||
|
|
||||||
# CALLED WHEN A SCRIPT IS SAVED
|
|
||||||
func on_resource_saved(resource: Resource):
|
|
||||||
if resource is Script:
|
|
||||||
var script: Script = resource
|
|
||||||
var current_script = get_editor_interface().get_script_editor().get_current_script()
|
|
||||||
var text_edit: CodeEdit = (
|
|
||||||
get_editor_interface().get_script_editor().get_current_editor().get_base_editor()
|
|
||||||
)
|
|
||||||
|
|
||||||
# Prevents other unsaved scripts from overwriting the active one
|
|
||||||
if current_script == script:
|
|
||||||
var filepath: String = ProjectSettings.globalize_path(resource.resource_path)
|
|
||||||
|
|
||||||
# Run gdformat
|
|
||||||
var exit_code = OS.execute("gdformat", [filepath])
|
|
||||||
|
|
||||||
# Replace source_code with formatted source_code
|
|
||||||
if exit_code == SUCCESS:
|
|
||||||
var formatted_source = FileAccess.get_file_as_string(resource.resource_path)
|
|
||||||
FormatOnSave.reload_script(text_edit, formatted_source)
|
|
||||||
|
|
||||||
|
|
||||||
# Workaround until this PR is merged:
|
|
||||||
# https://github.com/godotengine/godot/pull/83267
|
|
||||||
# Thanks, @KANAjetzt 💖
|
|
||||||
static func reload_script(text_edit: TextEdit, source_code: String) -> void:
|
|
||||||
var column := text_edit.get_caret_column()
|
|
||||||
var row := text_edit.get_caret_line()
|
|
||||||
var scroll_position_h := text_edit.get_h_scroll_bar().value
|
|
||||||
var scroll_position_v := text_edit.get_v_scroll_bar().value
|
|
||||||
|
|
||||||
text_edit.text = source_code
|
|
||||||
text_edit.set_caret_column(column)
|
|
||||||
text_edit.set_caret_line(row)
|
|
||||||
text_edit.scroll_horizontal = scroll_position_h
|
|
||||||
text_edit.scroll_vertical = scroll_position_v
|
|
||||||
|
|
||||||
text_edit.tag_saved_version()
|
|
||||||
|
|
||||||
|
|
||||||
# For this workaround to work, we need to disable the "Reload/Resave" pop-up
|
|
||||||
func activate_auto_reload_setting():
|
|
||||||
var settings := get_editor_interface().get_editor_settings()
|
|
||||||
original_auto_reload_setting = settings.get(AUTO_RELOAD_SETTING)
|
|
||||||
settings.set(AUTO_RELOAD_SETTING, true)
|
|
||||||
|
|
||||||
|
|
||||||
# If the plugin is disabled, let's attempt to restore the original editor setting
|
|
||||||
func restore_original_auto_reload_setting():
|
|
||||||
var settings := get_editor_interface().get_editor_settings()
|
|
||||||
settings.set(AUTO_RELOAD_SETTING, original_auto_reload_setting)
|
|
|
@ -1,6 +0,0 @@
|
||||||
[plugin]
|
|
||||||
name="Format on Save"
|
|
||||||
description="Runs `gdformat` on save to automatically format your GD script as you code."
|
|
||||||
author="Ryan Haskell-Glatz"
|
|
||||||
version="1.2.0"
|
|
||||||
script="format_on_save.gd"
|
|
|
@ -14,7 +14,6 @@ radius = 0.25
|
||||||
|
|
||||||
[node name="Player" type="StaticBody3D" node_paths=PackedStringArray("head", "body", "camera", "collision_shape", "state_chart")]
|
[node name="Player" type="StaticBody3D" node_paths=PackedStringArray("head", "body", "camera", "collision_shape", "state_chart")]
|
||||||
script = ExtResource("1_i6r2s")
|
script = ExtResource("1_i6r2s")
|
||||||
max_speed = 6
|
|
||||||
slope_limit = 40.0
|
slope_limit = 40.0
|
||||||
step_height = 0.3
|
step_height = 0.3
|
||||||
snap_to_ground_distance = 0.3
|
snap_to_ground_distance = 0.3
|
||||||
|
@ -49,7 +48,8 @@ script = ExtResource("5_mmqqh")
|
||||||
initial_state = NodePath("Grounded")
|
initial_state = NodePath("Grounded")
|
||||||
|
|
||||||
[node name="Grounded" type="Node" parent="StateChart/Root"]
|
[node name="Grounded" type="Node" parent="StateChart/Root"]
|
||||||
script = ExtResource("6_8xdrw")
|
script = ExtResource("5_mmqqh")
|
||||||
|
initial_state = NodePath("Idle")
|
||||||
|
|
||||||
[node name="On Jump" type="Node" parent="StateChart/Root/Grounded"]
|
[node name="On Jump" type="Node" parent="StateChart/Root/Grounded"]
|
||||||
script = ExtResource("7_525mu")
|
script = ExtResource("7_525mu")
|
||||||
|
@ -61,13 +61,73 @@ script = ExtResource("7_525mu")
|
||||||
to = NodePath("../../Airborne/Falling")
|
to = NodePath("../../Airborne/Falling")
|
||||||
event = &"Airborne"
|
event = &"Airborne"
|
||||||
|
|
||||||
|
[node name="Idle" type="Node" parent="StateChart/Root/Grounded"]
|
||||||
|
script = ExtResource("5_mmqqh")
|
||||||
|
initial_state = NodePath("Standling")
|
||||||
|
|
||||||
|
[node name="Crouched" type="Node" parent="StateChart/Root/Grounded/Idle"]
|
||||||
|
script = ExtResource("6_8xdrw")
|
||||||
|
|
||||||
|
[node name="On Crouch" type="Node" parent="StateChart/Root/Grounded/Idle/Crouched"]
|
||||||
|
script = ExtResource("7_525mu")
|
||||||
|
to = NodePath("../../Standling")
|
||||||
|
event = &"Crouch"
|
||||||
|
|
||||||
|
[node name="On Move" type="Node" parent="StateChart/Root/Grounded/Idle/Crouched"]
|
||||||
|
script = ExtResource("7_525mu")
|
||||||
|
to = NodePath("../../../Moving/Crouch Walking")
|
||||||
|
event = &"Move"
|
||||||
|
|
||||||
|
[node name="Standling" type="Node" parent="StateChart/Root/Grounded/Idle"]
|
||||||
|
script = ExtResource("6_8xdrw")
|
||||||
|
|
||||||
|
[node name="On Crouch" type="Node" parent="StateChart/Root/Grounded/Idle/Standling"]
|
||||||
|
script = ExtResource("7_525mu")
|
||||||
|
to = NodePath("../../Crouched")
|
||||||
|
event = &"Crouch"
|
||||||
|
|
||||||
|
[node name="On Move" type="Node" parent="StateChart/Root/Grounded/Idle/Standling"]
|
||||||
|
script = ExtResource("7_525mu")
|
||||||
|
to = NodePath("../../../Moving/Running")
|
||||||
|
event = &"Move"
|
||||||
|
|
||||||
|
[node name="Moving" type="Node" parent="StateChart/Root/Grounded"]
|
||||||
|
script = ExtResource("5_mmqqh")
|
||||||
|
initial_state = NodePath("Running")
|
||||||
|
|
||||||
|
[node name="Crouch Walking" type="Node" parent="StateChart/Root/Grounded/Moving"]
|
||||||
|
script = ExtResource("6_8xdrw")
|
||||||
|
|
||||||
|
[node name="On Idle" type="Node" parent="StateChart/Root/Grounded/Moving/Crouch Walking"]
|
||||||
|
script = ExtResource("7_525mu")
|
||||||
|
to = NodePath("../../../Idle/Crouched")
|
||||||
|
event = &"Idle"
|
||||||
|
|
||||||
|
[node name="On Crouch" type="Node" parent="StateChart/Root/Grounded/Moving/Crouch Walking"]
|
||||||
|
script = ExtResource("7_525mu")
|
||||||
|
to = NodePath("../../Running")
|
||||||
|
event = &"Crouch"
|
||||||
|
|
||||||
|
[node name="Running" type="Node" parent="StateChart/Root/Grounded/Moving"]
|
||||||
|
script = ExtResource("6_8xdrw")
|
||||||
|
|
||||||
|
[node name="On Idle" type="Node" parent="StateChart/Root/Grounded/Moving/Running"]
|
||||||
|
script = ExtResource("7_525mu")
|
||||||
|
to = NodePath("../../../Idle/Standling")
|
||||||
|
event = &"Idle"
|
||||||
|
|
||||||
|
[node name="On Crouch" type="Node" parent="StateChart/Root/Grounded/Moving/Running"]
|
||||||
|
script = ExtResource("7_525mu")
|
||||||
|
to = NodePath("../../Crouch Walking")
|
||||||
|
event = &"Crouch"
|
||||||
|
|
||||||
[node name="Airborne" type="Node" parent="StateChart/Root"]
|
[node name="Airborne" type="Node" parent="StateChart/Root"]
|
||||||
script = ExtResource("5_mmqqh")
|
script = ExtResource("5_mmqqh")
|
||||||
initial_state = NodePath("Jumping")
|
initial_state = NodePath("Jumping")
|
||||||
|
|
||||||
[node name="On Grounded" type="Node" parent="StateChart/Root/Airborne"]
|
[node name="On Grounded" type="Node" parent="StateChart/Root/Airborne"]
|
||||||
script = ExtResource("7_525mu")
|
script = ExtResource("7_525mu")
|
||||||
to = NodePath("../../Grounded")
|
to = NodePath("../../Grounded/Idle/Standling")
|
||||||
event = &"Grounded"
|
event = &"Grounded"
|
||||||
|
|
||||||
[node name="Jumping" type="Node" parent="StateChart/Root/Airborne"]
|
[node name="Jumping" type="Node" parent="StateChart/Root/Airborne"]
|
||||||
|
@ -81,6 +141,9 @@ event = &"Airborne"
|
||||||
[node name="Falling" type="Node" parent="StateChart/Root/Airborne"]
|
[node name="Falling" type="Node" parent="StateChart/Root/Airborne"]
|
||||||
script = ExtResource("6_8xdrw")
|
script = ExtResource("6_8xdrw")
|
||||||
|
|
||||||
[connection signal="state_physics_processing" from="StateChart/Root/Grounded" to="." method="_on_grounded_state_physics_processing"]
|
[connection signal="child_state_entered" from="StateChart/Root" to="." method="_on_root_child_state_entered"]
|
||||||
|
[connection signal="state_processing" from="StateChart/Root" to="." method="_on_root_state_processing"]
|
||||||
|
[connection signal="state_processing" from="StateChart/Root/Grounded/Idle" to="." method="_on_idle_state_processing"]
|
||||||
|
[connection signal="state_physics_processing" from="StateChart/Root/Grounded/Moving/Running" to="." method="_on_running_state_physics_processing"]
|
||||||
[connection signal="state_physics_processing" from="StateChart/Root/Airborne/Jumping" to="." method="_on_jumping_state_physics_processing"]
|
[connection signal="state_physics_processing" from="StateChart/Root/Airborne/Jumping" to="." method="_on_jumping_state_physics_processing"]
|
||||||
[connection signal="state_physics_processing" from="StateChart/Root/Airborne/Falling" to="." method="_on_falling_state_physics_processing"]
|
[connection signal="state_physics_processing" from="StateChart/Root/Airborne/Falling" to="." method="_on_falling_state_physics_processing"]
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
[gd_scene load_steps=274 format=3 uid="uid://dd4qlg15cchu0"]
|
[gd_scene load_steps=275 format=3 uid="uid://dd4qlg15cchu0"]
|
||||||
|
|
||||||
[ext_resource type="Script" path="res://addons/qodot/src/nodes/qodot_map.gd" id="1_7j4vn"]
|
[ext_resource type="Script" path="res://addons/qodot/src/nodes/qodot_map.gd" id="1_7j4vn"]
|
||||||
[ext_resource type="PackedScene" uid="uid://ul8o2n823qod" path="res://content/scenes/player.tscn" id="1_qpwbx"]
|
[ext_resource type="PackedScene" uid="uid://ul8o2n823qod" path="res://content/scenes/player.tscn" id="1_qpwbx"]
|
||||||
|
@ -8,6 +8,7 @@
|
||||||
[ext_resource type="Texture2D" uid="uid://cf6t1ogtfradb" path="res://content/trenchbroom/textures/Prototype/orange9.png" id="5_jv6xk"]
|
[ext_resource type="Texture2D" uid="uid://cf6t1ogtfradb" path="res://content/trenchbroom/textures/Prototype/orange9.png" id="5_jv6xk"]
|
||||||
[ext_resource type="Texture2D" uid="uid://dsocqlbvrhy5m" path="res://content/trenchbroom/textures/Prototype/green2.png" id="6_hoyxc"]
|
[ext_resource type="Texture2D" uid="uid://dsocqlbvrhy5m" path="res://content/trenchbroom/textures/Prototype/green2.png" id="6_hoyxc"]
|
||||||
[ext_resource type="Texture2D" uid="uid://dgxtptqsev380" path="res://content/trenchbroom/textures/Prototype/white6.png" id="7_xqo7b"]
|
[ext_resource type="Texture2D" uid="uid://dgxtptqsev380" path="res://content/trenchbroom/textures/Prototype/white6.png" id="7_xqo7b"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://bcwkugn6v3oy7" path="res://addons/godot_state_charts/utilities/state_chart_debugger.tscn" id="9_87np7"]
|
||||||
|
|
||||||
[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_2t7xo"]
|
[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_2t7xo"]
|
||||||
|
|
||||||
|
@ -1658,3 +1659,8 @@ shape = SubResource("ConvexPolygonShape3D_0n1bf")
|
||||||
|
|
||||||
[node name="Player" parent="." instance=ExtResource("1_qpwbx")]
|
[node name="Player" parent="." instance=ExtResource("1_qpwbx")]
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -7, 1, 10)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -7, 1, 10)
|
||||||
|
|
||||||
|
[node name="StateChartDebugger" parent="." instance=ExtResource("9_87np7")]
|
||||||
|
offset_right = -772.0
|
||||||
|
offset_bottom = -415.0
|
||||||
|
initial_node_to_watch = NodePath("../Player")
|
||||||
|
|
|
@ -2,22 +2,31 @@ class_name Player extends PhysicsBody3D
|
||||||
|
|
||||||
enum MovementType { VERTICAL, LATERAL }
|
enum MovementType { VERTICAL, LATERAL }
|
||||||
|
|
||||||
@export var jump_speed := 4.5
|
#region Exports
|
||||||
@export var max_speed := 8
|
|
||||||
@export var slow_speed := 2
|
|
||||||
@export var mouse_sensitivity := 0.002 # radians/pixel
|
@export var mouse_sensitivity := 0.002 # radians/pixel
|
||||||
|
|
||||||
## The character will be blocked from moving up slopes steeper than this angle
|
@export_group("Movement")
|
||||||
## The character will be not be flagged as 'grounded' when stood on slopes steeper than this angle
|
@export var slope_limit := 45.0
|
||||||
@export var slope_limit: float = 45
|
|
||||||
|
|
||||||
## The character will automatically adjust height to step over obstacles this high
|
|
||||||
@export var step_height := 0.2
|
@export var step_height := 0.2
|
||||||
|
|
||||||
## When grounded, the character will snap down this distance
|
|
||||||
## This keeps the character on steps, slopes, and helps keep behaviour consistent
|
|
||||||
@export var snap_to_ground_distance := 0.2
|
@export var snap_to_ground_distance := 0.2
|
||||||
|
|
||||||
|
@export_subgroup("Crouching")
|
||||||
|
@export var crouch_height_decrease := 1.0
|
||||||
|
@export var crouch_speed := 2.0
|
||||||
|
@export var crouch_acceleration_time := 0.5
|
||||||
|
@export var crouch_deceleration_time := 0.2
|
||||||
|
|
||||||
|
@export_subgroup("Running")
|
||||||
|
@export var run_speed := 8.0
|
||||||
|
@export var run_acceleration_time := 1.5
|
||||||
|
@export var run_deceleration_time := 0.5
|
||||||
|
|
||||||
|
# TODO Change jumping to take a height, time-to-peak, and time-to-ground. Gravity can be worked out from that
|
||||||
|
@export_subgroup("Jumping")
|
||||||
|
@export var jump_speed := 4.5
|
||||||
|
@export var jump_pre_grace_time := 0.1
|
||||||
|
@export var jump_post_grace_time := 0.1
|
||||||
|
|
||||||
@export_group("Connector Nodes")
|
@export_group("Connector Nodes")
|
||||||
@export var head: Node3D
|
@export var head: Node3D
|
||||||
@export var body: Node3D
|
@export var body: Node3D
|
||||||
|
@ -60,13 +69,15 @@ enum MovementType { VERTICAL, LATERAL }
|
||||||
## accurate. 4 is a decent number for low poly terrain!
|
## accurate. 4 is a decent number for low poly terrain!
|
||||||
@export var max_iteration_count := 4
|
@export var max_iteration_count := 4
|
||||||
|
|
||||||
var jump_pressed := false
|
#endregion
|
||||||
|
|
||||||
|
var target_speed := 0.0
|
||||||
|
var state_enter_speed := 0.0
|
||||||
|
|
||||||
var gravity := 9.8
|
var gravity := 9.8
|
||||||
var _velocity: Vector3 = Vector3()
|
var _velocity: Vector3 = Vector3()
|
||||||
var at_max_speed := true
|
var grounded_prev := false
|
||||||
|
var grounded := true
|
||||||
var grounded: bool = false
|
|
||||||
var ground_normal: Vector3
|
var ground_normal: Vector3
|
||||||
var steep_slope_normals: Array[Vector3] = []
|
var steep_slope_normals: Array[Vector3] = []
|
||||||
var total_stepped_height: float = 0
|
var total_stepped_height: float = 0
|
||||||
|
@ -76,17 +87,11 @@ var vertical_collisions: Array[KinematicCollision3D]
|
||||||
var lateral_collisions: Array[KinematicCollision3D]
|
var lateral_collisions: Array[KinematicCollision3D]
|
||||||
var snap_collisions: Array[KinematicCollision3D]
|
var snap_collisions: Array[KinematicCollision3D]
|
||||||
|
|
||||||
|
#region Godot Functions
|
||||||
|
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
lock_mouse()
|
_lock_mouse()
|
||||||
|
|
||||||
|
|
||||||
func lock_mouse() -> void:
|
|
||||||
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
|
|
||||||
|
|
||||||
|
|
||||||
func unlock_mouse() -> void:
|
|
||||||
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
|
|
||||||
|
|
||||||
|
|
||||||
# TODO should this have an action associated?
|
# TODO should this have an action associated?
|
||||||
|
@ -104,35 +109,13 @@ func _input(event: InputEvent) -> void:
|
||||||
var key_event := event as InputEventKey
|
var key_event := event as InputEventKey
|
||||||
if key_event.keycode == KEY_ESCAPE:
|
if key_event.keycode == KEY_ESCAPE:
|
||||||
if Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED:
|
if Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED:
|
||||||
unlock_mouse()
|
_unlock_mouse()
|
||||||
else:
|
else:
|
||||||
lock_mouse()
|
_lock_mouse()
|
||||||
|
|
||||||
|
|
||||||
# TODO should this be in unhandled input?
|
#endregion
|
||||||
# TODO this should return void and just set the appropriate fields (input_dir!!)
|
#region Core Movement
|
||||||
# Input buffering? lol lmao
|
|
||||||
func get_input() -> Vector2:
|
|
||||||
# We don't want to be moving if the mouse isn't captured!
|
|
||||||
if Input.get_mouse_mode() != Input.MOUSE_MODE_CAPTURED:
|
|
||||||
return Vector2(0, 0)
|
|
||||||
|
|
||||||
jump_pressed = Input.is_action_just_pressed("cc_jump")
|
|
||||||
at_max_speed = Input.is_action_pressed("cc_sprint")
|
|
||||||
|
|
||||||
var input_dir: Vector2 = Vector2()
|
|
||||||
if Input.is_action_pressed("cc_forward"):
|
|
||||||
input_dir += Vector2.UP
|
|
||||||
if Input.is_action_pressed("cc_backward"):
|
|
||||||
input_dir -= Vector2.UP
|
|
||||||
if Input.is_action_pressed("cc_left"):
|
|
||||||
input_dir += Vector2.LEFT
|
|
||||||
if Input.is_action_pressed("cc_right"):
|
|
||||||
input_dir -= Vector2.LEFT
|
|
||||||
input_dir = input_dir.normalized()
|
|
||||||
|
|
||||||
# Local rotation is fine given the parent isn't rotating ever
|
|
||||||
return input_dir.rotated(-body.rotation.y)
|
|
||||||
|
|
||||||
|
|
||||||
# Entry point to moving
|
# Entry point to moving
|
||||||
|
@ -414,6 +397,10 @@ func snap_down() -> void:
|
||||||
position = before_snap_pos
|
position = before_snap_pos
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
#region Utilities
|
||||||
|
|
||||||
|
|
||||||
func _under_slope_limit(normal: Vector3) -> bool:
|
func _under_slope_limit(normal: Vector3) -> bool:
|
||||||
return normal.angle_to(Vector3.UP) < deg_to_rad(slope_limit)
|
return normal.angle_to(Vector3.UP) < deg_to_rad(slope_limit)
|
||||||
|
|
||||||
|
@ -426,35 +413,96 @@ func _vert(value: Vector3) -> Vector3:
|
||||||
return Vector3(0, value.y, 0)
|
return Vector3(0, value.y, 0)
|
||||||
|
|
||||||
|
|
||||||
func _on_grounded_state_physics_processing(delta: float) -> void:
|
func _lock_mouse() -> void:
|
||||||
var move_speed := max_speed if at_max_speed else slow_speed
|
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
|
||||||
var target_velocity_h := get_input() * move_speed
|
|
||||||
|
|
||||||
|
func _unlock_mouse() -> void:
|
||||||
|
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
|
||||||
|
|
||||||
|
|
||||||
|
func _get_move_dir() -> Vector2:
|
||||||
|
# We don't want to be moving if the mouse isn't captured!
|
||||||
|
if Input.get_mouse_mode() != Input.MOUSE_MODE_CAPTURED:
|
||||||
|
return Vector2.ZERO
|
||||||
|
|
||||||
|
var input_dir := Vector2.ZERO
|
||||||
|
if Input.is_action_pressed("cc_forward"):
|
||||||
|
input_dir += Vector2.UP
|
||||||
|
if Input.is_action_pressed("cc_backward"):
|
||||||
|
input_dir -= Vector2.UP
|
||||||
|
if Input.is_action_pressed("cc_left"):
|
||||||
|
input_dir += Vector2.LEFT
|
||||||
|
if Input.is_action_pressed("cc_right"):
|
||||||
|
input_dir -= Vector2.LEFT
|
||||||
|
input_dir = input_dir.normalized()
|
||||||
|
|
||||||
|
# Local rotation is fine given the parent isn't rotating ever
|
||||||
|
return input_dir.rotated(-body.rotation.y)
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
#region States
|
||||||
|
|
||||||
|
|
||||||
|
func _on_root_state_processing(_delta: float) -> void:
|
||||||
|
# !HACK - Printing this here for tracking
|
||||||
|
print(target_speed)
|
||||||
|
|
||||||
|
if _get_move_dir() == Vector2.ZERO:
|
||||||
|
state_chart.send_event("Idle")
|
||||||
|
else:
|
||||||
|
state_chart.send_event("Move")
|
||||||
|
if Input.is_action_just_pressed("cc_sprint"):
|
||||||
|
state_chart.send_event("Crouch")
|
||||||
|
if Input.is_action_just_pressed("cc_jump"):
|
||||||
|
state_chart.send_event("Jump")
|
||||||
|
|
||||||
|
if grounded != grounded_prev:
|
||||||
|
var event := "Grounded" if grounded else "Airborne"
|
||||||
|
state_chart.send_event(event)
|
||||||
|
grounded_prev = grounded
|
||||||
|
|
||||||
|
|
||||||
|
# TODO Rename sprint to crouch
|
||||||
|
func _on_idle_state_processing(_delta: float) -> void:
|
||||||
|
# !HACK - No deceleration. Just reset the target speed for now
|
||||||
|
target_speed = 0.0
|
||||||
|
|
||||||
|
|
||||||
|
func _on_running_state_physics_processing(delta: float) -> void:
|
||||||
|
if state_enter_speed < run_speed:
|
||||||
|
target_speed += (run_speed / run_acceleration_time) * delta
|
||||||
|
target_speed = minf(target_speed, run_speed)
|
||||||
|
else:
|
||||||
|
var decel_rate := (state_enter_speed - run_speed) / run_deceleration_time
|
||||||
|
target_speed -= decel_rate * delta
|
||||||
|
target_speed = maxf(target_speed, run_speed)
|
||||||
|
|
||||||
|
var target_velocity_h := _get_move_dir() * target_speed
|
||||||
var target_velocity_v := -gravity * delta
|
var target_velocity_v := -gravity * delta
|
||||||
var target_velocity := Vector3(target_velocity_h.x, target_velocity_v, target_velocity_h.y)
|
var target_velocity := Vector3(target_velocity_h.x, target_velocity_v, target_velocity_h.y)
|
||||||
move(target_velocity, delta)
|
move(target_velocity, delta)
|
||||||
|
|
||||||
if jump_pressed:
|
|
||||||
state_chart.send_event("Jump")
|
|
||||||
elif !grounded:
|
|
||||||
state_chart.send_event("Airborne")
|
|
||||||
|
|
||||||
|
|
||||||
func _on_falling_state_physics_processing(delta: float) -> void:
|
func _on_falling_state_physics_processing(delta: float) -> void:
|
||||||
var move_speed := max_speed if at_max_speed else slow_speed
|
var move_speed := run_speed
|
||||||
var target_velocity_h := get_input() * move_speed
|
var target_velocity_h := _get_move_dir() * move_speed
|
||||||
var target_velocity_v := _velocity.y - gravity * delta
|
var target_velocity_v := _velocity.y - gravity * delta
|
||||||
var target_velocity := Vector3(target_velocity_h.x, target_velocity_v, target_velocity_h.y)
|
var target_velocity := Vector3(target_velocity_h.x, target_velocity_v, target_velocity_h.y)
|
||||||
move(target_velocity, delta)
|
move(target_velocity, delta)
|
||||||
|
|
||||||
if grounded:
|
|
||||||
state_chart.send_event("Grounded")
|
|
||||||
|
|
||||||
|
|
||||||
func _on_jumping_state_physics_processing(delta: float) -> void:
|
func _on_jumping_state_physics_processing(delta: float) -> void:
|
||||||
var move_speed := max_speed if at_max_speed else slow_speed
|
# !HACK - We're setting this to test run deceleration
|
||||||
var target_velocity_h := get_input() * move_speed
|
target_speed = run_speed + 2.0
|
||||||
|
var target_velocity_h := _get_move_dir() * target_speed
|
||||||
var target_velocity_v := jump_speed
|
var target_velocity_v := jump_speed
|
||||||
var target_velocity := Vector3(target_velocity_h.x, target_velocity_v, target_velocity_h.y)
|
var target_velocity := Vector3(target_velocity_h.x, target_velocity_v, target_velocity_h.y)
|
||||||
move(target_velocity, delta)
|
move(target_velocity, delta)
|
||||||
|
|
||||||
state_chart.send_event("Airborne")
|
|
||||||
|
func _on_root_child_state_entered() -> void:
|
||||||
|
state_enter_speed = target_speed
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
|
@ -29,7 +29,7 @@ project/assembly_name="Character Controller"
|
||||||
|
|
||||||
[editor_plugins]
|
[editor_plugins]
|
||||||
|
|
||||||
enabled=PackedStringArray("res://addons/format_on_save/plugin.cfg", "res://addons/godot_state_charts/plugin.cfg", "res://addons/qodot/plugin.cfg")
|
enabled=PackedStringArray("res://addons/godot_state_charts/plugin.cfg", "res://addons/qodot/plugin.cfg")
|
||||||
|
|
||||||
[input]
|
[input]
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue