Performance Statistics#
Arcade includes performance monitoring tools to help you optimize your game. This example demonstrates the following performance api features:
If you do not want to display graphs in your game window, you can use
arcade.print_timings()
to print out the count and average time for
all dispatched events with the function. The output looks like this:
Event Count Average Time
-------------- ----- ------------
on_activate 1 0.0000
on_resize 1 0.0000
on_show 1 0.0000
on_update 59 0.0000
on_expose 1 0.0000
on_draw 59 0.0021
on_mouse_enter 1 0.0000
on_mouse_motion 100 0.0000
See Performance Information for more information about the performance api.
1"""
2Performance Statistic Display Example
3
4This example demonstrates how to use a few performance profiling tools
5built into arcade:
6
7* arcade.enable_timings
8* arcade.PerfGraph
9* arcade.get_fps
10* arcade.print_timings
11* arcade.clear_timings
12
13A large number of sprites bounce around the screen to produce load. You
14can adjust the number of sprites by changing the COIN_COUNT constant.
15
16Artwork from https://kenney.nl
17
18If Python and Arcade are installed, this example can be run from the
19command line with:
20python -m arcade.examples.performance_statistics
21"""
22from __future__ import annotations
23
24import random
25from typing import Optional
26
27import arcade
28
29# --- Constants ---
30SPRITE_SCALING_COIN = 0.25
31SPRITE_NATIVE_SIZE = 128
32SPRITE_SIZE = int(SPRITE_NATIVE_SIZE * SPRITE_SCALING_COIN)
33
34SCREEN_WIDTH = 800
35SCREEN_HEIGHT = 600
36SCREEN_TITLE = "Performance Statistics Display Example"
37
38# Size of performance graphs and distance between them
39GRAPH_WIDTH = 200
40GRAPH_HEIGHT = 120
41GRAPH_MARGIN = 5
42
43COIN_COUNT = 1500
44
45
46# Turn on tracking for the number of event handler
47# calls and the average execution time of each type.
48arcade.enable_timings()
49
50
51class Coin(arcade.BasicSprite):
52 """ Our coin sprite class """
53 def __init__(self, texture: arcade.Texture, scale: float):
54 super().__init__(texture, scale=scale)
55 # Add a velocity to the coin
56 self.change_x = 0
57 self.change_y = 0
58
59 def update(self):
60 """ Update the sprite. """
61 # Setting the position is faster than setting x & y individually
62 self.position = (
63 self.position[0] + self.change_x,
64 self.position[1] + self.change_y
65 )
66
67 # Bounce the coin on the edge of the window
68 if self.position[0] < 0:
69 self.change_x *= -1
70 elif self.position[0] > SCREEN_WIDTH:
71 self.change_x *= -1
72 if self.position[1] < 0:
73 self.change_y *= -1
74 elif self.position[1] > SCREEN_HEIGHT:
75 self.change_y *= -1
76
77
78class MyGame(arcade.Window):
79 """ Our custom Window Class"""
80
81 def __init__(self):
82 """ Initializer """
83 # Call the parent class initializer
84 super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
85
86 # Variables to hold game objects and performance info
87 self.coin_list: Optional[arcade.SpriteList] = None
88 self.perf_graph_list: Optional[arcade.SpriteList] = None
89 self.fps_text: Optional[arcade.Text] = None
90 self.frame_count: int = 0 # for tracking the reset interval
91
92 self.coin_texture = arcade.load_texture(":resources:images/items/coinGold.png")
93 self.background_color = arcade.color.AMAZON
94
95 def add_coins(self, amount):
96
97 # Create the coins
98 for i in range(amount):
99 # Create the coin instance
100 # Coin image from kenney.nl
101 coin = Coin(self.coin_texture, scale=SPRITE_SCALING_COIN)
102
103 # Position the coin
104 coin.position = (
105 random.randrange(SPRITE_SIZE, SCREEN_WIDTH - SPRITE_SIZE),
106 random.randrange(SPRITE_SIZE, SCREEN_HEIGHT - SPRITE_SIZE)
107 )
108
109 coin.change_x = random.randrange(-3, 4)
110 coin.change_y = random.randrange(-3, 4)
111
112 # Add the coin to the lists
113 self.coin_list.append(coin)
114
115 def setup(self):
116 """ Set up the game and initialize the variables. """
117
118 # Sprite lists
119 self.coin_list = arcade.SpriteList(use_spatial_hash=False)
120
121 # Create some coins
122 self.add_coins(COIN_COUNT)
123
124 # Create a sprite list to put the performance graphs into
125 self.perf_graph_list = arcade.SpriteList()
126
127 # Calculate position helpers for the row of 3 performance graphs
128 row_y = self.height - GRAPH_HEIGHT / 2
129 starting_x = GRAPH_WIDTH / 2
130 step_x = GRAPH_WIDTH + GRAPH_MARGIN
131
132 # Create the FPS performance graph
133 graph = arcade.PerfGraph(GRAPH_WIDTH, GRAPH_HEIGHT, graph_data="FPS")
134 graph.position = starting_x, row_y
135 self.perf_graph_list.append(graph)
136
137 # Create the on_update graph
138 graph = arcade.PerfGraph(GRAPH_WIDTH, GRAPH_HEIGHT, graph_data="on_update")
139 graph.position = starting_x + step_x, row_y
140 self.perf_graph_list.append(graph)
141
142 # Create the on_draw graph
143 graph = arcade.PerfGraph(GRAPH_WIDTH, GRAPH_HEIGHT, graph_data="on_draw")
144 graph.position = starting_x + step_x * 2, row_y
145 self.perf_graph_list.append(graph)
146
147 # Create a Text object to show the current FPS
148 self.fps_text = arcade.Text(
149 f"FPS: {arcade.get_fps(60):5.1f}",
150 10, 10, arcade.color.BLACK, 22
151 )
152
153 def on_draw(self):
154 """ Draw everything """
155
156 # Clear the screen
157 self.clear()
158
159 # Draw all the coin sprites
160 self.coin_list.draw()
161
162 # Draw the graphs
163 self.perf_graph_list.draw()
164
165 # Get & draw the FPS for the last 60 frames
166 if arcade.timings_enabled():
167 self.fps_text.value = f"FPS: {arcade.get_fps(60):5.1f}"
168 self.fps_text.draw()
169
170 def on_update(self, delta_time):
171 """ Update method """
172 self.frame_count += 1
173
174 # Print and clear timings every 60 frames
175 if self.frame_count % 60 == 0:
176 arcade.print_timings()
177 arcade.clear_timings()
178
179 # Move the coins
180 self.coin_list.update()
181
182 def on_key_press(self, symbol: int, modifiers: int):
183 if symbol == arcade.key.SPACE:
184 if arcade.timings_enabled():
185 arcade.disable_timings()
186 else:
187 arcade.enable_timings()
188
189
190def main():
191 """ Main function """
192 window = MyGame()
193 window.setup()
194 arcade.run()
195
196
197if __name__ == "__main__":
198 main()