Sprite Depth Controlled by a Cosine Wave

sprite_depth_cosine.py
1"""
2Depth-sort sprites using a depth buffer in the GL context.
3
4Press the space bar to toggle depth testing during drawing.
5
6During each update, the depth of each sprite is updated to follow a
7cosine wave. Afterward, the following is drawn:
8
9* All sprites in depth-sorted order
10* A white square centered over each sprite along the x-axis, and moving
11 with the wave along the y-axis
12
13If Python and Arcade are installed, this example can be run from the command line with:
14python -m arcade.examples.sprite_depth_cosine
15"""
16
17import math
18
19from pyglet.graphics import Batch
20
21import arcade
22
23# All constants are in pixels
24WINDOW_WIDTH, WINDOW_HEIGHT = 1280, 720
25
26WINDOW_TITLE = "Sprite Depth Testing Example w/ a Cosine Wave"
27NUM_SPRITES = 10
28
29SPRITE_X_START = 150
30SPRITE_X_STEP = 50
31SPRITE_Y = WINDOW_HEIGHT // 2
32
33DOT_SIZE = 10
34
35
36class GameView(arcade.View):
37
38 def __init__(self):
39 super().__init__()
40
41 texture = arcade.load_texture(":resources:images/test_textures/xy_square.png")
42 self.text_batch = Batch()
43
44 self.use_depth: bool = True
45 self.text_use_depth = arcade.Text(
46 "SPACE: Toggle depth testing (True)",
47 x=10,
48 y=30,
49 font_size=15,
50 color=arcade.color.WHITE,
51 batch=self.text_batch,
52 )
53
54 self.sprite_list = arcade.SpriteList()
55
56 for i in range(NUM_SPRITES):
57 sprite = arcade.Sprite(
58 texture, center_x=SPRITE_X_START + SPRITE_X_STEP * i, center_y=SPRITE_Y
59 )
60 self.sprite_list.append(sprite)
61
62 def on_draw(self):
63 self.clear()
64
65 ctx = self.window.ctx
66 if self.use_depth:
67 # This with block temporarily enables depth testing
68 with ctx.enabled(ctx.DEPTH_TEST):
69 self.sprite_list.draw()
70 else:
71 self.sprite_list.draw()
72
73 # Draw wave visualization markers over each sprite
74 for i, sprite in enumerate(self.sprite_list):
75 arcade.draw_point(
76 SPRITE_X_START + SPRITE_X_STEP * i,
77 SPRITE_Y + sprite.depth,
78 arcade.color.WHITE,
79 DOT_SIZE,
80 )
81
82 self.text_batch.draw()
83
84 def on_key_press(self, symbol: int, modifiers: int):
85 if symbol == arcade.key.SPACE:
86 self.use_depth = not self.use_depth
87 self.text_use_depth.text = f"SPACE: Toggle depth testing ({self.use_depth})"
88
89 def on_update(self, delta_time):
90 # Using time from the window's clock simplifies the math below
91 time = self.window.time
92 for i, sprite in enumerate(self.sprite_list):
93 sprite.depth = math.cos(time + i) * SPRITE_X_STEP
94
95
96def main():
97 """ Main function """
98 # Create a window class. This is what actually shows up on screen
99 window = arcade.Window(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_TITLE)
100
101 # Create the GameView
102 game = GameView()
103
104 # Show GameView on screen
105 window.show_view(game)
106
107 # Start the arcade game loop
108 arcade.run()
109
110
111if __name__ == "__main__":
112 main()