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. Since we are making a 2D game, arcade.camera.Camera2D
will
be easiest.
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.camera.Camera2D()
Since we’re drawing to the entire screen, we can use Camera2D
’s default settings.
In other circumstances, we can create or adjust the camera so it has a different viewport.
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.position = self.player_sprite.position
Source Code
1"""
2Platformer Game
3
4python -m arcade.examples.platform_tutorial.07_camera
5"""
6import arcade
7
8# Constants
9WINDOW_WIDTH = 1280
10WINDOW_HEIGHT = 720
11WINDOW_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 GameView(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__(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_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(
55 ":resources:images/animated_characters/female_adventurer/femaleAdventurer_idle.png"
56 )
57
58 self.player_sprite = arcade.Sprite(self.player_texture)
59 self.player_sprite.center_x = 64
60 self.player_sprite.center_y = 128
61
62 self.player_list = arcade.SpriteList()
63 self.player_list.append(self.player_sprite)
64
65 self.wall_list = arcade.SpriteList(use_spatial_hash=True)
66
67 # Create the ground
68 # This shows using a loop to place multiple sprites horizontally
69 for x in range(0, 1250, 64):
70 wall = arcade.Sprite(":resources:images/tiles/grassMid.png", scale=TILE_SCALING)
71 wall.center_x = x
72 wall.center_y = 32
73 self.wall_list.append(wall)
74
75 # Put some crates on the ground
76 # This shows using a coordinate list to place sprites
77 coordinate_list = [[512, 96], [256, 96], [768, 96]]
78
79 for coordinate in coordinate_list:
80 # Add a crate on the ground
81 wall = arcade.Sprite(
82 ":resources:images/tiles/boxCrate_double.png", scale=TILE_SCALING
83 )
84 wall.position = coordinate
85 self.wall_list.append(wall)
86
87 # Create a Platformer Physics Engine, this will handle moving our
88 # player as well as collisions between the player sprite and
89 # whatever SpriteList we specify for the walls.
90 # It is important to supply static to the walls parameter. There is a
91 # platforms parameter that is intended for moving platforms.
92 # If a platform is supposed to move, and is added to the walls list,
93 # it will not be moved.
94 self.physics_engine = arcade.PhysicsEnginePlatformer(
95 self.player_sprite, walls=self.wall_list, gravity_constant=GRAVITY
96 )
97
98 # Initialize our camera, setting a viewport the size of our window.
99 self.camera = arcade.camera.Camera2D()
100
101 self.background_color = arcade.csscolor.CORNFLOWER_BLUE
102
103 def on_draw(self):
104 """Render the screen."""
105
106 # Clear the screen to the background color
107 self.clear()
108
109 # Activate our camera before drawing
110 self.camera.use()
111
112 # Draw our sprites
113 self.player_list.draw()
114 self.wall_list.draw()
115
116 def on_update(self, delta_time):
117 """Movement and Game Logic"""
118
119 # Move the player using our physics engine
120 self.physics_engine.update()
121
122 # Center our camera on the player
123 self.camera.position = self.player_sprite.position
124
125 def on_key_press(self, key, modifiers):
126 """Called whenever a key is pressed."""
127
128 if key == arcade.key.ESCAPE:
129 self.setup()
130
131 if key == arcade.key.UP or key == arcade.key.W:
132 if self.physics_engine.can_jump():
133 self.player_sprite.change_y = PLAYER_JUMP_SPEED
134
135 if key == arcade.key.LEFT or key == arcade.key.A:
136 self.player_sprite.change_x = -PLAYER_MOVEMENT_SPEED
137 elif key == arcade.key.RIGHT or key == arcade.key.D:
138 self.player_sprite.change_x = PLAYER_MOVEMENT_SPEED
139
140 def on_key_release(self, key, modifiers):
141 """Called whenever a key is released."""
142
143 if key == arcade.key.LEFT or key == arcade.key.A:
144 self.player_sprite.change_x = 0
145 elif key == arcade.key.RIGHT or key == arcade.key.D:
146 self.player_sprite.change_x = 0
147
148
149def main():
150 """Main function"""
151 window = GameView()
152 window.setup()
153 arcade.run()
154
155
156if __name__ == "__main__":
157 main()
Run This Chapter
python -m arcade.examples.platform_tutorial.07_camera