使用滚动屏幕移动-页边距#
不像 以滚动屏幕为中心移动 它将相机放在播放器的中心,此示例仅在用户到达边缘的如此多像素内时才移动相机。它允许在中间有一个‘盒子’,用户可以在那里四处移动,而不是移动摄像头。

sprite_move_scrolling_box.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_box
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 = 200
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 self.physics_engine = None
47
48 # Track the current state of what key is pressed
49 self.left_pressed = False
50 self.right_pressed = False
51 self.up_pressed = False
52 self.down_pressed = False
53
54 self.camera_sprites = arcade.camera.Camera2D()
55 self.camera_gui = arcade.camera.Camera2D()
56
57 def setup(self):
58 """ Set up the game and initialize the variables. """
59
60 # Sprite lists
61 self.player_list = arcade.SpriteList()
62 self.wall_list = arcade.SpriteList()
63
64 # Set up the player
65 self.player_sprite = arcade.Sprite(":resources:images/animated_characters/female_person/femalePerson_idle.png",
66 scale=0.4)
67 self.player_sprite.center_x = 256
68 self.player_sprite.center_y = 512
69 self.player_list.append(self.player_sprite)
70
71 # -- Set up several columns of walls
72 for x in range(200, 1650, 210):
73 for y in range(0, 1600, 64):
74 # Randomly skip a box so the player can find a way through
75 if random.randrange(5) > 0:
76 wall = arcade.Sprite(":resources:images/tiles/grassCenter.png", scale=SPRITE_SCALING)
77 wall.center_x = x
78 wall.center_y = y
79 self.wall_list.append(wall)
80
81 self.physics_engine = arcade.PhysicsEngineSimple(self.player_sprite, self.wall_list)
82
83 # Set the background color
84 self.background_color = arcade.color.AMAZON
85
86 def on_draw(self):
87 """
88 Render the screen.
89 """
90
91 # This command has to happen before we start drawing
92 self.clear()
93
94 # Select the camera we'll use to draw all our sprites
95 self.camera_sprites.use()
96
97 # Draw all the sprites.
98 self.wall_list.draw()
99 self.player_list.draw()
100
101 # Select the (unscrolled) camera for our GUI
102 self.camera_gui.use()
103
104 # Draw the GUI
105 arcade.draw_rectangle_filled(self.width // 2, 20, self.width, 40, arcade.color.ALMOND)
106 text = f"Scroll value: ({self.camera_sprites.position[0]:5.1f}, {self.camera_sprites.position[1]:5.1f})"
107 arcade.draw_text(text, 10, 10, arcade.color.BLACK_BEAN, 20)
108
109 # Draw the box that we work to make sure the user stays inside of.
110 # This is just for illustration purposes. You'd want to remove this
111 # in your game.
112 left_boundary = VIEWPORT_MARGIN
113 right_boundary = self.width - VIEWPORT_MARGIN
114 top_boundary = self.height - VIEWPORT_MARGIN
115 bottom_boundary = VIEWPORT_MARGIN
116 arcade.draw_lrbt_rectangle_outline(left_boundary, right_boundary, bottom_boundary, top_boundary,
117 arcade.color.RED, 2)
118
119 def on_key_press(self, key, modifiers):
120 """Called whenever a key is pressed. """
121
122 if key == arcade.key.UP:
123 self.up_pressed = True
124 elif key == arcade.key.DOWN:
125 self.down_pressed = True
126 elif key == arcade.key.LEFT:
127 self.left_pressed = True
128 elif key == arcade.key.RIGHT:
129 self.right_pressed = True
130
131 def on_key_release(self, key, modifiers):
132 """Called when the user releases a key. """
133
134 if key == arcade.key.UP:
135 self.up_pressed = False
136 elif key == arcade.key.DOWN:
137 self.down_pressed = False
138 elif key == arcade.key.LEFT:
139 self.left_pressed = False
140 elif key == arcade.key.RIGHT:
141 self.right_pressed = False
142
143 def on_update(self, delta_time):
144 """ Movement and game logic """
145
146 # Calculate speed based on the keys pressed
147 self.player_sprite.change_x = 0
148 self.player_sprite.change_y = 0
149
150 if self.up_pressed and not self.down_pressed:
151 self.player_sprite.change_y = PLAYER_MOVEMENT_SPEED
152 elif self.down_pressed and not self.up_pressed:
153 self.player_sprite.change_y = -PLAYER_MOVEMENT_SPEED
154 if self.left_pressed and not self.right_pressed:
155 self.player_sprite.change_x = -PLAYER_MOVEMENT_SPEED
156 elif self.right_pressed and not self.left_pressed:
157 self.player_sprite.change_x = PLAYER_MOVEMENT_SPEED
158
159 # Call update on all sprites (The sprites don't do much in this
160 # example though.)
161 self.physics_engine.update()
162
163 # Scroll the screen to the player
164 self.scroll_to_player()
165
166 def scroll_to_player(self):
167 """
168 Scroll the window to the player.
169 This method will attempt to keep the player at least VIEWPORT_MARGIN
170 pixels away from the edge.
171
172 if CAMERA_SPEED is 1, the camera will immediately move to the desired position.
173 Anything between 0 and 1 will have the camera move to the location with a smoother
174 pan.
175 """
176
177 # --- Manage Scrolling ---
178
179 _target_x, _target_y = self.camera_sprites.position
180
181 # Scroll left
182 left_boundary = self.camera_sprites.left + VIEWPORT_MARGIN
183 if self.player_sprite.left < left_boundary:
184 _target_x -= left_boundary - self.player_sprite.left
185
186 # Scroll right
187 right_boundary = self.camera_sprites.right - VIEWPORT_MARGIN
188 if self.player_sprite.right > right_boundary:
189 _target_x += self.player_sprite.right - right_boundary
190
191 # Scroll up
192 top_boundary = self.camera_sprites.top - VIEWPORT_MARGIN
193 if self.player_sprite.top > top_boundary:
194 _target_y += self.player_sprite.top - top_boundary
195
196 # Scroll down
197 bottom_boundary = self.camera_sprites.bottom + VIEWPORT_MARGIN
198 if self.player_sprite.bottom < bottom_boundary:
199 _target_y -= bottom_boundary - self.player_sprite.bottom
200
201 # Scroll to the proper location
202 position = _target_x, _target_y
203 self.camera_sprites.position = arcade.math.lerp_2d(self.camera_sprites.position, position, CAMERA_SPEED)
204
205 def on_resize(self, width: int, height: int):
206 """
207 Resize window
208 Handle the user grabbing the edge and resizing the window.
209 """
210 super().on_resize(width, height)
211 self.camera_sprites.match_screen(and_projection=True)
212 self.camera_gui.match_screen(and_projection=True)
213
214
215def main():
216 """ Main function """
217 window = MyGame(DEFAULT_SCREEN_WIDTH, DEFAULT_SCREEN_HEIGHT, SCREEN_TITLE)
218 window.setup()
219 arcade.run()
220
221
222if __name__ == "__main__":
223 main()