Step 6 - Add a Camera#
We can have our window be a small viewport into a much larger world by adding a camera to it.
First we need to create a new variable in our __init__
method:
self.physics_engine = None
Next we can initialize the camera in the setup
function:
"""Set up the game here. Call this function to restart the game."""
Then to use our camera when drawing, we can activate it in our on_draw
function:
self.clear()
Now at this point everything should be working the same, but the camera can do a lot
more than this. We can use the move
function of the camera to scroll it to a different
position. We can use this functionality to keep the camera centered on the player:
We can create a function to calculate the coordinates for the center of our player
relative to the screen, then move the camera to those. Then we can call that function in
on_update
to actually move it. The new position will be taken into account during
the use
function in on_draw
self.player_sprite.change_x = 0
def center_camera_to_player(self):
screen_center_x = self.player_sprite.center_x - (self.camera.viewport_width / 2)
screen_center_y = self.player_sprite.center_y - (
self.camera.viewport_height / 2
)
# Don't let camera travel past 0
if screen_center_x < 0:
screen_center_x = 0
if screen_center_y < 0:
screen_center_y = 0
player_centered = screen_center_x, screen_center_y
self.camera.move_to(player_centered)
def on_update(self, delta_time):
"""Movement and game logic"""
# Move the player with the physics engine
self.physics_engine.update()
Source Code#
1"""
2Platformer Game
3
4python -m arcade.examples.platform_tutorial.06_camera
5"""
6import arcade
7
8# Constants
9SCREEN_WIDTH = 1000
10SCREEN_HEIGHT = 650
11SCREEN_TITLE = "Platformer"
12
13# Constants used to scale our sprites from their original size
14CHARACTER_SCALING = 1
15TILE_SCALING = 0.5
16
17# Movement speed of player, in pixels per frame
18PLAYER_MOVEMENT_SPEED = 5
19GRAVITY = 1
20PLAYER_JUMP_SPEED = 20
21
22
23class MyGame(arcade.Window):
24 """
25 Main application class.
26 """
27
28 def __init__(self):
29
30 # Call the parent class and set up the window
31 super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
32
33 # Our Scene Object
34 self.scene = None
35
36 # Separate variable that holds the player sprite
37 self.player_sprite = None
38
39 # Our physics engine
40 self.physics_engine = None
41
42 # A Camera that can be used for scrolling the screen
43 self.camera = None
44
45 self.background_color = arcade.csscolor.CORNFLOWER_BLUE
46
47 def setup(self):
48 """Set up the game here. Call this function to restart the game."""
49
50 # Set up the Camera
51 self.camera = arcade.SimpleCamera(viewport=(0, 0, self.width, self.height))
52
53 # Initialize Scene
54 self.scene = arcade.Scene()
55
56 # Create the Sprite lists
57 self.scene.add_sprite_list("Player")
58 self.scene.add_sprite_list("Walls", use_spatial_hash=True)
59
60 # Set up the player, specifically placing it at these coordinates.
61 image_source = ":resources:images/animated_characters/female_adventurer/femaleAdventurer_idle.png"
62 self.player_sprite = arcade.Sprite(image_source, CHARACTER_SCALING)
63 self.player_sprite.center_x = 64
64 self.player_sprite.center_y = 96
65 self.scene.add_sprite("Player", self.player_sprite)
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", TILE_SCALING)
71 wall.center_x = x
72 wall.center_y = 32
73 self.scene.add_sprite("Walls", 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", TILE_SCALING
83 )
84 wall.position = coordinate
85 self.scene.add_sprite("Walls", wall)
86
87 # Create the 'physics engine'
88 self.physics_engine = arcade.PhysicsEnginePlatformer(
89 self.player_sprite, gravity_constant=GRAVITY, walls=self.scene["Walls"]
90 )
91
92 def on_draw(self):
93 """Render the screen."""
94
95 # Clear the screen to the background color
96 self.clear()
97
98 # Activate our Camera
99 self.camera.use()
100
101 # Draw our Scene
102 self.scene.draw()
103
104 def on_key_press(self, key, modifiers):
105 """Called whenever a key is pressed."""
106
107 if key == arcade.key.UP or key == arcade.key.W:
108 if self.physics_engine.can_jump():
109 self.player_sprite.change_y = PLAYER_JUMP_SPEED
110 elif key == arcade.key.LEFT or key == arcade.key.A:
111 self.player_sprite.change_x = -PLAYER_MOVEMENT_SPEED
112 elif key == arcade.key.RIGHT or key == arcade.key.D:
113 self.player_sprite.change_x = PLAYER_MOVEMENT_SPEED
114
115 def on_key_release(self, key, modifiers):
116 """Called when the user releases a key."""
117
118 if key == arcade.key.LEFT or key == arcade.key.A:
119 self.player_sprite.change_x = 0
120 elif key == arcade.key.RIGHT or key == arcade.key.D:
121 self.player_sprite.change_x = 0
122
123 def center_camera_to_player(self):
124 screen_center_x = self.player_sprite.center_x - (self.camera.viewport_width / 2)
125 screen_center_y = self.player_sprite.center_y - (
126 self.camera.viewport_height / 2
127 )
128
129 # Don't let camera travel past 0
130 if screen_center_x < 0:
131 screen_center_x = 0
132 if screen_center_y < 0:
133 screen_center_y = 0
134 player_centered = screen_center_x, screen_center_y
135
136 self.camera.move_to(player_centered)
137
138 def on_update(self, delta_time):
139 """Movement and game logic"""
140
141 # Move the player with the physics engine
142 self.physics_engine.update()
143
144 # Position the camera
145 self.center_camera_to_player()
146
147
148def main():
149 """Main function"""
150 window = MyGame()
151 window.setup()
152 arcade.run()
153
154
155if __name__ == "__main__":
156 main()