Step 7 - Adding a Camera#
Now that our player can move and jump around, we need to give them a way to explore the world beyond the original window. If you’ve ever played a platformer game, you might be familiar with the concept of the screen scrolling to reveal more of the map as the player moves.
To achieve this, we can use a Camera, Arcade provides arcade.SimpleCamera
and arcade.Camera
.
They both do the same base thing, but Camera has a bit of extra functionality that SimpleCamera doesn’t.
For now, we will just use the SimpleCamera.
To start with, let’s go ahead and add a variable in our __init__
function to hold it:
self.camera = None
Next we can go to our setup function, and initialize it like so:
self.camera = arcade.SimpleCamera(viewport=(0, 0, self.width, self.height))
The viewport
parameter here defines the size of the camera. In most circumstances, you will want this
to be the size of your window. So we specify the bottom and left coordinates of our camera viewport as
(0, 0), and provide it the width and height of our window.
In order to use our camera when drawing things to the screen, we only need to add one line to our on_draw
function. This line should typically come before anything you want to draw with the camera. In later chapters,
we’ll explore using multiple cameras to draw things in different positions. Go ahead and add this line before
drawing our SpriteLists
self.camera.use()
If you run the game at this point, you might notice that nothing has changed, our game is still one static un-moving
screen. This is because we are never updating the camera’s position. In our platformer game, we want the camera to follow
the player, and keep them in the center of the screen. Arcade provides a helpful function to do this with one line of code.
In other types of games or more advanced usage you may want to set the cameras position directly in order to create interesting
effects, but for now all we need is the center()
function of our camera.
If we add the following line to our on_update()
function and run the game, you should now see the player
stay at the center of the screen, while being able to scroll the screen around to the rest of our map. For fun, see what happens
if you fall off of the map! Later on, we’ll revisit a more advanced camera setup that will take the bounds of our world into
consideration.
self.camera.center(self.player_sprite.position)
Source Code#
1"""
2Platformer Game
3
4python -m arcade.examples.platform_tutorial.07_camera
5"""
6import arcade
7
8# Constants
9SCREEN_WIDTH = 800
10SCREEN_HEIGHT = 600
11SCREEN_TITLE = "Platformer"
12
13# Constants used to scale our sprites from their original size
14TILE_SCALING = 0.5
15
16# Movement speed of player, in pixels per frame
17PLAYER_MOVEMENT_SPEED = 5
18GRAVITY = 1
19PLAYER_JUMP_SPEED = 20
20
21
22class MyGame(arcade.Window):
23 """
24 Main application class.
25 """
26
27 def __init__(self):
28
29 # Call the parent class and set up the window
30 super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
31
32 # Variable to hold our texture for our player
33 self.player_texture = None
34
35 # Separate variable that holds the player sprite
36 self.player_sprite = None
37
38 # SpriteList for our player
39 self.player_list = None
40
41 # SpriteList for our boxes and ground
42 # Putting our ground and box Sprites in the same SpriteList
43 # will make it easier to perform collision detection against
44 # them later on. Setting the spatial hash to True will make
45 # collision detection much faster if the objects in this
46 # SpriteList do not move.
47 self.wall_list = None
48
49 # A variable to store our camera object
50 self.camera = None
51
52 def setup(self):
53 """Set up the game here. Call this function to restart the game."""
54 self.player_texture = arcade.load_texture(":resources:images/animated_characters/female_adventurer/femaleAdventurer_idle.png")
55
56 self.player_sprite = arcade.Sprite(self.player_texture)
57 self.player_sprite.center_x = 64
58 self.player_sprite.center_y = 128
59
60 self.player_list = arcade.SpriteList()
61 self.player_list.append(self.player_sprite)
62
63 self.wall_list = arcade.SpriteList(use_spatial_hash=True)
64
65 # Create the ground
66 # This shows using a loop to place multiple sprites horizontally
67 for x in range(0, 1250, 64):
68 wall = arcade.Sprite(":resources:images/tiles/grassMid.png", scale=TILE_SCALING)
69 wall.center_x = x
70 wall.center_y = 32
71 self.wall_list.append(wall)
72
73 # Put some crates on the ground
74 # This shows using a coordinate list to place sprites
75 coordinate_list = [[512, 96], [256, 96], [768, 96]]
76
77 for coordinate in coordinate_list:
78 # Add a crate on the ground
79 wall = arcade.Sprite(
80 ":resources:images/tiles/boxCrate_double.png", scale=TILE_SCALING
81 )
82 wall.position = coordinate
83 self.wall_list.append(wall)
84
85 # Create a Platformer Physics Engine, this will handle moving our
86 # player as well as collisions between the player sprite and
87 # whatever SpriteList we specify for the walls.
88 # It is important to supply static to the walls parameter. There is a
89 # platforms parameter that is intended for moving platforms.
90 # If a platform is supposed to move, and is added to the walls list,
91 # it will not be moved.
92 self.physics_engine = arcade.PhysicsEnginePlatformer(
93 self.player_sprite, walls=self.wall_list, gravity_constant=GRAVITY
94 )
95
96 # Initialize our camera, setting a viewport the size of our window.
97 self.camera = arcade.SimpleCamera(viewport=(0, 0, self.width, self.height))
98
99 self.background_color = arcade.csscolor.CORNFLOWER_BLUE
100
101 def on_draw(self):
102 """Render the screen."""
103
104 # Clear the screen to the background color
105 self.clear()
106
107 # Activate our camera before drawing
108 self.camera.use()
109
110 # Draw our sprites
111 self.player_list.draw()
112 self.wall_list.draw()
113
114 def on_update(self, delta_time):
115 """Movement and Game Logic"""
116
117 # Move the player using our physics engine
118 self.physics_engine.update()
119
120 # Center our camera on the player
121 self.camera.center(self.player_sprite.position)
122
123 def on_key_press(self, key, modifiers):
124 """Called whenever a key is pressed."""
125
126 if key == arcade.key.ESCAPE:
127 self.setup()
128
129 if key == arcade.key.UP or key == arcade.key.W:
130 if self.physics_engine.can_jump():
131 self.player_sprite.change_y = PLAYER_JUMP_SPEED
132
133 if key == arcade.key.LEFT or key == arcade.key.A:
134 self.player_sprite.change_x = -PLAYER_MOVEMENT_SPEED
135 elif key == arcade.key.RIGHT or key == arcade.key.D:
136 self.player_sprite.change_x = PLAYER_MOVEMENT_SPEED
137
138 def on_key_release(self, key, modifiers):
139 """Called whenever a key is released."""
140
141 if key == arcade.key.LEFT or key == arcade.key.A:
142 self.player_sprite.change_x = 0
143 elif key == arcade.key.RIGHT or key == arcade.key.D:
144 self.player_sprite.change_x = 0
145
146
147def main():
148 """Main function"""
149 window = MyGame()
150 window.setup()
151 arcade.run()
152
153
154if __name__ == "__main__":
155 main()
Run This Chapter#
python -m arcade.examples.platform_tutorial.07_camera