gd,refacto: added state chart addon and namespace cleanup

This commit is contained in:
2025-06-05 14:47:51 +02:00
parent 8818e77d23
commit 5c36765a36
239 changed files with 10430 additions and 115 deletions

View File

@ -0,0 +1,276 @@
extends CharacterBody2D
signal clicked(node:Node2D)
@export var marker_scene:PackedScene
## The navigation agent we use.
@onready var navigation_agent:NavigationAgent2D = $NavigationAgent2D
## The state chart
@onready var state_chart:StateChart = $StateChart
## Set of close food markers
var food_markers:Dictionary = {}
## Set of close nest markers
var nest_markers:Dictionary = {}
## Set of food nearby
var food:Dictionary = {}
## The nest, if nearby
var nest:Node2D = null
## The currently carried food
var carried_food:Node = null
const SEGMENT_LENGTH = 150
func _ready():
# start the state chart
state_chart.send_event.call_deferred("initialized")
## Called when we are seeking for food and need a new target.
func _on_idle_seeking_food():
var current_position := get_global_position()
# if we have food nearby grab it
if food.size() > 0:
state_chart.send_event("food_detected")
return
var target_position := Vector2()
# if we have food markers nearby travel into the general direction of the closest one points
if food_markers.size() > 0:
var closest_food_marker := _find_closest(food_markers.keys(), current_position)
var direction = Vector2.RIGHT.rotated(closest_food_marker.get_rotation())
target_position = current_position + (direction * SEGMENT_LENGTH)
# otherwise or if we couldn't reach the last target position, pick a random
# direction
if food_markers.size() == 0 or not navigation_agent.is_target_reachable():
# otherwise pick a random position in a radius of SEGMENT_LENGTH pixels
# first calculate a random angle in radians
var random_angle := randf() * 2 * PI
# then calculate the x and y components of the vector
var random_x := cos(random_angle) * SEGMENT_LENGTH
var random_y := sin(random_angle) * SEGMENT_LENGTH
# add the random vector to the current position
target_position = current_position + Vector2(random_x, random_y)
navigation_agent.set_target_position(target_position)
state_chart.set_expression_property("target_position", target_position)
state_chart.send_event("destination_set")
## Called when we have found food nearby and want to go to it
func _on_food_detected():
# set the target position to the closest food
var closest_food_position = _find_closest(food.keys(), get_global_position()).global_position
navigation_agent.set_target_position(closest_food_position)
## Called when we arrived at the food and want to pick it up
func _on_food_reached():
var closest_food = _find_closest(food.keys(), get_global_position())
if not is_instance_valid(closest_food):
# some other ant must have picked it up
state_chart.send_event("food_vanished")
return
closest_food.get_parent().remove_child(closest_food)
carried_food = closest_food
# remove it from the food set
food.erase(closest_food)
# it's collected, so remove it from the food group
closest_food.remove_from_group("food")
# add it to our ant so it moves with us
add_child(closest_food)
closest_food.position = Vector2.ZERO
closest_food.scale = Vector2(0.5, 0.5)
# place a marker pointing to the food (0 means point into the current direction)
var marker = _place_marker(Marker.MarkerType.FOOD, global_position, 0)
food_markers[marker] = true
# notify the state chart that we picked up food
state_chart.send_event("food_picked_up")
## Called when we are returning home and need a new target.
func _on_idle_returning_home():
var current_position := get_global_position()
# if the nest is nearby, drop off the food
if nest != null:
state_chart.send_event("nest_detected")
return
var target_position := Vector2()
# if we have nest markers nearby travel into the general direction of the closest one points
if nest_markers.size() > 0:
# refresh them
for marker in nest_markers.keys():
marker.refresh()
var closest_nest_marker := _find_closest(nest_markers.keys(), current_position)
var direction = Vector2.RIGHT.rotated(closest_nest_marker.get_rotation())
target_position = current_position + (direction * SEGMENT_LENGTH)
# if we have no nest markers or the navigation agent couldn't reach
# the position of the last target pick a random direction
if nest_markers.size() == 0 or not navigation_agent.is_target_reachable():
var random_angle := randf() * 2 * PI
# then calculate the x and y components of the vector
var random_x := cos(random_angle) * SEGMENT_LENGTH
var random_y := sin(random_angle) * SEGMENT_LENGTH
# add the random vector to the current position
target_position = current_position + Vector2(random_x, random_y)
navigation_agent.set_target_position(target_position)
state_chart.set_expression_property("target_position", target_position)
state_chart.send_event("destination_set")
return
## Called when we are returning home and detected the nest
func _on_nest_detected():
# travel to the nest
navigation_agent.set_target_position(nest.global_position)
state_chart.set_expression_property("target_position", nest.global_position)
## Called when we have arrived at the nest and want to drop off the food
func _on_nest_reached():
# drop off the food
carried_food.get_parent().remove_child(carried_food)
carried_food.queue_free()
carried_food = null
# notify the state chart that we dropped off the food
state_chart.send_event("food_dropped")
## Called while travelling to a destination
func _on_travelling_state_physics_processing(_delta):
# get the next position on the path
var path_position = navigation_agent.get_next_path_position()
# and move towards it
velocity = (path_position - get_global_position()).normalized() * navigation_agent.max_speed
look_at(path_position)
move_and_slide()
func _on_input_event(_viewport, event, _shape_idx):
# if the left mouse button is up emit the clicked signal
if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.is_pressed() == false:
# print("clicked")
clicked.emit(self)
## Called when the ant is sensing something nearby.
func _on_sensor_area_area_entered(area:Area2D):
var node = area
if area.has_meta("owner"):
node = area.get_node(area.get_meta("owner"))
if node.is_in_group("marker"):
# it's a marker
if node.is_in_group("food"):
food_markers[node] = true
elif node.is_in_group("nest"):
nest_markers[node] = true
elif node.is_in_group("food"):
# it's food
food[node] = true
elif node.is_in_group("nest"):
# it's the nest
nest = node
state_chart.set_expression_property("nest_markers", nest_markers.size())
state_chart.set_expression_property("food_markers", food_markers.size())
func _on_sensor_area_area_exited(area:Area2D):
var node = area
if area.has_meta("owner"):
node = area.get_node(area.get_meta("owner"))
if node.is_in_group("marker"):
# it's a marker
if node.is_in_group("food"):
food_markers.erase(node)
elif node.is_in_group("nest"):
nest_markers.erase(node)
elif node.is_in_group("food"):
# it's food
food.erase(node)
elif node.is_in_group("nest"):
# it's the nest
nest = null
state_chart.set_expression_property("nest_markers", nest_markers.size())
state_chart.set_expression_property("food_markers", nest_markers.size())
## Finds the closest position to the given position from the given list of nodes.
func _find_closest(targets:Array, from:Vector2) -> Node2D:
var shortest_distance := 99999999.00
var result = null
for target in targets:
var distance := from.distance_squared_to(target.get_global_position())
if distance < shortest_distance:
shortest_distance = distance
result = target
return result
## Places a marker of the given type at the given position
func _place_marker(type:Marker.MarkerType, target_position:Vector2, offset:float = PI) -> Marker:
var marker = marker_scene.instantiate()
marker.initialize(type)
# add to the tree on our parent
get_parent().add_child.call_deferred(marker)
# set the position to our current position
marker.set_global_position(target_position)
# set the marker rotation to look opposite to the direction we are facing
marker.set_rotation(get_rotation() + offset)
return marker
func _place_nest_marker():
# if there are already nest markers around, just refresh them
if nest_markers.size() > 0:
for marker in nest_markers:
marker.refresh()
else:
# otherwise place a new one
_place_marker(Marker.MarkerType.NEST, global_position)
func _place_food_marker():
_place_marker(Marker.MarkerType.FOOD, global_position)
func _maintenance(_delta):
# remove all markers which are no longer valid
for marker in food_markers.keys():
if not is_instance_valid(marker):
food_markers.erase(marker)
for marker in nest_markers.keys():
if not is_instance_valid(marker):
nest_markers.erase(marker)

View File

@ -0,0 +1 @@
uid://d4ld8mlrjp04a

View File

@ -0,0 +1,5 @@
shader_type canvas_item;
void fragment() {
COLOR = COLOR + vec4(.3,.3,.1,.0);
}

View File

@ -0,0 +1 @@
uid://bx4vu24rcr0m5

View File

@ -0,0 +1,686 @@
[gd_scene load_steps=75 format=3 uid="uid://dy43c80qlfftx"]
[ext_resource type="Shader" path="res://godot_state_charts_examples/ant_hill/ant/ant.gdshader" id="1_01qat"]
[ext_resource type="Texture2D" uid="uid://bqgc7cft671q0" path="res://godot_state_charts_examples/ant_hill/ant/walk.png" id="1_7ajse"]
[ext_resource type="Script" path="res://godot_state_charts_examples/ant_hill/ant/ant.gd" id="1_i761n"]
[ext_resource type="PackedScene" uid="uid://dy5xrmjffewnk" path="res://godot_state_charts_examples/ant_hill/marker/marker.tscn" id="2_lqnr1"]
[ext_resource type="Script" path="res://addons/godot_state_charts/state_chart.gd" id="3_lard5"]
[ext_resource type="Script" path="res://addons/godot_state_charts/compound_state.gd" id="4_ejp2e"]
[ext_resource type="Script" path="res://addons/godot_state_charts/atomic_state.gd" id="5_21sgy"]
[ext_resource type="Script" path="res://addons/godot_state_charts/transition.gd" id="7_qj278"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_bjtx1"]
shader = ExtResource("1_01qat")
[sub_resource type="AtlasTexture" id="AtlasTexture_p0h5v"]
atlas = ExtResource("1_7ajse")
region = Rect2(0, 0, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_mubvl"]
atlas = ExtResource("1_7ajse")
region = Rect2(202, 0, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_nj3h7"]
atlas = ExtResource("1_7ajse")
region = Rect2(404, 0, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_fij1g"]
atlas = ExtResource("1_7ajse")
region = Rect2(606, 0, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_i21td"]
atlas = ExtResource("1_7ajse")
region = Rect2(808, 0, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_a0fxu"]
atlas = ExtResource("1_7ajse")
region = Rect2(1010, 0, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_bwhdr"]
atlas = ExtResource("1_7ajse")
region = Rect2(1212, 0, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_hm8dw"]
atlas = ExtResource("1_7ajse")
region = Rect2(1414, 0, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_lfnfv"]
atlas = ExtResource("1_7ajse")
region = Rect2(0, 248, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_kljff"]
atlas = ExtResource("1_7ajse")
region = Rect2(202, 248, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_t8fco"]
atlas = ExtResource("1_7ajse")
region = Rect2(404, 248, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_blb68"]
atlas = ExtResource("1_7ajse")
region = Rect2(606, 248, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_2k7ie"]
atlas = ExtResource("1_7ajse")
region = Rect2(808, 248, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_vpjgq"]
atlas = ExtResource("1_7ajse")
region = Rect2(1010, 248, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_ykqrl"]
atlas = ExtResource("1_7ajse")
region = Rect2(1212, 248, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_yq06r"]
atlas = ExtResource("1_7ajse")
region = Rect2(1414, 248, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_m8wtm"]
atlas = ExtResource("1_7ajse")
region = Rect2(0, 496, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_ytxlu"]
atlas = ExtResource("1_7ajse")
region = Rect2(202, 496, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_jiy2o"]
atlas = ExtResource("1_7ajse")
region = Rect2(404, 496, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_vfiyg"]
atlas = ExtResource("1_7ajse")
region = Rect2(606, 496, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_sl3a2"]
atlas = ExtResource("1_7ajse")
region = Rect2(808, 496, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_nmj2f"]
atlas = ExtResource("1_7ajse")
region = Rect2(1010, 496, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_sngog"]
atlas = ExtResource("1_7ajse")
region = Rect2(1212, 496, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_71qgv"]
atlas = ExtResource("1_7ajse")
region = Rect2(1414, 496, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_88uru"]
atlas = ExtResource("1_7ajse")
region = Rect2(0, 744, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_kqc1k"]
atlas = ExtResource("1_7ajse")
region = Rect2(202, 744, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_ar5xr"]
atlas = ExtResource("1_7ajse")
region = Rect2(404, 744, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_xs12g"]
atlas = ExtResource("1_7ajse")
region = Rect2(606, 744, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_6mpdc"]
atlas = ExtResource("1_7ajse")
region = Rect2(808, 744, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_lqwgf"]
atlas = ExtResource("1_7ajse")
region = Rect2(1010, 744, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_xrg7o"]
atlas = ExtResource("1_7ajse")
region = Rect2(1212, 744, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_kmp2k"]
atlas = ExtResource("1_7ajse")
region = Rect2(1414, 744, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_hpmfd"]
atlas = ExtResource("1_7ajse")
region = Rect2(0, 992, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_3osu6"]
atlas = ExtResource("1_7ajse")
region = Rect2(202, 992, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_gdwlg"]
atlas = ExtResource("1_7ajse")
region = Rect2(404, 992, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_hau5u"]
atlas = ExtResource("1_7ajse")
region = Rect2(606, 992, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_2uawa"]
atlas = ExtResource("1_7ajse")
region = Rect2(808, 992, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_aj6m3"]
atlas = ExtResource("1_7ajse")
region = Rect2(1010, 992, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_lnduy"]
atlas = ExtResource("1_7ajse")
region = Rect2(1212, 992, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_bqt77"]
atlas = ExtResource("1_7ajse")
region = Rect2(1414, 992, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_plrtj"]
atlas = ExtResource("1_7ajse")
region = Rect2(0, 1240, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_ggvde"]
atlas = ExtResource("1_7ajse")
region = Rect2(202, 1240, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_xavhi"]
atlas = ExtResource("1_7ajse")
region = Rect2(404, 1240, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_ev8ji"]
atlas = ExtResource("1_7ajse")
region = Rect2(606, 1240, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_65x5e"]
atlas = ExtResource("1_7ajse")
region = Rect2(808, 1240, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_yi6fp"]
atlas = ExtResource("1_7ajse")
region = Rect2(1010, 1240, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_eseb1"]
atlas = ExtResource("1_7ajse")
region = Rect2(1212, 1240, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_ux63t"]
atlas = ExtResource("1_7ajse")
region = Rect2(1414, 1240, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_ocabh"]
atlas = ExtResource("1_7ajse")
region = Rect2(0, 1488, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_8sepc"]
atlas = ExtResource("1_7ajse")
region = Rect2(202, 1488, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_4d7on"]
atlas = ExtResource("1_7ajse")
region = Rect2(404, 1488, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_jsu7m"]
atlas = ExtResource("1_7ajse")
region = Rect2(606, 1488, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_vhyb2"]
atlas = ExtResource("1_7ajse")
region = Rect2(808, 1488, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_t2dka"]
atlas = ExtResource("1_7ajse")
region = Rect2(1010, 1488, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_e6l64"]
atlas = ExtResource("1_7ajse")
region = Rect2(1212, 1488, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_mdp8v"]
atlas = ExtResource("1_7ajse")
region = Rect2(1414, 1488, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_ywpdo"]
atlas = ExtResource("1_7ajse")
region = Rect2(0, 1736, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_1d2bj"]
atlas = ExtResource("1_7ajse")
region = Rect2(202, 1736, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_80asc"]
atlas = ExtResource("1_7ajse")
region = Rect2(404, 1736, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_m5ngl"]
atlas = ExtResource("1_7ajse")
region = Rect2(606, 1736, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_r7ql0"]
atlas = ExtResource("1_7ajse")
region = Rect2(808, 1736, 202, 248)
[sub_resource type="AtlasTexture" id="AtlasTexture_w0vp4"]
atlas = ExtResource("1_7ajse")
region = Rect2(1010, 1736, 202, 248)
[sub_resource type="SpriteFrames" id="SpriteFrames_kcoy1"]
animations = [{
"frames": [],
"loop": true,
"name": &"default",
"speed": 5.0
}, {
"frames": [{
"duration": 1.0,
"texture": SubResource("AtlasTexture_p0h5v")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_mubvl")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_nj3h7")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_fij1g")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_i21td")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_a0fxu")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_bwhdr")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_hm8dw")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_lfnfv")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_kljff")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_t8fco")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_blb68")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_2k7ie")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_vpjgq")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_ykqrl")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_yq06r")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_m8wtm")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_ytxlu")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_jiy2o")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_vfiyg")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_sl3a2")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_nmj2f")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_sngog")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_71qgv")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_88uru")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_kqc1k")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_ar5xr")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_xs12g")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_6mpdc")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_lqwgf")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_xrg7o")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_kmp2k")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_hpmfd")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_3osu6")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_gdwlg")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_hau5u")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_2uawa")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_aj6m3")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_lnduy")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_bqt77")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_plrtj")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_ggvde")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_xavhi")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_ev8ji")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_65x5e")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_yi6fp")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_eseb1")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_ux63t")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_ocabh")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_8sepc")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_4d7on")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_jsu7m")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_vhyb2")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_t2dka")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_e6l64")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_mdp8v")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_ywpdo")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_1d2bj")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_80asc")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_m5ngl")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_r7ql0")
}, {
"duration": 1.0,
"texture": SubResource("AtlasTexture_w0vp4")
}],
"loop": true,
"name": &"walk",
"speed": 64.0
}]
[sub_resource type="CapsuleShape2D" id="CapsuleShape2D_1lk3q"]
radius = 4.0
height = 12.0
[sub_resource type="CircleShape2D" id="CircleShape2D_htg24"]
radius = 80.0
[node name="Ant" type="CharacterBody2D"]
z_index = 2048
z_as_relative = false
collision_layer = 16
input_pickable = true
motion_mode = 1
platform_on_leave = 2
safe_margin = 2.615
script = ExtResource("1_i761n")
marker_scene = ExtResource("2_lqnr1")
[node name="Sprite2D" type="AnimatedSprite2D" parent="."]
material = SubResource("ShaderMaterial_bjtx1")
rotation = 1.5708
scale = Vector2(0.05, 0.05)
sprite_frames = SubResource("SpriteFrames_kcoy1")
animation = &"walk"
frame_progress = 0.938219
[node name="NavigationAgent2D" type="NavigationAgent2D" parent="."]
editor_description = "This navigation agent sends the \"navigation_finished\" event to the state chart whenever the navigation is done."
avoidance_enabled = true
radius = 40.0
max_speed = 50.0
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
position = Vector2(0, 1)
shape = SubResource("CapsuleShape2D_1lk3q")
[node name="SensorArea" type="Area2D" parent="."]
[node name="CollisionShape2D" type="CollisionShape2D" parent="SensorArea"]
shape = SubResource("CircleShape2D_htg24")
[node name="StateChart" type="Node" parent="."]
script = ExtResource("3_lard5")
track_in_editor = true
[node name="Root" type="Node" parent="StateChart"]
script = ExtResource("4_ejp2e")
initial_state = NodePath("Initializing")
[node name="Initializing" type="Node" parent="StateChart/Root"]
editor_description = "This state is used for script initialization."
script = ExtResource("5_21sgy")
[node name="Transition" type="Node" parent="StateChart/Root/Initializing"]
script = ExtResource("7_qj278")
to = NodePath("../../Seeking Food")
event = &"initialized"
[node name="Seeking Food" type="Node" parent="StateChart/Root"]
editor_description = "In this state, the ant will look for food."
script = ExtResource("4_ejp2e")
initial_state = NodePath("Idle")
[node name="Idle" type="Node" parent="StateChart/Root/Seeking Food"]
editor_description = "This state is active when the ant currently has no target. It is connected to the script which will look for a new target."
script = ExtResource("5_21sgy")
[node name="On Next Destination" type="Node" parent="StateChart/Root/Seeking Food/Idle"]
script = ExtResource("7_qj278")
to = NodePath("../../Travelling/Place Marker")
event = &"destination_set"
[node name="On Food Detected" type="Node" parent="StateChart/Root/Seeking Food/Idle"]
script = ExtResource("7_qj278")
to = NodePath("../../../Picking up Food")
event = &"food_detected"
[node name="Travelling" type="Node" parent="StateChart/Root/Seeking Food"]
script = ExtResource("4_ejp2e")
initial_state = NodePath("Travel")
[node name="On Navigation Finish" type="Node" parent="StateChart/Root/Seeking Food/Travelling"]
editor_description = "When navigation is finished return to idle state."
script = ExtResource("7_qj278")
to = NodePath("../../Idle")
event = &"navigation_finished"
[node name="Travel" type="Node" parent="StateChart/Root/Seeking Food/Travelling"]
editor_description = "This state is active while the ant is travelling when searching for food. Periodically the state will be left for placing a marker."
script = ExtResource("5_21sgy")
[node name="Periodically Place Marker" type="Node" parent="StateChart/Root/Seeking Food/Travelling/Travel"]
editor_description = "While searching for food, periodically place a marker pointing towards the nest. This transition will move to the \"Place Marker\" state which will trigger the placement of the marker. The \"Place Marker\" state will immediately return back to the \"Travel\" state."
script = ExtResource("7_qj278")
to = NodePath("../../Place Marker")
delay_seconds = 0.75
[node name="Place Marker" type="Node" parent="StateChart/Root/Seeking Food/Travelling"]
editor_description = "This state is briefly activated when the ant wants to place a marker. It will immediately exit again to the \"Travel\" state."
script = ExtResource("5_21sgy")
[node name="Return travelling" type="Node" parent="StateChart/Root/Seeking Food/Travelling/Place Marker"]
script = ExtResource("7_qj278")
to = NodePath("../../Travel")
[node name="Picking up Food" type="Node" parent="StateChart/Root"]
editor_description = "This state is active when the ant has detected food and wants to pick it up."
script = ExtResource("4_ejp2e")
initial_state = NodePath("Travelling")
[node name="Travelling" type="Node" parent="StateChart/Root/Picking up Food"]
editor_description = "This state is active while the ant is moving towards the food."
script = ExtResource("5_21sgy")
[node name="On Navigation Finish" type="Node" parent="StateChart/Root/Picking up Food/Travelling"]
editor_description = "When navigation is finished we can pick up the food."
script = ExtResource("7_qj278")
to = NodePath("../../Picking Up")
event = &"navigation_finished"
[node name="Picking Up" type="Node" parent="StateChart/Root/Picking up Food"]
editor_description = "This state is active when the ant has reached the food and now picks it up."
script = ExtResource("5_21sgy")
[node name="On Picked Up" type="Node" parent="StateChart/Root/Picking up Food/Picking Up"]
editor_description = "When navigation is finished return to idle state."
script = ExtResource("7_qj278")
to = NodePath("../../../Returning Home")
event = &"food_picked_up"
[node name="On Food Vanished" type="Node" parent="StateChart/Root/Picking up Food/Picking Up"]
editor_description = "When navigation is finished return to idle state."
script = ExtResource("7_qj278")
to = NodePath("../../../Seeking Food")
event = &"food_vanished"
[node name="Returning Home" type="Node" parent="StateChart/Root"]
editor_description = "This state is active when the ant has found food and wants to return home."
script = ExtResource("4_ejp2e")
initial_state = NodePath("Idle")
[node name="Idle" type="Node" parent="StateChart/Root/Returning Home"]
editor_description = "This state is active when the ant currently has no destination. It calls back into the script which will setup a new destination."
script = ExtResource("5_21sgy")
[node name="On Next Destination" type="Node" parent="StateChart/Root/Returning Home/Idle"]
script = ExtResource("7_qj278")
to = NodePath("../../Travelling")
event = &"destination_set"
[node name="On Nest Detected" type="Node" parent="StateChart/Root/Returning Home/Idle"]
script = ExtResource("7_qj278")
to = NodePath("../../../Delivering Food")
event = &"nest_detected"
[node name="Travelling" type="Node" parent="StateChart/Root/Returning Home"]
editor_description = "This state is active when the ant has a destination and is currently travelling."
script = ExtResource("4_ejp2e")
initial_state = NodePath("Travel")
[node name="On Navigation Finish" type="Node" parent="StateChart/Root/Returning Home/Travelling"]
editor_description = "When navigation is finished return to idle state."
script = ExtResource("7_qj278")
to = NodePath("../../Idle")
event = &"navigation_finished"
[node name="Travel" type="Node" parent="StateChart/Root/Returning Home/Travelling"]
script = ExtResource("5_21sgy")
[node name="Periodically Place Marker" type="Node" parent="StateChart/Root/Returning Home/Travelling/Travel"]
script = ExtResource("7_qj278")
to = NodePath("../../Place Marker")
delay_seconds = 1.0
[node name="Place Marker" type="Node" parent="StateChart/Root/Returning Home/Travelling"]
editor_description = "This state is active when the ant has a destination and is moving towards it."
script = ExtResource("5_21sgy")
[node name="Return travelling" type="Node" parent="StateChart/Root/Returning Home/Travelling/Place Marker"]
script = ExtResource("7_qj278")
to = NodePath("../../Travel")
[node name="Delivering Food" type="Node" parent="StateChart/Root"]
editor_description = "This state is active when the ant has detected the nest and wants to bring food back."
script = ExtResource("4_ejp2e")
initial_state = NodePath("Travelling")
[node name="Travelling" type="Node" parent="StateChart/Root/Delivering Food"]
editor_description = "This state is active when the ant is moving towards the nest."
script = ExtResource("5_21sgy")
[node name="On Navigation Finish" type="Node" parent="StateChart/Root/Delivering Food/Travelling"]
editor_description = "When navigation is finished we can pick up the food."
script = ExtResource("7_qj278")
to = NodePath("../../Dropping")
event = &"navigation_finished"
[node name="Dropping" type="Node" parent="StateChart/Root/Delivering Food"]
editor_description = "This state is active when the ant is dropping the food off at the nest."
script = ExtResource("5_21sgy")
[node name="On Dropped" type="Node" parent="StateChart/Root/Delivering Food/Dropping"]
editor_description = "When navigation is finished return to idle state."
script = ExtResource("7_qj278")
to = NodePath("../../../Seeking Food")
event = &"food_dropped"
[connection signal="input_event" from="." to="." method="_on_input_event"]
[connection signal="ready" from="Sprite2D" to="Sprite2D" method="play" binds= ["walk"]]
[connection signal="navigation_finished" from="NavigationAgent2D" to="StateChart" method="send_event" binds= [&"navigation_finished"]]
[connection signal="area_entered" from="SensorArea" to="." method="_on_sensor_area_area_entered"]
[connection signal="area_exited" from="SensorArea" to="." method="_on_sensor_area_area_exited"]
[connection signal="state_physics_processing" from="StateChart/Root" to="." method="_maintenance"]
[connection signal="state_entered" from="StateChart/Root/Seeking Food/Idle" to="." method="_on_idle_seeking_food"]
[connection signal="state_physics_processing" from="StateChart/Root/Seeking Food/Travelling" to="." method="_on_travelling_state_physics_processing"]
[connection signal="state_entered" from="StateChart/Root/Seeking Food/Travelling/Place Marker" to="." method="_place_nest_marker"]
[connection signal="state_entered" from="StateChart/Root/Picking up Food/Travelling" to="." method="_on_food_detected"]
[connection signal="state_physics_processing" from="StateChart/Root/Picking up Food/Travelling" to="." method="_on_travelling_state_physics_processing"]
[connection signal="state_entered" from="StateChart/Root/Picking up Food/Picking Up" to="." method="_on_food_reached"]
[connection signal="state_entered" from="StateChart/Root/Returning Home/Idle" to="." method="_on_idle_returning_home"]
[connection signal="state_physics_processing" from="StateChart/Root/Returning Home/Travelling" to="." method="_on_travelling_state_physics_processing"]
[connection signal="state_entered" from="StateChart/Root/Returning Home/Travelling/Place Marker" to="." method="_place_food_marker"]
[connection signal="state_entered" from="StateChart/Root/Delivering Food/Travelling" to="." method="_on_nest_detected"]
[connection signal="state_physics_processing" from="StateChart/Root/Delivering Food/Travelling" to="." method="_on_travelling_state_physics_processing"]
[connection signal="state_entered" from="StateChart/Root/Delivering Food/Dropping" to="." method="_on_nest_reached"]

Binary file not shown.

After

Width:  |  Height:  |  Size: 716 KiB

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bqgc7cft671q0"
path="res://.godot/imported/walk.png-77b94883438df4792795bd4b6c922fa6.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://godot_state_charts_examples/ant_hill/ant/walk.png"
dest_files=["res://.godot/imported/walk.png-77b94883438df4792795bd4b6c922fa6.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

@ -0,0 +1,9 @@
extends Node2D
func _ready():
# initialize the RNG
randomize()

View File

@ -0,0 +1 @@
uid://dyop2ixs375ks

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<path d="M5.333,13.165C5.333,13.165 10.079,16.966 13.732,17.071C17.386,17.176 23.307,15.769 24.798,14.929C26.289,14.089 26.856,11.297 26.856,11.297L28.325,9.953L26.94,14.32L25.995,19.003C25.995,19.003 21.018,22.152 17.26,22.635C13.501,23.118 6.971,20.598 5.879,19.276C4.787,17.953 3.566,15.518 3.36,14.488C3.152,13.453 3.57,12.388 3.57,12.388L5.333,13.165Z" style="fill:url(#_Linear1);"/>
<path d="M3.302,13.48C3.302,13.48 7.692,16.731 9.344,17.659C10.751,18.449 12.374,18.937 13.984,19.045C15.871,19.171 18.789,18.922 20.661,18.415C22.32,17.965 26.478,14.446 26.478,14.446C26.478,14.446 24.209,18.586 22.719,19.171C21.078,19.815 17.813,20.71 16,20.724C14.407,20.737 12.122,20.406 10.625,19.864C8.997,19.274 6.156,17.773 5.06,16.828C4.245,16.125 3.302,13.48 3.302,13.48Z" style="fill:url(#_Radial2);"/>
<defs>
<linearGradient id="_Linear1" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-3.92912,9.49081,-9.49081,-3.92912,17.2441,14.2665)"><stop offset="0" style="stop-color:rgb(214,255,76);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(157,238,0);stop-opacity:1"/></linearGradient>
<radialGradient id="_Radial2" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(2.48819,-23.1229,23.1229,2.48819,12.1575,18.7297)"><stop offset="0" style="stop-color:black;stop-opacity:0.16"/><stop offset="0.38" style="stop-color:black;stop-opacity:0"/><stop offset="1" style="stop-color:black;stop-opacity:0"/></radialGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cqt6bgiwgqym7"
path="res://.godot/imported/banana.svg-e48dc3ddd49722cb94ca8f088061cec6.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://godot_state_charts_examples/ant_hill/banana/banana.svg"
dest_files=["res://.godot/imported/banana.svg-e48dc3ddd49722cb94ca8f088061cec6.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View File

@ -0,0 +1,20 @@
[gd_scene load_steps=3 format=3 uid="uid://bqalfgp8jjady"]
[ext_resource type="Texture2D" uid="uid://cqt6bgiwgqym7" path="res://godot_state_charts_examples/ant_hill/banana/banana.svg" id="1_uoy0d"]
[sub_resource type="CapsuleShape2D" id="CapsuleShape2D_vo3bi"]
radius = 7.99901
height = 32.0275
[node name="banana" type="Node2D" groups=["food"]]
[node name="Sprite2D" type="Sprite2D" parent="."]
texture_filter = 1
texture = ExtResource("1_uoy0d")
[node name="Area2D" type="Area2D" parent="."]
metadata/owner = NodePath("..")
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"]
rotation = 1.5865
shape = SubResource("CapsuleShape2D_vo3bi")

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:1.5;">
<g transform="matrix(1.89907,0,0,1.89907,-11.2249,-10.4075)">
<circle cx="10.123" cy="9.693" r="4.213" style="fill:white;"/>
</g>
<path d="M8,1.533L13.596,6.688L8,6.824L8,13.638L8,6.824L2.394,6.688L8,1.533Z" style="fill:none;stroke:black;stroke-width:1px;"/>
</svg>

After

Width:  |  Height:  |  Size: 752 B

View File

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://b3k7i5rrn5hhl"
path="res://.godot/imported/circle_white.svg-63c895b75f0338e9c3ca264b87816990.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://godot_state_charts_examples/ant_hill/marker/circle_white.svg"
dest_files=["res://.godot/imported/circle_white.svg-63c895b75f0338e9c3ca264b87816990.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View File

@ -0,0 +1,47 @@
class_name Marker
extends Node2D
## How long should the marker live for?
@export var lifetime_seconds:float = 30.0
var expired_time:float = 0
enum MarkerType {
## A marker guiding towards food.
FOOD,
## A marker guiding towards a nest.
NEST
}
func initialize(type:MarkerType):
add_to_group("marker")
match type:
MarkerType.FOOD:
modulate = Color.YELLOW
add_to_group("food")
MarkerType.NEST:
modulate = Color.CORNFLOWER_BLUE
add_to_group("nest")
lifetime_seconds *= 2
## Refreshes the marker, so it stays for another lifetime
func refresh():
expired_time = 0
## Updates the marker and destroys it if has evaporated.
func _process(delta):
expired_time += delta
# Fade out the marker as it expires.
modulate.a = max(0, 1 - (expired_time / lifetime_seconds))
if expired_time > lifetime_seconds:
queue_free()
## Some debug drawing currently disabled.
func __draw():
var offset = 0.0 if is_in_group("food") else PI
var start_angle = - PI / 2 + offset
var end_angle = PI / 2 + offset
draw_arc(Vector2.ZERO, 30, start_angle, end_angle, 10, modulate, 1, true )

View File

@ -0,0 +1 @@
uid://dikixfhsqssxf

View File

@ -0,0 +1,20 @@
[gd_scene load_steps=4 format=3 uid="uid://dy5xrmjffewnk"]
[ext_resource type="Texture2D" uid="uid://b3k7i5rrn5hhl" path="res://godot_state_charts_examples/ant_hill/marker/circle_white.svg" id="1_2vg4s"]
[ext_resource type="Script" path="res://godot_state_charts_examples/ant_hill/marker/marker.gd" id="2_2b6iy"]
[sub_resource type="CircleShape2D" id="CircleShape2D_0xsut"]
[node name="Node2D" type="Node2D"]
script = ExtResource("2_2b6iy")
[node name="Sprite" type="Sprite2D" parent="."]
texture_filter = 1
rotation = 1.5708
texture = ExtResource("1_2vg4s")
[node name="Area2D" type="Area2D" parent="."]
metadata/owner = NodePath("..")
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"]
shape = SubResource("CircleShape2D_0xsut")

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:1.5;">
<path d="M2.751,26.163C2.751,26.163 9.264,27.569 14.887,28.036C21.176,28.559 29.249,27.192 29.249,27.192L28.619,18.541L24.672,14.026C24.672,14.026 21.585,13.858 20.367,11.108C19.15,8.357 17.071,7.853 15.349,7.496C13.627,7.139 10.457,9.869 9.68,10.079C8.903,10.289 9.722,11.717 8.063,14.278C6.404,16.84 7.307,18.667 5.921,19.864C4.535,21.06 2.751,26.163 2.751,26.163" style="fill:url(#_Linear1);"/>
<path d="M21.816,25.071C21.816,25.071 23.097,21.585 24.714,21.858C26.331,22.131 25.512,21.186 26.268,20.367" style="fill:none;stroke:rgb(174,159,25);stroke-width:1px;"/>
<g transform="matrix(1,0,0,0.592883,0,8.94162)">
<path d="M5.438,21.963C5.438,21.963 8.987,25.743 11.801,25.512C14.614,25.281 16.567,23.643 16.567,23.643" style="fill:none;stroke:url(#_Linear2);stroke-width:1.22px;"/>
</g>
<g transform="matrix(1,0,0,0.592883,3.65354,1.99149)">
<path d="M5.438,21.963C5.438,21.963 9.533,27.089 12.346,26.858C15.16,26.627 18.163,29.664 18.163,29.664" style="fill:none;stroke:url(#_Linear3);stroke-width:1.22px;"/>
</g>
<defs>
<linearGradient id="_Linear1" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(2.09974,-9.07087,9.07087,2.09974,12.6404,23.2021)"><stop offset="0" style="stop-color:rgb(73,64,28);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(140,131,94);stop-opacity:1"/></linearGradient>
<linearGradient id="_Linear2" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(11.1286,0,0,3.55873,5.43832,23.7426)"><stop offset="0" style="stop-color:rgb(30,100,0);stop-opacity:1"/><stop offset="0.54" style="stop-color:rgb(207,198,119);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(174,159,25);stop-opacity:1"/></linearGradient>
<linearGradient id="_Linear3" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(11.1286,0,0,3.55873,5.43832,23.7426)"><stop offset="0" style="stop-color:rgb(30,100,0);stop-opacity:1"/><stop offset="0.54" style="stop-color:rgb(207,198,119);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(174,159,25);stop-opacity:1"/></linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://xb5fialweqfw"
path="res://.godot/imported/nest.svg-4361abbd79cc59afa101f89034d762a6.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://godot_state_charts_examples/ant_hill/nest/nest.svg"
dest_files=["res://.godot/imported/nest.svg-4361abbd79cc59afa101f89034d762a6.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=2.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View File

@ -0,0 +1,16 @@
[gd_scene load_steps=3 format=3]
[ext_resource type="Texture2D" uid="uid://xb5fialweqfw" path="res://godot_state_charts_examples/ant_hill/nest/nest.svg" id="1_8slek"]
[sub_resource type="CircleShape2D" id="CircleShape2D_b8f1n"]
radius = 37.1214
[node name="Nest" type="Sprite2D" groups=["nest"]]
texture = ExtResource("1_8slek")
[node name="Area2D" type="Area2D" parent="."]
metadata/owner = NodePath("..")
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"]
position = Vector2(-1, -1)
shape = SubResource("CircleShape2D_b8f1n")

View File

@ -0,0 +1,10 @@
extends Node
func _ready():
process_mode = Node.PROCESS_MODE_ALWAYS
func _input(event):
if event is InputEventKey and event.is_pressed() and event.keycode == KEY_SPACE:
get_tree().paused = not get_tree().paused
print("Paused ", get_tree().paused)

View File

@ -0,0 +1 @@
uid://nonu8fobnml7

View File

@ -0,0 +1,201 @@
[gd_scene load_steps=21 format=3 uid="uid://huy14b6x10bh"]
[ext_resource type="Texture2D" uid="uid://bgswg1pgd01d1" path="res://godot_state_charts_examples/platformer/ninja_frog/full.png" id="2_dka03"]
[ext_resource type="Script" path="res://addons/godot_state_charts/state_chart.gd" id="3_7ryss"]
[ext_resource type="Script" path="res://godot_state_charts_examples/automatic_transitions/the_frog.gd" id="3_q65wd"]
[ext_resource type="Script" path="res://addons/godot_state_charts/compound_state.gd" id="4_64ox6"]
[ext_resource type="Script" path="res://addons/godot_state_charts/atomic_state.gd" id="5_ooc8l"]
[ext_resource type="Script" path="res://addons/godot_state_charts/parallel_state.gd" id="5_uojl1"]
[ext_resource type="PackedScene" uid="uid://bcwkugn6v3oy7" path="res://addons/godot_state_charts/utilities/state_chart_debugger.tscn" id="6_xggmu"]
[ext_resource type="Script" path="res://addons/godot_state_charts/transition.gd" id="7_v4wmr"]
[ext_resource type="Script" path="res://godot_state_charts_examples/automatic_transitions/stamina_bar.gd" id="9_rtmjc"]
[ext_resource type="Script" path="res://addons/godot_state_charts/state_is_active_guard.gd" id="10_caxti"]
[ext_resource type="Script" path="res://addons/godot_state_charts/not_guard.gd" id="11_rfa1s"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_2fogg"]
size = Vector2(275, 15)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_tsftx"]
size = Vector2(18.5, 227)
[sub_resource type="CapsuleShape2D" id="CapsuleShape2D_bocu2"]
radius = 15.0
height = 32.0
[sub_resource type="Resource" id="Resource_m8fyc"]
script = ExtResource("10_caxti")
state = NodePath("../../../Walking Control/Needs Rest")
[sub_resource type="Resource" id="Resource_4i0ee"]
script = ExtResource("10_caxti")
state = NodePath("../../../Walking Control/Needs Rest")
[sub_resource type="Resource" id="Resource_br5hd"]
script = ExtResource("11_rfa1s")
guard = SubResource("Resource_4i0ee")
[sub_resource type="Animation" id="Animation_nb642"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:modulate")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Color(1, 1, 1, 1)]
}
[sub_resource type="Animation" id="Animation_wtk5r"]
resource_name = "pulsate"
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:modulate")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.5, 1),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 0,
"values": [Color(1, 1, 1, 1), Color(1, 0, 0, 1), Color(1, 1, 1, 1)]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_ghdrh"]
_data = {
"RESET": SubResource("Animation_nb642"),
"pulsate": SubResource("Animation_wtk5r")
}
[node name="Node2D" type="Node2D"]
[node name="StateChartDebugger" parent="." instance=ExtResource("6_xggmu")]
offset_left = 293.0
offset_top = 10.0
offset_right = 624.0
offset_bottom = 441.0
initial_node_to_watch = NodePath("../TheFrog/StateChart")
[node name="Borders" type="StaticBody2D" parent="."]
[node name="Top" type="CollisionShape2D" parent="Borders"]
position = Vector2(139.25, 170)
shape = SubResource("RectangleShape2D_2fogg")
[node name="Bottom" type="CollisionShape2D" parent="Borders"]
position = Vector2(143.25, 385)
shape = SubResource("RectangleShape2D_2fogg")
[node name="Left" type="CollisionShape2D" parent="Borders"]
position = Vector2(11, 280.5)
shape = SubResource("RectangleShape2D_tsftx")
[node name="Right" type="CollisionShape2D" parent="Borders"]
position = Vector2(268.25, 276)
shape = SubResource("RectangleShape2D_tsftx")
[node name="TheFrog" type="CharacterBody2D" parent="."]
unique_name_in_owner = true
position = Vector2(65.25, 288)
script = ExtResource("3_q65wd")
[node name="Icon" type="Sprite2D" parent="TheFrog"]
texture = ExtResource("2_dka03")
region_enabled = true
region_rect = Rect2(0, 0, 32, 32)
[node name="CollisionShape2D" type="CollisionShape2D" parent="TheFrog"]
shape = SubResource("CapsuleShape2D_bocu2")
[node name="StateChart" type="Node" parent="TheFrog"]
unique_name_in_owner = true
script = ExtResource("3_7ryss")
track_in_editor = true
[node name="ParallelState" type="Node" parent="TheFrog/StateChart"]
script = ExtResource("5_uojl1")
[node name="Walking Control" type="Node" parent="TheFrog/StateChart/ParallelState"]
script = ExtResource("4_64ox6")
initial_state = NodePath("Can Walk")
[node name="Can Walk" type="Node" parent="TheFrog/StateChart/ParallelState/Walking Control"]
editor_description = "In this state the frog can move around and will lose stamina. If stamina drops to 0 the frog will automatically transition to \"Needs Rest\"."
script = ExtResource("5_ooc8l")
[node name="On Exhausted To Needs Rest" type="Node" parent="TheFrog/StateChart/ParallelState/Walking Control/Can Walk"]
editor_description = "This transition will listen to the \"exhausted\" event, triggered when the frog's stamina sinks to 0. We could also use an expression property tracking the stamina but using a dedicated event is faster and more extensible."
script = ExtResource("7_v4wmr")
to = NodePath("../../Needs Rest")
event = &"exhausted"
delay_in_seconds = "0.0"
[node name="Needs Rest" type="Node" parent="TheFrog/StateChart/ParallelState/Walking Control"]
editor_description = "In this state the frog cannot move for 3 seconds."
script = ExtResource("5_ooc8l")
[node name="After 3 seconds To Can Walk" type="Node" parent="TheFrog/StateChart/ParallelState/Walking Control/Needs Rest"]
editor_description = "This will automatically transition back to \"Can Walk\" after 3 seconds."
script = ExtResource("7_v4wmr")
to = NodePath("../../Can Walk")
delay_in_seconds = "3"
[node name="Animation Control" type="Node" parent="TheFrog/StateChart/ParallelState"]
editor_description = "This controls the pulsating red animation when the frog is exhausted. Note that you could also model this using state_entered and state_exited events on the \"Needs Rest\" state, which is simpler (and more performant). Its only done this way to show automatic events."
script = ExtResource("4_64ox6")
initial_state = NodePath("Normal")
[node name="Normal" type="Node" parent="TheFrog/StateChart/ParallelState/Animation Control"]
script = ExtResource("5_ooc8l")
[node name="On Needs Rest to Pulsating Red" type="Node" parent="TheFrog/StateChart/ParallelState/Animation Control/Normal"]
editor_description = "This is another example of an automatic transition. When the \"Needs Rest\" state becomes active, this will automatically transition to the \"Pulsating Red\" state."
script = ExtResource("7_v4wmr")
to = NodePath("../../Pulsating Red")
guard = SubResource("Resource_m8fyc")
delay_in_seconds = "0.0"
[node name="Pulsating Red" type="Node" parent="TheFrog/StateChart/ParallelState/Animation Control"]
script = ExtResource("5_ooc8l")
[node name="On Not Needs Rest to Normal" type="Node" parent="TheFrog/StateChart/ParallelState/Animation Control/Pulsating Red"]
editor_description = "When the \"Needs Rest\" state becomes inactive, this will automatically transition to the \"Normal\" state."
script = ExtResource("7_v4wmr")
to = NodePath("../../Normal")
guard = SubResource("Resource_br5hd")
delay_in_seconds = "0.0"
[node name="AnimationPlayer" type="AnimationPlayer" parent="TheFrog"]
unique_name_in_owner = true
libraries = {
"": SubResource("AnimationLibrary_ghdrh")
}
[node name="VBoxContainer" type="VBoxContainer" parent="."]
offset_left = 19.25
offset_top = 401.0
offset_right = 272.25
offset_bottom = 458.0
[node name="Label" type="Label" parent="VBoxContainer"]
layout_mode = 2
text = "Stamina"
[node name="StaminaBar" type="ProgressBar" parent="VBoxContainer"]
layout_mode = 2
script = ExtResource("9_rtmjc")
[node name="Label" type="Label" parent="."]
offset_right = 286.0
offset_bottom = 156.0
text = "This example shows automatic transitions. Move the frog with the arrow keys. If the frog loses all stamina, it automatically transitions to a state where it will be unable to move for 3 seconds."
autowrap_mode = 2
[connection signal="state_physics_processing" from="TheFrog/StateChart/ParallelState/Walking Control/Can Walk" to="TheFrog" method="_on_can_walk_state_physics_processing"]
[connection signal="state_physics_processing" from="TheFrog/StateChart/ParallelState/Walking Control/Needs Rest" to="TheFrog" method="_on_needs_rest_state_physics_processing"]
[connection signal="state_entered" from="TheFrog/StateChart/ParallelState/Animation Control/Normal" to="TheFrog" method="_on_normal_state_entered"]
[connection signal="state_entered" from="TheFrog/StateChart/ParallelState/Animation Control/Pulsating Red" to="TheFrog" method="_on_pulsating_red_state_entered"]

View File

@ -0,0 +1,9 @@
extends ProgressBar
@onready var the_frog = %TheFrog
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(_delta):
value = the_frog.stamina

View File

@ -0,0 +1 @@
uid://dn780r00o0xam

View File

@ -0,0 +1,48 @@
extends CharacterBody2D
# We can move 100 pixels per second
const SPEED = 100.0
# We recover 20 stamina per second
const RECOVER_RATE = 20.0
@onready var state_chart:StateChart = %StateChart
@onready var animation_player = %AnimationPlayer
var stamina:float = 100
### WALKING CONTROL STATES
# In the "Can Walk" state we can walk around and lose stamina.
func _on_can_walk_state_physics_processing(delta):
# Get the direction
var direction = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
# Calculate velocity
velocity = direction * SPEED
# if we moved, subtract stamina
if velocity.length() > 0:
stamina = max(0, stamina - RECOVER_RATE * delta)
else:
# else add it.
stamina = min(100, stamina + RECOVER_RATE * delta)
if stamina <= 0:
state_chart.send_event("exhausted")
move_and_slide()
# If our stamina hits 0, we enter the "Needs rest" state which
# only allows us to recover stamina.
func _on_needs_rest_state_physics_processing(delta):
stamina = min(100, stamina + RECOVER_RATE * delta)
### ANIMATION CONTROL STATES
func _on_pulsating_red_state_entered():
animation_player.play("pulsate")
func _on_normal_state_entered():
animation_player.play("RESET")

View File

@ -0,0 +1 @@
uid://jjduf53mb1hc

View File

@ -0,0 +1,6 @@
The icons in this demo are used under CC BY 3.0 DEED license
(https://creativecommons.org/licenses/by/3.0/).
Original author:
J. W. Bjerk (eleazzaar) -- www.jwbjerk.com/art -- find this and other open art at: http://opengameart.org

View File

@ -0,0 +1,140 @@
[gd_scene load_steps=11 format=3 uid="uid://cnqh7qot0estd"]
[ext_resource type="PackedScene" uid="uid://bcwkugn6v3oy7" path="res://addons/godot_state_charts/utilities/state_chart_debugger.tscn" id="1_oec6f"]
[ext_resource type="PackedScene" uid="uid://ch1pukkyc07qo" path="res://godot_state_charts_examples/cooldown/skill_button/skill_button.tscn" id="2_aahy2"]
[ext_resource type="Texture2D" uid="uid://bphe0g2d306fe" path="res://godot_state_charts_examples/cooldown/icons/enchant-red-3.png" id="3_a8h0q"]
[ext_resource type="Texture2D" uid="uid://bjmc4abduaxww" path="res://godot_state_charts_examples/cooldown/icons/fireball-eerie-2.png" id="4_jhd8u"]
[ext_resource type="Texture2D" uid="uid://b87nmomi1l48x" path="res://godot_state_charts_examples/cooldown/icons/heal-jade-2.png" id="5_xxunm"]
[ext_resource type="Script" path="res://addons/godot_state_charts/state_chart.gd" id="6_d3pqh"]
[ext_resource type="Script" path="res://addons/godot_state_charts/parallel_state.gd" id="7_l6ahs"]
[ext_resource type="Script" path="res://addons/godot_state_charts/compound_state.gd" id="8_pvst5"]
[ext_resource type="Script" path="res://addons/godot_state_charts/atomic_state.gd" id="9_h41ei"]
[ext_resource type="Script" path="res://addons/godot_state_charts/transition.gd" id="10_5fig4"]
[node name="Cooldown Example" type="Node2D"]
[node name="StateChartDebugger" parent="." instance=ExtResource("1_oec6f")]
offset_left = 290.0
offset_top = 16.0
offset_right = 629.0
offset_bottom = 466.0
initial_node_to_watch = NodePath("../StateChart")
[node name="InfoLabel" type="Label" parent="."]
offset_left = 10.0
offset_top = 24.0
offset_right = 277.0
offset_bottom = 128.0
text = "This example shows how to connect delayed transitions with game UI to model skill buttons that have cooldowns. Click the buttons to try it."
autowrap_mode = 2
[node name="VBoxContainer" type="VBoxContainer" parent="."]
offset_left = 18.0
offset_top = 164.0
offset_right = 278.0
offset_bottom = 435.0
theme_override_constants/separation = 15
[node name="AttackSkillButton" parent="VBoxContainer" instance=ExtResource("2_aahy2")]
editor_description = "This is the attack skill button. When you press it, it will send the \"attack\" event to the state chart."
layout_mode = 2
size_flags_horizontal = 4
texture = ExtResource("3_a8h0q")
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer"]
layout_mode = 2
alignment = 1
[node name="MagicSkillButton" parent="VBoxContainer/HBoxContainer" instance=ExtResource("2_aahy2")]
editor_description = "This is the magic skill button. When you press it, it will send the \"magic\" event to the state chart."
layout_mode = 2
texture = ExtResource("4_jhd8u")
[node name="HealSkillButton" parent="VBoxContainer/HBoxContainer" instance=ExtResource("2_aahy2")]
editor_description = "This is the heal skill button. When you press it, it will send the \"heal\" event to the state chart."
layout_mode = 2
texture = ExtResource("5_xxunm")
[node name="StateChart" type="Node" parent="."]
script = ExtResource("6_d3pqh")
track_in_editor = true
[node name="Root" type="Node" parent="StateChart"]
editor_description = "Since all three skills can be used independently of each other we use a parallel state as the root here."
script = ExtResource("7_l6ahs")
[node name="AttackSkill" type="Node" parent="StateChart/Root"]
script = ExtResource("8_pvst5")
initial_state = NodePath("Available")
[node name="Available" type="Node" parent="StateChart/Root/AttackSkill"]
editor_description = "State indicating that attack is available. Entering this state will reset the cooldown on the attack skill button."
script = ExtResource("9_h41ei")
[node name="On Attack To Cooldown" type="Node" parent="StateChart/Root/AttackSkill/Available"]
script = ExtResource("10_5fig4")
to = NodePath("../../Cooldown")
event = &"attack"
[node name="Cooldown" type="Node" parent="StateChart/Root/AttackSkill"]
editor_description = "Cooldown state for the attack skill. While the delayed transition is pending, this state will send status updates on the pending transition to the attack skill button. The attack skill button will then update itself and show the remaining cooldown."
script = ExtResource("9_h41ei")
[node name="Back to Available" type="Node" parent="StateChart/Root/AttackSkill/Cooldown"]
script = ExtResource("10_5fig4")
to = NodePath("../../Available")
delay_seconds = 1.0
[node name="MagicSkill" type="Node" parent="StateChart/Root"]
script = ExtResource("8_pvst5")
initial_state = NodePath("Available")
[node name="Available" type="Node" parent="StateChart/Root/MagicSkill"]
editor_description = "State indicating that the magic skill is available. Entering this state will reset the cooldown on the magic skill button."
script = ExtResource("9_h41ei")
[node name="On Magic To Cooldown" type="Node" parent="StateChart/Root/MagicSkill/Available"]
script = ExtResource("10_5fig4")
to = NodePath("../../Cooldown")
event = &"magic"
[node name="Cooldown" type="Node" parent="StateChart/Root/MagicSkill"]
editor_description = "Cooldown state for the magic skill. While the delayed transition is pending, this state will send status updates on the pending transition to the magic skill button. The magic skill button will then update itself and show the remaining cooldown."
script = ExtResource("9_h41ei")
[node name="Back to Available" type="Node" parent="StateChart/Root/MagicSkill/Cooldown"]
script = ExtResource("10_5fig4")
to = NodePath("../../Available")
delay_seconds = 3.0
[node name="HealSkill" type="Node" parent="StateChart/Root"]
script = ExtResource("8_pvst5")
initial_state = NodePath("Available")
[node name="Available" type="Node" parent="StateChart/Root/HealSkill"]
editor_description = "State indicating that the heal skill is available. Entering this state will reset the cooldown on the heal skill button."
script = ExtResource("9_h41ei")
[node name="On Heal To Cooldown" type="Node" parent="StateChart/Root/HealSkill/Available"]
script = ExtResource("10_5fig4")
to = NodePath("../../Cooldown")
event = &"heal"
[node name="Cooldown" type="Node" parent="StateChart/Root/HealSkill"]
editor_description = "Cooldown state for the heal skill. While the delayed transition is pending, this state will send status updates on the pending transition to the heal skill button. The heal skill button will then update itself and show the remaining cooldown."
script = ExtResource("9_h41ei")
[node name="Back to Available" type="Node" parent="StateChart/Root/HealSkill/Cooldown"]
script = ExtResource("10_5fig4")
to = NodePath("../../Available")
delay_seconds = 10.0
[connection signal="pressed" from="VBoxContainer/AttackSkillButton" to="StateChart" method="send_event" binds= ["attack"]]
[connection signal="pressed" from="VBoxContainer/HBoxContainer/MagicSkillButton" to="StateChart" method="send_event" binds= ["magic"]]
[connection signal="pressed" from="VBoxContainer/HBoxContainer/HealSkillButton" to="StateChart" method="send_event" binds= ["heal"]]
[connection signal="state_entered" from="StateChart/Root/AttackSkill/Available" to="VBoxContainer/AttackSkillButton" method="clear_cooldown"]
[connection signal="transition_pending" from="StateChart/Root/AttackSkill/Cooldown" to="VBoxContainer/AttackSkillButton" method="set_cooldown"]
[connection signal="state_entered" from="StateChart/Root/MagicSkill/Available" to="VBoxContainer/HBoxContainer/MagicSkillButton" method="clear_cooldown"]
[connection signal="transition_pending" from="StateChart/Root/MagicSkill/Cooldown" to="VBoxContainer/HBoxContainer/MagicSkillButton" method="set_cooldown"]
[connection signal="state_entered" from="StateChart/Root/HealSkill/Available" to="VBoxContainer/HBoxContainer/HealSkillButton" method="clear_cooldown"]
[connection signal="transition_pending" from="StateChart/Root/HealSkill/Cooldown" to="VBoxContainer/HBoxContainer/HealSkillButton" method="set_cooldown"]

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://tgsnqiq40n41"
path="res://.godot/imported/cooldown_overlay.png-5594f471c10cac21fce498b609075490.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://godot_state_charts_examples/cooldown/icons/cooldown_overlay.png"
dest_files=["res://.godot/imported/cooldown_overlay.png-5594f471c10cac21fce498b609075490.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bphe0g2d306fe"
path="res://.godot/imported/enchant-red-3.png-1df2c19bbfe03c22227b3db03bc16eee.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://godot_state_charts_examples/cooldown/icons/enchant-red-3.png"
dest_files=["res://.godot/imported/enchant-red-3.png-1df2c19bbfe03c22227b3db03bc16eee.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bjmc4abduaxww"
path="res://.godot/imported/fireball-eerie-2.png-a420ae5d8f4f4f86ea5ef03eeea7f3c6.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://godot_state_charts_examples/cooldown/icons/fireball-eerie-2.png"
dest_files=["res://.godot/imported/fireball-eerie-2.png-a420ae5d8f4f4f86ea5ef03eeea7f3c6.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://b87nmomi1l48x"
path="res://.godot/imported/heal-jade-2.png-5317fa8cf716c70c254fee8762a0dfda.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://godot_state_charts_examples/cooldown/icons/heal-jade-2.png"
dest_files=["res://.godot/imported/heal-jade-2.png-5317fa8cf716c70c254fee8762a0dfda.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

@ -0,0 +1,51 @@
## This is tool so we can show the selected texture immediately in the editor.
@tool
extends MarginContainer
signal pressed()
@export var texture:Texture2D:
set(value):
texture = value
_apply_settings()
## The progressbar we control
@onready var _texture_progress_bar:TextureProgressBar = %TextureProgressBar
## The label showing the cooldown in seconds
@onready var _label:Label = %Label
## The button that can be pressed
@onready var _button:Button = %Button
func _ready():
_apply_settings()
func _apply_settings():
if _texture_progress_bar != null:
_texture_progress_bar.texture_under = texture
## Called while cooldown transitions run. Will update the state of the
## cooldown in the UI elements and disable the button until clear_cooldown
## is called.
func set_cooldown(total:float, current:float):
_label.visible = true
_button.disabled = true
_texture_progress_bar.max_value = total
_texture_progress_bar.value = current
_label.text = "%.1f" % current
## Called to clear the cooldown. Will enable the button and clear all cooldown
## indicators.
func clear_cooldown():
_label.visible = false
_button.disabled = false
_texture_progress_bar.value = 0
_texture_progress_bar.max_value = 100
## Signal relay for the inner button.
func _on_button_pressed():
pressed.emit()

View File

@ -0,0 +1 @@
uid://cjlrmcmit4jhm

View File

@ -0,0 +1,34 @@
[gd_scene load_steps=3 format=3 uid="uid://ch1pukkyc07qo"]
[ext_resource type="Script" path="res://godot_state_charts_examples/cooldown/skill_button/skill_button.gd" id="1_r0ivs"]
[ext_resource type="Texture2D" uid="uid://tgsnqiq40n41" path="res://godot_state_charts_examples/cooldown/icons/cooldown_overlay.png" id="3_pgrfi"]
[node name="SkillButton" type="MarginContainer"]
offset_right = 32.0
offset_bottom = 32.0
script = ExtResource("1_r0ivs")
[node name="Button" type="Button" parent="."]
unique_name_in_owner = true
layout_mode = 2
[node name="TextureProgressBar" type="TextureProgressBar" parent="."]
unique_name_in_owner = true
layout_mode = 2
mouse_filter = 2
step = 0.0
fill_mode = 4
texture_progress = ExtResource("3_pgrfi")
tint_progress = Color(0, 0, 0, 1)
[node name="Label" type="Label" parent="."]
unique_name_in_owner = true
layout_mode = 2
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
theme_override_constants/outline_size = 8
theme_override_font_sizes/font_size = 48
text = "10"
horizontal_alignment = 1
vertical_alignment = 1
[connection signal="pressed" from="Button" to="." method="_on_button_pressed"]

View File

@ -0,0 +1,115 @@
using Godot;
using GodotStateCharts;
namespace Movementtests.godot_state_charts_examples.csharp;
/// <summary>
/// This is an example of how to use the state chart from C#.
/// </summary>
// ReSharper disable once CheckNamespace
public partial class CSharpExample : Node2D
{
private StateChart _stateChart;
private Label _feelLabel;
private int _health = 20;
private StateChartState _poisonedStateChartState;
public override void _Ready()
{
// Get the state chart node and wrap it in a StateChart object, so we can easily
// interact with it from C#.
_stateChart = StateChart.Of(GetNode("%StateChart"));
// Get the poisoned state node and wrap it in a State object, so we can easily
// interact with it from C#.
_poisonedStateChartState = StateChartState.Of(GetNode("%Poisoned"));
// The the UI label.
_feelLabel = GetNode<Label>("%FeelLabel");
RefreshUi();
}
/// <summary>
/// Called when the drink poison button is pressed.
/// </summary>
private void OnDrinkPoisonButtonPressed()
{
// This uses the regular API to interact with the state chart.
var currentPoisonCount = _stateChart.GetExpressionProperty("poison_count", 0);
currentPoisonCount += 3; // we add three rounds worth of poison
_stateChart.SetExpressionProperty("poison_count", currentPoisonCount);
_stateChart.SendEvent("poisoned");
// Ends the round
EndRound();
}
/// <summary>
/// Called when the drink cure button is pressed.
/// </summary>
private void OnDrinkCureButtonPressed()
{
// Here we use some custom-made extension methods from StateChartExt.cs to have a nicer API
// that is specific to our game. This avoids having to use strings for property names and
// event names and it also helps with type safety and when you need to find all places where
// a certain property is set or an event is sent.
_stateChart.SetPoisonCount(0);
_stateChart.SendCuredEvent();
// Ends the round
EndRound();
}
/// <summary>
/// Called when the next round button is pressed.
/// </summary>
private void OnWaitButtonPressed()
{
// Ends the round
EndRound();
}
private void EndRound()
{
// then send a "next_round" event
_stateChart.SendEvent("next_round");
// and finally call Step to calculate this round's effects, based on the current state
_stateChart.Step();
// Then at the beginning of the next round, we reduce any poison count by 1
_stateChart.SetPoisonCount( Mathf.Max(0, _stateChart.GetPoisonCount() - 1));
// And update the UI
RefreshUi();
}
private void OnPoisonedStateStepped()
{
// when we step while poisoned, remove the amount of poison from our health (but not below 0)
_health = Mathf.Max(0, _health - _stateChart.GetPoisonCount());
}
private void OnNormalStateStepped()
{
// when we step while not poisoned, heal 1 health, up to a maximum of 20
_health = Mathf.Min(20, _health + 1);
}
private void RefreshUi()
{
_feelLabel.Text = $"Health: {_health} Poison: {_stateChart.GetPoisonCount()}";
}
private void OnDebugButtonPressed()
{
// States have an "Active" property that can be used to check if they are currently active.
// Note that you should usually not use this in your game code, as it sort of defeats the
// purpose of using a state chart. But it can be useful for debugging.
GD.Print("Are we poisoned? ", _poisonedStateChartState.Active ? "Yes" : "No");
}
}

View File

@ -0,0 +1 @@
uid://cpw6fi5fyccic

View File

@ -0,0 +1,9 @@
This example requires the .NET version of Godot to work. It will not work with the
standard version of Godot. You can download the .NET version of Godot from
https://godotengine.org/download. Note that the Steam version of Godot is the
standard version and will not work with this example.
If you just freshly imported this into Godot and have not yet added other C# files
to the project, you will need to initialize the project for C# by going to
Project -> Tools -> C# -> Create C# Solution. Otherwise the demo will not
work because its files have not been compiled.

View File

@ -0,0 +1,27 @@

using GodotStateCharts;
namespace Movementtests.godot_state_charts_examples.csharp;
/// <summary>
/// This is an example on how to add extension methods to the state chart class to get
/// more type safety and a nicer API.
/// </summary>
// ReSharper disable once CheckNamespace
public static class StateChartExt
{
public static void SetPoisonCount(this StateChart stateChart, int poisonCount)
{
stateChart.SetExpressionProperty("poison_count", poisonCount);
}
public static int GetPoisonCount(this StateChart stateChart)
{
return stateChart.GetExpressionProperty("poison_count", 0);
}
public static void SendCuredEvent(this StateChart stateChart)
{
stateChart.SendEvent("cured");
}
}

View File

@ -0,0 +1 @@
uid://btrfg0cn5wgrg

View File

@ -0,0 +1,109 @@
[gd_scene load_steps=9 format=3 uid="uid://dlxg641x8w8tn"]
[ext_resource type="Script" uid="uid://cpw6fi5fyccic" path="res://godot_state_charts_examples/csharp/CSharpExample.cs" id="1_fkf0f"]
[ext_resource type="Script" uid="uid://couw105c3bde4" path="res://addons/godot_state_charts/state_chart.gd" id="2_b878w"]
[ext_resource type="Script" uid="uid://jk2jm1g6q853" path="res://addons/godot_state_charts/compound_state.gd" id="3_ck7cw"]
[ext_resource type="Script" uid="uid://cytafq8i1y8qm" path="res://addons/godot_state_charts/atomic_state.gd" id="4_ovkn7"]
[ext_resource type="Script" uid="uid://cf1nsco3w0mf6" path="res://addons/godot_state_charts/transition.gd" id="5_um7g8"]
[ext_resource type="Script" uid="uid://le5w1cm0ul8p" path="res://addons/godot_state_charts/expression_guard.gd" id="6_ecpvf"]
[ext_resource type="PackedScene" uid="uid://bcwkugn6v3oy7" path="res://addons/godot_state_charts/utilities/state_chart_debugger.tscn" id="7_yrwaw"]
[sub_resource type="Resource" id="Resource_j6fet"]
script = ExtResource("6_ecpvf")
expression = "poison_count <= 0"
[node name="csharp_example" type="Node2D"]
script = ExtResource("1_fkf0f")
[node name="InfoLabel" type="Label" parent="."]
offset_left = 19.0
offset_top = 33.0
offset_right = 293.0
offset_bottom = 111.0
text = "This is a demo on how to use Godot State Charts with C#.
We have a turn-based game here. You can click \"Drink Poison\" to ingest 3 poison. \"Drink Cure\" will clear all poison. Wait will just wait a round. At the end of each round poison is subtracted from health or health regenerates if no poison is in the system. Print Debug prints out whether we are currently poisoned."
autowrap_mode = 2
[node name="FeelLabel" type="Label" parent="."]
unique_name_in_owner = true
offset_left = 23.0
offset_top = 367.0
offset_right = 63.0
offset_bottom = 390.0
[node name="HBoxContainer" type="HBoxContainer" parent="."]
offset_left = 90.0
offset_top = 407.0
offset_right = 540.0
offset_bottom = 447.0
[node name="DrinkPoisonButton" type="Button" parent="HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
text = "Drink Poison"
[node name="DrinkCureButton" type="Button" parent="HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
text = "Drink Cure"
[node name="WaitButton" type="Button" parent="HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
text = "Wait"
[node name="PrintDebugButton" type="Button" parent="HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
text = "Print Debug"
[node name="StateChart" type="Node" parent="."]
unique_name_in_owner = true
script = ExtResource("2_b878w")
track_in_editor = true
[node name="Root" type="Node" parent="StateChart"]
script = ExtResource("3_ck7cw")
initial_state = NodePath("Normal")
[node name="Normal" type="Node" parent="StateChart/Root"]
script = ExtResource("4_ovkn7")
[node name="To Poisoned" type="Node" parent="StateChart/Root/Normal"]
script = ExtResource("5_um7g8")
to = NodePath("../../Poisoned")
event = &"poisoned"
delay_in_seconds = "0.0"
[node name="Poisoned" type="Node" parent="StateChart/Root"]
unique_name_in_owner = true
script = ExtResource("4_ovkn7")
[node name="To Normal On Wear Off" type="Node" parent="StateChart/Root/Poisoned"]
editor_description = "This transition checks at the beginning of the round i the poison count is 0 and if so transitions back to normal state."
script = ExtResource("5_um7g8")
to = NodePath("../../Normal")
event = &"next_round"
guard = SubResource("Resource_j6fet")
delay_in_seconds = "0.0"
[node name="To Normal On Cure" type="Node" parent="StateChart/Root/Poisoned"]
editor_description = "This transition immediately goes back to normal state when the cure is taken."
script = ExtResource("5_um7g8")
to = NodePath("../../Normal")
event = &"cured"
delay_in_seconds = "0.0"
[node name="StateChartDebugger" parent="." instance=ExtResource("7_yrwaw")]
offset_left = 309.0
offset_top = 4.0
offset_right = 636.0
offset_bottom = 370.0
initial_node_to_watch = NodePath("../StateChart")
[connection signal="pressed" from="HBoxContainer/DrinkPoisonButton" to="." method="OnDrinkPoisonButtonPressed"]
[connection signal="pressed" from="HBoxContainer/DrinkCureButton" to="." method="OnDrinkCureButtonPressed"]
[connection signal="pressed" from="HBoxContainer/WaitButton" to="." method="OnWaitButtonPressed"]
[connection signal="pressed" from="HBoxContainer/PrintDebugButton" to="." method="OnDebugButtonPressed"]
[connection signal="state_stepped" from="StateChart/Root/Normal" to="." method="OnNormalStateStepped"]
[connection signal="state_stepped" from="StateChart/Root/Poisoned" to="." method="OnPoisonedStateStepped"]

View File

@ -0,0 +1,11 @@
extends Node
@onready var state_chart:StateChart = $StateChart
func _on_area_2d_input_event(_viewport:Node, event:InputEvent, _shape_idx:int):
if event is InputEventMouseButton:
if event.button_index == MOUSE_BUTTON_LEFT:
# on release send clicked event to state chart
if not event.is_pressed():
state_chart.send_event("clicked")

View File

@ -0,0 +1 @@
uid://bad613wfktgah

View File

@ -0,0 +1,102 @@
[gd_scene load_steps=11 format=3 uid="uid://b18rv6o4duide"]
[ext_resource type="Texture2D" uid="uid://bgw8xgbwc2flx" path="res://godot_state_charts_examples/history_states/white_rectangle.svg" id="1_3v23e"]
[ext_resource type="PackedScene" uid="uid://bcwkugn6v3oy7" path="res://addons/godot_state_charts/utilities/state_chart_debugger.tscn" id="2_fgw1q"]
[ext_resource type="Script" path="res://addons/godot_state_charts/state_chart.gd" id="2_pqmip"]
[ext_resource type="Script" path="res://godot_state_charts_examples/history_states/history_demo.gd" id="2_vphtk"]
[ext_resource type="Script" path="res://addons/godot_state_charts/compound_state.gd" id="3_nsw2j"]
[ext_resource type="Script" path="res://addons/godot_state_charts/history_state.gd" id="4_0qaqv"]
[ext_resource type="Script" path="res://addons/godot_state_charts/atomic_state.gd" id="5_lh5sp"]
[ext_resource type="Script" path="res://addons/godot_state_charts/transition.gd" id="6_xvm5g"]
[ext_resource type="Theme" uid="uid://s2bj74tt0y7f" path="res://godot_state_charts_examples/new_theme.tres" id="8_najew"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_kl3ga"]
size = Vector2(34.243, 33.536)
[node name="Node" type="Node"]
script = ExtResource("2_vphtk")
[node name="StateChartDebugger" parent="." instance=ExtResource("2_fgw1q")]
offset_left = 280.0
offset_top = 9.0
offset_right = -12.0
offset_bottom = -190.0
theme = ExtResource("8_najew")
initial_node_to_watch = NodePath("../StateChart")
[node name="Node2D" type="Sprite2D" parent="."]
position = Vector2(145, 206)
scale = Vector2(6.6875, 3.90625)
texture = ExtResource("1_3v23e")
[node name="Area2D" type="Area2D" parent="Node2D"]
[node name="CollisionShape2D" type="CollisionShape2D" parent="Node2D/Area2D"]
position = Vector2(0.0747795, 3.8147e-06)
shape = SubResource("RectangleShape2D_kl3ga")
[node name="StateChart" type="Node" parent="."]
script = ExtResource("2_pqmip")
track_in_editor = true
[node name="Root" type="Node" parent="StateChart"]
script = ExtResource("3_nsw2j")
initial_state = NodePath("Red Or Blue")
[node name="Red Or Blue" type="Node" parent="StateChart/Root"]
script = ExtResource("3_nsw2j")
initial_state = NodePath("Red")
[node name="Resume" type="Node" parent="StateChart/Root/Red Or Blue"]
script = ExtResource("4_0qaqv")
default_state = NodePath("../Red")
[node name="Red" type="Node" parent="StateChart/Root/Red Or Blue"]
script = ExtResource("5_lh5sp")
[node name="To Blue" type="Node" parent="StateChart/Root/Red Or Blue/Red"]
script = ExtResource("6_xvm5g")
to = NodePath("../../Blue")
delay_in_seconds = "3"
[node name="Blue" type="Node" parent="StateChart/Root/Red Or Blue"]
script = ExtResource("5_lh5sp")
[node name="To Red" type="Node" parent="StateChart/Root/Red Or Blue/Blue"]
script = ExtResource("6_xvm5g")
to = NodePath("../../Red")
delay_in_seconds = "3"
[node name="On Clicked To White" type="Node" parent="StateChart/Root/Red Or Blue"]
script = ExtResource("6_xvm5g")
to = NodePath("../../White")
event = &"clicked"
delay_in_seconds = "0.0"
[node name="White" type="Node" parent="StateChart/Root"]
script = ExtResource("5_lh5sp")
[node name="Resume" type="Node" parent="StateChart/Root/White"]
script = ExtResource("6_xvm5g")
to = NodePath("../../Red Or Blue/Resume")
delay_in_seconds = "1"
[node name="Label" type="RichTextLabel" parent="."]
offset_left = 26.0
offset_top = 318.0
offset_right = 376.0
offset_bottom = 416.0
mouse_filter = 2
bbcode_enabled = true
text = "[font_size=10]
[ul]
The rectangle will switch from red to blue every 3 seconds.
When you click the rectangle it will temporarily turn white and then return to whatever color it was previously by transitioning to the \"Resume\" state. The timer will also be properly restored, so the previously active color will remain active for the rest of the 5 seconds.
[/ul]
[/font_size]"
fit_content = true
[connection signal="input_event" from="Node2D/Area2D" to="." method="_on_area_2d_input_event"]
[connection signal="state_entered" from="StateChart/Root/Red Or Blue/Red" to="Node2D" method="set_modulate" binds= [Color(1, 0.231373, 0.172549, 1)]]
[connection signal="state_entered" from="StateChart/Root/Red Or Blue/Blue" to="Node2D" method="set_modulate" binds= [Color(0.286275, 0.501961, 1, 1)]]
[connection signal="state_entered" from="StateChart/Root/White" to="Node2D" method="set_modulate" binds= [Color(1, 1, 1, 1)]]

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<rect id="Artboard1" x="0" y="0" width="32" height="32" style="fill:none;"/>
<clipPath id="_clip1">
<rect id="Artboard11" serif:id="Artboard1" x="0" y="0" width="32" height="32"/>
</clipPath>
<g clip-path="url(#_clip1)">
<g transform="matrix(1.018,0,0,1.02155,-0.335834,-0.355613)">
<rect x="0.33" y="0.348" width="31.434" height="31.325" style="fill:rgb(235,235,235);"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 888 B

View File

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bgw8xgbwc2flx"
path="res://.godot/imported/white_rectangle.svg-4d0041e2d5db811b29367f0371ead08c.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://godot_state_charts_examples/history_states/white_rectangle.svg"
dest_files=["res://.godot/imported/white_rectangle.svg-4d0041e2d5db811b29367f0371ead08c.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View File

@ -0,0 +1,4 @@
[gd_resource type="Theme" format=3 uid="uid://s2bj74tt0y7f"]
[resource]
default_font_size = 10

View File

@ -0,0 +1,106 @@
[gd_scene load_steps=7 format=3 uid="uid://qr4pvbbdopme"]
[ext_resource type="Script" path="res://addons/godot_state_charts/state_chart.gd" id="1_67wci"]
[ext_resource type="Script" path="res://addons/godot_state_charts/compound_state.gd" id="2_oks48"]
[ext_resource type="Script" path="res://addons/godot_state_charts/parallel_state.gd" id="3_p72eh"]
[ext_resource type="Script" path="res://addons/godot_state_charts/atomic_state.gd" id="4_v7oq1"]
[ext_resource type="Script" path="res://addons/godot_state_charts/transition.gd" id="5_qwp21"]
[ext_resource type="PackedScene" uid="uid://bcwkugn6v3oy7" path="res://addons/godot_state_charts/utilities/state_chart_debugger.tscn" id="5_xychp"]
[node name="order_of_events" type="Node2D"]
[node name="StateChart" type="Node" parent="."]
editor_description = "This is just an example state chart to complement the documentation. See the section \"order of events\" in the manual for details."
script = ExtResource("1_67wci")
track_in_editor = true
[node name="A" type="Node" parent="StateChart"]
script = ExtResource("2_oks48")
initial_state = NodePath("B")
[node name="B" type="Node" parent="StateChart/A"]
script = ExtResource("3_p72eh")
[node name="B1" type="Node" parent="StateChart/A/B"]
script = ExtResource("4_v7oq1")
[node name="B2" type="Node" parent="StateChart/A/B"]
script = ExtResource("4_v7oq1")
[node name="To C" type="Node" parent="StateChart/A/B"]
script = ExtResource("5_qwp21")
to = NodePath("../../C")
event = &"c_button_pressed"
[node name="C" type="Node" parent="StateChart/A"]
script = ExtResource("2_oks48")
initial_state = NodePath("C1")
[node name="C1" type="Node" parent="StateChart/A/C"]
script = ExtResource("4_v7oq1")
[node name="Immediately To C2" type="Node" parent="StateChart/A/C/C1"]
editor_description = "This transition will immediately transition this state to the C2 state."
script = ExtResource("5_qwp21")
to = NodePath("../../C2")
[node name="C2" type="Node" parent="StateChart/A/C"]
editor_description = "This state has it's state_entered signal connected. The receiver of this signal will immediately trigger the \"To C3\" transition below."
script = ExtResource("4_v7oq1")
[node name="To C3" type="Node" parent="StateChart/A/C/C2"]
editor_description = "This transition will be called by a signal receiver connected to C2's `state_entered` signal. It will be triggered immediately when C2 is entered."
script = ExtResource("5_qwp21")
to = NodePath("../../C3")
event = &"c2_entered"
[node name="C3" type="Node" parent="StateChart/A/C"]
script = ExtResource("4_v7oq1")
[node name="To C4 after delay" type="Node" parent="StateChart/A/C/C3"]
editor_description = "Another automatic transition, this time with a delay."
script = ExtResource("5_qwp21")
to = NodePath("../../C4")
delay_seconds = 0.5
[node name="C4" type="Node" parent="StateChart/A/C"]
script = ExtResource("4_v7oq1")
[node name="To B" type="Node" parent="StateChart/A/C/C4"]
script = ExtResource("5_qwp21")
to = NodePath("../../../B")
event = &"b_button_pressed"
[node name="StateChartDebugger" parent="." instance=ExtResource("5_xychp")]
offset_left = 201.0
offset_top = 11.0
offset_right = 627.0
offset_bottom = 450.0
initial_node_to_watch = NodePath("../StateChart")
[node name="VBoxContainer" type="VBoxContainer" parent="."]
offset_left = 18.0
offset_top = 16.0
offset_right = 174.0
offset_bottom = 444.0
[node name="To C Button" type="Button" parent="VBoxContainer"]
layout_mode = 2
text = "Go To C"
[node name="To B Button" type="Button" parent="VBoxContainer"]
layout_mode = 2
text = "Go To B"
[node name="Spacer" type="Control" parent="VBoxContainer"]
layout_mode = 2
size_flags_vertical = 3
[node name="Label" type="Label" parent="VBoxContainer"]
layout_mode = 2
text = "This demo shows the order of events when states are changing under various conditions. See the \"Order of events\" section in the manual for some explainers."
autowrap_mode = 2
[connection signal="state_entered" from="StateChart/A/C/C2" to="StateChart" method="send_event" binds= ["c2_entered"]]
[connection signal="pressed" from="VBoxContainer/To C Button" to="StateChart" method="send_event" binds= ["c_button_pressed"]]
[connection signal="pressed" from="VBoxContainer/To B Button" to="StateChart" method="send_event" binds= ["b_button_pressed"]]

View File

@ -0,0 +1,23 @@
[gd_scene load_steps=2 format=3 uid="uid://bddhmoj1g5lv3"]
[ext_resource type="PackedScene" uid="uid://berg2d0lm33m0" path="res://godot_state_charts_examples/performance_test/ten_state_charts.tscn" id="1_djj1b"]
[node name="hundred_state_charts" type="Node2D"]
[node name="ten_state_charts" parent="." instance=ExtResource("1_djj1b")]
[node name="ten_state_charts2" parent="." instance=ExtResource("1_djj1b")]
[node name="ten_state_charts3" parent="." instance=ExtResource("1_djj1b")]
[node name="ten_state_charts4" parent="." instance=ExtResource("1_djj1b")]
[node name="ten_state_charts5" parent="." instance=ExtResource("1_djj1b")]
[node name="ten_state_charts6" parent="." instance=ExtResource("1_djj1b")]
[node name="ten_state_charts7" parent="." instance=ExtResource("1_djj1b")]
[node name="ten_state_charts8" parent="." instance=ExtResource("1_djj1b")]
[node name="ten_state_charts9" parent="." instance=ExtResource("1_djj1b")]

View File

@ -0,0 +1,36 @@
[gd_scene load_steps=6 format=3 uid="uid://b8rr57grye1kw"]
[ext_resource type="Script" path="res://godot_state_charts_examples/performance_test/state_chart_receiver.gd" id="1_44fbg"]
[ext_resource type="Script" path="res://addons/godot_state_charts/state_chart.gd" id="1_x4how"]
[ext_resource type="Script" path="res://addons/godot_state_charts/compound_state.gd" id="2_2eb2m"]
[ext_resource type="Script" path="res://addons/godot_state_charts/atomic_state.gd" id="3_qtc2o"]
[ext_resource type="Script" path="res://addons/godot_state_charts/transition.gd" id="4_ue85n"]
[node name="state_chart" type="Node2D"]
script = ExtResource("1_44fbg")
[node name="StateChart" type="Node" parent="."]
script = ExtResource("1_x4how")
[node name="Root" type="Node" parent="StateChart"]
script = ExtResource("2_2eb2m")
initial_state = NodePath("A")
[node name="A" type="Node" parent="StateChart/Root"]
script = ExtResource("3_qtc2o")
[node name="To B" type="Node" parent="StateChart/Root/A"]
script = ExtResource("4_ue85n")
to = NodePath("../../B")
delay_seconds = 10.0
[node name="B" type="Node" parent="StateChart/Root"]
script = ExtResource("3_qtc2o")
[node name="To A" type="Node" parent="StateChart/Root/B"]
script = ExtResource("4_ue85n")
to = NodePath("../../A")
delay_seconds = 20.0
[connection signal="state_processing" from="StateChart/Root/A" to="." method="_on_a_state_processing"]
[connection signal="state_physics_processing" from="StateChart/Root/B" to="." method="_on_b_state_physics_processing"]

View File

@ -0,0 +1,12 @@
extends Node2D
func _on_a_state_processing(_delta):
pass
func _on_b_state_physics_processing(_delta):
pass

View File

@ -0,0 +1 @@
uid://bv6xx4hxfew5j

View File

@ -0,0 +1,25 @@
[gd_scene load_steps=2 format=3 uid="uid://berg2d0lm33m0"]
[ext_resource type="PackedScene" uid="uid://b8rr57grye1kw" path="res://godot_state_charts_examples/performance_test/state_chart.tscn" id="1_sc64n"]
[node name="ten_state_charts" type="Node2D"]
[node name="state_chart" parent="." instance=ExtResource("1_sc64n")]
[node name="state_chart2" parent="." instance=ExtResource("1_sc64n")]
[node name="state_chart3" parent="." instance=ExtResource("1_sc64n")]
[node name="state_chart4" parent="." instance=ExtResource("1_sc64n")]
[node name="state_chart5" parent="." instance=ExtResource("1_sc64n")]
[node name="state_chart6" parent="." instance=ExtResource("1_sc64n")]
[node name="state_chart7" parent="." instance=ExtResource("1_sc64n")]
[node name="state_chart8" parent="." instance=ExtResource("1_sc64n")]
[node name="state_chart9" parent="." instance=ExtResource("1_sc64n")]
[node name="state_chart10" parent="." instance=ExtResource("1_sc64n")]

View File

@ -0,0 +1,23 @@
[gd_scene load_steps=2 format=3 uid="uid://byh6mcqhp6ky2"]
[ext_resource type="PackedScene" uid="uid://bddhmoj1g5lv3" path="res://godot_state_charts_examples/performance_test/hundred_state_charts.tscn" id="1_1oume"]
[node name="thousand_state_charts" type="Node2D"]
[node name="hundred_state_charts" parent="." instance=ExtResource("1_1oume")]
[node name="hundred_state_charts2" parent="." instance=ExtResource("1_1oume")]
[node name="hundred_state_charts3" parent="." instance=ExtResource("1_1oume")]
[node name="hundred_state_charts4" parent="." instance=ExtResource("1_1oume")]
[node name="hundred_state_charts5" parent="." instance=ExtResource("1_1oume")]
[node name="hundred_state_charts6" parent="." instance=ExtResource("1_1oume")]
[node name="hundred_state_charts7" parent="." instance=ExtResource("1_1oume")]
[node name="hundred_state_charts8" parent="." instance=ExtResource("1_1oume")]
[node name="hundred_state_charts9" parent="." instance=ExtResource("1_1oume")]

Binary file not shown.

After

Width:  |  Height:  |  Size: 635 B

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://p8vbysdruo4o"
path="res://.godot/imported/break.png-76e3da8567a2ce2ef66cf2a31e3edc5e.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://godot_state_charts_examples/platformer/breaking_box/break.png"
dest_files=["res://.godot/imported/break.png-76e3da8567a2ce2ef66cf2a31e3edc5e.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

@ -0,0 +1,54 @@
extends StaticBody2D
signal clicked(node)
@export var health:int = 3
@onready var _state_chart:StateChart = %StateChart
@onready var _label:Label = %Label
@onready var _detection_shape = %CollisionShape2D
@onready var _animation_player = %AnimationPlayer
func _ready():
_label.text = str(health)
func _on_idle_state_entered():
# When we enter idle state we play the idle animation
_animation_player.play("Idle")
func _on_detection_area_body_entered(_body):
# When someone enters the area, reduce the health
# and notify the state chart.
health = max(0, health-1)
_label.text = str(health)
_state_chart.set_expression_property("health", health)
_state_chart.send_event("health_changed")
func _on_blinking_state_entered():
# when we enter blinking state, play the hit animation
_animation_player.play("Hit")
func _on_dying_state_entered():
# When we enter dying state, play the final death animation
_animation_player.play("Break")
func _on_dead_state_entered():
# When we enter dead state, we're done and can free the node.
queue_free()
func _on_animation_player_animation_finished(_anim_name):
# Forward animation_finished events to the state chart
_state_chart.send_event("animation_finished")
# This is to make the box clickable. Clicking it will show it in the debugger.
func _on_input_event(_viewport, event, _shape_idx):
# if the left mouse button is up emit the clicked signal
if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.is_pressed() == false:
clicked.emit(self)

View File

@ -0,0 +1 @@
uid://b7gcoyovuxkvo

View File

@ -0,0 +1,425 @@
[gd_scene load_steps=19 format=3 uid="uid://h0af1dot82p3"]
[ext_resource type="Script" path="res://godot_state_charts_examples/platformer/breaking_box/breaking_box.gd" id="1_c2rh2"]
[ext_resource type="Texture2D" uid="uid://c5dogybcf6yfo" path="res://godot_state_charts_examples/platformer/breaking_box/idle.png" id="1_dixph"]
[ext_resource type="Script" path="res://addons/godot_state_charts/state_chart.gd" id="2_atynw"]
[ext_resource type="Texture2D" uid="uid://dq0ww6xvgeap3" path="res://godot_state_charts_examples/platformer/breaking_box/hit.png" id="3_ngvxc"]
[ext_resource type="Texture2D" uid="uid://p8vbysdruo4o" path="res://godot_state_charts_examples/platformer/breaking_box/break.png" id="4_jb7vf"]
[ext_resource type="Script" path="res://addons/godot_state_charts/compound_state.gd" id="5_wouwd"]
[ext_resource type="Script" path="res://addons/godot_state_charts/atomic_state.gd" id="6_p4jwe"]
[ext_resource type="Script" path="res://addons/godot_state_charts/transition.gd" id="7_1ecad"]
[ext_resource type="Script" path="res://addons/godot_state_charts/expression_guard.gd" id="8_8riiw"]
[sub_resource type="Animation" id="Animation_toibu"]
resource_name = "Break"
length = 0.3
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("BoxSprite:texture")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [ExtResource("4_jb7vf")]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("BoxSprite:hframes")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [4]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("BoxSprite:frame")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0, 0.2),
"transitions": PackedFloat32Array(16.5643, 1),
"update": 0,
"values": [0, 3]
}
tracks/3/type = "value"
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/path = NodePath("Label:visible")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
tracks/4/type = "value"
tracks/4/imported = false
tracks/4/enabled = true
tracks/4/path = NodePath("BoxCollider:disabled")
tracks/4/interp = 1
tracks/4/loop_wrap = true
tracks/4/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [true]
}
tracks/5/type = "value"
tracks/5/imported = false
tracks/5/enabled = true
tracks/5/path = NodePath("BoxSprite:position")
tracks/5/interp = 1
tracks/5/loop_wrap = true
tracks/5/keys = {
"times": PackedFloat32Array(0, 0.2),
"transitions": PackedFloat32Array(1, 8.87654),
"update": 0,
"values": [Vector2(0, -10), Vector2(0, 50)]
}
tracks/6/type = "value"
tracks/6/imported = false
tracks/6/enabled = true
tracks/6/path = NodePath("BoxSprite:modulate:a")
tracks/6/interp = 1
tracks/6/loop_wrap = true
tracks/6/keys = {
"times": PackedFloat32Array(0, 0.2),
"transitions": PackedFloat32Array(1, 1),
"update": 0,
"values": [1.0, 0.0]
}
[sub_resource type="Animation" id="Animation_rc67x"]
resource_name = "Hit"
length = 0.2
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("BoxSprite:texture")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [ExtResource("3_ngvxc")]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("BoxSprite:hframes")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [2]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("BoxSprite:frame")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0, 0.1),
"transitions": PackedFloat32Array(1, 1),
"update": 1,
"values": [0, 1]
}
tracks/3/type = "value"
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/path = NodePath("Label:visible")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
[sub_resource type="Animation" id="Animation_yu346"]
resource_name = "Idle"
length = 0.1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("BoxSprite:texture")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [ExtResource("1_dixph")]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("BoxSprite:hframes")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [1]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("BoxSprite:frame")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [0]
}
tracks/3/type = "value"
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/path = NodePath("Label:visible")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [true]
}
tracks/4/type = "value"
tracks/4/imported = false
tracks/4/enabled = true
tracks/4/path = NodePath("BoxCollider:disabled")
tracks/4/interp = 1
tracks/4/loop_wrap = true
tracks/4/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
[sub_resource type="Animation" id="Animation_a7q8m"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("BoxSprite:texture")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [ExtResource("1_dixph")]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("BoxSprite:hframes")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [1]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("BoxSprite:frame")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [0]
}
tracks/3/type = "value"
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/path = NodePath("Label:visible")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [true]
}
tracks/4/type = "value"
tracks/4/imported = false
tracks/4/enabled = true
tracks/4/path = NodePath("BoxCollider:disabled")
tracks/4/interp = 1
tracks/4/loop_wrap = true
tracks/4/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
tracks/5/type = "value"
tracks/5/imported = false
tracks/5/enabled = true
tracks/5/path = NodePath("BoxSprite:position")
tracks/5/interp = 1
tracks/5/loop_wrap = true
tracks/5/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector2(0, -10)]
}
tracks/6/type = "value"
tracks/6/imported = false
tracks/6/enabled = true
tracks/6/path = NodePath("BoxSprite:modulate")
tracks/6/interp = 1
tracks/6/loop_wrap = true
tracks/6/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Color(1, 1, 1, 1)]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_t7nrw"]
_data = {
"Break": SubResource("Animation_toibu"),
"Hit": SubResource("Animation_rc67x"),
"Idle": SubResource("Animation_yu346"),
"RESET": SubResource("Animation_a7q8m")
}
[sub_resource type="RectangleShape2D" id="RectangleShape2D_8vd2b"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_jbwph"]
size = Vector2(14.5, 2)
[sub_resource type="Resource" id="Resource_v858x"]
script = ExtResource("8_8riiw")
expression = "health > 0"
[sub_resource type="Resource" id="Resource_j86i4"]
script = ExtResource("8_8riiw")
expression = "health <= 0"
[node name="BreakingBox" type="StaticBody2D"]
input_pickable = true
script = ExtResource("1_c2rh2")
[node name="BoxSprite" type="Sprite2D" parent="."]
texture_filter = 1
position = Vector2(0, -10)
texture = ExtResource("1_dixph")
[node name="Label" type="Label" parent="."]
unique_name_in_owner = true
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -20.0
offset_top = -23.0
offset_right = 20.0
offset_bottom = 3.0
grow_horizontal = 2
grow_vertical = 2
theme_override_font_sizes/font_size = 10
text = "3"
horizontal_alignment = 1
vertical_alignment = 1
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
unique_name_in_owner = true
editor_description = "The animation player will send an \"animation_finished\" event back to the state chart. This will then take the appropriate transitions (e.g. switch back to the idle animation)."
libraries = {
"": SubResource("AnimationLibrary_t7nrw")
}
[node name="BoxCollider" type="CollisionShape2D" parent="."]
position = Vector2(0, -10)
shape = SubResource("RectangleShape2D_8vd2b")
[node name="DetectionArea" type="Area2D" parent="."]
position = Vector2(0, -3)
collision_layer = 0
[node name="CollisionShape2D" type="CollisionShape2D" parent="DetectionArea"]
unique_name_in_owner = true
position = Vector2(0, -19)
shape = SubResource("RectangleShape2D_jbwph")
[node name="StateChart" type="Node" parent="."]
unique_name_in_owner = true
script = ExtResource("2_atynw")
track_in_editor = true
[node name="Root" type="Node" parent="StateChart"]
script = ExtResource("5_wouwd")
initial_state = NodePath("Idle")
[node name="Idle" type="Node" parent="StateChart/Root"]
script = ExtResource("6_p4jwe")
[node name="On Damage" type="Node" parent="StateChart/Root/Idle"]
script = ExtResource("7_1ecad")
to = NodePath("../../Blinking")
event = &"health_changed"
guard = SubResource("Resource_v858x")
delay_in_seconds = "0.0"
[node name="On Break" type="Node" parent="StateChart/Root/Idle"]
script = ExtResource("7_1ecad")
to = NodePath("../../Dying")
event = &"health_changed"
guard = SubResource("Resource_j86i4")
delay_in_seconds = "0.0"
[node name="Blinking" type="Node" parent="StateChart/Root"]
script = ExtResource("6_p4jwe")
[node name="Animation Finished" type="Node" parent="StateChart/Root/Blinking"]
script = ExtResource("7_1ecad")
to = NodePath("../../Idle")
event = &"animation_finished"
delay_in_seconds = "0.0"
[node name="Dying" type="Node" parent="StateChart/Root"]
script = ExtResource("6_p4jwe")
[node name="Animation Finished" type="Node" parent="StateChart/Root/Dying"]
script = ExtResource("7_1ecad")
to = NodePath("../../Dead")
event = &"animation_finished"
delay_in_seconds = "0.0"
[node name="Dead" type="Node" parent="StateChart/Root"]
script = ExtResource("6_p4jwe")
[connection signal="input_event" from="." to="." method="_on_input_event"]
[connection signal="animation_finished" from="AnimationPlayer" to="." method="_on_animation_player_animation_finished"]
[connection signal="body_entered" from="DetectionArea" to="." method="_on_detection_area_body_entered"]
[connection signal="state_entered" from="StateChart/Root/Idle" to="." method="_on_idle_state_entered"]
[connection signal="state_entered" from="StateChart/Root/Blinking" to="." method="_on_blinking_state_entered"]
[connection signal="state_entered" from="StateChart/Root/Dying" to="." method="_on_dying_state_entered"]
[connection signal="state_entered" from="StateChart/Root/Dead" to="." method="_on_dead_state_entered"]

Binary file not shown.

After

Width:  |  Height:  |  Size: 454 B

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dq0ww6xvgeap3"
path="res://.godot/imported/hit.png-1c36fd330c418d67632dbaced016a36f.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://godot_state_charts_examples/platformer/breaking_box/hit.png"
dest_files=["res://.godot/imported/hit.png-1c36fd330c418d67632dbaced016a36f.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 B

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://c5dogybcf6yfo"
path="res://.godot/imported/idle.png-ceff55276331d87b08aa0aee62d3e6af.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://godot_state_charts_examples/platformer/breaking_box/idle.png"
dest_files=["res://.godot/imported/idle.png-ceff55276331d87b08aa0aee62d3e6af.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

@ -0,0 +1,36 @@
extends Node2D
## emitted when this checkpoint is clicked with the mouse
signal clicked(checkpoint:Node2D)
## emitted when this checkpoint is activated
signal activated(checkpoint:Node2D)
## emitted when this checkpoint is deactivated
signal deactivated(checkpoint:Node2D)
@onready var _state_chart:StateChart = get_node("StateChart")
func _on_area_2d_input_event(_viewport:Node, event:InputEvent, _shape_idx:int):
# if event was left mouse button up, emit clicked signal
if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.is_pressed() == false:
# print("Checkpoint clicked")
clicked.emit(self)
func _on_area_2d_body_entered(body:Node2D):
if body.is_in_group("player"):
_state_chart.send_event("player_entered")
func _on_area_2d_body_exited(body:Node2D):
if body.is_in_group("player"):
_state_chart.send_event("player_exited")
func emit_activated():
activated.emit(self)
func emit_deactivated():
deactivated.emit(self)

View File

@ -0,0 +1 @@
uid://ccsukp7vuknqs

View File

@ -0,0 +1,343 @@
[gd_scene load_steps=19 format=3 uid="uid://b22lg10c7wxrq"]
[ext_resource type="Texture2D" uid="uid://4nlen5j7etvq" path="res://godot_state_charts_examples/platformer/checkpoint/checkpoint_no_flag.png" id="1_7vf2w"]
[ext_resource type="Script" path="res://godot_state_charts_examples/platformer/checkpoint/checkpoint.gd" id="1_jot5v"]
[ext_resource type="Texture2D" uid="uid://dfju87f6rw0nm" path="res://godot_state_charts_examples/platformer/checkpoint/checkpoint_idle.png" id="2_ns71f"]
[ext_resource type="Texture2D" uid="uid://beoe1hh5aggor" path="res://godot_state_charts_examples/platformer/checkpoint/checkpoint_flag_out.png" id="3_fbg27"]
[ext_resource type="Script" path="res://addons/godot_state_charts/state_chart.gd" id="5_a58ma"]
[ext_resource type="Script" path="res://addons/godot_state_charts/parallel_state.gd" id="6_53g38"]
[ext_resource type="Script" path="res://addons/godot_state_charts/compound_state.gd" id="6_qkwqk"]
[ext_resource type="Script" path="res://addons/godot_state_charts/atomic_state.gd" id="7_a74k1"]
[ext_resource type="Script" path="res://addons/godot_state_charts/transition.gd" id="8_7tjvh"]
[ext_resource type="Script" path="res://addons/godot_state_charts/state_is_active_guard.gd" id="10_fk2fi"]
[sub_resource type="Animation" id="Animation_xvggk"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite2D:texture")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [ExtResource("1_7vf2w")]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("Sprite2D:hframes")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [1]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("Sprite2D:frame")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [0]
}
[sub_resource type="Animation" id="Animation_p66ga"]
resource_name = "close_flag"
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite2D:texture")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [ExtResource("3_fbg27")]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("Sprite2D:hframes")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [26]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("Sprite2D:frame")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0, 1),
"transitions": PackedFloat32Array(1, 1),
"update": 0,
"values": [25, 0]
}
[sub_resource type="Animation" id="Animation_w48c8"]
resource_name = "idle_no_flag"
length = 0.1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite2D:texture")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [ExtResource("1_7vf2w")]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("Sprite2D:hframes")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [1]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("Sprite2D:frame")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [0]
}
[sub_resource type="Animation" id="Animation_judeo"]
resource_name = "idle_with_flag"
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite2D:texture")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [ExtResource("2_ns71f")]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("Sprite2D:hframes")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [10]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("Sprite2D:frame")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0, 1),
"transitions": PackedFloat32Array(1, 1),
"update": 0,
"values": [0, 9]
}
[sub_resource type="Animation" id="Animation_gr2w7"]
resource_name = "open_flag"
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite2D:texture")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [ExtResource("3_fbg27")]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("Sprite2D:hframes")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [26]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("Sprite2D:frame")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0, 1),
"transitions": PackedFloat32Array(1, 1),
"update": 0,
"values": [0, 25]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_5pqa5"]
_data = {
"RESET": SubResource("Animation_xvggk"),
"close_flag": SubResource("Animation_p66ga"),
"idle_no_flag": SubResource("Animation_w48c8"),
"idle_with_flag": SubResource("Animation_judeo"),
"open_flag": SubResource("Animation_gr2w7")
}
[sub_resource type="CapsuleShape2D" id="CapsuleShape2D_06im6"]
radius = 18.445
height = 59.4
[sub_resource type="Resource" id="Resource_22wfi"]
script = ExtResource("10_fk2fi")
state = NodePath("../../../../Player Presence/Absent")
metadata/_editor_prop_ptr_state = NodePath("../../../Player Presence/Absent")
[node name="Checkpoint" type="Node2D"]
script = ExtResource("1_jot5v")
[node name="Sprite2D" type="Sprite2D" parent="."]
texture_filter = 1
texture = ExtResource("1_7vf2w")
offset = Vector2(0, -32)
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
libraries = {
"": SubResource("AnimationLibrary_5pqa5")
}
[node name="Area2D" type="Area2D" parent="."]
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"]
position = Vector2(-2, -26)
shape = SubResource("CapsuleShape2D_06im6")
[node name="StateChart" type="Node" parent="."]
script = ExtResource("5_a58ma")
track_in_editor = true
[node name="Root" type="Node" parent="StateChart"]
script = ExtResource("6_53g38")
[node name="Player Presence" type="Node" parent="StateChart/Root"]
editor_description = "This compound state represents whether the player is currently present at the checkpoint."
script = ExtResource("6_qkwqk")
initial_state = NodePath("Absent")
[node name="Absent" type="Node" parent="StateChart/Root/Player Presence"]
script = ExtResource("7_a74k1")
[node name="On Player Enter" type="Node" parent="StateChart/Root/Player Presence/Absent"]
script = ExtResource("8_7tjvh")
to = NodePath("../../Present")
event = &"player_entered"
[node name="Present" type="Node" parent="StateChart/Root/Player Presence"]
script = ExtResource("7_a74k1")
[node name="On Player Exit" type="Node" parent="StateChart/Root/Player Presence/Present"]
script = ExtResource("8_7tjvh")
to = NodePath("../../Absent")
event = &"player_exited"
[node name="Animation Control" type="Node" parent="StateChart/Root"]
script = ExtResource("6_qkwqk")
initial_state = NodePath("Idle")
[node name="Idle" type="Node" parent="StateChart/Root/Animation Control"]
script = ExtResource("7_a74k1")
[node name="On Player Enter" type="Node" parent="StateChart/Root/Animation Control/Idle"]
script = ExtResource("8_7tjvh")
to = NodePath("../../Expanding")
event = &"player_entered"
[node name="Expanding" type="Node" parent="StateChart/Root/Animation Control"]
script = ExtResource("7_a74k1")
[node name="After 1 s" type="Node" parent="StateChart/Root/Animation Control/Expanding"]
script = ExtResource("8_7tjvh")
to = NodePath("../../Activated/Expanded")
delay_seconds = 0.9
[node name="Activated" type="Node" parent="StateChart/Root/Animation Control"]
script = ExtResource("6_qkwqk")
initial_state = NodePath("Expanded")
[node name="Expanded" type="Node" parent="StateChart/Root/Animation Control/Activated"]
script = ExtResource("7_a74k1")
[node name="Immediately" type="Node" parent="StateChart/Root/Animation Control/Activated/Expanded"]
editor_description = "Immediately go to the retracting state when the player is no longer present when entering this state."
script = ExtResource("8_7tjvh")
to = NodePath("../../Waiting To Retract")
guard = SubResource("Resource_22wfi")
[node name="On Player Leave" type="Node" parent="StateChart/Root/Animation Control/Activated/Expanded"]
script = ExtResource("8_7tjvh")
to = NodePath("../../Waiting To Retract")
event = &"player_exited"
[node name="Waiting To Retract" type="Node" parent="StateChart/Root/Animation Control/Activated"]
script = ExtResource("7_a74k1")
[node name="After 5 s" type="Node" parent="StateChart/Root/Animation Control/Activated/Waiting To Retract"]
script = ExtResource("8_7tjvh")
to = NodePath("../../../Retracting")
delay_seconds = 5.0
[node name="On Player Enter" type="Node" parent="StateChart/Root/Animation Control/Activated/Waiting To Retract"]
script = ExtResource("8_7tjvh")
to = NodePath("../../Expanded")
event = &"player_entered"
[node name="Retracting" type="Node" parent="StateChart/Root/Animation Control"]
script = ExtResource("7_a74k1")
[node name="After 1 s" type="Node" parent="StateChart/Root/Animation Control/Retracting"]
script = ExtResource("8_7tjvh")
to = NodePath("../../Idle")
delay_seconds = 0.9
[connection signal="body_entered" from="Area2D" to="." method="_on_area_2d_body_entered"]
[connection signal="body_exited" from="Area2D" to="." method="_on_area_2d_body_exited"]
[connection signal="input_event" from="Area2D" to="." method="_on_area_2d_input_event"]
[connection signal="state_entered" from="StateChart/Root/Animation Control/Idle" to="AnimationPlayer" method="play" binds= ["idle_no_flag"]]
[connection signal="state_entered" from="StateChart/Root/Animation Control/Expanding" to="AnimationPlayer" method="play" binds= ["open_flag"]]
[connection signal="state_entered" from="StateChart/Root/Animation Control/Activated" to="." method="emit_activated"]
[connection signal="state_exited" from="StateChart/Root/Animation Control/Activated" to="." method="emit_deactivated"]
[connection signal="state_entered" from="StateChart/Root/Animation Control/Activated/Expanded" to="AnimationPlayer" method="play" binds= ["idle_with_flag"]]
[connection signal="state_entered" from="StateChart/Root/Animation Control/Retracting" to="AnimationPlayer" method="play" binds= ["close_flag"]]

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://beoe1hh5aggor"
path="res://.godot/imported/checkpoint_flag_out.png-d1302c67d10e0b187eb8c484888649f3.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://godot_state_charts_examples/platformer/checkpoint/checkpoint_flag_out.png"
dest_files=["res://.godot/imported/checkpoint_flag_out.png-d1302c67d10e0b187eb8c484888649f3.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dfju87f6rw0nm"
path="res://.godot/imported/checkpoint_idle.png-450aa64af9f9812b4e2bfc351c4acc23.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://godot_state_charts_examples/platformer/checkpoint/checkpoint_idle.png"
dest_files=["res://.godot/imported/checkpoint_idle.png-450aa64af9f9812b4e2bfc351c4acc23.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 530 B

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://4nlen5j7etvq"
path="res://.godot/imported/checkpoint_no_flag.png-439157dcb5eca60e80049ff3b7e7a879.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://godot_state_charts_examples/platformer/checkpoint/checkpoint_no_flag.png"
dest_files=["res://.godot/imported/checkpoint_no_flag.png-439157dcb5eca60e80049ff3b7e7a879.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 399 B

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://roilgifkgiii"
path="res://.godot/imported/box.png-c36de003bc6b3890e50f6a4e0637c2de.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://godot_state_charts_examples/platformer/fireworks_box/box.png"
dest_files=["res://.godot/imported/box.png-c36de003bc6b3890e50f6a4e0637c2de.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

@ -0,0 +1,24 @@
extends Node2D
signal clicked(node:Node2D)
@onready var _state_chart:StateChart = $StateChart as StateChart
var _counter = 0
func count_up():
_counter += 1
_notify()
func count_down():
_counter -= 1
_notify()
func _notify():
_state_chart.set_expression_property("counter", _counter)
_state_chart.send_event("counter_changed")
func _on_area_2d_input_event(_viewport, event,_shape_idx):
# if the left mouse button is up emit the clicked signal
if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.is_pressed() == false:
clicked.emit(self)

View File

@ -0,0 +1 @@
uid://dn46gqfbbvsnk

View File

@ -0,0 +1,244 @@
[gd_scene load_steps=18 format=3 uid="uid://bvrbfp870t0kd"]
[ext_resource type="Script" path="res://godot_state_charts_examples/platformer/fireworks_box/fireworks_box.gd" id="1_6vg3k"]
[ext_resource type="Texture2D" uid="uid://roilgifkgiii" path="res://godot_state_charts_examples/platformer/fireworks_box/box.png" id="1_aido8"]
[ext_resource type="Script" path="res://addons/godot_state_charts/state_chart.gd" id="2_ahjdl"]
[ext_resource type="Script" path="res://addons/godot_state_charts/compound_state.gd" id="3_b1cau"]
[ext_resource type="Script" path="res://addons/godot_state_charts/atomic_state.gd" id="4_ot1ih"]
[ext_resource type="Script" path="res://addons/godot_state_charts/transition.gd" id="6_bf3gq"]
[ext_resource type="Script" path="res://addons/godot_state_charts/expression_guard.gd" id="7_tu34q"]
[sub_resource type="Resource" id="Resource_y5h70"]
script = ExtResource("7_tu34q")
expression = "counter > 0"
[sub_resource type="Resource" id="Resource_lsbaa"]
script = ExtResource("7_tu34q")
expression = "counter > 2"
[sub_resource type="Resource" id="Resource_t7gf7"]
script = ExtResource("7_tu34q")
expression = "counter == 0"
[sub_resource type="Animation" id="Animation_0njji"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Box:position")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector2(0, -10)]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("Box:rotation")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [-0.132645]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("Box:scale")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector2(1, 1)]
}
tracks/3/type = "value"
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/path = NodePath("GPUParticles2D:emitting")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [true]
}
[sub_resource type="Animation" id="Animation_81tef"]
resource_name = "explode"
length = 0.2
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Box:scale")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.1, 0.2),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 0,
"values": [Vector2(1, 1), Vector2(0.2, 0.2), Vector2(1e-05, 1e-05)]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("GPUParticles2D:emitting")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0.2),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [true]
}
[sub_resource type="Animation" id="Animation_yw5k5"]
resource_name = "idle"
length = 0.2
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Box:rotation")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [0.0]
}
[sub_resource type="Animation" id="Animation_tug1d"]
resource_name = "rattle"
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Box:position")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector2(0, -10)]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("Box:rotation")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0, 0.1, 0.3, 0.5, 0.7, 0.9, 1),
"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1, 1),
"update": 0,
"values": [0.0, -0.132645, 0.263545, -0.139626, -0.261799, -0.122173, 0.0]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_stxxq"]
_data = {
"RESET": SubResource("Animation_0njji"),
"explode": SubResource("Animation_81tef"),
"idle": SubResource("Animation_yw5k5"),
"rattle": SubResource("Animation_tug1d")
}
[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_c15xx"]
lifetime_randomness = 0.17
particle_flag_disable_z = true
direction = Vector3(0, -1, 0)
spread = 42.97
gravity = Vector3(0, 20, 0)
initial_velocity_min = 26.32
initial_velocity_max = 52.63
orbit_velocity_min = 0.0
orbit_velocity_max = 0.0
turbulence_noise_scale = 8.14
[sub_resource type="RectangleShape2D" id="RectangleShape2D_4ryt0"]
[node name="FireworksBox" type="Node2D"]
script = ExtResource("1_6vg3k")
[node name="Box" type="Sprite2D" parent="."]
position = Vector2(0, -10)
texture = ExtResource("1_aido8")
[node name="StateChart" type="Node" parent="."]
editor_description = "A state chart controlling the rattling and explosion of a box. You can probably use a simple script to achieve the same behaviour but it shows how to use expression guards."
script = ExtResource("2_ahjdl")
track_in_editor = true
[node name="Root" type="Node" parent="StateChart"]
script = ExtResource("3_b1cau")
initial_state = NodePath("Idle")
[node name="Idle" type="Node" parent="StateChart/Root"]
script = ExtResource("4_ot1ih")
[node name="Rattle on Counter" type="Node" parent="StateChart/Root/Idle"]
script = ExtResource("6_bf3gq")
to = NodePath("../../Rattling")
event = &"counter_changed"
guard = SubResource("Resource_y5h70")
[node name="Rattling" type="Node" parent="StateChart/Root"]
script = ExtResource("4_ot1ih")
[node name="Explode on Counter" type="Node" parent="StateChart/Root/Rattling"]
script = ExtResource("6_bf3gq")
to = NodePath("../../Exploding")
event = &"counter_changed"
guard = SubResource("Resource_lsbaa")
[node name="Get back to Idle" type="Node" parent="StateChart/Root/Rattling"]
script = ExtResource("6_bf3gq")
to = NodePath("../../Idle")
event = &"counter_changed"
guard = SubResource("Resource_t7gf7")
[node name="Exploding" type="Node" parent="StateChart/Root"]
script = ExtResource("4_ot1ih")
[node name="Die after 4s" type="Node" parent="StateChart/Root/Exploding"]
script = ExtResource("6_bf3gq")
to = NodePath("../../Dead")
delay_seconds = 4.0
[node name="Dead" type="Node" parent="StateChart/Root"]
script = ExtResource("4_ot1ih")
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
reset_on_save = false
libraries = {
"": SubResource("AnimationLibrary_stxxq")
}
[node name="GPUParticles2D" type="GPUParticles2D" parent="."]
position = Vector2(0, -10)
emitting = false
amount = 300
process_material = SubResource("ParticleProcessMaterial_c15xx")
lifetime = 2.81
one_shot = true
explosiveness = 0.86
[node name="Area2D" type="Area2D" parent="."]
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"]
position = Vector2(0, -10)
shape = SubResource("RectangleShape2D_4ryt0")
[connection signal="state_entered" from="StateChart/Root/Idle" to="AnimationPlayer" method="play" binds= ["idle"]]
[connection signal="state_entered" from="StateChart/Root/Rattling" to="AnimationPlayer" method="play" binds= ["rattle"]]
[connection signal="state_entered" from="StateChart/Root/Exploding" to="AnimationPlayer" method="play" binds= ["explode"]]
[connection signal="state_entered" from="StateChart/Root/Dead" to="." method="queue_free"]
[connection signal="input_event" from="Area2D" to="." method="_on_area_2d_input_event"]

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bgswg1pgd01d1"
path="res://.godot/imported/full.png-a85a82780a54dfe88e1678c76076d884.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://godot_state_charts_examples/platformer/ninja_frog/full.png"
dest_files=["res://.godot/imported/full.png-a85a82780a54dfe88e1678c76076d884.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

@ -0,0 +1,80 @@
extends CharacterBody2D
## Emitted when this node is clicked with a mouse
signal clicked(node:Node2D)
const SPEED = 300.0
const JUMP_VELOCITY = -400.0
# Get the gravity from the project settings to be synced with RigidBody nodes.
var _gravity = ProjectSettings.get_setting("physics/2d/default_gravity")
@onready var _sprite: Sprite2D = $Sprite
@onready var _state_chart: StateChart = $StateChart
@onready var _animation_tree: AnimationTree = $AnimationTree
@onready var _animation_state_machine: AnimationNodeStateMachinePlayback = _animation_tree.get("parameters/playback")
## Flag indicating if the character was on the floor in the last frame.
var _was_on_floor:bool = false
# In all states, move and slide and handle left/right movement and gravity.
func _physics_process(delta):
# handle left/right movement
var direction = Input.get_axis("ui_left", "ui_right")
if direction:
velocity.x = direction * SPEED
else:
velocity.x = move_toward(velocity.x, 0, SPEED)
# flip the sprite. we do this before moving, so it flips
# even if we stand at a wall
if signf(velocity.x) != 0:
_sprite.flip_h = velocity.x < 0
# gravity handled in Grounded and Airborne states
move_and_slide()
# if we are on the floor right now
if is_on_floor():
velocity.y = 0
# if we just touched the floor, notify the state chart
if not _was_on_floor:
_was_on_floor = true
_state_chart.send_event("grounded")
else:
velocity.y += _gravity * delta
# if we just left the floor, notify the state chart
if _was_on_floor:
_was_on_floor = false
_state_chart.send_event("airborne")
# let the state machine know if we are moving or not
if velocity.length_squared() <= 0.005:
_animation_state_machine.travel("Idle")
else:
_animation_state_machine.travel("Move")
# set the velocity to the animation tree, so it can blend between animations
_animation_tree["parameters/Move/blend_position"] = signf(velocity.y)
## Called in states that allow jumping, we process jumps only in these.
func _on_jump_enabled_state_physics_processing(_delta):
if Input.is_action_just_pressed("ui_accept"):
velocity.y = JUMP_VELOCITY
_state_chart.send_event("jump")
## Called when the jump transition is taken in the double-jump
## state. Only used to play the double jump animation.
func _on_double_jump_jump():
_animation_state_machine.travel("DoubleJump")
func _on_input_event(_viewport:Node, event:InputEvent, _shape_idx:int):
# if the left mouse button is up emit the clicked signal
if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.is_pressed() == false:
clicked.emit(self)

View File

@ -0,0 +1 @@
uid://qid37o42he05

View File

@ -0,0 +1,275 @@
[gd_scene load_steps=28 format=3 uid="uid://v5vg88it87oj"]
[ext_resource type="Script" path="res://godot_state_charts_examples/platformer/ninja_frog/ninja_frog.gd" id="1_xi1lh"]
[ext_resource type="Script" path="res://addons/godot_state_charts/state_chart.gd" id="3_qw75p"]
[ext_resource type="Script" path="res://addons/godot_state_charts/compound_state.gd" id="4_g6c55"]
[ext_resource type="Script" path="res://addons/godot_state_charts/atomic_state.gd" id="6_vmkuk"]
[ext_resource type="Texture2D" uid="uid://bgswg1pgd01d1" path="res://godot_state_charts_examples/platformer/ninja_frog/full.png" id="7_fehuj"]
[ext_resource type="Script" path="res://addons/godot_state_charts/transition.gd" id="9_wswdv"]
[sub_resource type="CapsuleShape2D" id="CapsuleShape2D_1ethx"]
radius = 12.0
[sub_resource type="Animation" id="Animation_uq0h4"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite:frame")
tracks/0/interp = 0
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [0]
}
[sub_resource type="Animation" id="Animation_10ku2"]
resource_name = "double_jump"
length = 0.4
step = 0.05
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.4),
"transitions": PackedFloat32Array(1, 1),
"update": 0,
"values": [23, 28]
}
[sub_resource type="Animation" id="Animation_ibg22"]
resource_name = "fall"
length = 0.1
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [29]
}
[sub_resource type="Animation" id="Animation_5rh2e"]
resource_name = "idle"
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 1),
"transitions": PackedFloat32Array(1, 1),
"update": 0,
"values": [12, 22]
}
[sub_resource type="Animation" id="Animation_jaga7"]
resource_name = "jump"
length = 0.1
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [30]
}
[sub_resource type="Animation" id="Animation_6odvc"]
resource_name = "walk"
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 1),
"transitions": PackedFloat32Array(1, 1),
"update": 0,
"values": [0, 11]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_au2ov"]
_data = {
"RESET": SubResource("Animation_uq0h4"),
"double_jump": SubResource("Animation_10ku2"),
"fall": SubResource("Animation_ibg22"),
"idle": SubResource("Animation_5rh2e"),
"jump": SubResource("Animation_jaga7"),
"walk": SubResource("Animation_6odvc")
}
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_k3ia7"]
animation = &"double_jump"
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_iie7f"]
animation = &"idle"
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_oetyn"]
animation = &"jump"
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_gw83y"]
animation = &"walk"
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_iq3nb"]
animation = &"fall"
[sub_resource type="AnimationNodeBlendSpace1D" id="AnimationNodeBlendSpace1D_o7w1c"]
blend_point_0/node = SubResource("AnimationNodeAnimation_oetyn")
blend_point_0/pos = -1.0
blend_point_1/node = SubResource("AnimationNodeAnimation_gw83y")
blend_point_1/pos = 0.0
blend_point_2/node = SubResource("AnimationNodeAnimation_iq3nb")
blend_point_2/pos = 1.0
blend_mode = 1
[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_i3ow4"]
advance_mode = 2
[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_a52qu"]
[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_1q7sj"]
[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_4cnci"]
[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_ddbej"]
switch_mode = 2
advance_mode = 2
[sub_resource type="AnimationNodeStateMachine" id="AnimationNodeStateMachine_ckafx"]
states/DoubleJump/node = SubResource("AnimationNodeAnimation_k3ia7")
states/DoubleJump/position = Vector2(767.5, 63.4141)
states/End/position = Vector2(962, 49)
states/Idle/node = SubResource("AnimationNodeAnimation_iie7f")
states/Idle/position = Vector2(342.5, 63.625)
states/Move/node = SubResource("AnimationNodeBlendSpace1D_o7w1c")
states/Move/position = Vector2(575.5, 62.7813)
states/Start/position = Vector2(210.5, 73.75)
transitions = ["Start", "Idle", SubResource("AnimationNodeStateMachineTransition_i3ow4"), "Idle", "Move", SubResource("AnimationNodeStateMachineTransition_a52qu"), "Move", "Idle", SubResource("AnimationNodeStateMachineTransition_1q7sj"), "Move", "DoubleJump", SubResource("AnimationNodeStateMachineTransition_4cnci"), "DoubleJump", "Move", SubResource("AnimationNodeStateMachineTransition_ddbej")]
graph_offset = Vector2(84, -7)
[sub_resource type="AnimationNodeStateMachinePlayback" id="AnimationNodeStateMachinePlayback_63x7j"]
[node name="NinjaFrog" type="CharacterBody2D" groups=["player"]]
input_pickable = true
script = ExtResource("1_xi1lh")
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
position = Vector2(0, -15)
shape = SubResource("CapsuleShape2D_1ethx")
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
libraries = {
"": SubResource("AnimationLibrary_au2ov")
}
[node name="Sprite" type="Sprite2D" parent="."]
texture_filter = 1
texture = ExtResource("7_fehuj")
offset = Vector2(0, -12)
hframes = 31
[node name="AnimationTree" type="AnimationTree" parent="."]
tree_root = SubResource("AnimationNodeStateMachine_ckafx")
anim_player = NodePath("../AnimationPlayer")
active = true
process_callback = 0
parameters/playback = SubResource("AnimationNodeStateMachinePlayback_63x7j")
parameters/Move/blend_position = -0.380028
[node name="StateChart" type="Node" parent="."]
script = ExtResource("3_qw75p")
track_in_editor = true
[node name="Root" type="Node" parent="StateChart"]
editor_description = "This is the root of all movement related states."
script = ExtResource("4_g6c55")
initial_state = NodePath("Grounded")
[node name="Grounded" type="Node" parent="StateChart/Root"]
editor_description = "This state is active when the player is on the ground."
script = ExtResource("6_vmkuk")
[node name="On Jump" type="Node" parent="StateChart/Root/Grounded"]
editor_description = "When jumping become airborne and enable double-jump."
script = ExtResource("9_wswdv")
to = NodePath("../../Airborne/DoubleJumpEnabled")
event = &"jump"
delay_in_seconds = "0.0"
[node name="On Airborne" type="Node" parent="StateChart/Root/Grounded"]
editor_description = "When becoming airborne (e.g. through falling) move to airborne state."
script = ExtResource("9_wswdv")
to = NodePath("../../Airborne")
event = &"airborne"
delay_in_seconds = "0.0"
[node name="Airborne" type="Node" parent="StateChart/Root"]
editor_description = "This is the root state for when the player is in the air. We have sub-states to handle the various input that is allowed when in the air."
script = ExtResource("4_g6c55")
initial_state = NodePath("CoyoteJumpEnabled")
[node name="On Grounded" type="Node" parent="StateChart/Root/Airborne"]
script = ExtResource("9_wswdv")
to = NodePath("../../Grounded")
event = &"grounded"
delay_in_seconds = "0.0"
[node name="CoyoteJumpEnabled" type="Node" parent="StateChart/Root/Airborne"]
editor_description = "While in this state, the player can jump for a short time. The state is activated by default when the player becomes airborne from falling. Allowing a jump for a short time makes the controls feel nicer. The \"On Expiration\" transition will leave this state after the grace period."
script = ExtResource("6_vmkuk")
[node name="On Jump" type="Node" parent="StateChart/Root/Airborne/CoyoteJumpEnabled"]
editor_description = "On jump handle this as if the player originally jumped."
script = ExtResource("9_wswdv")
to = NodePath("../../DoubleJumpEnabled")
event = &"jump"
delay_in_seconds = "0.0"
[node name="On Expiration" type="Node" parent="StateChart/Root/Airborne/CoyoteJumpEnabled"]
editor_description = "After 0.2 seconds automatically move to falling state where no more jump is possible."
script = ExtResource("9_wswdv")
to = NodePath("../../CannotJump")
delay_in_seconds = "0.2"
[node name="DoubleJumpEnabled" type="Node" parent="StateChart/Root/Airborne"]
editor_description = "This state is active while the player is in the air and has jumped one time already. While the state is active, a second jump is allowed."
script = ExtResource("6_vmkuk")
[node name="On Jump" type="Node" parent="StateChart/Root/Airborne/DoubleJumpEnabled"]
editor_description = "When jumping in double jump state, move to a state where no more jumps are possible.
Triggers the double-jump animation as a side effect."
script = ExtResource("9_wswdv")
to = NodePath("../../CannotJump")
event = &"jump"
delay_in_seconds = "0.0"
[node name="CannotJump" type="Node" parent="StateChart/Root/Airborne"]
editor_description = "This state is active when the player is airborne but can no longer jump either because the coyote-jump grace period has expired or the player has already used the double-jump."
script = ExtResource("6_vmkuk")
[connection signal="input_event" from="." to="." method="_on_input_event"]
[connection signal="state_physics_processing" from="StateChart/Root/Grounded" to="." method="_on_jump_enabled_state_physics_processing"]
[connection signal="state_physics_processing" from="StateChart/Root/Airborne/CoyoteJumpEnabled" to="." method="_on_jump_enabled_state_physics_processing"]
[connection signal="state_physics_processing" from="StateChart/Root/Airborne/DoubleJumpEnabled" to="." method="_on_jump_enabled_state_physics_processing"]
[connection signal="taken" from="StateChart/Root/Airborne/DoubleJumpEnabled/On Jump" to="." method="_on_double_jump_jump"]

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 543 B

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bap00a5gcipy6"
path="res://.godot/imported/green.png-7e931e8924aaf6f1ff626e30e2c63319.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://godot_state_charts_examples/platformer/terrain/green.png"
dest_files=["res://.godot/imported/green.png-7e931e8924aaf6f1ff626e30e2c63319.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://d2evtvw3l7jug"
path="res://.godot/imported/terrain_tiles.png-2247cd6621fc9988b0ae044edcccf620.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://godot_state_charts_examples/platformer/terrain/terrain_tiles.png"
dest_files=["res://.godot/imported/terrain_tiles.png-2247cd6621fc9988b0ae044edcccf620.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

@ -0,0 +1,199 @@
[gd_resource type="TileSet" load_steps=6 format=3 uid="uid://cd6hbvgl1e2xy"]
[ext_resource type="Texture2D" uid="uid://d2evtvw3l7jug" path="res://godot_state_charts_examples/platformer/terrain/terrain_tiles.png" id="1_g8rgd"]
[ext_resource type="Texture2D" uid="uid://bap00a5gcipy6" path="res://godot_state_charts_examples/platformer/terrain/green.png" id="2_q18a4"]
[sub_resource type="PhysicsMaterial" id="PhysicsMaterial_8w8gx"]
friction = 0.0
[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_p8in1"]
texture = ExtResource("1_g8rgd")
6:4/0 = 0
6:4/0/physics_layer_0/linear_velocity = Vector2(0, 0)
6:4/0/physics_layer_0/angular_velocity = 0.0
6:4/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
7:4/0 = 0
7:4/0/physics_layer_0/linear_velocity = Vector2(0, 0)
7:4/0/physics_layer_0/angular_velocity = 0.0
7:4/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
8:4/0 = 0
8:4/0/physics_layer_0/linear_velocity = Vector2(0, 0)
8:4/0/physics_layer_0/angular_velocity = 0.0
8:4/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
8:5/0 = 0
8:5/0/physics_layer_0/linear_velocity = Vector2(0, 0)
8:5/0/physics_layer_0/angular_velocity = 0.0
8:5/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
8:6/0 = 0
8:6/0/physics_layer_0/linear_velocity = Vector2(0, 0)
8:6/0/physics_layer_0/angular_velocity = 0.0
8:6/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
7:6/0 = 0
7:6/0/physics_layer_0/linear_velocity = Vector2(0, 0)
7:6/0/physics_layer_0/angular_velocity = 0.0
7:6/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
6:6/0 = 0
6:6/0/physics_layer_0/linear_velocity = Vector2(0, 0)
6:6/0/physics_layer_0/angular_velocity = 0.0
6:6/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
6:5/0 = 0
6:5/0/physics_layer_0/linear_velocity = Vector2(0, 0)
6:5/0/physics_layer_0/angular_velocity = 0.0
6:5/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
7:5/0 = 0
7:5/0/physics_layer_0/linear_velocity = Vector2(0, 0)
7:5/0/physics_layer_0/angular_velocity = 0.0
7:5/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
0:0/0 = 0
0:0/0/terrain_set = 0
0:0/0/terrain = 0
0:0/0/physics_layer_0/linear_velocity = Vector2(0, 0)
0:0/0/physics_layer_0/angular_velocity = 0.0
0:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 0.3125, 0.5, 0.5, 0, 8, -8, 7.5)
0:0/0/terrains_peering_bit/right_side = 0
0:0/0/terrains_peering_bit/bottom_right_corner = 0
0:0/0/terrains_peering_bit/bottom_side = 0
1:0/0 = 0
1:0/0/terrain_set = 0
1:0/0/terrain = 0
1:0/0/physics_layer_0/linear_velocity = Vector2(0, 0)
1:0/0/physics_layer_0/angular_velocity = 0.0
1:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(8, -8, 8, 0, -8, 0, -8, -8)
1:0/0/terrains_peering_bit/right_side = 0
1:0/0/terrains_peering_bit/bottom_right_corner = 0
1:0/0/terrains_peering_bit/bottom_side = 0
1:0/0/terrains_peering_bit/bottom_left_corner = 0
1:0/0/terrains_peering_bit/left_side = 0
1:1/0 = 0
1:1/0/terrain_set = 0
1:1/0/terrain = 0
1:1/0/physics_layer_0/linear_velocity = Vector2(0, 0)
1:1/0/physics_layer_0/angular_velocity = 0.0
1:1/0/terrains_peering_bit/right_side = 0
1:1/0/terrains_peering_bit/bottom_right_corner = 0
1:1/0/terrains_peering_bit/bottom_side = 0
1:1/0/terrains_peering_bit/bottom_left_corner = 0
1:1/0/terrains_peering_bit/left_side = 0
1:1/0/terrains_peering_bit/top_left_corner = 0
1:1/0/terrains_peering_bit/top_side = 0
1:1/0/terrains_peering_bit/top_right_corner = 0
2:1/0 = 0
2:1/0/terrain_set = 0
2:1/0/terrain = 0
2:1/0/physics_layer_0/linear_velocity = Vector2(0, 0)
2:1/0/physics_layer_0/angular_velocity = 0.0
2:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(0, -8, 8, -8, 8, 8, 0, 8)
2:1/0/terrains_peering_bit/bottom_side = 0
2:1/0/terrains_peering_bit/bottom_left_corner = 0
2:1/0/terrains_peering_bit/left_side = 0
2:1/0/terrains_peering_bit/top_left_corner = 0
2:1/0/terrains_peering_bit/top_side = 0
2:2/0 = 0
2:2/0/terrain_set = 0
2:2/0/terrain = 0
2:2/0/physics_layer_0/linear_velocity = Vector2(0, 0)
2:2/0/physics_layer_0/angular_velocity = 0.0
2:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(0, -8, 8, -8, 8, 8, -8, 8, -8, 0, 0, 0)
2:2/0/terrains_peering_bit/left_side = 0
2:2/0/terrains_peering_bit/top_left_corner = 0
2:2/0/terrains_peering_bit/top_side = 0
2:0/0 = 0
2:0/0/terrain_set = 0
2:0/0/terrain = 0
2:0/0/physics_layer_0/linear_velocity = Vector2(0, 0)
2:0/0/physics_layer_0/angular_velocity = 0.0
2:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(8, -8, 8, 8, -8, 8, -8, -8)
2:0/0/terrains_peering_bit/bottom_side = 0
2:0/0/terrains_peering_bit/bottom_left_corner = 0
2:0/0/terrains_peering_bit/left_side = 0
0:1/0 = 0
0:1/0/terrain_set = 0
0:1/0/terrain = 0
0:1/0/physics_layer_0/linear_velocity = Vector2(0, 0)
0:1/0/physics_layer_0/angular_velocity = 0.0
0:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 0, -8, 0, 8, -8, 7.5)
0:1/0/terrains_peering_bit/right_side = 0
0:1/0/terrains_peering_bit/bottom_right_corner = 0
0:1/0/terrains_peering_bit/bottom_side = 0
0:1/0/terrains_peering_bit/top_side = 0
0:1/0/terrains_peering_bit/top_right_corner = 0
0:2/0 = 0
0:2/0/terrain_set = 0
0:2/0/terrain = 0
0:2/0/physics_layer_0/linear_velocity = Vector2(0, 0)
0:2/0/physics_layer_0/angular_velocity = 0.0
0:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
0:2/0/terrains_peering_bit/right_side = 0
0:2/0/terrains_peering_bit/top_side = 0
0:2/0/terrains_peering_bit/top_right_corner = 0
1:2/0 = 0
1:2/0/terrain_set = 0
1:2/0/terrain = 0
1:2/0/physics_layer_0/linear_velocity = Vector2(0, 0)
1:2/0/physics_layer_0/angular_velocity = 0.0
1:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(8, 0, 8, 8, -8, 8, -8, 0)
1:2/0/terrains_peering_bit/right_side = 0
1:2/0/terrains_peering_bit/left_side = 0
1:2/0/terrains_peering_bit/top_left_corner = 0
1:2/0/terrains_peering_bit/top_side = 0
1:2/0/terrains_peering_bit/top_right_corner = 0
[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_gpldh"]
texture = ExtResource("2_q18a4")
0:0/0 = 0
0:0/0/physics_layer_0/linear_velocity = Vector2(0, 0)
0:0/0/physics_layer_0/angular_velocity = 0.0
1:0/0 = 0
1:0/0/physics_layer_0/linear_velocity = Vector2(0, 0)
1:0/0/physics_layer_0/angular_velocity = 0.0
1:1/0 = 0
1:1/0/physics_layer_0/linear_velocity = Vector2(0, 0)
1:1/0/physics_layer_0/angular_velocity = 0.0
1:2/0 = 0
1:2/0/physics_layer_0/linear_velocity = Vector2(0, 0)
1:2/0/physics_layer_0/angular_velocity = 0.0
2:2/0 = 0
2:2/0/physics_layer_0/linear_velocity = Vector2(0, 0)
2:2/0/physics_layer_0/angular_velocity = 0.0
0:2/0 = 0
0:2/0/physics_layer_0/linear_velocity = Vector2(0, 0)
0:2/0/physics_layer_0/angular_velocity = 0.0
0:1/0 = 0
0:1/0/physics_layer_0/linear_velocity = Vector2(0, 0)
0:1/0/physics_layer_0/angular_velocity = 0.0
2:0/0 = 0
2:0/0/physics_layer_0/linear_velocity = Vector2(0, 0)
2:0/0/physics_layer_0/angular_velocity = 0.0
3:0/0 = 0
3:0/0/physics_layer_0/linear_velocity = Vector2(0, 0)
3:0/0/physics_layer_0/angular_velocity = 0.0
3:1/0 = 0
3:1/0/physics_layer_0/linear_velocity = Vector2(0, 0)
3:1/0/physics_layer_0/angular_velocity = 0.0
2:1/0 = 0
2:1/0/physics_layer_0/linear_velocity = Vector2(0, 0)
2:1/0/physics_layer_0/angular_velocity = 0.0
3:2/0 = 0
3:2/0/physics_layer_0/linear_velocity = Vector2(0, 0)
3:2/0/physics_layer_0/angular_velocity = 0.0
2:3/0 = 0
2:3/0/physics_layer_0/linear_velocity = Vector2(0, 0)
2:3/0/physics_layer_0/angular_velocity = 0.0
1:3/0 = 0
1:3/0/physics_layer_0/linear_velocity = Vector2(0, 0)
1:3/0/physics_layer_0/angular_velocity = 0.0
0:3/0 = 0
0:3/0/physics_layer_0/linear_velocity = Vector2(0, 0)
0:3/0/physics_layer_0/angular_velocity = 0.0
3:3/0 = 0
3:3/0/physics_layer_0/linear_velocity = Vector2(0, 0)
3:3/0/physics_layer_0/angular_velocity = 0.0
[resource]
physics_layer_0/collision_layer = 1
physics_layer_0/physics_material = SubResource("PhysicsMaterial_8w8gx")
terrain_set_0/mode = 0
terrain_set_0/terrain_0/name = "Stuff"
terrain_set_0/terrain_0/color = Color(0.501961, 0.345098, 0.25098, 1)
sources/0 = SubResource("TileSetAtlasSource_p8in1")
sources/2 = SubResource("TileSetAtlasSource_gpldh")

View File

@ -0,0 +1,108 @@
[gd_scene load_steps=7 format=3 uid="uid://i4v5fyt2ix01"]
[ext_resource type="PackedScene" uid="uid://nji5r3vfeuwg" path="res://godot_state_charts_examples/random_transitions/wandering_frog/wandering_frog.tscn" id="1_r2x6m"]
[ext_resource type="PackedScene" uid="uid://bcwkugn6v3oy7" path="res://addons/godot_state_charts/utilities/state_chart_debugger.tscn" id="2_n8tkm"]
[sub_resource type="Shader" id="Shader_8j6vc"]
code = "shader_type canvas_item;
void fragment() {
COLOR.rgb *= (1.0-0.3*(1.0-UV.y));
}
void vertex() {
VERTEX.x -= UV.y * (0.5 - UV.x) * 100.0;
}
"
[sub_resource type="ShaderMaterial" id="ShaderMaterial_8axp2"]
shader = SubResource("Shader_8j6vc")
[sub_resource type="RectangleShape2D" id="RectangleShape2D_fkyfr"]
size = Vector2(36, 418)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_e3j0h"]
size = Vector2(405, 35)
[node name="Random Transitions" type="Node2D"]
[node name="Ground" type="ColorRect" parent="."]
material = SubResource("ShaderMaterial_8axp2")
offset_left = 39.0
offset_top = 68.0
offset_right = 319.0
offset_bottom = 478.0
color = Color(0.0980392, 0.560784, 0.152941, 1)
[node name="ColliderLeft" type="StaticBody2D" parent="."]
position = Vector2(0, 40)
collision_layer = 2
[node name="CollisionShape2D" type="CollisionShape2D" parent="ColliderLeft"]
position = Vector2(35, 199)
shape = SubResource("RectangleShape2D_fkyfr")
[node name="ColliderRight" type="StaticBody2D" parent="."]
position = Vector2(329, 45)
collision_layer = 2
collision_mask = 2
[node name="CollisionShape2D" type="CollisionShape2D" parent="ColliderRight"]
position = Vector2(-9, 196)
shape = SubResource("RectangleShape2D_fkyfr")
[node name="ColliderTop" type="StaticBody2D" parent="."]
position = Vector2(375, 45)
collision_layer = 2
collision_mask = 2
[node name="CollisionShape2D" type="CollisionShape2D" parent="ColliderTop"]
position = Vector2(-176, 12)
shape = SubResource("RectangleShape2D_e3j0h")
[node name="ColliderBottom" type="StaticBody2D" parent="."]
position = Vector2(375, 428)
collision_layer = 2
collision_mask = 2
[node name="CollisionShape2D" type="CollisionShape2D" parent="ColliderBottom"]
position = Vector2(-188, -27)
shape = SubResource("RectangleShape2D_e3j0h")
[node name="WanderingFrog" parent="." instance=ExtResource("1_r2x6m")]
modulate = Color(0.454902, 0.458824, 1, 1)
position = Vector2(106, 158)
[node name="WanderingFrog2" parent="." instance=ExtResource("1_r2x6m")]
position = Vector2(224, 208)
[node name="WanderingFrog3" parent="." instance=ExtResource("1_r2x6m")]
position = Vector2(149, 275)
[node name="WanderingFrog4" parent="." instance=ExtResource("1_r2x6m")]
position = Vector2(297, 340)
[node name="WanderingFrog5" parent="." instance=ExtResource("1_r2x6m")]
position = Vector2(79, 359)
[node name="WanderingFrog6" parent="." instance=ExtResource("1_r2x6m")]
position = Vector2(225, 126)
[node name="StateChartDebugger" parent="." instance=ExtResource("2_n8tkm")]
offset_left = 344.0
offset_top = 33.0
offset_right = 636.0
offset_bottom = 438.0
initial_node_to_watch = NodePath("../WanderingFrog")
[node name="Label" type="RichTextLabel" parent="."]
offset_left = 10.0
offset_top = 375.0
offset_right = 334.0
offset_bottom = 459.0
mouse_filter = 2
bbcode_enabled = true
text = "[font_size=10]
The frogs random movement is controlled by the state chart. Each frog choses to wander or be idle for a random amount of seconds. Even though all frog instances use the same state chart they behave differently because they use random expressions to control which state they enter and for how long they stay in there. The debugger shows the state chart of the blue-tinted frog.
[/font_size]"
fit_content = true

View File

@ -0,0 +1,49 @@
extends CharacterBody2D
const SPEED:float = 50.0
@onready var _sprite: Sprite2D = $Sprite
@onready var _animation_player:AnimationPlayer = $AnimationPlayer
var _direction:Vector2
# When we enter walk state ...
func _on_walk_state_entered():
# pick a random direction to walk in (360 degrees)
_direction = Vector2(randf() * 2 - 1, randf() * 2 - 1).normalized()
# and play the walk animation
_animation_player.play("walk")
# flip the sprite. since we keep this direction for as long as
# we are in the walk state, we don't need to do this per frame.
_sprite.flip_h = _direction.x < 0
# While we are in walk state...
func _on_walk_state_physics_processing(_delta):
# set a new velocity
velocity = _direction * SPEED
# and move into the given direction
move_and_slide()
# and update scale
rescale()
# When we enter idle state ...
func _on_idle_state_entered():
# clear the direction
_direction = Vector2.ZERO
# and play the idle animation
_animation_player.play("idle")
# also rescale here in case we entered idle state first
rescale()
func rescale():
# scale the frog depending on its y position to achieve some pseudo-3d effect
# this is hard-coded for resolution of this project which has 480 vertical pixels
# so we assume 240 to be 100% size, 0 would be 50% size and 480 would be 150% size.
var scale_factor = 1.0 + ((global_position.y - 240) / 480)
scale = Vector2(scale_factor, scale_factor)

View File

@ -0,0 +1 @@
uid://dg7apxhe32cgj

View File

@ -0,0 +1,211 @@
[gd_scene load_steps=19 format=3 uid="uid://nji5r3vfeuwg"]
[ext_resource type="Script" path="res://godot_state_charts_examples/random_transitions/wandering_frog/wandering_frog.gd" id="1_tfcjx"]
[ext_resource type="Texture2D" uid="uid://bgswg1pgd01d1" path="res://godot_state_charts_examples/platformer/ninja_frog/full.png" id="2_hm4wf"]
[ext_resource type="Script" path="res://addons/godot_state_charts/state_chart.gd" id="3_2vqqk"]
[ext_resource type="Script" path="res://addons/godot_state_charts/compound_state.gd" id="4_44md5"]
[ext_resource type="Script" path="res://addons/godot_state_charts/atomic_state.gd" id="5_j65h7"]
[ext_resource type="Script" path="res://addons/godot_state_charts/transition.gd" id="6_s6am2"]
[ext_resource type="Script" path="res://addons/godot_state_charts/expression_guard.gd" id="7_f5w5i"]
[sub_resource type="Shader" id="Shader_pnpgx"]
code = "shader_type canvas_item;
void fragment() {
COLOR.rgb = vec3(0);
COLOR.a = 0.5 * 1.0-smoothstep(0.0, 1.0, distance(UV, vec2(0.5)));
}
"
[sub_resource type="ShaderMaterial" id="ShaderMaterial_fnfpn"]
shader = SubResource("Shader_pnpgx")
[sub_resource type="CapsuleShape2D" id="CapsuleShape2D_1ethx"]
radius = 12.0
[sub_resource type="Animation" id="Animation_uq0h4"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite:frame")
tracks/0/interp = 0
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [0]
}
[sub_resource type="Animation" id="Animation_10ku2"]
resource_name = "double_jump"
length = 0.4
step = 0.05
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.4),
"transitions": PackedFloat32Array(1, 1),
"update": 0,
"values": [23, 28]
}
[sub_resource type="Animation" id="Animation_ibg22"]
resource_name = "fall"
length = 0.1
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [29]
}
[sub_resource type="Animation" id="Animation_5rh2e"]
resource_name = "idle"
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 1),
"transitions": PackedFloat32Array(1, 1),
"update": 0,
"values": [12, 22]
}
[sub_resource type="Animation" id="Animation_jaga7"]
resource_name = "jump"
length = 0.1
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [30]
}
[sub_resource type="Animation" id="Animation_6odvc"]
resource_name = "walk"
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 1),
"transitions": PackedFloat32Array(1, 1),
"update": 0,
"values": [0, 11]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_au2ov"]
_data = {
"RESET": SubResource("Animation_uq0h4"),
"double_jump": SubResource("Animation_10ku2"),
"fall": SubResource("Animation_ibg22"),
"idle": SubResource("Animation_5rh2e"),
"jump": SubResource("Animation_jaga7"),
"walk": SubResource("Animation_6odvc")
}
[sub_resource type="Resource" id="Resource_27kjk"]
script = ExtResource("7_f5w5i")
expression = "randf() < 0.5"
[node name="WanderingFrog" type="CharacterBody2D"]
collision_mask = 2
input_pickable = true
script = ExtResource("1_tfcjx")
[node name="Shadow" type="ColorRect" parent="."]
material = SubResource("ShaderMaterial_fnfpn")
offset_left = -19.0
offset_top = -6.0
offset_right = 21.0
offset_bottom = 12.0
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
position = Vector2(0, -15)
shape = SubResource("CapsuleShape2D_1ethx")
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
libraries = {
"": SubResource("AnimationLibrary_au2ov")
}
[node name="Sprite" type="Sprite2D" parent="."]
texture_filter = 1
texture = ExtResource("2_hm4wf")
offset = Vector2(0, -12)
hframes = 31
[node name="StateChart" type="Node" parent="."]
script = ExtResource("3_2vqqk")
track_in_editor = true
[node name="Wander" type="Node" parent="StateChart"]
editor_description = "This controls the wandering."
script = ExtResource("4_44md5")
initial_state = NodePath("Decide Next")
[node name="Decide Next" type="Node" parent="StateChart/Wander"]
editor_description = "In this state the frog randomly decides what to do next. The \"To Idle\" transition has a guard which will pick it with a chance of 50%. If it is not picked, then the \"To Walk\" transition is picked. "
script = ExtResource("5_j65h7")
[node name="To Idle" type="Node" parent="StateChart/Wander/Decide Next"]
script = ExtResource("6_s6am2")
to = NodePath("../../Idle")
guard = SubResource("Resource_27kjk")
delay_in_seconds = "0.0"
[node name="To Walk" type="Node" parent="StateChart/Wander/Decide Next"]
script = ExtResource("6_s6am2")
to = NodePath("../../Walk")
delay_in_seconds = "0.0"
[node name="Idle" type="Node" parent="StateChart/Wander"]
editor_description = "In this state the frog stands idly around for a random time."
script = ExtResource("5_j65h7")
[node name="To Decide Next" type="Node" parent="StateChart/Wander/Idle"]
editor_description = "This will bring the frog back into the \"Decide Next\" state after a random amount of time."
script = ExtResource("6_s6am2")
to = NodePath("../../Decide Next")
delay_in_seconds = "randf_range(1.5, 3)"
[node name="Walk" type="Node" parent="StateChart/Wander"]
editor_description = "In this state the frog walks into a random direction for a random amount of time."
script = ExtResource("5_j65h7")
[node name="To Decide Next" type="Node" parent="StateChart/Wander/Walk"]
editor_description = "This will bring the frog back into the \"Decide Next\" state after a random amount of time."
script = ExtResource("6_s6am2")
to = NodePath("../../Idle")
delay_in_seconds = "randf_range(3, 7)"
[connection signal="state_entered" from="StateChart/Wander/Idle" to="." method="_on_idle_state_entered"]
[connection signal="state_entered" from="StateChart/Wander/Walk" to="." method="_on_walk_state_entered"]
[connection signal="state_physics_processing" from="StateChart/Wander/Walk" to="." method="_on_walk_state_physics_processing"]

View File

@ -0,0 +1,59 @@
extends Node2D
@onready var _add_coal_to_drill_button:Button = %AddCoalToDrillButton
@onready var _coal_available_label:Label = %CoalAvailableLabel
@onready var _coal_in_drill_label:Label = %CoalInDrillLabel
@onready var _state_chart:StateChart = %StateChart
var _coal_available:int = 0:
set(value):
_coal_available = value
# update the UI when this changes
_coal_available_label.text = str(_coal_available)
_add_coal_to_drill_button.disabled = _coal_available == 0
var _coal_in_drill:int = 0:
set(value):
_coal_in_drill = value
# update the UI when this changes
_coal_in_drill_label.text = str(_coal_in_drill)
if _coal_in_drill == 0:
# if there is no more coal in the drill send the
# coal_depleted event
_state_chart.send_event("coal_depleted")
else:
# otherwise send the coal_available event
_state_chart.send_event("coal_available")
func _ready():
_coal_available = 1 # we start with 1 coal
func _on_add_coal_to_drill_button_pressed():
# take one coal from the pile and put it into the generator
_coal_available -= 1
_coal_in_drill += 1
func _on_drill_has_coal_state_stepped():
# when we are in this state, we produce 2 coal and consume one of the coal in
# the drill
_coal_available += 2
_coal_in_drill -= 1
func _on_drill_has_no_coal_state_stepped():
# when we are in this state, the drill has no coal so we just flash
# the label red.
_coal_in_drill_label.modulate = Color.RED
create_tween().tween_property(_coal_in_drill_label, "modulate", Color.WHITE, 0.5)
func _on_next_round_button_pressed():
# when the next round button is pressed we handle all currently active states
_state_chart.step()

View File

@ -0,0 +1 @@
uid://dctc1yeiwh0wx

Some files were not shown because too many files have changed in this diff Show More