1"""
2This simple animation example shows how to use classes to animate
3multiple objects on the screen at the same time.
4
5Because this is redraws the shapes from scratch each frame, this is SLOW
6and inefficient.
7
8Using buffered drawing commands (Vertex Buffer Objects) is a bit more complex,
9but faster.
10
11See http://arcade.academy/examples/shapes_buffered.html for this same example
12using shape element lists.
13
14Also, any Sprite class put in a SpriteList and drawn with the SpriteList will
15be drawn using Vertex Buffer Objects for better performance.
16
17If Python and Arcade are installed, this example can be run from the command line with:
18python -m arcade.examples.shapes_buffered
19"""
20
21import arcade
22import random
23import timeit
24
25# Set up the constants
26SCREEN_WIDTH = 800
27SCREEN_HEIGHT = 600
28SCREEN_TITLE = "Shapes! Non-buffered"
29
30RECT_WIDTH = 50
31RECT_HEIGHT = 50
32
33NUMBER_OF_SHAPES = 500
34
35
36class Shape:
37 """ Generic base shape class """
38 def __init__(self, x, y, width, height, angle, delta_x, delta_y,
39 delta_angle, color):
40 self.x = x
41 self.y = y
42 self.width = width
43 self.height = height
44 self.angle = angle
45 self.delta_x = delta_x
46 self.delta_y = delta_y
47 self.delta_angle = delta_angle
48 self.color = color
49
50 def move(self):
51 self.x += self.delta_x
52 self.y += self.delta_y
53 self.angle += self.delta_angle
54 if self.x < 0 and self.delta_x < 0:
55 self.delta_x *= -1
56 if self.y < 0 and self.delta_y < 0:
57 self.delta_y *= -1
58 if self.x > SCREEN_WIDTH and self.delta_x > 0:
59 self.delta_x *= -1
60 if self.y > SCREEN_HEIGHT and self.delta_y > 0:
61 self.delta_y *= -1
62
63class Ellipse(Shape):
64
65 def draw(self):
66 arcade.draw_ellipse_filled(self.x, self.y, self.width, self.height,
67 self.color, self.angle)
68
69
70class Rectangle(Shape):
71
72 def draw(self):
73 arcade.draw_rectangle_filled(self.x, self.y, self.width, self.height,
74 self.color, self.angle)
75
76class Line(Shape):
77
78 def draw(self):
79 arcade.draw_line(self.x, self.y,
80 self.x + self.width, self.y + self.height,
81 self.color, 2)
82
83
84class MyGame(arcade.Window):
85 """ Main application class. """
86
87 def __init__(self):
88 super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
89 self.shape_list = None
90
91 self.processing_time = 0
92 self.draw_time = 0
93 self.frame_count = 0
94 self.fps_start_timer = None
95 self.fps = None
96
97 def setup(self):
98 """ Set up the game and initialize the variables. """
99 self.shape_list = []
100
101 for i in range(NUMBER_OF_SHAPES):
102 x = random.randrange(0, SCREEN_WIDTH)
103 y = random.randrange(0, SCREEN_HEIGHT)
104 width = random.randrange(10, 30)
105 height = random.randrange(10, 30)
106 angle = random.randrange(0, 360)
107
108 d_x = random.randrange(-3, 4)
109 d_y = random.randrange(-3, 4)
110 d_angle = random.randrange(-3, 4)
111
112 red = random.randrange(256)
113 green = random.randrange(256)
114 blue = random.randrange(256)
115 alpha = random.randrange(256)
116
117 shape_type = random.randrange(3)
118 # shape_type = 2
119
120 if shape_type == 0:
121 shape = Rectangle(x, y, width, height, angle, d_x, d_y,
122 d_angle, (red, green, blue, alpha))
123 elif shape_type == 1:
124 shape = Ellipse(x, y, width, height, angle, d_x, d_y,
125 d_angle, (red, green, blue, alpha))
126 elif shape_type == 2:
127 shape = Line(x, y, width, height, angle, d_x, d_y,
128 d_angle, (red, green, blue, alpha))
129
130 self.shape_list.append(shape)
131
132 def on_update(self, dt):
133 """ Move everything """
134 start_time = timeit.default_timer()
135
136 for shape in self.shape_list:
137 shape.move()
138
139 self.processing_time = timeit.default_timer() - start_time
140
141 def on_draw(self):
142 """
143 Render the screen.
144 """
145 # Start timing how long this takes
146 draw_start_time = timeit.default_timer()
147
148 if self.frame_count % 60 == 0:
149 if self.fps_start_timer is not None:
150 total_time = timeit.default_timer() - self.fps_start_timer
151 self.fps = 60 / total_time
152 self.fps_start_timer = timeit.default_timer()
153 self.frame_count += 1
154
155 arcade.start_render()
156
157 for shape in self.shape_list:
158 shape.draw()
159
160 # Display timings
161 output = f"Processing time: {self.processing_time:.3f}"
162 arcade.draw_text(output, 20, SCREEN_HEIGHT - 20, arcade.color.WHITE, 16)
163
164 output = f"Drawing time: {self.draw_time:.3f}"
165 arcade.draw_text(output, 20, SCREEN_HEIGHT - 40, arcade.color.WHITE, 16)
166
167 if self.fps is not None:
168 output = f"FPS: {self.fps:.0f}"
169 arcade.draw_text(output, 20, SCREEN_HEIGHT - 60, arcade.color.WHITE, 16)
170
171 self.draw_time = timeit.default_timer() - draw_start_time
172
173
174def main():
175 window = MyGame()
176 window.setup()
177 arcade.run()
178
179
180if __name__ == "__main__":
181 main()