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=[ {
|
||||
"base": "KinematicBody2D",
|
||||
"class": "Actor",
|
||||
"class": "Player",
|
||||
"language": "GDScript",
|
||||
"path": "res://src/Actor/Actor.gd"
|
||||
"path": "res://src/Actor/Player.gd"
|
||||
}, {
|
||||
"base": "Line2D",
|
||||
"class": "RayCastDebugLines",
|
||||
@ -30,7 +30,7 @@ _global_script_classes=[ {
|
||||
"path": "res://src/StateMachines/StateMachine.gd"
|
||||
} ]
|
||||
_global_script_class_icons={
|
||||
"Actor": "",
|
||||
"Player": "",
|
||||
"RayCastDebugLines": "",
|
||||
"RayCaster": "",
|
||||
"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)
|
||||
]
|
||||
}
|
||||
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]
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
export var stomp_impulse := 1000.0
|
||||
extends Player
|
||||
|
||||
|
||||
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:
|
||||
die()
|
||||
|
||||
|
||||
func handle_grounded_movement(delta: float, direction: Vector2) -> Vector2:
|
||||
return calculate_grounded_velocity(_velocity, delta, speed, direction)
|
||||
func handle_grounded_movement(delta: float, direction: Vector2, state: String) -> Vector2:
|
||||
return calculate_grounded_velocity(_velocity, delta, direction, state)
|
||||
|
||||
|
||||
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:
|
||||
return calculate_fall_velocity(_velocity, delta, speed, direction)
|
||||
|
||||
|
||||
func apply_gravity(delta, velocity: Vector2):
|
||||
velocity.y += gravity * delta
|
||||
return velocity
|
||||
return calculate_fall_velocity(_velocity, delta, direction)
|
||||
|
||||
|
||||
func calculate_grounded_velocity(
|
||||
linear_velocity: Vector2, delta: float, speed: Vector2, direction: Vector2
|
||||
linear_velocity: Vector2, delta: float, direction: Vector2, state: String
|
||||
) -> Vector2:
|
||||
var out_vel := linear_velocity
|
||||
var velocity_direction = 1.0
|
||||
if _velocity.x < 0:
|
||||
velocity_direction = -1.0
|
||||
|
||||
# Stopping movement
|
||||
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
|
||||
var result_force = (
|
||||
abs(convert_velocity_to_force(_velocity.x, mass, delta))
|
||||
@ -46,49 +42,96 @@ func calculate_grounded_velocity(
|
||||
if result_force <= 0:
|
||||
out_vel.x = 0
|
||||
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:
|
||||
# Reversing movement
|
||||
# When turning the opposite direction, friction is added to the opposite acceleration movement
|
||||
if is_reverse_horizontal_direction(direction):
|
||||
out_vel.x -= convert_force_to_velocity(calculate_deceleration_force(gravity, mass, delta), mass, delta) * velocity_direction
|
||||
out_vel.x += (delta * ((acceleration_force.x / mass) * direction.x))
|
||||
|
||||
var reverse_move = is_reversing_horizontal_movement(direction)
|
||||
if reverse_move:
|
||||
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?
|
||||
if is_on_floor():
|
||||
var additive_jump_force = 0.2 * abs(_velocity.x) * mass
|
||||
# Jumping when grounded
|
||||
if is_on_floor() && Input.is_action_pressed("jump"):
|
||||
var additive_jump_force = 0.2383 * abs(_velocity.x) * mass
|
||||
out_vel.y = (
|
||||
((acceleration_force.y + additive_jump_force) / mass)
|
||||
* direction.y
|
||||
((acceleration_force[state].y + additive_jump_force) / mass)
|
||||
* -1
|
||||
)
|
||||
else:
|
||||
out_vel.y = gravity * delta
|
||||
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:
|
||||
return (velocity*mass)/delta
|
||||
return (velocity * mass) / delta
|
||||
|
||||
|
||||
func convert_force_to_velocity(force, mass, delta) -> float:
|
||||
return (force/mass)*delta
|
||||
return (force / mass) * delta
|
||||
|
||||
|
||||
func get_ground_friction() -> float:
|
||||
return 30.5
|
||||
return 25.0
|
||||
|
||||
|
||||
# TODO Comments for parameters
|
||||
func calculate_deceleration_force(gravity: float, mass: float, delta: float) -> float:
|
||||
return get_ground_friction() * gravity * mass * delta
|
||||
|
||||
|
||||
func calculate_jump_velocity(
|
||||
linear_velocity: Vector2, delta: float, speed: Vector2, direction: Vector2
|
||||
linear_velocity: Vector2, delta: float, direction: Vector2
|
||||
) -> Vector2:
|
||||
linear_velocity.y += gravity * delta
|
||||
if _velocity.x == 0:
|
||||
linear_velocity.x += inair_velocity * direction.x
|
||||
return linear_velocity
|
||||
|
||||
|
||||
# Only applicable to downwards gravity
|
||||
func calculate_fall_velocity(
|
||||
linear_velocity: Vector2, delta: float, speed: Vector2, direction: Vector2
|
||||
linear_velocity: Vector2, delta: float, direction: 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
|
||||
|
||||
|
||||
|
||||
@ -1,16 +1,18 @@
|
||||
extends Actor
|
||||
extends Player
|
||||
|
||||
export var score := 100
|
||||
|
||||
export var score: = 100
|
||||
|
||||
func _ready() -> void:
|
||||
set_physics_process(false)
|
||||
_velocity.x = -speed.x
|
||||
_velocity.x = -300
|
||||
|
||||
|
||||
func _on_StompDetector_body_entered(body: Node) -> void:
|
||||
if body.global_position.y > get_node("StompDetector").global_position.y:
|
||||
return
|
||||
get_node("CollisionShape2D").disabled = true
|
||||
die()
|
||||
die()
|
||||
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
@ -19,6 +21,7 @@ func _physics_process(delta: float) -> void:
|
||||
_velocity.x *= -1.0
|
||||
_velocity.y = move_and_slide(_velocity, FLOOR_NORMAL).y
|
||||
|
||||
|
||||
func die() -> void:
|
||||
queue_free()
|
||||
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():
|
||||
add_state("idle")
|
||||
add_state("run")
|
||||
add_state("walk")
|
||||
add_state("jump")
|
||||
add_state("fall")
|
||||
print_debug(states)
|
||||
@ -27,6 +28,8 @@ func _state_logic(delta):
|
||||
match self.state:
|
||||
"idle":
|
||||
handle_input_ref = funcref(self, 'handle_idle_input')
|
||||
"walk":
|
||||
handle_input_ref = funcref(self, 'handle_walk_input')
|
||||
"run":
|
||||
handle_input_ref = funcref(self, 'handle_run_input')
|
||||
"jump":
|
||||
@ -40,56 +43,74 @@ func _state_logic(delta):
|
||||
parent.execute_movement()
|
||||
|
||||
|
||||
func handle_idle_input(delta, direction := get_direction()) -> Vector2:
|
||||
return parent.handle_grounded_movement(delta, direction)
|
||||
func handle_idle_input(delta, direction := get_horizontal_direction()) -> Vector2:
|
||||
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:
|
||||
return parent.handle_grounded_movement(delta, direction)
|
||||
func handle_walk_input(delta, direction := get_horizontal_direction()) -> Vector2:
|
||||
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)
|
||||
|
||||
|
||||
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)
|
||||
|
||||
|
||||
func get_direction() -> Vector2:
|
||||
func get_horizontal_direction() -> Vector2:
|
||||
return Vector2(
|
||||
(
|
||||
Input.get_action_strength("move_right")
|
||||
- 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
|
||||
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
|
||||
# TODO Can get stuck in Fall on ledges
|
||||
if !parent.is_on_floor():
|
||||
if ! parent.is_on_floor():
|
||||
if parent._velocity.y < 0:
|
||||
new_state = states.jump
|
||||
new_state = states.jump
|
||||
if parent._velocity.y >= 0:
|
||||
# if self.state == states.run:
|
||||
# parent._velocity.y = 0
|
||||
new_state = states.fall
|
||||
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:
|
||||
# TODO How does this apply to enviornment induced movement?
|
||||
new_state = states.idle
|
||||
if new_state != self.state:
|
||||
return new_state
|
||||
parent.init_boost = false
|
||||
return null
|
||||
|
||||
|
||||
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):
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -1,13 +1,14 @@
|
||||
extends Node
|
||||
class_name StateMachine
|
||||
|
||||
class_name StateMachine
|
||||
|
||||
var state = null setget set_state
|
||||
var previous_state = null
|
||||
var previous_state = null
|
||||
var states = {}
|
||||
|
||||
# Parent Node that uses these states
|
||||
onready var parent = get_parent()
|
||||
|
||||
|
||||
# Basic process flow for every SM
|
||||
func _physics_process(delta):
|
||||
if state != null:
|
||||
@ -16,19 +17,24 @@ func _physics_process(delta):
|
||||
if transition != null:
|
||||
set_state(transition)
|
||||
|
||||
|
||||
# Game logic consequences of state
|
||||
func _state_logic(_delta):
|
||||
pass
|
||||
|
||||
|
||||
func _get_transition(_delta):
|
||||
return null
|
||||
|
||||
|
||||
func _enter_state(_new_state, _previous_state):
|
||||
pass
|
||||
|
||||
|
||||
func _exit_state(_previous_state, _new_state):
|
||||
pass
|
||||
|
||||
|
||||
func set_state(new_state):
|
||||
previous_state = state
|
||||
state = new_state
|
||||
@ -38,5 +44,6 @@ func set_state(new_state):
|
||||
if new_state != null:
|
||||
_enter_state(new_state, previous_state)
|
||||
|
||||
|
||||
func add_state(state_name):
|
||||
states[state_name] = state_name
|
||||
|
||||
Loading…
Reference in New Issue
Block a user