walk/run states, in-air movement, gravity fix
This commit is contained in:
parent
7d3a99b284
commit
ce04af9332
3
.vscode/settings.json
vendored
Normal file
3
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"godot_tools.scene_file_config": "c:\\Users\\Jakob\\Documents\\Godot\\Wumper\\src\\Levels\\ApproxLevel.tscn.tmp"
|
||||||
|
}
|
||||||
@ -10,9 +10,9 @@ config_version=4
|
|||||||
|
|
||||||
_global_script_classes=[ {
|
_global_script_classes=[ {
|
||||||
"base": "KinematicBody2D",
|
"base": "KinematicBody2D",
|
||||||
"class": "Actor",
|
"class": "Player",
|
||||||
"language": "GDScript",
|
"language": "GDScript",
|
||||||
"path": "res://src/Actor/Actor.gd"
|
"path": "res://src/Actor/Player.gd"
|
||||||
}, {
|
}, {
|
||||||
"base": "Line2D",
|
"base": "Line2D",
|
||||||
"class": "RayCastDebugLines",
|
"class": "RayCastDebugLines",
|
||||||
@ -30,7 +30,7 @@ _global_script_classes=[ {
|
|||||||
"path": "res://src/StateMachines/StateMachine.gd"
|
"path": "res://src/StateMachines/StateMachine.gd"
|
||||||
} ]
|
} ]
|
||||||
_global_script_class_icons={
|
_global_script_class_icons={
|
||||||
"Actor": "",
|
"Player": "",
|
||||||
"RayCastDebugLines": "",
|
"RayCastDebugLines": "",
|
||||||
"RayCaster": "",
|
"RayCaster": "",
|
||||||
"StateMachine": ""
|
"StateMachine": ""
|
||||||
@ -84,6 +84,12 @@ pause={
|
|||||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":11,"pressure":0.0,"pressed":false,"script":null)
|
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":11,"pressure":0.0,"pressed":false,"script":null)
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
boost_move={
|
||||||
|
"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":16777237,"unicode":0,"echo":false,"script":null)
|
||||||
|
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":1,"pressure":0.0,"pressed":false,"script":null)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
[layer_names]
|
[layer_names]
|
||||||
|
|
||||||
|
|||||||
@ -1,14 +0,0 @@
|
|||||||
extends KinematicBody2D
|
|
||||||
class_name Actor
|
|
||||||
|
|
||||||
const FLOOR_NORMAL := Vector2.UP
|
|
||||||
|
|
||||||
# TODO Round everyone up whoever still uses this variable and fucking kill them
|
|
||||||
export var speed := Vector2(300, 1000)
|
|
||||||
# newtonmeters is the unit
|
|
||||||
export var acceleration_force := Vector2(3050, 4575)
|
|
||||||
export var gravity := 4000.0
|
|
||||||
# Kilograms
|
|
||||||
export var mass := 6
|
|
||||||
|
|
||||||
var _velocity := Vector2.ZERO
|
|
||||||
@ -1,43 +1,39 @@
|
|||||||
extends Actor
|
extends Player
|
||||||
|
|
||||||
export var stomp_impulse := 1000.0
|
|
||||||
|
|
||||||
|
|
||||||
func _on_EnemyDetector_area_entered(area: Area2D) -> void:
|
func _on_EnemyDetector_area_entered(area: Area2D) -> void:
|
||||||
_velocity = calculate_stomp_velocity(_velocity, stomp_impulse)
|
_velocity = calculate_stomp_velocity(_velocity, stomp_feedback)
|
||||||
|
|
||||||
|
|
||||||
func _on_EnemyDetector_body_entered(body: Node) -> void:
|
func _on_EnemyDetector_body_entered(body: Node) -> void:
|
||||||
die()
|
die()
|
||||||
|
|
||||||
|
|
||||||
func handle_grounded_movement(delta: float, direction: Vector2) -> Vector2:
|
func handle_grounded_movement(delta: float, direction: Vector2, state: String) -> Vector2:
|
||||||
return calculate_grounded_velocity(_velocity, delta, speed, direction)
|
return calculate_grounded_velocity(_velocity, delta, direction, state)
|
||||||
|
|
||||||
|
|
||||||
func handle_jump_movement(delta: float, direction: Vector2) -> Vector2:
|
func handle_jump_movement(delta: float, direction: Vector2) -> Vector2:
|
||||||
return calculate_jump_velocity(_velocity, delta, speed, direction)
|
return calculate_jump_velocity(_velocity, delta, direction)
|
||||||
|
|
||||||
|
|
||||||
func handle_fall_movement(delta: float, direction: Vector2) -> Vector2:
|
func handle_fall_movement(delta: float, direction: Vector2) -> Vector2:
|
||||||
return calculate_fall_velocity(_velocity, delta, speed, direction)
|
return calculate_fall_velocity(_velocity, delta, direction)
|
||||||
|
|
||||||
|
|
||||||
func apply_gravity(delta, velocity: Vector2):
|
|
||||||
velocity.y += gravity * delta
|
|
||||||
return velocity
|
|
||||||
|
|
||||||
|
|
||||||
func calculate_grounded_velocity(
|
func calculate_grounded_velocity(
|
||||||
linear_velocity: Vector2, delta: float, speed: Vector2, direction: Vector2
|
linear_velocity: Vector2, delta: float, direction: Vector2, state: String
|
||||||
) -> Vector2:
|
) -> Vector2:
|
||||||
var out_vel := linear_velocity
|
var out_vel := linear_velocity
|
||||||
var velocity_direction = 1.0
|
var velocity_direction = 1.0
|
||||||
if _velocity.x < 0:
|
if _velocity.x < 0:
|
||||||
velocity_direction = -1.0
|
velocity_direction = -1.0
|
||||||
|
|
||||||
|
# Stopping movement
|
||||||
if direction.x == 0.0:
|
if direction.x == 0.0:
|
||||||
var deceleration_force = calculate_deceleration_force(gravity, mass, delta)
|
var deceleration_force = calculate_deceleration_force(
|
||||||
|
gravity, mass, delta
|
||||||
|
)
|
||||||
# Translates velocity back to force and subtracts deceleration force
|
# Translates velocity back to force and subtracts deceleration force
|
||||||
var result_force = (
|
var result_force = (
|
||||||
abs(convert_velocity_to_force(_velocity.x, mass, delta))
|
abs(convert_velocity_to_force(_velocity.x, mass, delta))
|
||||||
@ -46,49 +42,96 @@ func calculate_grounded_velocity(
|
|||||||
if result_force <= 0:
|
if result_force <= 0:
|
||||||
out_vel.x = 0
|
out_vel.x = 0
|
||||||
else:
|
else:
|
||||||
out_vel.x = convert_force_to_velocity(result_force, mass, delta) * velocity_direction
|
out_vel.x = (
|
||||||
|
convert_force_to_velocity(result_force, mass, delta)
|
||||||
|
* velocity_direction
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
|
# Reversing movement
|
||||||
# When turning the opposite direction, friction is added to the opposite acceleration movement
|
# When turning the opposite direction, friction is added to the opposite acceleration movement
|
||||||
if is_reverse_horizontal_direction(direction):
|
var reverse_move = is_reversing_horizontal_movement(direction)
|
||||||
out_vel.x -= convert_force_to_velocity(calculate_deceleration_force(gravity, mass, delta), mass, delta) * velocity_direction
|
if reverse_move:
|
||||||
out_vel.x += (delta * ((acceleration_force.x / mass) * direction.x))
|
out_vel.x -= (
|
||||||
|
convert_force_to_velocity(
|
||||||
|
calculate_deceleration_force(gravity, mass, delta),
|
||||||
|
mass,
|
||||||
|
delta
|
||||||
|
)
|
||||||
|
* velocity_direction
|
||||||
|
)
|
||||||
|
# Normal movement
|
||||||
|
if abs(_velocity.x) < max_velocity[state]:
|
||||||
|
out_vel.x += (
|
||||||
|
delta
|
||||||
|
* (
|
||||||
|
(
|
||||||
|
(
|
||||||
|
acceleration_force[state].x
|
||||||
|
+ init_acceleration_force[state] * int(init_boost)
|
||||||
|
)
|
||||||
|
/ mass
|
||||||
|
)
|
||||||
|
* direction.x
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif ! reverse_move:
|
||||||
|
out_vel.x = max_velocity[state] * direction.x
|
||||||
# TODO Is this the right place to determine this?
|
# TODO Is this the right place to determine this?
|
||||||
if is_on_floor():
|
# Jumping when grounded
|
||||||
var additive_jump_force = 0.2 * abs(_velocity.x) * mass
|
if is_on_floor() && Input.is_action_pressed("jump"):
|
||||||
|
var additive_jump_force = 0.2383 * abs(_velocity.x) * mass
|
||||||
out_vel.y = (
|
out_vel.y = (
|
||||||
((acceleration_force.y + additive_jump_force) / mass)
|
((acceleration_force[state].y + additive_jump_force) / mass)
|
||||||
* direction.y
|
* -1
|
||||||
)
|
)
|
||||||
|
else:
|
||||||
|
out_vel.y = gravity * delta
|
||||||
return out_vel
|
return out_vel
|
||||||
|
|
||||||
func is_reverse_horizontal_direction(direction: Vector2) -> bool:
|
|
||||||
return (direction.x > 0 && _velocity.x < 0) || (direction.x < 0 && _velocity.x > 0)
|
func is_reversing_horizontal_movement(direction: Vector2) -> bool:
|
||||||
|
return (
|
||||||
|
(direction.x > 0 && _velocity.x < 0)
|
||||||
|
|| (direction.x < 0 && _velocity.x >= 0)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
func convert_velocity_to_force(velocity, mass, delta) -> float:
|
func convert_velocity_to_force(velocity, mass, delta) -> float:
|
||||||
return (velocity*mass)/delta
|
return (velocity * mass) / delta
|
||||||
|
|
||||||
|
|
||||||
func convert_force_to_velocity(force, mass, delta) -> float:
|
func convert_force_to_velocity(force, mass, delta) -> float:
|
||||||
return (force/mass)*delta
|
return (force / mass) * delta
|
||||||
|
|
||||||
|
|
||||||
func get_ground_friction() -> float:
|
func get_ground_friction() -> float:
|
||||||
return 30.5
|
return 25.0
|
||||||
|
|
||||||
|
|
||||||
# TODO Comments for parameters
|
# TODO Comments for parameters
|
||||||
func calculate_deceleration_force(gravity: float, mass: float, delta: float) -> float:
|
func calculate_deceleration_force(gravity: float, mass: float, delta: float) -> float:
|
||||||
return get_ground_friction() * gravity * mass * delta
|
return get_ground_friction() * gravity * mass * delta
|
||||||
|
|
||||||
|
|
||||||
func calculate_jump_velocity(
|
func calculate_jump_velocity(
|
||||||
linear_velocity: Vector2, delta: float, speed: Vector2, direction: Vector2
|
linear_velocity: Vector2, delta: float, direction: Vector2
|
||||||
) -> Vector2:
|
) -> Vector2:
|
||||||
linear_velocity.y += gravity * delta
|
linear_velocity.y += gravity * delta
|
||||||
|
if _velocity.x == 0:
|
||||||
|
linear_velocity.x += inair_velocity * direction.x
|
||||||
return linear_velocity
|
return linear_velocity
|
||||||
|
|
||||||
|
|
||||||
|
# Only applicable to downwards gravity
|
||||||
func calculate_fall_velocity(
|
func calculate_fall_velocity(
|
||||||
linear_velocity: Vector2, delta: float, speed: Vector2, direction: Vector2
|
linear_velocity: Vector2, delta: float, direction: Vector2
|
||||||
) -> Vector2:
|
) -> Vector2:
|
||||||
linear_velocity.y += gravity * delta
|
if _velocity.y < max_velocity["fall"]:
|
||||||
|
linear_velocity.y += gravity * delta
|
||||||
|
else:
|
||||||
|
linear_velocity.y = max_velocity["fall"]
|
||||||
|
if _velocity.x == 0:
|
||||||
|
linear_velocity.x += inair_velocity * direction.x
|
||||||
return linear_velocity
|
return linear_velocity
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,12 @@
|
|||||||
extends Actor
|
extends Player
|
||||||
|
|
||||||
|
export var score := 100
|
||||||
|
|
||||||
export var score: = 100
|
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
set_physics_process(false)
|
set_physics_process(false)
|
||||||
_velocity.x = -speed.x
|
_velocity.x = -300
|
||||||
|
|
||||||
|
|
||||||
func _on_StompDetector_body_entered(body: Node) -> void:
|
func _on_StompDetector_body_entered(body: Node) -> void:
|
||||||
if body.global_position.y > get_node("StompDetector").global_position.y:
|
if body.global_position.y > get_node("StompDetector").global_position.y:
|
||||||
@ -19,6 +21,7 @@ func _physics_process(delta: float) -> void:
|
|||||||
_velocity.x *= -1.0
|
_velocity.x *= -1.0
|
||||||
_velocity.y = move_and_slide(_velocity, FLOOR_NORMAL).y
|
_velocity.y = move_and_slide(_velocity, FLOOR_NORMAL).y
|
||||||
|
|
||||||
|
|
||||||
func die() -> void:
|
func die() -> void:
|
||||||
queue_free()
|
queue_free()
|
||||||
PlayerData.score += score
|
PlayerData.score += score
|
||||||
|
|||||||
20
src/Actor/Player.gd
Normal file
20
src/Actor/Player.gd
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
extends KinematicBody2D
|
||||||
|
class_name Player
|
||||||
|
|
||||||
|
const FLOOR_NORMAL := Vector2.UP
|
||||||
|
|
||||||
|
export var stomp_feedback := 1000.0
|
||||||
|
export var init_boost := false
|
||||||
|
export var inair_velocity := 18.3
|
||||||
|
export var max_velocity := {"walk": 183, "run": 305, "fall": 832}
|
||||||
|
# This is added to the acceleration force initially
|
||||||
|
export var init_acceleration_force := {"walk": 3904, "run": 6506.67}
|
||||||
|
# newtonmeters is the unit
|
||||||
|
export var acceleration_force := {
|
||||||
|
"walk": Vector2(2928, 4575), "run": Vector2(2928, 4575)
|
||||||
|
}
|
||||||
|
export var gravity := 3904.0
|
||||||
|
# Kilograms
|
||||||
|
export var mass := 6
|
||||||
|
|
||||||
|
var _velocity := Vector2.ZERO
|
||||||
@ -5,6 +5,7 @@ extends StateMachine
|
|||||||
func _ready():
|
func _ready():
|
||||||
add_state("idle")
|
add_state("idle")
|
||||||
add_state("run")
|
add_state("run")
|
||||||
|
add_state("walk")
|
||||||
add_state("jump")
|
add_state("jump")
|
||||||
add_state("fall")
|
add_state("fall")
|
||||||
print_debug(states)
|
print_debug(states)
|
||||||
@ -27,6 +28,8 @@ func _state_logic(delta):
|
|||||||
match self.state:
|
match self.state:
|
||||||
"idle":
|
"idle":
|
||||||
handle_input_ref = funcref(self, 'handle_idle_input')
|
handle_input_ref = funcref(self, 'handle_idle_input')
|
||||||
|
"walk":
|
||||||
|
handle_input_ref = funcref(self, 'handle_walk_input')
|
||||||
"run":
|
"run":
|
||||||
handle_input_ref = funcref(self, 'handle_run_input')
|
handle_input_ref = funcref(self, 'handle_run_input')
|
||||||
"jump":
|
"jump":
|
||||||
@ -40,56 +43,74 @@ func _state_logic(delta):
|
|||||||
parent.execute_movement()
|
parent.execute_movement()
|
||||||
|
|
||||||
|
|
||||||
func handle_idle_input(delta, direction := get_direction()) -> Vector2:
|
func handle_idle_input(delta, direction := get_horizontal_direction()) -> Vector2:
|
||||||
return parent.handle_grounded_movement(delta, direction)
|
if Input.is_action_pressed("boost_move"):
|
||||||
|
return parent.handle_grounded_movement(delta, direction, "run")
|
||||||
|
else:
|
||||||
|
return parent.handle_grounded_movement(delta, direction, "walk")
|
||||||
|
|
||||||
|
|
||||||
func handle_run_input(delta, direction := get_direction()) -> Vector2:
|
func handle_walk_input(delta, direction := get_horizontal_direction()) -> Vector2:
|
||||||
return parent.handle_grounded_movement(delta, direction)
|
return parent.handle_grounded_movement(delta, direction, state)
|
||||||
|
|
||||||
|
|
||||||
func handle_jump_input(delta, direction := get_direction()) -> Vector2:
|
func handle_run_input(delta, direction := get_horizontal_direction()) -> Vector2:
|
||||||
|
return parent.handle_grounded_movement(delta, direction, state)
|
||||||
|
|
||||||
|
|
||||||
|
func handle_jump_input(delta, direction := get_horizontal_direction()) -> Vector2:
|
||||||
return parent.handle_jump_movement(delta, direction)
|
return parent.handle_jump_movement(delta, direction)
|
||||||
|
|
||||||
|
|
||||||
func handle_fall_input(delta, direction := get_direction()) -> Vector2:
|
func handle_fall_input(delta, direction := get_horizontal_direction()) -> Vector2:
|
||||||
return parent.handle_fall_movement(delta, direction)
|
return parent.handle_fall_movement(delta, direction)
|
||||||
|
|
||||||
|
|
||||||
func get_direction() -> Vector2:
|
func get_horizontal_direction() -> Vector2:
|
||||||
return Vector2(
|
return Vector2(
|
||||||
(
|
(
|
||||||
Input.get_action_strength("move_right")
|
Input.get_action_strength("move_right")
|
||||||
- Input.get_action_strength("move_left")
|
- Input.get_action_strength("move_left")
|
||||||
),
|
),
|
||||||
-1.0 if Input.is_action_pressed("jump") else 1.0
|
0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# Determines which state should be active at the moment
|
# Determines which state should be active at the moment
|
||||||
func _get_transition(delta):
|
func _get_transition(delta):
|
||||||
parent.get_node("StateLable").text = self.state
|
parent.get_node("StateLable").text = (
|
||||||
|
self.state
|
||||||
|
+ " x vel:"
|
||||||
|
+ String(round(parent._velocity.x))
|
||||||
|
)
|
||||||
var new_state
|
var new_state
|
||||||
# TODO Can get stuck in Fall on ledges
|
# TODO Can get stuck in Fall on ledges
|
||||||
if !parent.is_on_floor():
|
if ! parent.is_on_floor():
|
||||||
if parent._velocity.y < 0:
|
if parent._velocity.y < 0:
|
||||||
new_state = states.jump
|
new_state = states.jump
|
||||||
if parent._velocity.y >= 0:
|
if parent._velocity.y >= 0:
|
||||||
# if self.state == states.run:
|
# if self.state == states.run:
|
||||||
# parent._velocity.y = 0
|
# parent._velocity.y = 0
|
||||||
new_state = states.fall
|
new_state = states.fall
|
||||||
elif parent._velocity.x != 0:
|
elif parent._velocity.x != 0:
|
||||||
new_state = states.run
|
if Input.is_action_pressed("boost_move"):
|
||||||
|
new_state = states.run
|
||||||
|
else:
|
||||||
|
new_state = states.walk
|
||||||
else:
|
else:
|
||||||
# TODO How does this apply to enviornment induced movement?
|
# TODO How does this apply to enviornment induced movement?
|
||||||
new_state = states.idle
|
new_state = states.idle
|
||||||
if new_state != self.state:
|
if new_state != self.state:
|
||||||
return new_state
|
return new_state
|
||||||
|
parent.init_boost = false
|
||||||
return null
|
return null
|
||||||
|
|
||||||
|
|
||||||
func _enter_state(new_state, old_state):
|
func _enter_state(new_state, old_state):
|
||||||
pass
|
if new_state == "run" || "walk":
|
||||||
|
parent.init_boost = true
|
||||||
|
if old_state == "run" && new_state == "walk":
|
||||||
|
parent.init_boost = false
|
||||||
|
|
||||||
|
|
||||||
func _exit_state(old_state, new_state):
|
func _exit_state(old_state, new_state):
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@ -8,6 +8,7 @@ var states = {}
|
|||||||
# Parent Node that uses these states
|
# Parent Node that uses these states
|
||||||
onready var parent = get_parent()
|
onready var parent = get_parent()
|
||||||
|
|
||||||
|
|
||||||
# Basic process flow for every SM
|
# Basic process flow for every SM
|
||||||
func _physics_process(delta):
|
func _physics_process(delta):
|
||||||
if state != null:
|
if state != null:
|
||||||
@ -16,19 +17,24 @@ func _physics_process(delta):
|
|||||||
if transition != null:
|
if transition != null:
|
||||||
set_state(transition)
|
set_state(transition)
|
||||||
|
|
||||||
|
|
||||||
# Game logic consequences of state
|
# Game logic consequences of state
|
||||||
func _state_logic(_delta):
|
func _state_logic(_delta):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
func _get_transition(_delta):
|
func _get_transition(_delta):
|
||||||
return null
|
return null
|
||||||
|
|
||||||
|
|
||||||
func _enter_state(_new_state, _previous_state):
|
func _enter_state(_new_state, _previous_state):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
func _exit_state(_previous_state, _new_state):
|
func _exit_state(_previous_state, _new_state):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
func set_state(new_state):
|
func set_state(new_state):
|
||||||
previous_state = state
|
previous_state = state
|
||||||
state = new_state
|
state = new_state
|
||||||
@ -38,5 +44,6 @@ func set_state(new_state):
|
|||||||
if new_state != null:
|
if new_state != null:
|
||||||
_enter_state(new_state, previous_state)
|
_enter_state(new_state, previous_state)
|
||||||
|
|
||||||
|
|
||||||
func add_state(state_name):
|
func add_state(state_name):
|
||||||
states[state_name] = state_name
|
states[state_name] = state_name
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user