Move with a Sprite Animation

GIF animation of animated walking character.
sprite_move_animation.py
  1"""
  2Move with a Sprite Animation
  3
  4Simple program to show basic sprite usage.
  5
  6Artwork from http://kenney.nl
  7
  8If Python and Arcade are installed, this example can be run from the command line with:
  9python -m arcade.examples.sprite_move_animation
 10"""
 11import arcade
 12import random
 13
 14SCREEN_WIDTH = 800
 15SCREEN_HEIGHT = 600
 16SCREEN_TITLE = "Move with a Sprite Animation Example"
 17
 18COIN_SCALE = 0.5
 19COIN_COUNT = 50
 20CHARACTER_SCALING = 1
 21
 22# How fast to move, and how fast to run the animation
 23MOVEMENT_SPEED = 5
 24UPDATES_PER_FRAME = 5
 25
 26# Constants used to track if the player is facing left or right
 27RIGHT_FACING = 0
 28LEFT_FACING = 1
 29
 30
 31def load_texture_pair(filename):
 32    """
 33    Load a texture pair, with the second being a mirror image.
 34    """
 35    return [
 36        arcade.load_texture(filename),
 37        arcade.load_texture(filename, flipped_horizontally=True)
 38    ]
 39
 40
 41class PlayerCharacter(arcade.Sprite):
 42    def __init__(self):
 43
 44        # Set up parent class
 45        super().__init__()
 46
 47        # Default to face-right
 48        self.character_face_direction = RIGHT_FACING
 49
 50        # Used for flipping between image sequences
 51        self.cur_texture = 0
 52
 53        self.scale = CHARACTER_SCALING
 54
 55        # Adjust the collision box. Default includes too much empty space
 56        # side-to-side. Box is centered at sprite center, (0, 0)
 57        self.points = [[-22, -64], [22, -64], [22, 28], [-22, 28]]
 58
 59        # --- Load Textures ---
 60
 61        # Images from Kenney.nl's Asset Pack 3
 62        main_path = ":resources:images/animated_characters/female_adventurer/femaleAdventurer"
 63        # main_path = ":resources:images/animated_characters/female_person/femalePerson"
 64        # main_path = ":resources:images/animated_characters/male_person/malePerson"
 65        # main_path = ":resources:images/animated_characters/male_adventurer/maleAdventurer"
 66        # main_path = ":resources:images/animated_characters/zombie/zombie"
 67        # main_path = ":resources:images/animated_characters/robot/robot"
 68
 69        # Load textures for idle standing
 70        self.idle_texture_pair = load_texture_pair(f"{main_path}_idle.png")
 71
 72        # Load textures for walking
 73        self.walk_textures = []
 74        for i in range(8):
 75            texture = load_texture_pair(f"{main_path}_walk{i}.png")
 76            self.walk_textures.append(texture)
 77
 78    def update_animation(self, delta_time: float = 1/60):
 79
 80        # Figure out if we need to flip face left or right
 81        if self.change_x < 0 and self.character_face_direction == RIGHT_FACING:
 82            self.character_face_direction = LEFT_FACING
 83        elif self.change_x > 0 and self.character_face_direction == LEFT_FACING:
 84            self.character_face_direction = RIGHT_FACING
 85
 86        # Idle animation
 87        if self.change_x == 0 and self.change_y == 0:
 88            self.texture = self.idle_texture_pair[self.character_face_direction]
 89            return
 90
 91        # Walking animation
 92        self.cur_texture += 1
 93        if self.cur_texture > 7 * UPDATES_PER_FRAME:
 94            self.cur_texture = 0
 95        frame = self.cur_texture // UPDATES_PER_FRAME
 96        direction = self.character_face_direction
 97        self.texture = self.walk_textures[frame][direction]
 98
 99
100class MyGame(arcade.Window):
101    """ Main application class. """
102
103    def __init__(self, width, height, title):
104        """ Set up the game and initialize the variables. """
105        super().__init__(width, height, title)
106
107        # Sprite lists
108        self.player_list = None
109        self.coin_list = None
110
111        # Set up the player
112        self.score = 0
113        self.player = None
114
115    def setup(self):
116        self.player_list = arcade.SpriteList()
117        self.coin_list = arcade.SpriteList()
118
119        # Set up the player
120        self.score = 0
121        self.player = PlayerCharacter()
122
123        self.player.center_x = SCREEN_WIDTH // 2
124        self.player.center_y = SCREEN_HEIGHT // 2
125        self.player.scale = 0.8
126
127        self.player_list.append(self.player)
128
129        for i in range(COIN_COUNT):
130            coin = arcade.Sprite(":resources:images/items/gold_1.png",
131                                 scale=0.5)
132            coin.center_x = random.randrange(SCREEN_WIDTH)
133            coin.center_y = random.randrange(SCREEN_HEIGHT)
134
135            self.coin_list.append(coin)
136
137        # Set the background color
138        arcade.set_background_color(arcade.color.AMAZON)
139
140    def on_draw(self):
141        """
142        Render the screen.
143        """
144
145        # This command has to happen before we start drawing
146        arcade.start_render()
147
148        # Draw all the sprites.
149        self.coin_list.draw()
150        self.player_list.draw()
151
152        # Put the text on the screen.
153        output = f"Score: {self.score}"
154        arcade.draw_text(output, 10, 20, arcade.color.WHITE, 14)
155
156    def on_key_press(self, key, modifiers):
157        """
158        Called whenever a key is pressed.
159        """
160        if key == arcade.key.UP:
161            self.player.change_y = MOVEMENT_SPEED
162        elif key == arcade.key.DOWN:
163            self.player.change_y = -MOVEMENT_SPEED
164        elif key == arcade.key.LEFT:
165            self.player.change_x = -MOVEMENT_SPEED
166        elif key == arcade.key.RIGHT:
167            self.player.change_x = MOVEMENT_SPEED
168
169    def on_key_release(self, key, modifiers):
170        """
171        Called when the user releases a key.
172        """
173        if key == arcade.key.UP or key == arcade.key.DOWN:
174            self.player.change_y = 0
175        elif key == arcade.key.LEFT or key == arcade.key.RIGHT:
176            self.player.change_x = 0
177
178    def on_update(self, delta_time):
179        """ Movement and game logic """
180
181        # Move the player
182        self.player_list.update()
183
184        # Update the players animation
185        self.player_list.update_animation()
186
187        # Generate a list of all sprites that collided with the player.
188        hit_list = arcade.check_for_collision_with_list(self.player, self.coin_list)
189
190        # Loop through each colliding sprite, remove it, and add to the score.
191        for coin in hit_list:
192            coin.remove_from_sprite_lists()
193            self.score += 1
194
195
196def main():
197    """ Main method """
198    window = MyGame(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
199    window.setup()
200    arcade.run()
201
202
203if __name__ == "__main__":
204    main()