Player Movement intiated via the PlayerStateMachine

This commit is contained in:
Jakob Feldmann 2021-03-14 13:25:52 +01:00
parent 6500d525cd
commit 67f2466f8c
13 changed files with 191 additions and 98 deletions

18
.vscode/launch.json vendored Normal file
View File

@ -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 Godot",
"type": "godot",
"request": "launch",
"project": "${workspaceFolder}",
"port": 6007,
"address": "127.0.0.1",
"launch_game_instance": true,
"launch_scene": false
}
]
}

View File

@ -14,6 +14,16 @@ _global_script_classes=[ {
"language": "GDScript",
"path": "res://src/Actor/Actor.gd"
}, {
"base": "Line2D",
"class": "RayCastDebugLines",
"language": "GDScript",
"path": "res://src/RayCasters/RayCastDebugLines.gd"
}, {
"base": "Node2D",
"class": "RayCaster",
"language": "GDScript",
"path": "res://src/RayCasters/RayCaster.gd"
}, {
"base": "Node",
"class": "StateMachine",
"language": "GDScript",
@ -21,6 +31,8 @@ _global_script_classes=[ {
} ]
_global_script_class_icons={
"Actor": "",
"RayCastDebugLines": "",
"RayCaster": "",
"StateMachine": ""
}
@ -34,6 +46,10 @@ config/icon="res://icon.png"
PlayerData="*res://src/Autoload/PlayerData.tscn"
[debug]
settings/fps/force_fps=144
[display]
window/stretch/mode="2d"

View File

@ -4,6 +4,6 @@ class_name Actor
const FLOOR_NORMAL: = Vector2.UP
export var speed: = Vector2(300, 1000)
export var gravity: = 100.0
export var gravity: = 9800.0
var _velocity: = Vector2.ZERO
var _velocity: = Vector2.ZERO

View File

@ -2,7 +2,7 @@ extends Actor
export var stomp_impulse: = 1000.0
# TODO Move events to StateMachine
func _on_EnemyDetector_area_entered(area: Area2D) -> void:
_velocity = calculate_stomp_velocity(_velocity, stomp_impulse)
@ -11,7 +11,7 @@ func _on_EnemyDetector_body_entered(body: Node) -> void:
die()
func _physics_process(delta: float) -> void:
func apply_movement(delta: float) -> void:
var is_jump_interrupted: = Input.is_action_just_released("jump") and _velocity.y < 0.0
var direction: = get_direction()
_velocity = calculate_move_velocity(_velocity, speed, direction, is_jump_interrupted)
@ -60,5 +60,3 @@ func die() -> void:
queue_free()
PlayerData.deaths += 1

View File

@ -1,30 +1,37 @@
[gd_scene load_steps=5 format=2]
[gd_scene load_steps=8 format=2]
[ext_resource path="res://start-assets/player.png" type="Texture" id=1]
[ext_resource path="res://src/Actor/Blobby.gd" type="Script" id=2]
[ext_resource path="res://src/Actor/PlayerStateMachine.gd" type="Script" id=2]
[ext_resource path="res://src/RayCasters/RayCaster.gd" type="Script" id=3]
[ext_resource path="res://src/RayCasters/RayCastDebugLines.gd" type="Script" id=4]
[ext_resource path="res://src/Actor/Blobby.gd" type="Script" id=5]
[sub_resource type="RectangleShape2D" id=1]
extents = Vector2( 4.85252, 5.80644 )
extents = Vector2( 30.8418, 32 )
[sub_resource type="RectangleShape2D" id=2]
extents = Vector2( 30.9321, 24.5597 )
[node name="Blobby" type="KinematicBody2D"]
collision_mask = 8
script = ExtResource( 2 )
speed = Vector2( 300, 3000 )
script = ExtResource( 5 )
[node name="player" type="Sprite" parent="."]
position = Vector2( 2.38419e-07, -31.3866 )
scale = Vector2( 0.641109, 0.653888 )
position = Vector2( 1.79366e-43, 5.72205e-06 )
scale = Vector2( 0.64, 0.64 )
texture = ExtResource( 1 )
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
position = Vector2( 1.05112, -31.5796 )
scale = Vector2( 5.68128, 5.29182 )
shape = SubResource( 1 )
[node name="RayCaster" type="Node2D" parent="CollisionShape2D"]
script = ExtResource( 3 )
[node name="RayCastDebugLines" type="Line2D" parent="CollisionShape2D/RayCaster"]
script = ExtResource( 4 )
[node name="Camera2D" type="Camera2D" parent="."]
visible = false
position = Vector2( 0, -181 )
current = true
limit_left = 0
@ -42,7 +49,9 @@ collision_mask = 2
[node name="CollisionShape2D" type="CollisionShape2D" parent="EnemyDetector"]
modulate = Color( 0.2, 0, 0.494118, 1 )
position = Vector2( -0.210228, -30.5284 )
shape = SubResource( 2 )
[node name="StateMachine" type="Node" parent="."]
script = ExtResource( 2 )
[connection signal="area_entered" from="EnemyDetector" to="." method="_on_EnemyDetector_area_entered"]
[connection signal="body_entered" from="EnemyDetector" to="." method="_on_EnemyDetector_body_entered"]

View File

@ -1,22 +1,30 @@
extends StateMachine
# Adds the intial states
func _ready():
add_state("idle")
add_state("run")
add_state("jump")
add_state("fall")
call_deferred("set_state", states.idle)
print_debug(states)
set_state(states.idle);
# Calls the parent behaviours according to state
func _state_logic(delta):
parent.handle_move_input()
parent.apply_gravity(delta)
parent.apply_movement()
parent.get_node("CollisionShape2D/RayCaster")._raycast(Vector2.DOWN, parent.get_node("CollisionShape2D").get_shape(), parent.collision_mask)
parent.apply_movement(delta)
# Determines which state should be active at the moment
func _get_transition(delta):
return null
func _enter_state(new_state, old_state):
pass
func _exit_state(old_state, new_state):
pass
pass

View File

@ -39,8 +39,6 @@ tile_data = PoolIntArray( -1048576, 0, 0, -1048564, 0, 0, -983040, 0, 0, -983028
[node name="Blobby" parent="." instance=ExtResource( 1 )]
position = Vector2( 131, 560 )
speed = Vector2( 800, 1500 )
gravity = 4000.0
[node name="player" parent="Blobby" index="0"]
position = Vector2( 0, -32 )

View File

@ -64,8 +64,6 @@ tile_data = PoolIntArray( 0, 0, 0, 34, 0, 0, 35, 0, 0, 65536, 0, 0, 65570, 0, 0,
[node name="Blobby" parent="." instance=ExtResource( 1 )]
position = Vector2( 131, 560 )
speed = Vector2( 800, 3000 )
gravity = 4000.0
[node name="Camera2D" parent="Blobby" index="2"]
limit_top = 100000000

View File

@ -1,57 +0,0 @@
extends Node2D
const UP = Vector2(0, -1)
const DOWN = Vector2(0, 1)
const LEFT = Vector2(-1, 0)
const RIGHT = Vector2(1, 0)
const SKIN_WIDTH = 1
export (int) var buffer_size = 3 setget _set_buffer_size
var buffer = []
func _raycast(direction, rect, mask, exceptions = [], ray_length = 16, buffer = self.buffer):
if !(direction == UP || direction == DOWN || direction == LEFT || direction == RIGHT):
return 0
var space_state = get_world_2d().direct_space_state
var extents = rect.extents - Vector2(SKIN_WIDTH, SKIN_WIDTH)
var count = 0
var ray_count = buffer.size()
var cast_to = (ray_length + SKIN_WIDTH) * direction
var origin
var spacing
if direction == UP || direction == DOWN:
spacing = extents.x * 2 / (ray_count - 1)
else:
spacing = extents.y * 2 / (ray_count - 1)
for i in range(ray_count):
if direction == UP || direction == DOWN:
origin = Vector2(-extents.x + spacing * i, extents.y)
if direction == UP:
origin.y = -origin.y
else:
origin = Vector2(extents.x, -extents.y + spacing * i)
if direction == UP:
origin.x = -origin.x
var result = space_state.intersect_ray(global_position + origin, global_position + origin + cast_to,
exceptions, mask)
if result:
buffer[count] = result
count += 1
return {buffer = buffer, count = count}
func _set_buffer_size(value):
buffer_size = max(value, 2)
buffer.resize(buffer_size)
# Called when the node enters the scene tree for the first time.
func _ready():
_set_buffer_size(buffer_size)

View File

@ -0,0 +1,25 @@
extends Line2D
class_name RayCastDebugLines
# Declare member variables here. Examples:
# var a: int = 2
# var b: String = "text"
var Lines = []
func add_line(origin, destination, color):
Lines.append([origin, destination, color])
func clear_lines():
Lines = []
func _draw():
for i in range(len(Lines)):
draw_line(Lines[i][0],Lines[i][1],Lines[i][2])
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
pass # Replace with function body.
# Called every frame. 'delta' is the elapsed time since the previous frame.
#func _process(delta: float) -> void:
# pass

View File

@ -0,0 +1,73 @@
extends Node2D
class_name RayCaster
const UP = Vector2(0, -1)
const DOWN = Vector2(0, 1)
const LEFT = Vector2(-1, 0)
const RIGHT = Vector2(1, 0)
const SKIN_WIDTH = 0
export (int) var buffer_size = 10 setget _set_buffer_size
var buffer = []
# Casts Rays into a given direction.
# direction: 2D up, down, left or right vector
# rect: Shape of the node the raycaster is attached to
# mask: Collision layers
# exceptions: Excepted collision layers
# ray_length: Length of the rays
# ray_buffer: Array to which the rays get saved
func _raycast(direction, rect, mask, exceptions = [], ray_length = 16, ray_buffer = self.buffer):
if !(direction == UP || direction == DOWN || direction == LEFT || direction == RIGHT):
return 0
# TODO Manage debug options globally
self.get_child(0).clear_lines()
var space_state = get_world_2d().direct_space_state
var extents = rect.extents - Vector2(SKIN_WIDTH, SKIN_WIDTH)
var count = 0
var ray_count = ray_buffer.size()
var cast_to = (ray_length + SKIN_WIDTH) * direction
var origin
var spacing
if direction == UP || direction == DOWN:
spacing = extents.x * 2 / (ray_count - 1)
else:
spacing = extents.y * 2 / (ray_count - 1)
for i in range(ray_count):
if direction == UP || direction == DOWN:
origin = Vector2(-extents.x + spacing * i, extents.y)
if direction == UP:
origin.y = -origin.y
else:
# TODO Manage debug options globally
self.get_child(0).add_line(origin, Vector2(origin.x, origin.y + ray_length), Color( 1, 0, 0, 1 ))
else:
origin = Vector2(extents.x, -extents.y + spacing * i)
if direction == LEFT:
origin.x = -origin.x
else:
draw_line(origin, Vector2(origin.x + ray_length, origin.y), Color( 1, 0, 0, 1 ))
var result = space_state.intersect_ray(global_position + origin, global_position + origin + cast_to,
exceptions, mask)
if result:
ray_buffer[count] = result
count += 1
self.get_child(0).update()
return {ray_buffer = ray_buffer, count = count}
func _set_buffer_size(value):
buffer_size = max(value, 2)
self.buffer.resize(buffer_size)
# Called when the node enters the scene tree for the first time.
func _ready():
_set_buffer_size(buffer_size)

View File

@ -19,6 +19,10 @@ __meta__ = {
[node name="background" type="TextureRect" parent="."]
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = -1.5874
margin_top = 3.96851
margin_right = -1.5874
margin_bottom = 3.96851
texture = ExtResource( 4 )
expand = true
stretch_mode = 2

View File

@ -5,35 +5,38 @@ var state = null setget set_state
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:
_state_logic(delta)
var transition = _get_transition(delta)
if transition != null:
set_state(transition)
if state != null:
_state_logic(delta)
var transition = _get_transition(delta)
if transition != null:
set_state(transition)
# Game logic consequences of state
func _state_logic(_delta):
pass
pass
func _get_transition(_delta):
return null
return null
func _enter_state(_new_state, _previous_state):
pass
pass
func _exit_state(_previous_state, _new_state):
pass
pass
func set_state(new_state):
previous_state = state
state = new_state
previous_state = state
state = new_state
if previous_state != null:
_exit_state(previous_state, new_state)
if new_state != null:
_enter_state(new_state, previous_state)
if previous_state != null:
_exit_state(previous_state, new_state)
if new_state != null:
_enter_state(new_state, previous_state)
func add_state(state_name):
states[states.size()] = state_name
states[state_name] = state_name