What is a Character
Characters in your game are dynamic entities capable of moving and performing various actions within a level. By using a StateMachine node, you can configure and manage different states to control their behavior seamlessly.
State scripts interact with functions defined in the CharacterEntity
class (or any script that extends from it).
The pre-built system allows your characters to:
- Move
- Run
- Jump
- Attack
- Flash (for example, when receiving damage)
- Interact with other game elements and entities
These capabilities can be further expanded by adding new functions to the character’s script and customizing the states defined in the character’s StateMachine.
Additionally, you can integrate a HealthController node to manage a character’s health points, making it easy to handle damage, healing, or showing a custom health bar.
Pre-built Characters
The template includes two pre-built characters: a player (player.tscn
) and an enemy (enemy.tscn
).
Both characters share the same base script, character_entity.gd
. The difference lies in their implementation:
- The player extends the
CharacterEntity
class through theplayer_entity.gd
script. - The enemy uses the
character_entity.gd
script directly.
You’re free to create a custom enemy_entity.gd
script that extends from CharacterEntity
to add specific functionality for enemies that are not present in the base class.
Player
What makes the player character unique is the ability to respond to user inputs.
This functionality is managed by a specialized state called StateInputListener
.
By adding this state to any character, you can make it responsive to inputs, not just the player.
The actions that StateInputListener
listens for are defined in Project Settings > Input Map.
You can customize the controls to fit your needs.
Furthermore, the player character includes:
- a
StateMachine
node with pre-built states to handle movement, attack, hurt, fall, and death. - a
InteractionTrigger
node to detect interactions with other game elements. - a
SmokeParticles
node for visual effects when the character runs. - an
Inventory
node for managing items. - a
HealthController
node to manage health points.
Enemy
The enemy character is a simplified version of the player character.
It includes a StateMachine
node to handle death.
The enemy character also includes a HealthController
node to manage health points.
Create a New Character
To create new characters, simply create a new scene inheriting from the entity.tscn
scene.
![Inheriting from the entity.tscn scene](/_astro/new-inherited-scene.RWdTKttC_Z2kta4W.webp)
This scene serves as the foundation for all characters, including the pre-built
ones in the template. Features of the entity.tscn
scene include:
- Pre-Built animations: idle, walk, run, jump, and attack animations managed by an
AnimationPlayer
node and anAnimationTree
. - Dynamic shadow: a
Shadow
node that adjusts its size dynamically based on the character’s height (e.g., when the character jumps). - Flash shader: a shader applied to the AnimatedSprite2D node that creates a flash effect, useful for visual feedback (e.g., when the character takes damage).
- Collision detection:
- the
BlocksDetector
node detects collisions with walls and obstacles. - the
FallDetector
node identifies when the character has jumped into a non-walkable area.
- the
- Combat features:
- the
HitBox
node detects collisions with enemies. - the
HurtBox
node detects collisions with enemy hitboxes.
- the
For more specialized characters, you can also inherit from the player.tscn
or enemy.tscn
scenes.
Character Actions
The CharacterEntity
class includes several functions that you can call to perform actions on the character.
Move
The move()
function moves the character in a given direction.
This function is used by the StateInputListener
state to move the player character based on user inputs and also by other states to move the character in a specific direction.
When the character moves, the facing
property is updated to reflect the direction of movement and the is_moving
property is set to true
.
Run
To make the character run, you just need to pass a value higher than 1 to the property speed_multiplier
.
This value is used to multiply the character’s speed when moving.
In the StateInputListener
state the speed_multiplier
property is updated to make the character run when the run
action is pressed.
When the character runs, the is_running
property is set to true
and the running_particles
, if present, are activated.
Jump
The jump()
function makes the character jump.
In the StateInputListener
state the jump()
function is called when the jump
action is pressed.
In the jump()
function, the is_jumping
property is set to true
and other properties are updated to manage the jump.
At the end of the jump, you have to call the end_jump()
function to reset the character’s properties. Ideally this function should be called when the character lands on the ground.
In a CharacterEntity
this is handled by the jump
animation of the AnimationPlayer
.
Attack
The attack()
function makes the character attack.
In the StateInputListener
state the attack()
function is called when the attack
action is pressed.
In the PlayerEntity
, the value of the is_attacking
is handled by the attack
state of the StateMachine
with a StateParamsSetter
state.
At the end of the attack, you have to call the end_attack()
function to reset the character’s properties. Ideally this function should be called when the attack animation ends.
In a CharacterEntity
this is handled by the char-attack/
animations of the AnimationPlayer
.
Flash
The flash()
function makes the character sprites flash.
To make the sprites flash:
- The sprites must have a shader material with the
flash.gdshader
shader. - The sprites must be in the
flash
group.
Interact
To enable interactions, a character requires the following:
- An
Area2D
node with themonitorable
property set totrue
. - The
collision_layer
property of theArea2D
must match thecollision_mask
property of anInteractionArea
defined within aStateInteract
state.
Check the Interaction System for more details.
Health Controller
The HealthController is a versatile node that can be added to any character or entity (or node) to manage its health points (HP).
It keeps track of the current HP value and provides a simple way to handle health-related events.
If you want to display a visual representation of the entity’s health, you can assign a scene to the health_bar
property, which will automatically update based on the current HP.
The behavior of the Health Controller can be customized using states from the StateMachine . You can define what happens when HP increases, decreases, or reaches zero. This makes it easy to trigger effects such as damage animations, healing effects, or death sequences.
By default, both the player.tscn
and enemy.tscn
scenes include a HealthController node, allowing you to easily manage their health status.
If needed, you can extend this system by adding a Health Controller to other entities and customizing how they react to HP changes.
Health Bars
A Health Bar provides a visual representation of an entity’s health, making it easier for players to track damage and healing.
To display a health bar for any character or entity, assign a scene to the health_bar
property of the HealthController.
This allows the health bar to automatically update whenever HP changes.
For an example of how to set up a health bar, check the pre-built player_hud.tscn
scene.
This scene demonstrates how to properly configure a health bar to follow an entity and visually represent its health status.
You can use it as a reference to create custom health bars for enemies, NPCs, or other game elements.