Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions animation/animation_states/all.texture_profiles
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
path_settings {
path: "**"
profile: "Default"
}
profiles {
name: "Default"
platforms {
os: OS_ID_GENERIC
formats {
format: TEXTURE_FORMAT_RGBA
compression_level: BEST
compression_type: COMPRESSION_TYPE_DEFAULT
}
mipmaps: false
max_texture_size: 0
premultiply_alpha: true
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
20 changes: 20 additions & 0 deletions animation/animation_states/assets/example.input_binding
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
key_trigger {
input: KEY_SPACE
action: "jump"
}
key_trigger {
input: KEY_C
action: "crouch"
}
key_trigger {
input: KEY_X
action: "attack"
}
key_trigger {
input: KEY_RIGHT
action: "right"
}
key_trigger {
input: KEY_LEFT
action: "left"
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added animation/animation_states/assets/images/Crouch1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added animation/animation_states/assets/images/Crouch2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added animation/animation_states/assets/images/Crouch3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added animation/animation_states/assets/images/Idle2.png
Binary file added animation/animation_states/assets/images/Run1.png
Binary file added animation/animation_states/assets/images/Run2.png
Binary file added animation/animation_states/assets/images/Run3.png
Binary file added animation/animation_states/assets/images/Run4.png
Binary file added animation/animation_states/assets/images/Run5.png
Binary file added animation/animation_states/assets/images/Run6.png
Binary file added animation/animation_states/assets/images/Run7.png
Binary file added animation/animation_states/assets/images/Run8.png
Binary file added animation/animation_states/assets/images/Run9.png
197 changes: 197 additions & 0 deletions animation/animation_states/assets/knight.atlas
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
animations {
id: "idle"
images {
image: "/assets/images/Idle1.png"
}
images {
image: "/assets/images/Idle10.png"
}
images {
image: "/assets/images/Idle2.png"
}
images {
image: "/assets/images/Idle3.png"
}
images {
image: "/assets/images/Idle4.png"
}
images {
image: "/assets/images/Idle5.png"
}
images {
image: "/assets/images/Idle6.png"
}
images {
image: "/assets/images/Idle7.png"
}
images {
image: "/assets/images/Idle8.png"
}
images {
image: "/assets/images/Idle9.png"
}
playback: PLAYBACK_LOOP_FORWARD
fps: 15
}
animations {
id: "run"
images {
image: "/assets/images/Run1.png"
}
images {
image: "/assets/images/Run2.png"
}
images {
image: "/assets/images/Run3.png"
}
images {
image: "/assets/images/Run4.png"
}
images {
image: "/assets/images/Run5.png"
}
images {
image: "/assets/images/Run6.png"
}
images {
image: "/assets/images/Run7.png"
}
images {
image: "/assets/images/Run8.png"
}
images {
image: "/assets/images/Run9.png"
}
images {
image: "/assets/images/Run10.png"
}
playback: PLAYBACK_LOOP_FORWARD
fps: 15
}
animations {
id: "turn_around"
images {
image: "/assets/images/TurnAround1.png"
}
images {
image: "/assets/images/TurnAround2.png"
}
images {
image: "/assets/images/TurnAround3.png"
}
fps: 15
}
animations {
id: "jump"
images {
image: "/assets/images/Jump1.png"
}
images {
image: "/assets/images/Jump2.png"
}
images {
image: "/assets/images/Jump3.png"
}
images {
image: "/assets/images/JumpToFall1.png"
}
images {
image: "/assets/images/JumpToFall2.png"
}
images {
image: "/assets/images/Fall1.png"
}
images {
image: "/assets/images/Fall2.png"
}
images {
image: "/assets/images/Fall3.png"
}
fps: 15
}
animations {
id: "attack"
images {
image: "/assets/images/AttackRight1.png"
}
images {
image: "/assets/images/AttackRight2.png"
}
images {
image: "/assets/images/AttackRight3.png"
}
images {
image: "/assets/images/AttackRight4.png"
}
fps: 15
}
animations {
id: "to_crouch"
images {
image: "/assets/images/Crouch1.png"
}
playback: PLAYBACK_ONCE_FORWARD
fps: 15
}
animations {
id: "crouch_attack"
images {
image: "/assets/images/CrouchAttack1.png"
}
images {
image: "/assets/images/CrouchAttack2.png"
}
images {
image: "/assets/images/CrouchAttack3.png"
}
images {
image: "/assets/images/CrouchAttack4.png"
}
fps: 15
}
animations {
id: "crouch_walk"
images {
image: "/assets/images/CrouchWalk1.png"
}
images {
image: "/assets/images/CrouchWalk2.png"
}
images {
image: "/assets/images/CrouchWalk3.png"
}
images {
image: "/assets/images/CrouchWalk4.png"
}
images {
image: "/assets/images/CrouchWalk5.png"
}
images {
image: "/assets/images/CrouchWalk6.png"
}
images {
image: "/assets/images/CrouchWalk7.png"
}
images {
image: "/assets/images/CrouchWalk8.png"
}
playback: PLAYBACK_LOOP_FORWARD
fps: 15
}
animations {
id: "crouch_idle"
images {
image: "/assets/images/Crouch2.png"
}
playback: PLAYBACK_LOOP_FORWARD
fps: 15
}
animations {
id: "from_crouch"
images {
image: "/assets/images/Crouch3.png"
}
playback: PLAYBACK_ONCE_FORWARD
fps: 15
}
extrude_borders: 2
4 changes: 4 additions & 0 deletions animation/animation_states/assets/text32.font
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
font: "/assets/SourceSansPro-Semibold.ttf"
material: "/builtins/fonts/font.material"
size: 32
characters: " !\"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
Binary file added animation/animation_states/atlas.png
102 changes: 102 additions & 0 deletions animation/animation_states/example.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
---
tags: animation, state_machine, input
title: Animation State Machine
brief: This example demonstrates how to create a character animation system using a Finite State Machine (FSM) with smooth transitions between different character states.
author: The Defold Foundation
scripts: knight.script
thumbnail: thumbnail.png
---

# A simple Finite State Machine for animations.

This example shows how to create a responsive character animation system using a **Finite State Machine (FSM)**. The character can smoothly transition between different states like idle, running, jumping, attacking, and crouching based on player input. This is a fundamental technique used in most 2D platformers and action games.

## What You'll Learn?

- How to implement a state machine for character animations
- How to handle complex input combinations and priorities## Key Concepts

**State Machine**: A design pattern where an object can be in only one state at a time, with clear rules for transitioning between states.

**Input Priority**: A system that determines which actions take precedence when multiple keys are pressed simultaneously.

**Animation Transitions**: Smooth changes between different animations, often with intermediate "transition" animations.## Key Concepts

**State Machine**: A design pattern where an object can be in only one state at a time, with clear rules for transitioning between states.

**Input Priority**: A system that determines which actions take precedence when multiple keys are pressed simultaneously.

**Animation Transitions**: Smooth changes between different animations, often with intermediate "transition" animations.
- How to create smooth transitions between animation states
- How to make sprites flip direction based on movement
- How to add visual effects (like jump animations)
- How to communicate between game objects using messages

## Setup

The example consists of two main game objects:

knight
: The animated character. Contains:
- A *Sprite* component with the knight character image and animations.
- A *Script* component (`knight.script`) that implements the state machine logic, handles input, and manages animation transitions.

gui
: The user interface. Contains:
- A *GUI* component (`control.gui`) that has 6 nodes displaying states and text description for the example.
- A *GUI Script* component (`control.gui_script`) that receives messages from the knight and updates the visual state indicators.

> **Note:**
> The GUI in this example is not required for understanding the state machine logic, it only visually shows the active animation state. You can view the GUI source in the project files on Github still though.

![animation_states_collection](animation_states_collection.png)

## Animation Atlas

The sprite component uses a flipbook animation that is set up in an atlas:

> For this example we used the Free Knight Character by Nauris 'aamatniekss' available here: https://aamatniekss.itch.io/fantasy-knight-free-pixelart-animated-character

![atlas](atlas.png)

The atlas contains multiple animations for different character states:
- **idle**: Standing still animation
- **run**: Running animation (looped)
- **jump**: Jumping animation (plays once)
- **attack**: Attacking animation (plays once)
- **turn_around**: Turning animation (plays once)
- **crouch_idle**: Crouching idle anim **Note:** ation
- **crouch_walk**: Crouch walking animation
- **crouch_attack**: Crouch attacking animation
- **to_crouch**: Transition from standing to crouching
- **from_crouch**: Transition from crouching to standing

## Input Bindings

| Key | Action |
|-----------------|--------------------------------|
| **Left Arrow / Right Arrow** | Move left/right |
| **Space** | Jump |
| **X** | Attack |
| **C** | Crouch (hold to stay crouched) |

![input_bindings](input_bindings.png)


## How It Works?

The character uses a **finite state machine** - a programming pattern where the character can only be in one "state" at a time. Each state can define certain things like:
- Which animation to play
- Whether the animation loops or plays once
- What happens when different keys are pressed
- What state to go to when the animation finishes

The system processes input with **priorities**: Attack > Jump > Movement > Crouch/Stand > Turning. This ensures that important actions (like attacking) can interrupt less important ones (like walking).

## Key Concepts

**State Machine**: A design pattern where an object can be in only one state at a time, with clear rules for transitioning between states.

**Input Priority**: A system that determines which actions take precedence when multiple keys are pressed simultaneously.

**Animation Transitions**: Smooth changes between different animations, often with intermediate "transition" animations.
37 changes: 37 additions & 0 deletions animation/animation_states/example/animation_states.collection
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: "default"
scale_along_z: 0
embedded_instances {
id: "knight"
data: "components {\n"
" id: \"knight\"\n"
" component: \"/example/knight.script\"\n"
"}\n"
"embedded_components {\n"
" id: \"sprite\"\n"
" type: \"sprite\"\n"
" data: \"default_animation: \\\"idle\\\"\\n"
"material: \\\"/builtins/materials/sprite.material\\\"\\n"
"textures {\\n"
" sampler: \\\"texture_sampler\\\"\\n"
" texture: \\\"/assets/knight.atlas\\\"\\n"
"}\\n"
"\"\n"
"}\n"
""
position {
x: 360.0
y: 600.0
}
scale3 {
x: 5.0
y: 5.0
}
}
embedded_instances {
id: "gui"
data: "components {\n"
" id: \"control\"\n"
" component: \"/example/control.gui\"\n"
"}\n"
""
}
Loading