1"""
2Show how to do enemies in a platformer
3
4Artwork from: https://kenney.nl
5Tiled available from: https://www.mapeditor.org/
6
7If Python and Arcade are installed, this example can be run from the command line with:
8python -m arcade.examples.sprite_enemies_in_platformer
9"""
10
11from __future__ import annotations
12
13import arcade
14
15SPRITE_SCALING = 0.5
16SPRITE_NATIVE_SIZE = 128
17SPRITE_SIZE = int(SPRITE_NATIVE_SIZE * SPRITE_SCALING)
18
19SCREEN_WIDTH = 800
20SCREEN_HEIGHT = 600
21SCREEN_TITLE = "Sprite Enemies in a Platformer Example"
22
23# How many pixels to keep as a minimum margin between the character
24# and the edge of the screen.
25VIEWPORT_MARGIN = 40
26RIGHT_MARGIN = 150
27
28# Physics
29MOVEMENT_SPEED = 5
30JUMP_SPEED = 14
31GRAVITY = 0.5
32
33
34class MyGame(arcade.Window):
35 """ Main application class. """
36
37 def __init__(self):
38 """
39 Initializer
40 """
41 super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
42
43 # Sprite lists
44 self.wall_list = None
45 self.enemy_list = None
46 self.player_list = None
47
48 # Set up the player
49 self.player_sprite = None
50 self.physics_engine = None
51 self.view_left = 0
52 self.view_bottom = 0
53 self.game_over = False
54
55 def setup(self):
56 """ Set up the game and initialize the variables. """
57
58 # Sprite lists
59 self.wall_list = arcade.SpriteList()
60 self.enemy_list = arcade.SpriteList()
61 self.player_list = arcade.SpriteList()
62
63 # Draw the walls on the bottom
64 for x in range(0, SCREEN_WIDTH, SPRITE_SIZE):
65 wall = arcade.Sprite(":resources:images/tiles/grassMid.png", scale=SPRITE_SCALING)
66
67 wall.bottom = 0
68 wall.left = x
69 self.wall_list.append(wall)
70
71 # Draw the platform
72 for x in range(SPRITE_SIZE * 3, SPRITE_SIZE * 8, SPRITE_SIZE):
73 wall = arcade.Sprite(":resources:images/tiles/grassMid.png", scale=SPRITE_SCALING)
74
75 wall.bottom = SPRITE_SIZE * 3
76 wall.left = x
77 self.wall_list.append(wall)
78
79 # Draw the crates
80 for x in range(0, SCREEN_WIDTH, SPRITE_SIZE * 5):
81 wall = arcade.Sprite(":resources:images/tiles/boxCrate_double.png", scale=SPRITE_SCALING)
82
83 wall.bottom = SPRITE_SIZE
84 wall.left = x
85 self.wall_list.append(wall)
86
87 # -- Draw an enemy on the ground
88 enemy = arcade.Sprite(":resources:images/enemies/wormGreen.png", scale=SPRITE_SCALING)
89
90 enemy.bottom = SPRITE_SIZE
91 enemy.left = SPRITE_SIZE * 2
92
93 # Set enemy initial speed
94 enemy.change_x = 2
95 self.enemy_list.append(enemy)
96
97 # -- Draw a enemy on the platform
98 enemy = arcade.Sprite(":resources:images/enemies/wormGreen.png", scale=SPRITE_SCALING)
99
100 enemy.bottom = SPRITE_SIZE * 4
101 enemy.left = SPRITE_SIZE * 4
102
103 # Set boundaries on the left/right the enemy can't cross
104 enemy.boundary_right = SPRITE_SIZE * 8
105 enemy.boundary_left = SPRITE_SIZE * 3
106 enemy.change_x = 2
107 self.enemy_list.append(enemy)
108
109 # -- Set up the player
110 self.player_sprite = arcade.Sprite(":resources:images/animated_characters/female_person/femalePerson_idle.png",
111 scale=SPRITE_SCALING)
112 self.player_list.append(self.player_sprite)
113
114 # Starting position of the player
115 self.player_sprite.center_x = 64
116 self.player_sprite.center_y = 270
117
118 self.physics_engine = arcade.PhysicsEnginePlatformer(self.player_sprite,
119 self.wall_list,
120 gravity_constant=GRAVITY)
121
122 # Set the background color
123 self.background_color = arcade.color.AMAZON
124
125 def on_draw(self):
126 """
127 Render the screen.
128 """
129
130 # This command has to happen before we start drawing
131 self.clear()
132
133 # Draw all the sprites.
134 self.player_list.draw()
135 self.wall_list.draw()
136 self.enemy_list.draw()
137
138 def on_key_press(self, key, modifiers):
139 """
140 Called whenever the mouse moves.
141 """
142 if key == arcade.key.UP:
143 if self.physics_engine.can_jump():
144 self.player_sprite.change_y = JUMP_SPEED
145 elif key == arcade.key.LEFT:
146 self.player_sprite.change_x = -MOVEMENT_SPEED
147 elif key == arcade.key.RIGHT:
148 self.player_sprite.change_x = MOVEMENT_SPEED
149
150 def on_key_release(self, key, modifiers):
151 """
152 Called when the user presses a mouse button.
153 """
154 if key == arcade.key.LEFT or key == arcade.key.RIGHT:
155 self.player_sprite.change_x = 0
156
157 def on_update(self, delta_time):
158 """ Movement and game logic """
159
160 # Update the player based on the physics engine
161 if not self.game_over:
162 # Move the enemies
163 self.enemy_list.update()
164
165 # Check each enemy
166 for enemy in self.enemy_list:
167 # If the enemy hit a wall, reverse
168 if len(arcade.check_for_collision_with_list(enemy, self.wall_list)) > 0:
169 enemy.change_x *= -1
170 # If the enemy hit the left boundary, reverse
171 elif enemy.boundary_left is not None and enemy.left < enemy.boundary_left:
172 enemy.change_x *= -1
173 # If the enemy hit the right boundary, reverse
174 elif enemy.boundary_right is not None and enemy.right > enemy.boundary_right:
175 enemy.change_x *= -1
176
177 # Update the player using the physics engine
178 self.physics_engine.update()
179
180 # See if the player hit a worm. If so, game over.
181 if len(arcade.check_for_collision_with_list(self.player_sprite, self.enemy_list)) > 0:
182 self.game_over = True
183
184
185def main():
186 window = MyGame()
187 window.setup()
188 arcade.run()
189
190
191if __name__ == "__main__":
192 main()