Grid Using Sprites v1

You may also want to look at:
Array-Backed Grid - very slow but simple, uses drawing commands
Array-Backed Grid Buffered - slow and uses buffered shapes
Grid Using Sprites v1 - (This program) super-fast and uses sprites. Resyncs to number grid in one function call
Grid Using Sprites v2 - super-fast and uses sprites. Keeps a second 2D grid of sprites to match 2D grid of numbers
array_backed_grid_sprites_1.py
1"""
2Array Backed Grid Shown By Sprites
3
4Show how to use a two-dimensional list/array to back the display of a
5grid on-screen.
6
7This version syncs the grid to the sprite list in one go using resync_grid_with_sprites.
8This is faster than rebuilding a shape list every time the grid changes,
9but we are still inspecting every single cell of the grid when it updates.
10There are faster ways, but this works for smaller grid sizes.
11
12If Python and Arcade are installed, this example can be run from the command line with:
13python -m arcade.examples.array_backed_grid_sprites_1
14"""
15import arcade
16
17# Set how many rows and columns we will have
18ROW_COUNT = 15
19COLUMN_COUNT = 15
20
21# This sets the WIDTH and HEIGHT of each grid location
22WIDTH = 30
23HEIGHT = 30
24
25# This sets the margin between each cell
26# and on the edges of the screen.
27MARGIN = 5
28
29# Do the math to figure out our screen dimensions
30WINDOW_WIDTH = (WIDTH + MARGIN) * COLUMN_COUNT + MARGIN
31WINDOW_HEIGHT = (HEIGHT + MARGIN) * ROW_COUNT + MARGIN
32WINDOW_TITLE = "Array Backed Grid Example"
33
34
35class GameView(arcade.View):
36 """
37 Main application class.
38 """
39
40 def __init__(self):
41 """
42 Set up the application.
43 """
44 super().__init__()
45
46 # Create a 2 dimensional array. A two dimensional
47 # array is simply a list of lists.
48 # This array can be altered later to contain 0 or 1
49 # to show a white or green cell.
50 #
51 # A 4 x 4 grid would look like this
52 #
53 # grid = [
54 # [0, 0, 0, 0],
55 # [0, 0, 0, 0],
56 # [0, 0, 0, 0],
57 # [0, 0, 0, 0],
58 # ]
59 # We can quickly build a grid with python list comprehension
60 # self.grid = [[0] * COLUMN_COUNT for _ in range(ROW_COUNT)]
61 # Making the grid with loops:
62 self.grid = []
63 for row in range(ROW_COUNT):
64 # Add an empty array that will hold each cell
65 # in this row
66 self.grid.append([])
67 for column in range(COLUMN_COUNT):
68 self.grid[row].append(0) # Append a cell
69
70 # Set the window's background color
71 self.background_color = arcade.color.BLACK
72 # Create a spritelist for batch drawing all the grid sprites
73 self.grid_sprite_list = arcade.SpriteList()
74
75 # Create a list of solid-color sprites to represent each grid location
76 for row in range(ROW_COUNT):
77 for column in range(COLUMN_COUNT):
78 x = column * (WIDTH + MARGIN) + (WIDTH / 2 + MARGIN)
79 y = row * (HEIGHT + MARGIN) + (HEIGHT / 2 + MARGIN)
80 sprite = arcade.SpriteSolidColor(WIDTH, HEIGHT, color=arcade.color.WHITE)
81 sprite.center_x = x
82 sprite.center_y = y
83 self.grid_sprite_list.append(sprite)
84
85 def resync_grid_with_sprites(self):
86 """
87 Update the color of all the sprites to match
88 the color/stats in the grid.
89
90 We look at the values in each cell.
91 If the cell contains 0 we assign a white color.
92 If the cell contains 1 we assign a green color.
93 """
94 for row in range(ROW_COUNT):
95 for column in range(COLUMN_COUNT):
96 # We need to convert our two dimensional grid to our
97 # one-dimensional sprite list. For example a 10x10 grid might have
98 # row 2, column 8 mapped to location 28. (Zero-basing throws things
99 # off, but you get the idea.)
100 # ALTERNATIVELY you could set self.grid_sprite_list[pos].texture
101 # to different textures to change the image instead of the color.
102 pos = row * COLUMN_COUNT + column
103 if self.grid[row][column] == 0:
104 self.grid_sprite_list[pos].color = arcade.color.WHITE
105 else:
106 self.grid_sprite_list[pos].color = arcade.color.GREEN
107
108 def on_draw(self):
109 """
110 Render the screen.
111 """
112 # We should always start by clearing the window pixels
113 self.clear()
114
115 # Batch draw all the sprites
116 self.grid_sprite_list.draw()
117
118 def on_mouse_press(self, x, y, button, modifiers):
119 """
120 Called when the user presses a mouse button.
121 """
122
123 # Convert the clicked mouse position into grid coordinates
124 column = int(x // (WIDTH + MARGIN))
125 row = int(y // (HEIGHT + MARGIN))
126
127 print(f"Click coordinates: ({x}, {y}). Grid coordinates: ({row}, {column})")
128
129 # Make sure we are on-grid. It is possible to click in the upper right
130 # corner in the margin and go to a grid location that doesn't exist
131 if row >= ROW_COUNT or column >= COLUMN_COUNT:
132 # Simply return from this method since nothing needs updating
133 return
134
135 # Flip the location between 1 and 0.
136 if self.grid[row][column] == 0:
137 self.grid[row][column] = 1
138 else:
139 self.grid[row][column] = 0
140
141 # Update the sprite colors to match the new grid
142 self.resync_grid_with_sprites()
143
144
145def main():
146 """ Main function """
147 # Create a window class. This is what actually shows up on screen
148 window = arcade.Window(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_TITLE)
149
150 # Create the GameView
151 game = GameView()
152
153 # Show GameView on screen
154 window.show_view(game)
155
156 # Start the arcade game loop
157 arcade.run()
158
159
160if __name__ == "__main__":
161 main()