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()