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