Skip to content

Commit

Permalink
Update READMEs for 0.4.0
Browse files Browse the repository at this point in the history
  • Loading branch information
imjp94 committed Jan 15, 2021
1 parent e457ea3 commit 6bec509
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 9 deletions.
107 changes: 101 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,20 @@ Designer-friendly Finite State Machine implemented in "Godotic" way
> It is not recommended to be used in production yet, as api might be changed before v1.0.
> Testing & reporting bugs are greatly appreciated.
## Content

- [Feature](#feature)
- [Installation](#installation)
- [Getting Started](#getting-started)
- [Editor](#editor)
- [Code](#code)
- [Nested FSM](#nested-fsm)
- [State](#state)
- [Parameter](#parameter)
- [Debug](#debug)
- [Demo](#demo)
- [Documentation](addons/imjp94.yafsm/README.md)

## Feature

- Designer-friendly
Expand All @@ -18,6 +32,8 @@ Designer-friendly Finite State Machine implemented in "Godotic" way
> Visualize game/UI state from flowchart
- Zero learning curve
> Similar workflow as using `AnimationTree`, and not required to inherit any custom class, just plug and play
- Nested FSM
> Nested Finite State Machine workflow supported to create complex state machine with ease
- Reusability
> As a `Resource`, `StateMachine` can be used repeatedly in different scenarios(`StateMachinePlayer`) and provide different outcome based on the input.
- Minimal
Expand All @@ -27,13 +43,13 @@ For more detail, see [CHANGELOG.md](CHANGELOG.md)

## Installation

- Install directly from Godot Asset Library
1. Install directly from Godot Asset Library

or

- Download this respository,
1. Move `addons/imjp94.yafsm` to your `{project_dir}`
2. Enable it from Project -> Settings -> Plugins
1. Download this respository, move `addons/imjp94.yafsm` to your `{project_dir}`

2. Enable it from Project -> Settings -> Plugins

## Getting Started

Expand All @@ -47,7 +63,7 @@ or

3. Click on "Create StateMachine" button to get started.

Finally, right-click on graph to add state node.
Finally, `Right-Click` on graph to add state node and `Shift + Drag` on node to start connect(`Shift + Drag` again on line to reconnect)

Special states:

Expand All @@ -64,20 +80,99 @@ After setup `StateMachine` with editor, you can connect to the following signals
![Signal Example](screenshots/yafsm_state_machine_player_signal_example.png)
*Example code snippet of KinematicBody connect "updated" signal*

And control `StateMachinePlayer` by accessing parameter:

```gdscript
var smp = get_node(StateMachinePlayer)
smp.set_trigger("jump")
smp.set_param("jump_count", 1)
smp.get_param("on_floor", false)
smp.has_param("velocity")
```

That's it!

For most of the case, you don't have to inherit from any custom class by this plugin, simply just connect signals to your existing node and you're good to go.

> See documentation below for more details
## Nested FSM

The only different between nested/normal FSM is how state/parameters are accessed.

### State

- normal state - "State"
- nested state - "BaseState/AnotherState/EndState"

```gdscript
var normal_state = "Idle"
var nested_state = "App/Game/Play" # EndState can be Entry/Exit
```

`StateDirectory` class is provided to traverse state path like file directory:

```gdscript
const StateDirectory = preload("addons/imjp94.yafsm/src/StateDirectory.gd)
# Handle "transited" signal
func _on_normal_state_transited(from, to):
match to:
"Entry":
print("Enter")
"Game":
print("Game")
"Exit":
print("Exit)
# Handle "transited" signal
func _on_nested_state_transited(from, to):
var to_dir = StateDirectory.new(to)
match to_dir.next(): # Initial next() required to move to base state
"Entry":
print("Enter")
"Game":
match to_dir.next(): # It can be called recursively, until return null
"Entry":
print("Game Enter") # Game/Entry
"Exit":
print("Exit)
```

### Parameter

Behind the scene, `StateMachinePlayer` always differentiate parameters into 2 types: global & local

- global parameter
- Just a normal parameter - "param_name"
- Never erased automatically, unless `erase_param`/`clear_param` called by user
- local parameter
- Parameter that local to nested state - "BaseState/TargetState/param_name"
- Erased upon Exit, for example, "App/Game/Exit" will cause all local parameter("App/Game/{param_name}") to be erased

```gdscript
var smp = get_node(StateMachinePlayer)
var global_param = smp.get_param("state")
var local_param = smp.get_param("App/Game/playing")
```

Besides of controlling `StateMachinePlayer`, it's useful to set arbitrary value with `set_param`

```gdscript
var smp = get_node(StateMachinePlayer)
smp.set_param("game", preload("game.scn"))
var game_scn = smp.get_param("game")
```

### Debug

- Stack
> Add `res://addons/imjp94.yafsm/src/debugger/StackPlayerDebugger.tscn` to `StackPlayer`(so as `StateMachinePlayer`) to visualize the stack on screen.
## Demo

Check out [gd-YAFSM-demo](https://github.com/imjp94/gd-yafsm-demo) for how you can integrate gd-YAFSM into you project.
Check out [gd-YAFSM-demo](https://github.com/imjp94/gd-yafsm-demo) for how you can integrate gd-YAFSM into you project and manage app state with `StateMachine`

## Documentation

Expand Down
12 changes: 9 additions & 3 deletions addons/imjp94.yafsm/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Classes

All of the classes are located in `res://addons/imjp94.yafsm/src` but you can just preload `res://addons/imjp94.yafsm/YAFSM.gd` to import all classes available:
All of the class are located in `res://addons/imjp94.yafsm/src` but you can just preload `res://addons/imjp94.yafsm/YAFSM.gd` to import all class available:

```gdscript
const YAFSM = preload("res://addons/imjp94.yafsm/YAFSM.gd")
Expand All @@ -29,15 +29,20 @@ const State = YAFSM.State
- `process_mode # ProcessMode of player`
- signals:
- `transited(from, to) # Transition of state`
- `entered() # Entry of state machine`
- `exited() # Exit of state machine`
- `entered(to) # Entry of state machine(including nested), empty string equals to root`
- `exited(from) # Exit of state machine(including nested, empty string equals to root`
- `updated(state, delta) # Time to update(based on process_mode), up to user to handle any logic, for example, update movement of KinematicBody`

### Control

- [StackPlayerDebugger](src/debugger/StackPlayerDebugger.gd)
> Visualize stack of parent StackPlayer on screen
### Reference

- [StateDirectory](src/StateDirectory.gd)
> Convert state path to directory object for traversal, mainly used for nested state
### Resource

Relationship between all `Resource`s can be best represented as below:
Expand Down Expand Up @@ -73,3 +78,4 @@ var condition = transition.conditions[condition_name] # keyed by condition name
- [BooleanCondition](src/conditions/BooleanCondition.gd)(`extends ValueCondition`)
- [IntegerCondition](src/conditions/IntegerCondition.gd)(`extends ValueCondition`)
- [FloatCondition](src/conditions/FloatCondition.gd)(`extends ValueCondition`)
- [StringCondition](src/conditions/StringCondition.gd)(`extends ValueCondition`)
Binary file modified screenshots/yafsm_editor_showcase.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 6bec509

Please sign in to comment.