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