gd,refacto: added state chart addon and namespace cleanup
This commit is contained in:
115
godot_state_charts_examples/csharp/CSharpExample.cs
Normal file
115
godot_state_charts_examples/csharp/CSharpExample.cs
Normal 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");
|
||||
}
|
||||
|
||||
}
|
1
godot_state_charts_examples/csharp/CSharpExample.cs.uid
Normal file
1
godot_state_charts_examples/csharp/CSharpExample.cs.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://cpw6fi5fyccic
|
9
godot_state_charts_examples/csharp/README.txt
Normal file
9
godot_state_charts_examples/csharp/README.txt
Normal 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.
|
27
godot_state_charts_examples/csharp/StateChartExt.cs
Normal file
27
godot_state_charts_examples/csharp/StateChartExt.cs
Normal 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");
|
||||
}
|
||||
}
|
1
godot_state_charts_examples/csharp/StateChartExt.cs.uid
Normal file
1
godot_state_charts_examples/csharp/StateChartExt.cs.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://btrfg0cn5wgrg
|
109
godot_state_charts_examples/csharp/csharp_example.tscn
Normal file
109
godot_state_charts_examples/csharp/csharp_example.tscn
Normal 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"]
|
Reference in New Issue
Block a user