Let’s Add Animation
In this chapter, we’ll build a mechanism that makes sprites look animated by switching images rapidly.
1. Add Ninja Images
Add the following images to the ninja folder inside the images directory.
| Image | File name | Image | File name | Image | File name |
|---|---|---|---|---|---|
| front_01.png | front_02.png | front_03.png | |||
| front_04.png | front_05.png |
The folder structure should look like this:
# Folder structure
working_folder/
├ main.py
├ sprite.py
└ images/
├ bg_temple.png
└ ninja/ # Folder for ninja images
├ front_01.png
├ front_02.png
├ front_03.png
├ front_04.png
└ front_05.png
2. Add Coin Images
Just like before, add the following images to the coin folder inside the images directory.
| Image | File name | Image | File name | Image | File name |
|---|---|---|---|---|---|
| coin_01.png | coin_02.png | coin_03.png | |||
| coin_04.png | coin_05.png |
The folder structure should look like this:
# Folder structure
working_folder/
├ main.py
├ sprite.py
└ images/
├ bg_temple.png
├ ninja/
└ coin/ # Folder for coin images
├ coin_01.png
├ coin_02.png
├ coin_03.png
├ coin_04.png
└ coin_05.png
3. Load Ninja Images
Next, in the constructor of the Player class in sprite.py,
load five ninja images into the anim list.
# sprite.py (added to Player)
def __init__(self, filename, x, y):
super().__init__(filename, x, y)
# Load 5 ninja images
self.anim.append(arcade.load_texture("images/ninja/front_01.png"))
self.anim.append(arcade.load_texture("images/ninja/front_02.png"))
self.anim.append(arcade.load_texture("images/ninja/front_03.png"))
self.anim.append(arcade.load_texture("images/ninja/front_04.png"))
self.anim.append(arcade.load_texture("images/ninja/front_05.png"))
4. Load Coin Images
Similarly, in the constructor of the Coin class in sprite.py,
load five coin images into the anim list.
# sprite.py (added to Coin)
def __init__(self, filename, x, y):
super().__init__(filename, x, y)
# Load 5 coin images
self.anim.append(arcade.load_texture("images/coin/coin_01.png"))
self.anim.append(arcade.load_texture("images/coin/coin_02.png"))
self.anim.append(arcade.load_texture("images/coin/coin_03.png"))
self.anim.append(arcade.load_texture("images/coin/coin_04.png"))
self.anim.append(arcade.load_texture("images/coin/coin_05.png"))
5. Add Variables to the Base Class
In the base class BaseSprite in sprite.py,
add four new variables.
These variables will be used by the update_animation() method,
which we’ll implement next.
# sprite.py (added to BaseSprite)
def __init__(self, filename, x, y):
super().__init__(filename)
# Position
self.center_x = x
self.center_y = y
# Velocity
self.vx = 0
self.vy = 0
# Animation
self.anim_counter = 0 # counter
self.anim_interval = 4 # count every 4 frames
self.anim_index = 0 # frame index
self.anim = [] # list of textures
6. Add an Animation Method
In the same BaseSprite class, add a new method called update_animation().
# sprite.py (added to BaseSprite)
def update_animation(self):
""" Animation """
if not self.anim:
return
self.anim_counter += 1 # increment counter
if self.anim_counter < self.anim_interval:
return # switch every 4 frames
self.anim_counter = 0 # reset counter
self.anim_index += 1 # next frame
if len(self.anim) <= self.anim_index:
self.anim_index = 0 # loop back to start
self.texture = self.anim[self.anim_index] # set texture
This code switches the images stored in anim
one by one every 4 frames.
If you decrease this value, the animation becomes faster.
If you increase it, the animation becomes slower.
(Definitely try tweaking it!)
7. Call It from the Update Method
Finally, call update_animation() from inside the update() method.
# sprite.py (added to BaseSprite)
def update(self, delta_time):
""" Update """
self.center_x += self.vx * delta_time
self.center_y += self.vy * delta_time
# Animation
self.update_animation()
Complete Code
Below is the complete code with all features implemented so far.
You can copy and run it as-is.
# sprite.py (complete code)
import arcade
import math
class BaseSprite(arcade.Sprite):
def __init__(self, filename, x, y):
super().__init__(filename)
# Position
self.center_x = x
self.center_y = y
# Velocity
self.vx = 0
self.vy = 0
# Animation
self.anim_counter = 0 # counter
self.anim_interval = 4 # count every 4 frames
self.anim_index = 0 # frame index
self.anim = [] # list of textures
def update(self, delta_time):
""" Update """
self.center_x += self.vx * delta_time
self.center_y += self.vy * delta_time
# Animation
self.update_animation()
def move(self, spd, deg):
""" Move Sprite """
rad = deg * math.pi / 180
self.vx = spd * math.cos(rad)
self.vy = spd * math.sin(rad)
def stop(self):
""" Stop Sprite """
self.vx = 0
self.vy = 0
def update_animation(self):
""" Animation """
if not self.anim:
return
self.anim_counter += 1
if self.anim_counter < self.anim_interval:
return
self.anim_counter = 0
self.anim_index += 1
if len(self.anim) <= self.anim_index:
self.anim_index = 0
self.texture = self.anim[self.anim_index]
class Player(BaseSprite):
def __init__(self, filename, x, y):
super().__init__(filename, x, y)
# Load 5 ninja images
self.anim.append(arcade.load_texture("images/ninja/front_01.png"))
self.anim.append(arcade.load_texture("images/ninja/front_02.png"))
self.anim.append(arcade.load_texture("images/ninja/front_03.png"))
self.anim.append(arcade.load_texture("images/ninja/front_04.png"))
self.anim.append(arcade.load_texture("images/ninja/front_05.png"))
class Coin(BaseSprite):
def __init__(self, filename, x, y):
super().__init__(filename, x, y)
# Load 5 coin images
self.anim.append(arcade.load_texture("images/coin/coin_01.png"))
self.anim.append(arcade.load_texture("images/coin/coin_02.png"))
self.anim.append(arcade.load_texture("images/coin/coin_03.png"))
self.anim.append(arcade.load_texture("images/coin/coin_04.png"))
self.anim.append(arcade.load_texture("images/coin/coin_05.png"))
# main.py (complete code)
import arcade
import sprite
import random
class GameView(arcade.View):
def __init__(self, window):
super().__init__()
self.window = window
self.w = self.window.width
self.h = self.window.height
# Background color
self.background_color = arcade.color.PAYNE_GREY
# Background sprites
self.backgrounds = arcade.SpriteList()
bkg = arcade.Sprite("images/bg_temple.png")
bkg.center_x = self.w / 2
bkg.center_y = self.h / 2
self.backgrounds.append(bkg)
# Player sprites
self.players = arcade.SpriteList()
self.player = sprite.Player(
"images/ninja/front_01.png",
x=self.w / 2,
y=self.h / 2
)
self.players.append(self.player)
# Coin sprites
self.coins = arcade.SpriteList()
for i in range(10):
x = random.random() * self.w
y = random.random() * self.h
coin = sprite.Coin(
"images/coin/coin_01.png",
x=x,
y=y
)
self.coins.append(coin)
def on_key_press(self, key, key_modifiers):
# Move (WASD)
if key == arcade.key.W: self.player.move(90, 90)
if key == arcade.key.A: self.player.move(90, 180)
if key == arcade.key.S: self.player.move(90, 270)
if key == arcade.key.D: self.player.move(90, 0)
def on_key_release(self, key, key_modifiers):
self.player.stop()
def on_update(self, delta_time):
self.players.update(delta_time)
self.coins.update(delta_time)
# Player x coin list
hit_coins = arcade.check_for_collision_with_list(
self.player,
self.coins
)
for coin in hit_coins:
coin.remove_from_sprite_lists()
def on_draw(self):
self.clear() # Clear
self.backgrounds.draw()
self.players.draw()
self.coins.draw()
def main():
""" main process """
window = arcade.Window(480, 320, "Hello, Arcade!!")
game = GameView(window)
window.show_view(game)
arcade.run()
if __name__ == "__main__":
main()
When you run the program, it will look like this:
Coming Up Next...
Thank you for reading.
The next chapter is titled “Let’s Display the Score.”
Stay tuned 👍

Top comments (0)