mirror of
https://github.com/godotengine/godot-demo-projects.git
synced 2026-01-04 23:10:08 +01:00
Update Finite State Machine demo
This commit is contained in:
@@ -1,13 +1,13 @@
|
||||
[gd_scene load_steps=5 format=2]
|
||||
|
||||
[ext_resource path="res://debug/ControlsPanel.tscn" type="PackedScene" id=1]
|
||||
[ext_resource path="res://player/Player.tscn" type="PackedScene" id=1]
|
||||
[ext_resource path="res://debug/Explanations.tscn" type="PackedScene" id=2]
|
||||
[ext_resource path="res://debug/StatesStackDiplayer.tscn" type="PackedScene" id=3]
|
||||
[ext_resource path="res://player/Player.tscn" type="PackedScene" id=4]
|
||||
[ext_resource path="res://debug/ControlsPanel.tscn" type="PackedScene" id=4]
|
||||
|
||||
[node name="Demo" type="Node"]
|
||||
|
||||
[node name="Player" parent="." instance=ExtResource( 4 )]
|
||||
[node name="Player" parent="." instance=ExtResource( 1 )]
|
||||
|
||||
[node name="Explanations" parent="." instance=ExtResource( 2 )]
|
||||
|
||||
@@ -20,6 +20,6 @@ __meta__ = {
|
||||
|
||||
[node name="StatesStackDiplayer" parent="Control" instance=ExtResource( 3 )]
|
||||
|
||||
[node name="ControlsPanel" parent="Control" instance=ExtResource( 1 )]
|
||||
[node name="ControlsPanel" parent="Control" instance=ExtResource( 4 )]
|
||||
|
||||
[editable path="Player"]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://fonts/source_code_pro_explanations.tres" type="DynamicFont" id=2]
|
||||
[ext_resource path="res://fonts/source_code_pro_explanations.tres" type="DynamicFont" id=1]
|
||||
|
||||
[node name="ControlsPanel" type="Panel"]
|
||||
anchor_left = 1.0
|
||||
@@ -18,7 +18,7 @@ margin_left = 10.0
|
||||
margin_top = 10.0
|
||||
margin_right = -10.0
|
||||
margin_bottom = -10.0
|
||||
custom_fonts/font = ExtResource( 2 )
|
||||
custom_fonts/font = ExtResource( 1 )
|
||||
text = "Shoot:
|
||||
Attack:
|
||||
Stagger:
|
||||
@@ -32,7 +32,7 @@ margin_left = 10.0
|
||||
margin_top = 10.0
|
||||
margin_right = -10.0
|
||||
margin_bottom = -10.0
|
||||
custom_fonts/font = ExtResource( 2 )
|
||||
custom_fonts/font = ExtResource( 1 )
|
||||
text = "R
|
||||
F
|
||||
X
|
||||
|
||||
@@ -2,14 +2,13 @@ extends Panel
|
||||
|
||||
onready var fsm_node = get_node("../../Player/StateMachine")
|
||||
|
||||
func _process(delta):
|
||||
var states_names = ''
|
||||
var numbers = ''
|
||||
func _process(_delta):
|
||||
var states_names = ""
|
||||
var numbers = ""
|
||||
var index = 0
|
||||
for state in fsm_node.states_stack:
|
||||
states_names += state.get_name() + '\n'
|
||||
numbers += str(index) + '\n'
|
||||
index += 1
|
||||
|
||||
$States.text = states_names
|
||||
$Numbers.text = numbers
|
||||
|
||||
@@ -49,7 +49,6 @@ __meta__ = {
|
||||
|
||||
[node name="StateMachine" type="Node" parent="."]
|
||||
script = ExtResource( 2 )
|
||||
START_STATE = NodePath("Idle")
|
||||
|
||||
[node name="Idle" type="Node" parent="StateMachine"]
|
||||
script = ExtResource( 3 )
|
||||
@@ -116,7 +115,6 @@ align = 1
|
||||
valign = 1
|
||||
uppercase = true
|
||||
script = ExtResource( 15 )
|
||||
|
||||
[connection signal="state_changed" from="StateMachine" to="BodyPivot/WeaponPivot/Offset/Sword" method="_on_StateMachine_state_changed"]
|
||||
[connection signal="state_changed" from="StateMachine" to="StateNameDisplayer" method="_on_StateMachine_state_changed"]
|
||||
[connection signal="animation_finished" from="AnimationPlayer" to="StateMachine" method="_on_animation_finished"]
|
||||
|
||||
@@ -12,4 +12,3 @@ script = ExtResource( 1 )
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
|
||||
shape = SubResource( 1 )
|
||||
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
extends KinematicBody2D
|
||||
|
||||
|
||||
var direction = Vector2()
|
||||
export(float) var SPEED = 1000.0
|
||||
|
||||
export(float) var speed = 1000.0
|
||||
|
||||
func _ready():
|
||||
set_as_toplevel(true)
|
||||
@@ -13,7 +11,7 @@ func _physics_process(delta):
|
||||
if is_outside_view_bounds():
|
||||
queue_free()
|
||||
|
||||
var motion = direction * SPEED * delta
|
||||
var motion = direction * speed * delta
|
||||
var collision_info = move_and_collide(motion)
|
||||
if collision_info:
|
||||
queue_free()
|
||||
@@ -21,8 +19,8 @@ func _physics_process(delta):
|
||||
|
||||
func is_outside_view_bounds():
|
||||
return position.x > OS.get_screen_size().x or position.x < 0.0 \
|
||||
or position.y > OS.get_screen_size().y or position.y < 0.0
|
||||
or position.y > OS.get_screen_size().y or position.y < 0.0
|
||||
|
||||
|
||||
func _draw():
|
||||
draw_circle(Vector2(), $CollisionShape2D.shape.radius, Color('#ffffff'))
|
||||
draw_circle(Vector2(), $CollisionShape2D.shape.radius, Color.white)
|
||||
|
||||
@@ -6,6 +6,7 @@ func _input(event):
|
||||
if event.is_action_pressed("fire"):
|
||||
fire(owner.look_direction)
|
||||
|
||||
|
||||
func fire(direction):
|
||||
if not $CooldownTimer.is_stopped():
|
||||
return
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
"""
|
||||
The Player is a KinematicBody2D, in other words a physics-driven object.
|
||||
It can move, collide with the world...
|
||||
It HAS a state machine, but the body and the state machine are separate.
|
||||
"""
|
||||
extends KinematicBody2D
|
||||
# The Player is a KinematicBody2D, in other words a physics-driven object.
|
||||
# It can move, collide with the world, etc...
|
||||
# The player has a state machine, but the body and the state machine are separate.
|
||||
|
||||
signal direction_changed(new_direction)
|
||||
|
||||
var look_direction = Vector2(1, 0) setget set_look_direction
|
||||
var look_direction = Vector2.RIGHT setget set_look_direction
|
||||
|
||||
func take_damage(attacker, amount, effect=null):
|
||||
if self.is_a_parent_of(attacker):
|
||||
func take_damage(attacker, amount, effect = null):
|
||||
if is_a_parent_of(attacker):
|
||||
return
|
||||
$States/Stagger.knockback_direction = (attacker.global_position - global_position).normalized()
|
||||
$Health.take_damage(amount, effect)
|
||||
|
||||
|
||||
func set_dead(value):
|
||||
set_process_input(not value)
|
||||
set_physics_process(not value)
|
||||
$CollisionPolygon2D.disabled = value
|
||||
|
||||
|
||||
func set_look_direction(value):
|
||||
look_direction = value
|
||||
emit_signal("direction_changed", value)
|
||||
|
||||
@@ -9,10 +9,9 @@ func _ready():
|
||||
"attack": $Attack,
|
||||
}
|
||||
|
||||
|
||||
func _change_state(state_name):
|
||||
"""
|
||||
The base state_machine interface this node extends does most of the work
|
||||
"""
|
||||
# The base state_machine interface this node extends does most of the work.
|
||||
if not _active:
|
||||
return
|
||||
if state_name in ["stagger", "jump", "attack"]:
|
||||
@@ -21,11 +20,10 @@ func _change_state(state_name):
|
||||
$Jump.initialize($Move.speed, $Move.velocity)
|
||||
._change_state(state_name)
|
||||
|
||||
|
||||
func _input(event):
|
||||
"""
|
||||
Here we only handle input that can interrupt states, attacking in this case
|
||||
otherwise we let the state node handle it
|
||||
"""
|
||||
# Here we only handle input that can interrupt states, attacking in this case,
|
||||
# otherwise we let the state node handle it.
|
||||
if event.is_action_pressed("attack"):
|
||||
if current_state in [$Attack, $Stagger]:
|
||||
return
|
||||
|
||||
@@ -3,5 +3,6 @@ extends "res://state_machine/state.gd"
|
||||
func enter():
|
||||
owner.get_node("AnimationPlayer").play("idle")
|
||||
|
||||
|
||||
func _on_Sword_attack_finished():
|
||||
emit_signal("finished", "previous")
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
"""
|
||||
The stagger state end with the stagger animation from the AnimationPlayer
|
||||
The animation only affects the Body Sprite's modulate property so
|
||||
it could stack with other animations if we had two AnimationPlayer nodes
|
||||
"""
|
||||
extends "res://state_machine/state.gd"
|
||||
|
||||
var knockback_direction = Vector2()
|
||||
# The stagger state end with the stagger animation from the AnimationPlayer.
|
||||
# The animation only affects the Body Sprite's modulate property so it
|
||||
# could stack with other animations if we had two AnimationPlayer nodes.
|
||||
|
||||
func enter():
|
||||
owner.get_node("AnimationPlayer").play("stagger")
|
||||
|
||||
|
||||
func _on_animation_finished(anim_name):
|
||||
assert(anim_name == "stagger")
|
||||
emit_signal("finished", "previous")
|
||||
|
||||
@@ -5,8 +5,10 @@ var start_position = Vector2()
|
||||
func _ready():
|
||||
start_position = rect_position
|
||||
|
||||
func _physics_process(delta):
|
||||
|
||||
func _physics_process(_delta):
|
||||
rect_position = $"../BodyPivot".position + start_position
|
||||
|
||||
|
||||
func _on_StateMachine_state_changed(current_state):
|
||||
text = current_state.get_name()
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
extends "res://state_machine/state.gd"
|
||||
|
||||
|
||||
# Initialize the state. E.g. change the animation
|
||||
# Initialize the state. E.g. change the animation.
|
||||
func enter():
|
||||
owner.set_dead(true)
|
||||
owner.get_node("AnimationPlayer").play("die")
|
||||
|
||||
func _on_animation_finished(anim_name):
|
||||
|
||||
func _on_animation_finished(_anim_name):
|
||||
emit_signal("finished", "dead")
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
extends "../motion.gd"
|
||||
|
||||
export(float) var BASE_MAX_HORIZONTAL_SPEED = 400.0
|
||||
export(float) var base_max_horizontal_speed = 400.0
|
||||
|
||||
export(float) var AIR_ACCELERATION = 1000.0
|
||||
export(float) var AIR_DECCELERATION = 2000.0
|
||||
export(float) var AIR_STEERING_POWER = 50.0
|
||||
export(float) var air_acceleration = 1000.0
|
||||
export(float) var air_deceleration = 2000.0
|
||||
export(float) var air_steering_power = 50.0
|
||||
|
||||
export(float) var JUMP_HEIGHT = 120.0
|
||||
export(float) var JUMP_DURATION = 0.8
|
||||
|
||||
export(float) var GRAVITY = 1600.0
|
||||
export(float) var gravity = 1600.0
|
||||
|
||||
var enter_velocity = Vector2()
|
||||
|
||||
@@ -22,7 +19,7 @@ var height = 0.0
|
||||
|
||||
func initialize(speed, velocity):
|
||||
horizontal_speed = speed
|
||||
max_horizontal_speed = speed if speed > 0.0 else BASE_MAX_HORIZONTAL_SPEED
|
||||
max_horizontal_speed = speed if speed > 0.0 else base_max_horizontal_speed
|
||||
enter_velocity = velocity
|
||||
|
||||
func enter():
|
||||
@@ -45,19 +42,19 @@ func update(delta):
|
||||
|
||||
func move_horizontally(delta, direction):
|
||||
if direction:
|
||||
horizontal_speed += AIR_ACCELERATION * delta
|
||||
horizontal_speed += air_acceleration * delta
|
||||
else:
|
||||
horizontal_speed -= AIR_DECCELERATION * delta
|
||||
horizontal_speed -= air_deceleration * delta
|
||||
horizontal_speed = clamp(horizontal_speed, 0, max_horizontal_speed)
|
||||
|
||||
var target_velocity = horizontal_speed * direction.normalized()
|
||||
var steering_velocity = (target_velocity - horizontal_velocity).normalized() * AIR_STEERING_POWER
|
||||
var steering_velocity = (target_velocity - horizontal_velocity).normalized() * air_steering_power
|
||||
horizontal_velocity += steering_velocity
|
||||
|
||||
owner.move_and_slide(horizontal_velocity)
|
||||
|
||||
func animate_jump_height(delta):
|
||||
vertical_speed -= GRAVITY * delta
|
||||
vertical_speed -= gravity * delta
|
||||
height += vertical_speed * delta
|
||||
height = max(0.0, height)
|
||||
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
# Collection of important methods to handle direction and animation
|
||||
extends "res://state_machine/state.gd"
|
||||
# Collection of important methods to handle direction and animation.
|
||||
|
||||
func handle_input(event):
|
||||
if event.is_action_pressed("simulate_damage"):
|
||||
emit_signal("finished", "stagger")
|
||||
|
||||
|
||||
func get_input_direction():
|
||||
var input_direction = Vector2()
|
||||
input_direction.x = int(Input.is_action_pressed("move_right")) - int(Input.is_action_pressed("move_left"))
|
||||
input_direction.y = int(Input.is_action_pressed("move_down")) - int(Input.is_action_pressed("move_up"))
|
||||
input_direction.x = Input.get_action_strength("move_right") - Input.get_action_strength("move_left")
|
||||
input_direction.y = Input.get_action_strength("move_down") - Input.get_action_strength("move_up")
|
||||
return input_direction
|
||||
|
||||
|
||||
func update_look_direction(direction):
|
||||
if direction and owner.look_direction != direction:
|
||||
owner.look_direction = direction
|
||||
|
||||
@@ -3,10 +3,12 @@ extends "on_ground.gd"
|
||||
func enter():
|
||||
owner.get_node("AnimationPlayer").play("idle")
|
||||
|
||||
|
||||
func handle_input(event):
|
||||
return .handle_input(event)
|
||||
|
||||
func update(delta):
|
||||
|
||||
func update(_delta):
|
||||
var input_direction = get_input_direction()
|
||||
if input_direction:
|
||||
emit_signal("finished", "move")
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
extends "on_ground.gd"
|
||||
|
||||
export(float) var MAX_WALK_SPEED = 450
|
||||
export(float) var MAX_RUN_SPEED = 700
|
||||
export(float) var max_walk_speed = 450
|
||||
export(float) var max_run_speed = 700
|
||||
|
||||
func enter():
|
||||
speed = 0.0
|
||||
@@ -11,22 +11,25 @@ func enter():
|
||||
update_look_direction(input_direction)
|
||||
owner.get_node("AnimationPlayer").play("walk")
|
||||
|
||||
|
||||
func handle_input(event):
|
||||
return .handle_input(event)
|
||||
|
||||
func update(delta):
|
||||
|
||||
func update(_delta):
|
||||
var input_direction = get_input_direction()
|
||||
if not input_direction:
|
||||
emit_signal("finished", "idle")
|
||||
update_look_direction(input_direction)
|
||||
|
||||
speed = MAX_RUN_SPEED if Input.is_action_pressed("run") else MAX_WALK_SPEED
|
||||
speed = max_run_speed if Input.is_action_pressed("run") else max_walk_speed
|
||||
var collision_info = move(speed, input_direction)
|
||||
if not collision_info:
|
||||
return
|
||||
if speed == MAX_RUN_SPEED and collision_info.collider.is_in_group("environment"):
|
||||
if speed == max_run_speed and collision_info.collider.is_in_group("environment"):
|
||||
return null
|
||||
|
||||
|
||||
func move(speed, direction):
|
||||
velocity = direction.normalized() * speed
|
||||
owner.move_and_slide(velocity, Vector2(), 5, 2)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
extends "../motion.gd"
|
||||
|
||||
# warning-ignore-all:unused_class_variable
|
||||
var speed = 0.0
|
||||
var velocity = Vector2()
|
||||
|
||||
|
||||
@@ -234,11 +234,10 @@ anims/attack_fast = SubResource( 3 )
|
||||
anims/attack_medium = SubResource( 4 )
|
||||
anims/idle = SubResource( 5 )
|
||||
|
||||
[node name="sword" type="Sprite" parent="."]
|
||||
[node name="Sword" type="Sprite" parent="."]
|
||||
position = Vector2( 4, 0 )
|
||||
texture = ExtResource( 2 )
|
||||
offset = Vector2( 67, 0 )
|
||||
|
||||
[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="."]
|
||||
polygon = PoolVector2Array( 28.0001, -15.9999, 136, -15.9995, 160, 0, 136, 16.0005, 27.9999, 16.0001 )
|
||||
|
||||
|
||||
@@ -2,101 +2,112 @@ extends Area2D
|
||||
|
||||
signal attack_finished
|
||||
|
||||
enum STATES { IDLE, ATTACK }
|
||||
enum States { IDLE, ATTACK }
|
||||
var state = null
|
||||
|
||||
enum ATTACK_INPUT_STATES { IDLE, LISTENING, REGISTERED }
|
||||
var attack_input_state = ATTACK_INPUT_STATES.IDLE
|
||||
enum AttackInputStates { IDLE, LISTENING, REGISTERED }
|
||||
var attack_input_state = AttackInputStates.IDLE
|
||||
var ready_for_next_attack = false
|
||||
const MAX_COMBO_COUNT = 3
|
||||
var combo_count = 0
|
||||
|
||||
var attack_current = {}
|
||||
var combo = [{
|
||||
'damage': 1,
|
||||
'animation': 'attack_fast',
|
||||
'effect': null
|
||||
"damage": 1,
|
||||
"animation": "attack_fast",
|
||||
"effect": null
|
||||
},
|
||||
{
|
||||
'damage': 1,
|
||||
'animation': 'attack_fast',
|
||||
'effect': null
|
||||
"damage": 1,
|
||||
"animation": "attack_fast",
|
||||
"effect": null
|
||||
},
|
||||
{
|
||||
'damage': 3,
|
||||
'animation': 'attack_medium',
|
||||
'effect': null
|
||||
"damage": 3,
|
||||
"animation": "attack_medium",
|
||||
"effect": null
|
||||
}]
|
||||
|
||||
var hit_objects = []
|
||||
|
||||
func _ready():
|
||||
$AnimationPlayer.connect('animation_finished', self, "_on_animation_finished")
|
||||
# warning-ignore:return_value_discarded
|
||||
$AnimationPlayer.connect("animation_finished", self, "_on_animation_finished")
|
||||
# warning-ignore:return_value_discarded
|
||||
self.connect("body_entered", self, "_on_body_entered")
|
||||
_change_state(STATES.IDLE)
|
||||
_change_state(States.IDLE)
|
||||
|
||||
|
||||
func _change_state(new_state):
|
||||
match state:
|
||||
STATES.ATTACK:
|
||||
States.ATTACK:
|
||||
hit_objects = []
|
||||
attack_input_state = ATTACK_INPUT_STATES.LISTENING
|
||||
attack_input_state = AttackInputStates.LISTENING
|
||||
ready_for_next_attack = false
|
||||
|
||||
match new_state:
|
||||
STATES.IDLE:
|
||||
States.IDLE:
|
||||
combo_count = 0
|
||||
$AnimationPlayer.stop()
|
||||
visible = false
|
||||
monitoring = false
|
||||
STATES.ATTACK:
|
||||
States.ATTACK:
|
||||
attack_current = combo[combo_count -1]
|
||||
$AnimationPlayer.play(attack_current['animation'])
|
||||
$AnimationPlayer.play(attack_current["animation"])
|
||||
visible = true
|
||||
monitoring = true
|
||||
state = new_state
|
||||
|
||||
func _input(event):
|
||||
if not state == STATES.ATTACK:
|
||||
return
|
||||
if attack_input_state != ATTACK_INPUT_STATES.LISTENING:
|
||||
return
|
||||
if event.is_action_pressed('attack'):
|
||||
attack_input_state = ATTACK_INPUT_STATES.REGISTERED
|
||||
|
||||
func _physics_process(delta):
|
||||
if attack_input_state == ATTACK_INPUT_STATES.REGISTERED and ready_for_next_attack:
|
||||
func _input(event):
|
||||
if not state == States.ATTACK:
|
||||
return
|
||||
if attack_input_state != AttackInputStates.LISTENING:
|
||||
return
|
||||
if event.is_action_pressed("attack"):
|
||||
attack_input_state = AttackInputStates.REGISTERED
|
||||
|
||||
|
||||
func _physics_process(_delta):
|
||||
if attack_input_state == AttackInputStates.REGISTERED and ready_for_next_attack:
|
||||
attack()
|
||||
|
||||
|
||||
func attack():
|
||||
combo_count += 1
|
||||
_change_state(STATES.ATTACK)
|
||||
_change_state(States.ATTACK)
|
||||
|
||||
# use with AnimationPlayer func track
|
||||
|
||||
# Use with AnimationPlayer func track.
|
||||
func set_attack_input_listening():
|
||||
attack_input_state = ATTACK_INPUT_STATES.LISTENING
|
||||
attack_input_state = AttackInputStates.LISTENING
|
||||
|
||||
# use with AnimationPlayer func track
|
||||
|
||||
# Use with AnimationPlayer func track.
|
||||
func set_ready_for_next_attack():
|
||||
ready_for_next_attack = true
|
||||
|
||||
|
||||
func _on_body_entered(body):
|
||||
if not body.has_node('Health'):
|
||||
if not body.has_node("Health"):
|
||||
return
|
||||
if body.get_rid().get_id() in hit_objects:
|
||||
return
|
||||
hit_objects.append(body.get_rid().get_id())
|
||||
body.take_damage(self, attack_current['damage'], attack_current['effect'])
|
||||
body.take_damage(self, attack_current["damage"], attack_current["effect"])
|
||||
|
||||
func _on_animation_finished(name):
|
||||
|
||||
func _on_animation_finished(_name):
|
||||
if not attack_current:
|
||||
return
|
||||
|
||||
if attack_input_state == ATTACK_INPUT_STATES.REGISTERED and combo_count < MAX_COMBO_COUNT:
|
||||
if attack_input_state == AttackInputStates.REGISTERED and combo_count < MAX_COMBO_COUNT:
|
||||
attack()
|
||||
else:
|
||||
_change_state(STATES.IDLE)
|
||||
_change_state(States.IDLE)
|
||||
emit_signal("attack_finished")
|
||||
|
||||
|
||||
func _on_StateMachine_state_changed(current_state):
|
||||
if current_state.name == "Attack":
|
||||
attack()
|
||||
|
||||
@@ -3,13 +3,15 @@ extends Position2D
|
||||
var z_index_start = 0
|
||||
|
||||
func _ready():
|
||||
owner.connect("direction_changed", self, '_on_Parent_direction_changed')
|
||||
#warning-ignore:return_value_discarded
|
||||
owner.connect("direction_changed", self, "_on_Parent_direction_changed")
|
||||
z_index_start = z_index
|
||||
|
||||
|
||||
func _on_Parent_direction_changed(direction):
|
||||
rotation = direction.angle()
|
||||
match direction:
|
||||
Vector2(0, -1):
|
||||
Vector2.UP:
|
||||
z_index = z_index_start - 1
|
||||
_:
|
||||
z_index = z_index_start
|
||||
|
||||
@@ -37,6 +37,7 @@ move_left={
|
||||
"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":16777231,"unicode":0,"echo":false,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":65,"unicode":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":0,"axis_value":-1.0,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":14,"pressure":0.0,"pressed":false,"script":null)
|
||||
]
|
||||
}
|
||||
move_up={
|
||||
@@ -44,6 +45,7 @@ move_up={
|
||||
"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":16777232,"unicode":0,"echo":false,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":87,"unicode":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":1,"axis_value":-1.0,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":12,"pressure":0.0,"pressed":false,"script":null)
|
||||
]
|
||||
}
|
||||
move_right={
|
||||
@@ -51,6 +53,7 @@ move_right={
|
||||
"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":16777233,"unicode":0,"echo":false,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":68,"unicode":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":0,"axis_value":1.0,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":15,"pressure":0.0,"pressed":false,"script":null)
|
||||
]
|
||||
}
|
||||
move_down={
|
||||
@@ -58,18 +61,19 @@ move_down={
|
||||
"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":16777234,"unicode":0,"echo":false,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":83,"unicode":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":1,"axis_value":1.0,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":13,"pressure":0.0,"pressed":false,"script":null)
|
||||
]
|
||||
}
|
||||
fire={
|
||||
"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":82,"unicode":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":2,"pressure":0.0,"pressed":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":7,"pressure":0.0,"pressed":false,"script":null)
|
||||
]
|
||||
}
|
||||
run={
|
||||
"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":7,"pressure":0.0,"pressed":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":1,"pressure":0.0,"pressed":false,"script":null)
|
||||
]
|
||||
}
|
||||
jump={
|
||||
@@ -81,11 +85,13 @@ jump={
|
||||
simulate_damage={
|
||||
"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":88,"unicode":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":3,"pressure":0.0,"pressed":false,"script":null)
|
||||
]
|
||||
}
|
||||
attack={
|
||||
"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":70,"unicode":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":6,"pressure":0.0,"pressed":false,"script":null)
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@@ -1,25 +1,28 @@
|
||||
"""
|
||||
Base interface for all states: it doesn't do anything in itself
|
||||
but forces us to pass the right arguments to the methods below
|
||||
and makes sure every State object had all of these methods.
|
||||
"""
|
||||
extends Node
|
||||
# Base interface for all states: it doesn't do anything by itself,
|
||||
# but forces us to pass the right arguments to the methods below
|
||||
# and makes sure every State object had all of these methods.
|
||||
|
||||
# warning-ignore:unused_signal
|
||||
signal finished(next_state_name)
|
||||
|
||||
# Initialize the state. E.g. change the animation
|
||||
# Initialize the state. E.g. change the animation.
|
||||
func enter():
|
||||
return
|
||||
pass
|
||||
|
||||
# Clean up the state. Reinitialize values like a timer
|
||||
|
||||
# Clean up the state. Reinitialize values like a timer.
|
||||
func exit():
|
||||
return
|
||||
pass
|
||||
|
||||
func handle_input(event):
|
||||
return
|
||||
|
||||
func update(delta):
|
||||
return
|
||||
func handle_input(_event):
|
||||
pass
|
||||
|
||||
func _on_animation_finished(anim_name):
|
||||
return
|
||||
|
||||
func update(_delta):
|
||||
pass
|
||||
|
||||
|
||||
func _on_animation_finished(_anim_name):
|
||||
pass
|
||||
|
||||
@@ -1,21 +1,17 @@
|
||||
"""
|
||||
Base interface for a generic state machine
|
||||
It handles initializing, setting the machine active or not
|
||||
delegating _physics_process, _input calls to the State nodes,
|
||||
and changing the current/active state.
|
||||
See the PlayerV2 scene for an example on how to use it
|
||||
"""
|
||||
extends Node
|
||||
# Base interface for a generic state machine.
|
||||
# It handles initializing, setting the machine active or not
|
||||
# delegating _physics_process, _input calls to the State nodes,
|
||||
# and changing the current/active state.
|
||||
# See the PlayerV2 scene for an example on how to use it.
|
||||
|
||||
signal state_changed(current_state)
|
||||
|
||||
"""
|
||||
You must set a starting node from the inspector or on
|
||||
the node that inherits from this state machine interface
|
||||
If you don't the game will crash (on purpose, so you won't
|
||||
forget to initialize the state machine)
|
||||
"""
|
||||
export(NodePath) var START_STATE
|
||||
# You must set a starting node from the inspector or on
|
||||
# the node that inherits from this state machine interface.
|
||||
# If you don't the game will crash (on purpose, so you won't
|
||||
# forget to initialize the state machine).
|
||||
export(NodePath) var start_state
|
||||
var states_map = {}
|
||||
|
||||
var states_stack = []
|
||||
@@ -23,18 +19,20 @@ var current_state = null
|
||||
var _active = false setget set_active
|
||||
|
||||
func _ready():
|
||||
if not START_STATE:
|
||||
START_STATE = get_child(0).get_path()
|
||||
if not start_state:
|
||||
start_state = get_child(0).get_path()
|
||||
for child in get_children():
|
||||
child.connect("finished", self, "_change_state")
|
||||
initialize(START_STATE)
|
||||
initialize(start_state)
|
||||
|
||||
func initialize(start_state):
|
||||
|
||||
func initialize(initial_state):
|
||||
set_active(true)
|
||||
states_stack.push_front(get_node(start_state))
|
||||
states_stack.push_front(get_node(initial_state))
|
||||
current_state = states_stack[0]
|
||||
current_state.enter()
|
||||
|
||||
|
||||
func set_active(value):
|
||||
_active = value
|
||||
set_physics_process(value)
|
||||
@@ -43,17 +41,21 @@ func set_active(value):
|
||||
states_stack = []
|
||||
current_state = null
|
||||
|
||||
|
||||
func _input(event):
|
||||
current_state.handle_input(event)
|
||||
|
||||
|
||||
func _physics_process(delta):
|
||||
current_state.update(delta)
|
||||
|
||||
|
||||
func _on_animation_finished(anim_name):
|
||||
if not _active:
|
||||
return
|
||||
current_state._on_animation_finished(anim_name)
|
||||
|
||||
|
||||
func _change_state(state_name):
|
||||
if not _active:
|
||||
return
|
||||
|
||||
@@ -74,7 +74,6 @@ directional_shadow_normal_bias = 0.1
|
||||
environment = SubResource( 2 )
|
||||
|
||||
[node name="Coins" type="Node" parent="."]
|
||||
editor/display_folded = true
|
||||
|
||||
[node name="coin" parent="Coins" instance=ExtResource( 3 )]
|
||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 18.5311, 2.85075, 5.24675 )
|
||||
@@ -278,7 +277,6 @@ interior_enable = true
|
||||
interior_ambient_color = Color( 0.403137, 0.55498, 0.884824, 1 )
|
||||
|
||||
[node name="SoundArea1" type="Area" parent="."]
|
||||
editor/display_folded = true
|
||||
reverb_bus_enable = true
|
||||
reverb_bus_name = "Reverb Large"
|
||||
reverb_bus_amount = 0.26
|
||||
@@ -289,7 +287,6 @@ transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 14.7075, 5.19958, 9.21556 )
|
||||
shape = SubResource( 7 )
|
||||
|
||||
[node name="SoundArea2" type="Area" parent="."]
|
||||
editor/display_folded = true
|
||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 27.1673, 0, 0 )
|
||||
reverb_bus_enable = true
|
||||
reverb_bus_name = "Reverb Small"
|
||||
@@ -301,7 +298,6 @@ transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 8.29529, 5.19958, 15.9933 )
|
||||
shape = SubResource( 8 )
|
||||
|
||||
[node name="SoundArea3" type="Area" parent="."]
|
||||
editor/display_folded = true
|
||||
reverb_bus_enable = true
|
||||
reverb_bus_name = "Reverb Large"
|
||||
reverb_bus_amount = 0.26
|
||||
|
||||
Reference in New Issue
Block a user