In this part, we’ll add code to change the character’s sprite depending on the player’s input direction.
We’ll use a dictionary lookup to achieve this. This will show you a creative way to use dictionaries.
The character’s
node uses a multi-frame texture. We call that a sprite sheet: a texture that packs multiple sprites into one image.Each sprite fits in a grid, cutting the texture into equal chunks. This sprite sheet has two rows and three columns.
If you set up your node’s Hframes and Vframes correctly, as we did earlier, only one sprite will show up at a time.
You can control the displayed sprite by changing the Animation -> Frame property in the Inspector.
Please notice how frame 0
is the character looking down,
1
is looking down and right, and so on. We’ll use these
values in our code.
Every property you see in the Inspector has a code equivalent. You can see it bold and underlined if you hover over the property name with the mouse.
For example, writing frame = 0
in GDScript will make the
character sprite look down.
Before moving on to code, please note the Offset -> Flip H and Offset -> Flip V properties.
Turning the properties on flips the image horizontally and vertically.
Our texture has five sprites: one looking down, one looking up, and three looking to the right.
We will use the Flip H property from the code to mirror the sprite horizontally when the character moves left.
We can hover over the property name in the Inspector again to learn how to access it in code.
Let’s head back to the script.
As mentioned in the intro, we’ll use a dictionary lookup. We start by defining a
that maps a value to a frame number.const DIRECTION_TO_FRAME := {
0,
Vector2.DOWN: + Vector2.RIGHT: 1,
Vector2.DOWN 2,
Vector2.RIGHT: + Vector2.RIGHT: 3,
Vector2.UP 4,
Vector2.UP: }
We use Godot’s predefined Vector2.DOWN
is equal to
Vector2(0, 1)
.
For diagonal directions, we add two vectors. For example, to
represent the southeast direction, we add Vector2.DOWN
and
Vector2.RIGHT
. This produces a value equal to
Vector2(1, 1)
.
We map that to frame number 1
, which is the character
going southeast.
Please note how the X and Y components of our 0
or
1
. We need numbers we can reproduce reliably in our code to
provide our with a valid key.
In the _physics_process()
function, we make calculations
to turn our direction
vector into a key in
DIRECTION_TO_FRAME
.
We first call Vector2.round()
to get a vector with the X
and Y components rounded to 0
or 1
.
We also use the abs()
function to ensure that
direction_to_frame_key
has a positive X component, as the
dictionary has no keys with negative X components.
func _physics_process(delta: float) -> void:
# ...
# The Vector2.round() function returns a new Vector2 with both the `x` and
# `y` rounded out.
var direction_key := direction.round()
# The abs() function makes negative numbers positive.
= abs(direction_key.x) direction_key.x
Then, we get the corresponding frame if the calculated key exists in
the DIRECTION_TO_FRAME
dictionary.
Also, we set the flip_h
property to
true
when the player goes to the left.
# We need to get the Sprite node to change its frame and flip it horizontally.
onready var sprite := $Godot
func _physics_process(delta: float) -> void:
# ...
if direction_key in DIRECTION_TO_FRAME:
= DIRECTION_TO_FRAME[direction_key]
sprite.frame # Notice how we directly assign the result of a comparison to flip_h.
# The computer converts comparisons to either true or false, which is
# compatible with boolean variables like flip_h.
= sign(direction.x) == -1 sprite.flip_h
The sign()
function returns -1
for negative
numbers, 0
for 0
, and 1
for
positive numbers.
If the input vector points even a bit to the left, the sprite will flip horizontally.
We now have a moving character whose textures align with its movement direction.
Note: the code above works for both keyboard and joystick input by default, but it will have a subtle bug if you lower the default joystick’s deadzone. By default, input actions will not trigger unless you push the joystick at least 50% towards its edges. That’s what we call the deadzone.
The default value works great with our code, but if you lower it in the input map, you’ll be able to move the character without changing the sprite’s texture when barely pushing the joystick.
In the next lesson, you’ll learn how to restrict the character’s movement to four directions.
Open the practice Changing sprite frames.
Open the practice Flipping sprites.
Open the practice Flipping when going left.
Open the practice Choose the right frame.
Here’s the complete code listing for
EightWayMovement.gd
.
extends KinematicBody2D
# Notice how we capitalize the constant's name. We do this to distinguish them
# from variable names.
const SPEED := 700.0
const DIRECTION_TO_FRAME := {
0,
Vector2.DOWN: + Vector2.RIGHT: 1,
Vector2.DOWN 2,
Vector2.RIGHT: + Vector2.RIGHT: 3,
Vector2.UP 4,
Vector2.UP:
}
# We need to get the Sprite node to change its frame and flip it horizontally.
onready var sprite := $Godot
func _physics_process(delta: float) -> void:
var direction := Input.get_vector("move_left", "move_right", "move_up", "move_down")
var velocity := direction * SPEED
move_and_slide(velocity)
# The Vector2.round() function returns a new Vector2 with both the `x` and
# `y` rounded out.
var direction_key := direction.round()
# The abs() function makes negative numbers positive.
= abs(direction_key.x)
direction_key.x if direction_key in DIRECTION_TO_FRAME:
= DIRECTION_TO_FRAME[direction_key]
sprite.frame # Notice how we directly assign the result of a comparison to flip_h.
# The computer converts comparisons to either true or false, which is
# compatible with boolean variables like flip_h.
= sign(direction.x) == -1 sprite.flip_h