以滚动屏幕为中心移动#
使用 arcade.Camera
,一个程序可以很容易地在一个更大的“世界”中滚动,而只在屏幕上显示它的一部分。
如果显示的是图形用户界面或其他一些不应该滚动的项目,则需要两个摄像头。一个显示未滚动的图形用户界面,另一个显示滚动的精灵。
另请参阅 使用滚动屏幕移动-页边距 。

sprite_move_scrolling.py#
1"""
2Scroll around a large screen.
3
4Artwork from https://kenney.nl
5
6If Python and Arcade are installed, this example can be run from the command line with:
7python -m arcade.examples.sprite_move_scrolling
8"""
9
10import random
11import arcade
12
13SPRITE_SCALING = 0.5
14
15DEFAULT_SCREEN_WIDTH = 800
16DEFAULT_SCREEN_HEIGHT = 600
17SCREEN_TITLE = "Sprite Move with Scrolling Screen Example"
18
19# How many pixels to keep as a minimum margin between the character
20# and the edge of the screen.
21VIEWPORT_MARGIN = 220
22
23# How fast the camera pans to the player. 1.0 is instant.
24CAMERA_SPEED = 0.1
25
26# How fast the character moves
27PLAYER_MOVEMENT_SPEED = 7
28
29
30class MyGame(arcade.Window):
31 """ Main application class. """
32
33 def __init__(self, width, height, title):
34 """
35 Initializer
36 """
37 super().__init__(width, height, title, resizable=True)
38
39 # Sprite lists
40 self.player_list = None
41 self.wall_list = None
42
43 # Set up the player
44 self.player_sprite = None
45
46 # Physics engine so we don't run into walls.
47 self.physics_engine = None
48
49 # Track the current state of what key is pressed
50 self.left_pressed = False
51 self.right_pressed = False
52 self.up_pressed = False
53 self.down_pressed = False
54
55 # Create the cameras. One for the GUI, one for the sprites.
56 # We scroll the 'sprite world' but not the GUI.
57 self.camera_sprites = arcade.camera.Camera2D()
58 self.camera_gui = arcade.camera.Camera2D()
59
60 def setup(self):
61 """ Set up the game and initialize the variables. """
62
63 # Sprite lists
64 self.player_list = arcade.SpriteList()
65 self.wall_list = arcade.SpriteList()
66
67 # Set up the player
68 self.player_sprite = arcade.Sprite(":resources:images/animated_characters/female_person/femalePerson_idle.png",
69 scale=0.4)
70 self.player_sprite.center_x = 256
71 self.player_sprite.center_y = 512
72 self.player_list.append(self.player_sprite)
73
74 # -- Set up several columns of walls
75 for x in range(200, 1650, 210):
76 for y in range(0, 1600, 64):
77 # Randomly skip a box so the player can find a way through
78 if random.randrange(5) > 0:
79 wall = arcade.Sprite(":resources:images/tiles/grassCenter.png", scale=SPRITE_SCALING)
80 wall.center_x = x
81 wall.center_y = y
82 self.wall_list.append(wall)
83
84 self.physics_engine = arcade.PhysicsEngineSimple(self.player_sprite, self.wall_list)
85
86 # Set the background color
87 self.background_color = arcade.color.AMAZON
88
89 def on_draw(self):
90 """ Render the screen. """
91
92 # This command has to happen before we start drawing
93 self.clear()
94
95 # Select the camera we'll use to draw all our sprites
96 self.camera_sprites.use()
97
98 # Draw all the sprites.
99 self.wall_list.draw()
100 self.player_list.draw()
101
102 # Select the (unscrolled) camera for our GUI
103 self.camera_gui.use()
104
105 # Draw the GUI
106 arcade.draw_rectangle_filled(self.width // 2,
107 20,
108 self.width,
109 40,
110 arcade.color.ALMOND)
111 text = f"Scroll value: ({self.camera_sprites.position[0]:5.1f}, " \
112 f"{self.camera_sprites.position[1]:5.1f})"
113 arcade.draw_text(text, 10, 10, arcade.color.BLACK_BEAN, 20)
114
115 def on_key_press(self, key, modifiers):
116 """Called whenever a key is pressed. """
117
118 if key == arcade.key.UP:
119 self.up_pressed = True
120 elif key == arcade.key.DOWN:
121 self.down_pressed = True
122 elif key == arcade.key.LEFT:
123 self.left_pressed = True
124 elif key == arcade.key.RIGHT:
125 self.right_pressed = True
126
127 def on_key_release(self, key, modifiers):
128 """Called when the user releases a key. """
129
130 if key == arcade.key.UP:
131 self.up_pressed = False
132 elif key == arcade.key.DOWN:
133 self.down_pressed = False
134 elif key == arcade.key.LEFT:
135 self.left_pressed = False
136 elif key == arcade.key.RIGHT:
137 self.right_pressed = False
138
139 def on_update(self, delta_time):
140 """ Movement and game logic """
141
142 # Calculate speed based on the keys pressed
143 self.player_sprite.change_x = 0
144 self.player_sprite.change_y = 0
145
146 if self.up_pressed and not self.down_pressed:
147 self.player_sprite.change_y = PLAYER_MOVEMENT_SPEED
148 elif self.down_pressed and not self.up_pressed:
149 self.player_sprite.change_y = -PLAYER_MOVEMENT_SPEED
150 if self.left_pressed and not self.right_pressed:
151 self.player_sprite.change_x = -PLAYER_MOVEMENT_SPEED
152 elif self.right_pressed and not self.left_pressed:
153 self.player_sprite.change_x = PLAYER_MOVEMENT_SPEED
154
155 # Call update on all sprites (The sprites don't do much in this
156 # example though.)
157 self.physics_engine.update()
158
159 # Scroll the screen to the player
160 self.scroll_to_player()
161
162 def scroll_to_player(self):
163 """
164 Scroll the window to the player.
165
166 if CAMERA_SPEED is 1, the camera will immediately move to the desired position.
167 Anything between 0 and 1 will have the camera move to the location with a smoother
168 pan.
169 """
170
171 position = (self.player_sprite.center_x, self.player_sprite.center_y)
172 self.camera_sprites.position = arcade.math.lerp_2d(self.camera_sprites.position, position, CAMERA_SPEED)
173
174 def on_resize(self, width: int, height: int):
175 """
176 Resize window
177 Handle the user grabbing the edge and resizing the window.
178 """
179 super().on_resize(width, height)
180 self.camera_sprites.match_screen(and_projection=True)
181 self.camera_gui.match_screen(and_projection=True)
182
183
184def main():
185 """ Main function """
186 window = MyGame(DEFAULT_SCREEN_WIDTH, DEFAULT_SCREEN_HEIGHT, SCREEN_TITLE)
187 window.setup()
188 arcade.run()
189
190
191if __name__ == "__main__":
192 main()