视差#
警告
这个例子是实验性的!
它使用的功能可能会迅速改变,或者在未来的arcade版本中被取代!

background_parallax.py#
1"""
2Parallax scrolling layers move slower the "farther" away they are.
3
4Use the right and left arrow keys to move the car.
5
6Arcade's ParallaxGroup allows you to implement this technique quickly
7to create more satisfying backgrounds to your games. The example below
8demonstrates how to fake an endless world by adjusting ParallaxGroup's
9position & offset values. For limited worlds or backgrounds, limit the
10repositioning to only occur within certain bounds, or delete it.
11
12If Python and Arcade are installed, this example can be run from the command line with:
13python -m arcade.examples.background_parallax
14"""
15
16import arcade
17import arcade.experimental.background as background
18
19
20SCREEN_TITLE = "Background Group Example"
21SCREEN_WIDTH = 800
22
23# How much we'll scale up our pixel art
24PIXEL_SCALE = 3
25
26# The original & scaled heights of our background layer image data in pixels.
27ORIGINAL_BG_LAYER_HEIGHT_PX = 240
28SCALED_BG_LAYER_HEIGHT_PX = ORIGINAL_BG_LAYER_HEIGHT_PX * PIXEL_SCALE
29
30
31PLAYER_SPEED = 300 # The player's speed in pixels / second
32
33
34class MyGame(arcade.Window):
35 def __init__(self):
36 super().__init__(SCREEN_WIDTH, SCALED_BG_LAYER_HEIGHT_PX, SCREEN_TITLE, resizable=True)
37
38 # Set the background color to match the sky in the background images
39 self.background_color = (162, 84, 162, 255)
40
41 self.camera = arcade.camera.Camera2D()
42
43 # Create a background group to hold all the landscape's layers
44 self.backgrounds = background.ParallaxGroup()
45
46 # Calculate the current size of each background fill layer in pixels
47 bg_layer_size_px = (SCREEN_WIDTH, SCALED_BG_LAYER_HEIGHT_PX)
48
49 # Import the image data for each background layer.
50 # Unlike sprites, the scale argument doesn't resize the layer
51 # itself. Instead, it changes the zoom level, while depth
52 # controls how fast each layer scrolls. This means you have to
53 # pass a correct size value when adding a layer. We calculated
54 # this above.
55 self.backgrounds.add_from_file(
56 ":resources:/images/miami_synth_parallax/layers/back.png",
57 size=bg_layer_size_px,
58 depth=10.0,
59 scale=PIXEL_SCALE
60 )
61 self.backgrounds.add_from_file(
62 ":resources:/images/miami_synth_parallax/layers/buildings.png",
63 size=bg_layer_size_px,
64 depth=5.0,
65 scale=PIXEL_SCALE
66 )
67 self.backgrounds.add_from_file(
68 ":resources:/images/miami_synth_parallax/layers/palms.png",
69 size=bg_layer_size_px,
70 depth=3.0,
71 scale=PIXEL_SCALE
72 )
73 self.backgrounds.add_from_file(
74 ":resources:/images/miami_synth_parallax/layers/highway.png",
75 size=bg_layer_size_px,
76 depth=1.0,
77 scale=PIXEL_SCALE
78 )
79
80 # Create & position the player sprite in the center of the camera's view
81 self.player_sprite = arcade.Sprite(
82 ":resources:/images/miami_synth_parallax/car/car-idle.png",
83 center_x=self.camera.viewport_width // 2, center_y=-200.0, scale=PIXEL_SCALE
84 )
85 self.player_sprite.bottom = 0
86
87 # Track the player's x velocity
88 self.x_velocity = 0
89
90 def pan_camera_to_player(self):
91 # Move the camera toward the center of the player's sprite
92 target_x = self.player_sprite.center_x
93 self.camera.position = arcade.math.lerp_2d(self.camera.position, (target_x, self.height//2), 0.1)
94
95 def on_update(self, delta_time: float):
96 # Move the player in our infinite world
97 self.player_sprite.center_x += self.x_velocity * delta_time
98 self.pan_camera_to_player()
99
100 def on_draw(self):
101
102 # Set up our drawing
103 self.clear()
104 self.camera.use()
105
106 # Store a reference to the background layers as shorthand
107 bg = self.backgrounds
108
109 # Fake an endless world with scrolling terrain
110 # Try experimenting with commenting out 1 or both of the 2 lines
111 # below to get an intuitive understanding of what each does!
112 bg.offset = self.camera.left, self.camera.bottom # Fake depth by moving layers
113 bg.pos = self.camera.left, self.camera.bottom # Follow the car to fake infinity
114
115 # Draw the background & the player's car
116 bg.draw()
117 self.player_sprite.draw(pixelated=True)
118
119 def update_car_direction(self):
120 """
121 Don't use the trick below in a real game!
122
123 It will cause problems! Instead, use different textures, either
124 from different files or by using Texture.flop_left_to_right().
125 """
126 if self.x_velocity < 0:
127 self.player_sprite.scale_xy = (-PIXEL_SCALE, PIXEL_SCALE)
128 print(self.player_sprite.width)
129 elif self.x_velocity > 0:
130 self.player_sprite.scale_xy = (PIXEL_SCALE, PIXEL_SCALE)
131
132 def on_key_press(self, symbol: int, modifiers: int):
133 if symbol == arcade.key.LEFT:
134 self.x_velocity -= PLAYER_SPEED
135 self.update_car_direction()
136 elif symbol == arcade.key.RIGHT:
137 self.x_velocity += PLAYER_SPEED
138 self.update_car_direction()
139
140 def on_key_release(self, symbol: int, modifiers: int):
141 if symbol == arcade.key.LEFT:
142 self.x_velocity += PLAYER_SPEED
143 self.update_car_direction()
144 elif symbol == arcade.key.RIGHT:
145 self.x_velocity -= PLAYER_SPEED
146 self.update_car_direction()
147
148 def on_resize(self, width: int, height: int):
149 super().on_resize(width, height)
150 self.camera.match_screen(and_projection=True)
151 full_width_size = (width, SCALED_BG_LAYER_HEIGHT_PX)
152
153 # We can iterate through a background group,
154 # but in the case of a parallax group the iter returns
155 # both the Backgrounds and the depths. (tuple[Background, float])
156 for layer, depth in self.backgrounds:
157 layer.size = full_width_size
158
159
160def main():
161 app = MyGame()
162 app.run()
163
164
165if __name__ == "__main__":
166 main()