Last active
April 12, 2021 11:31
-
-
Save PranavSK/4039860ea4ab214f73d561b8d9f7afa8 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| extends StateMachine | |
| const MAX_MOVE_SLIDES: = 6 | |
| const Ragdoll: = preload("states/ragdoll.gd") | |
| const Falling: = preload("states/falling.gd") | |
| const Grounded: = preload("states/grounded.gd") | |
| const Crouched: = preload("states/crouched.gd") | |
| const STATE_RAGDOLL: = "Ragdoll" | |
| const STATE_FALLING: = "Falling" | |
| const STATE_STAND_WALK: = "Walking" | |
| const STATE_STAND_RUN: = "Running" | |
| const STATE_STAND_SPRINT: = "Sprinting" | |
| const STATE_CROUCH_WALK: = "CrouchedWalking" | |
| const STATE_CROUCH_RUN: = "CrouchedRunning" | |
| enum Gait { WALK, RUN, SPRINT } | |
| # Setup | |
| export var skeleton_node_path: NodePath | |
| export var capsule_node_path: NodePath | |
| export (float, 0.0, 50.0, 0.1) var terminal_speed: = 10.0 | |
| # Slopes with angle greater than this value are considered as walls. | |
| export (float, 0.1, 90, 0.1) var floor_max_angle: = 40.0 | |
| var allowed_gait: int = Gait.SPRINT | |
| var desired_gait: int = Gait.RUN | |
| var velocity: = Vector3.ZERO | |
| # World | |
| var gravity_scale: = 1.0 setget _no_setter | |
| var gravity_dir := Vector3.ZERO setget _no_setter | |
| var up: = Vector3.ZERO setget _no_setter | |
| var right: = Vector3.ZERO setget _no_setter | |
| var forward: = Vector3.ZERO setget _no_setter | |
| onready var character: KinematicBody = get_parent() | |
| onready var skeleton: Skeleton = get_node_or_null(skeleton_node_path) | |
| onready var capsule: CollisionShape = get_node_or_null(capsule_node_path) | |
| func _physics_process(delta): | |
| _update_orientation_vectors() | |
| # Update the state machine | |
| update(delta) | |
| func move(input_direction: Vector2): | |
| # TODO: Change animation direction based on this. | |
| # TODO: Rootmotion setup | |
| if get_current_state().has_method("move"): | |
| var direction = right * input_direction.x + forward * input_direction.y | |
| if direction.length_squared() > 1: | |
| direction = direction.normalized() | |
| get_current_state().move(direction) | |
| func roll(): | |
| pass | |
| func crouch(): | |
| pass | |
| func uncrouch(): | |
| pass | |
| func set_ragdoll(): | |
| change_state(STATE_RAGDOLL) | |
| func is_ragdoll() -> bool: | |
| return get_current_state() is Ragdoll | |
| func set_falling() -> void: | |
| change_state(STATE_FALLING) | |
| func is_falling() -> bool: | |
| return get_current_state() is Falling | |
| func set_grounded() -> void: | |
| if desired_gait == Gait.SPRINT and allowed_gait >= Gait.SPRINT: | |
| change_state(STATE_STAND_SPRINT) | |
| elif desired_gait == Gait.RUN and allowed_gait >= Gait.RUN: | |
| change_state(STATE_STAND_RUN) | |
| else: | |
| change_state(STATE_STAND_WALK) | |
| func is_grounded() -> bool: | |
| return get_current_state() is Grounded | |
| func set_crouched() -> void: | |
| if desired_gait == Gait.RUN and allowed_gait >= Gait.RUN: | |
| change_state(STATE_CROUCH_RUN) | |
| else: | |
| change_state(STATE_CROUCH_WALK) | |
| func is_crouched() -> bool: | |
| return get_current_state() is Crouched | |
| func _update_orientation_vectors(): | |
| var state = PhysicsServer.body_get_direct_state(character.get_rid()) | |
| if not state.total_gravity.is_equal_approx(Vector3.ZERO): | |
| gravity_dir = state.total_gravity.normalized() | |
| gravity_scale = state.total_gravity.length() | |
| else: | |
| gravity_dir = ProjectSettings.get_setting("physics/3d/default_gravity_vector") | |
| gravity_scale = ProjectSettings.get_setting("physics/3d/default_gravity") | |
| up = -gravity_dir | |
| var plane = Plane(up, 0.0) | |
| right = plane.project(Vector3.RIGHT).normalized() | |
| forward = plane.project(Vector3.FORWARD).normalized() | |
| func _get_configuration_warning(): | |
| if not get_parent() is KinematicBody: | |
| return "Please use this as a child to a KinematicBody!" | |
| else: return "" | |
| func _no_setter(_value): | |
| assert(false, "The property has no valid setter!!") |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| extends Node | |
| var locomotor | |
| func _enter_tree(): | |
| locomotor = get_parent() | |
| locomotor.register_state(name, self) | |
| func _exit_tree(): | |
| locomotor.unregister_state(name) | |
| func _apply_velocity(floor_snap: = Vector3.ZERO, stop_on_slope: = false): | |
| locomotor.character.velocity = locomotor.character.move_and_slide_with_snap( | |
| locomotor.velocity, | |
| floor_snap, | |
| locomotor.up, | |
| stop_on_slope, | |
| locomotor.MAX_MOVE_SLIDES, | |
| deg2rad(locomotor.floor_max_angle), | |
| false | |
| ) | |
| func _apply_gravity(delta: float) -> void: | |
| var curr_up_speed = locomotor.velocity.dot(locomotor.up) | |
| var up_speed_change = locomotor.terminal_speed - curr_up_speed | |
| var max_up_speed_change = locomotor.gravity_scale * delta | |
| up_speed_change = clamp( | |
| up_speed_change, -max_up_speed_change, max_up_speed_change | |
| ) | |
| locomotor.velocity += up_speed_change * locomotor.gravity_dir |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| extends "grounded.gd" | |
| export (float) var crouched_height | |
| func on_enter(): | |
| pass | |
| func on_exit(): | |
| pass |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| extends "move_state.gd" | |
| # Ragdoll | |
| export var ragdoll_on_land: = false | |
| export (float, 0.0, 100.0, 0.1) var ragdoll_on_land_speed: = 20.0 | |
| # Breakfall | |
| export var breakfall_on_land: = false | |
| export (float, 0.0, 100.0, 0.1) var breakfall_on_land_speed: = 20.0 | |
| func on_update(delta: float) -> void: | |
| .on_update(delta) | |
| if (locomotor.character.is_on_floor()): | |
| var fall_speed = locomotor.velocity.dot(locomotor.gravity_dir) | |
| if (ragdoll_on_land and fall_speed >= ragdoll_on_land_speed): | |
| locomotor.set_ragdoll() | |
| elif (breakfall_on_land and fall_speed >= breakfall_on_land_speed): | |
| locomotor.roll() | |
| else: | |
| locomotor.set_grounded() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| extends "move_state.gd" | |
| export (float, 0.0, 100.0, 0.1) var max_snap_speed: = 50.0 | |
| export (float, 0.0, 16.0, 0.1) var floor_check_distance: = 2.0 | |
| func on_update(delta: float) -> void: | |
| # no gravity is applied since floor snap is used. | |
| var floor_snap | |
| if (locomotor.velocity.length_squared() > max_snap_speed * max_snap_speed): | |
| floor_snap = Vector3.ZERO | |
| else: | |
| floor_snap = -locomotor.up * floor_check_distance | |
| var floor_normal = locomotor.character.get_floor_normal() | |
| var current_move_velocity: = Plane( | |
| floor_normal, 0.0).project(locomotor.velocity | |
| ) | |
| var desired_move_velocity = ( | |
| Plane(floor_normal, 0.0).project(desired_direction).normalized() * | |
| move_speed | |
| ) | |
| var move_velocity_change = desired_move_velocity - current_move_velocity | |
| var max_move_speed_change = ( | |
| acceleration * delta | |
| if move_speed >= move_velocity_change.length() or | |
| is_zero_approx(desired_move_velocity.length()) | |
| else friction * delta | |
| ) | |
| locomotor.velocity += MathUtils.clamp_magnitude( | |
| move_velocity_change, max_move_speed_change | |
| ) | |
| _apply_velocity(floor_snap, true) # TODO: Support moving platforms | |
| if not locomotor.character.is_on_floor(): | |
| # TODO: implement coyote time | |
| locomotor.set_falling() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| extends "character_state.gd" | |
| export (float, 0.0, 100.0, 0.1) var move_speed: = 1.0 | |
| export (float, 0.0, 100.0, 0.1) var acceleration: = 1.0 | |
| export (float, 0.0, 100.0, 0.1) var friction: = 1.0 | |
| var desired_direction: = Vector3.ZERO | |
| func move(direction: Vector3) -> void: | |
| desired_direction = direction | |
| func on_update(delta: float) -> void: | |
| # Apply gravity | |
| _apply_gravity(delta) | |
| # Apply movement | |
| var desired_move_velocity = desired_direction * move_speed | |
| var move_velocity_change = desired_move_velocity - locomotor.velocity | |
| var max_move_speed_change = ( | |
| acceleration * delta | |
| if move_speed >= move_velocity_change.length() or | |
| is_zero_approx(desired_move_velocity.length()) | |
| else friction * delta | |
| ) | |
| locomotor.velocity += MathUtils.clamp_magnitude( | |
| move_velocity_change, max_move_speed_change | |
| ) | |
| _apply_velocity() | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| extends "character_state.gd" | |
| func on_enter(): | |
| # 1. Disable capsule collision and enable mesh physics simulation. | |
| # 2. Stop any active animations | |
| pass | |
| func on_exit(): | |
| # 1. If ragdoll is on ground change state to walking, and play get up anim. | |
| # Else, change to falling and set the velocity to match last ragdoll | |
| # velocity. | |
| # 3. Re-enable capsule collision and disable mesh physics simulation. | |
| pass | |
| func on_update(delta): | |
| # 1. Set the last ragdoll speed from the physics simulation of mesh. | |
| # 2. Use ragdoll velocity to scale joint strength for physical animation. | |
| # for the pin joint - param/bias = ranged map from velocity, | |
| # param/damping and param/impulse_clamp are 0.0. | |
| # 3. Disable gravity if falling too fast (above 4000?). This should also | |
| # prvent the ragdoll from falling through the floor. | |
| # 4. _set_character_location_during_ragdoll(delta) | |
| pass | |
| func _set_character_location_during_ragdoll(delta): | |
| # 1. Set the pelvis as target location. | |
| # 2. Determine if ragdoll is facing up or down and set the target rotation | |
| # accordingly. | |
| # 3. Raycast downward (along gravity) from the target location to offset the | |
| # target location, preventing the lower half of the capsule from going | |
| # through the floor when the ragdoll is laying on the ground. | |
| pass |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment