康威的生活游戏#
这个版本的Conway的生活游戏通过控制单元格的Alpha值来控制单元格的可见性,并将绘图逻辑交给图形卡,从而加快了速度。
基于网格的游戏可能需要一段时间才能使用经典的基于栅格的图形来渲染程序。每个单元格都必须在每一帧中重新绘制。如果单元格非常复杂,则会增加渲染时间。
在本程序中,我们首先创建网格中的所有单元格。(这会导致程序在启动时暂停一段时间。)
创建精灵后,我们根据其Alpha值打开和关闭单元格。我们只需将Alpha值列表发送到图形卡,即可更新整个网格。这显著缩短了绘制时间。
conway_alpha.py#
1"""
2Conway's Game of Life
3
4This code shows how to set up sprites in a grid, and then use their
5'alpha' value to quickly turn them on and off.
6
7After installing the "arcade" package version 2.4.4+, this program can be run by
8typing:
9python -m arcade.examples.conway_alpha
10"""
11import arcade
12import random
13
14# Set how many rows and columns we will have
15ROW_COUNT = 70
16COLUMN_COUNT = 128
17
18# This sets the WIDTH and HEIGHT of each grid location
19CELL_WIDTH = 15
20CELL_HEIGHT = 15
21
22# This sets the margin between each cell
23# and on the edges of the screen.
24CELL_MARGIN = 0
25
26# Do the math to figure out our screen dimensions
27SCREEN_WIDTH = (CELL_WIDTH + CELL_MARGIN) * COLUMN_COUNT + CELL_MARGIN
28SCREEN_HEIGHT = (CELL_HEIGHT + CELL_MARGIN) * ROW_COUNT + CELL_MARGIN
29SCREEN_TITLE = "Conway's Game of Life"
30
31# Colors and alpha values
32ALIVE_COLOR = arcade.color.BISTRE
33BACKGROUND_COLOR = arcade.color.ANTIQUE_WHITE
34ALPHA_ON = 255
35ALPHA_OFF = 0
36
37
38def create_grids():
39 """
40 Create a 2D and 1D grid of sprites. We use the 1D SpriteList for drawing,
41 and the 2D list for accessing via grid. Both lists point to the same set of
42 sprites.
43 """
44 # One dimensional list of all sprites in the two-dimensional sprite list
45 grid_sprites_one_dim = arcade.SpriteList()
46
47 # This will be a two-dimensional grid of sprites to mirror the two
48 # dimensional grid of numbers. This points to the SAME sprites that are
49 # in grid_sprite_list, just in a 2d manner.
50 grid_sprites_two_dim = []
51
52 # Create a list of sprites to represent each grid location
53 for row in range(ROW_COUNT):
54 grid_sprites_two_dim.append([])
55
56 for column in range(COLUMN_COUNT):
57
58 # Make the sprite as a soft circle
59 sprite = arcade.SpriteCircle(CELL_WIDTH // 2, ALIVE_COLOR, soft=True)
60
61 # Position the sprite
62 x = column * (CELL_WIDTH + CELL_MARGIN) + (CELL_WIDTH / 2 + CELL_MARGIN)
63 y = row * (CELL_HEIGHT + CELL_MARGIN) + (CELL_HEIGHT / 2 + CELL_MARGIN)
64 sprite.center_x = x
65 sprite.center_y = y
66
67 # Add the sprite to both lists
68 grid_sprites_one_dim.append(sprite)
69 grid_sprites_two_dim[row].append(sprite)
70
71 return grid_sprites_one_dim, grid_sprites_two_dim
72
73
74def randomize_grid(grid: arcade.SpriteList):
75 """ Randomize the grid to alive/dead """
76 for cell in grid:
77 pick = random.randrange(2)
78 if pick:
79 cell.alpha = ALPHA_ON
80 else:
81 cell.alpha = ALPHA_OFF
82
83
84class MyGame(arcade.Window):
85 """
86 Main application class.
87 """
88
89 def __init__(self, width: int, height: int, title: str):
90 """
91 Set up the application.
92 """
93 super().__init__(width, height, title)
94
95 self.background_color = BACKGROUND_COLOR
96
97 # We need two layers. One holds the current state of our grid, the other
98 # holds the next frame's state. We flip back and forth between the two.
99 grid_sprites_one_dim1, grid_sprites_two_dim1 = create_grids()
100 grid_sprites_one_dim2, grid_sprites_two_dim2 = create_grids()
101
102 self.layers_grid_sprites_one_dim = [grid_sprites_one_dim1, grid_sprites_one_dim2]
103 self.layers_grid_sprites_two_dim = [grid_sprites_two_dim1, grid_sprites_two_dim2]
104
105 self.cur_layer = 0
106 randomize_grid(self.layers_grid_sprites_one_dim[0])
107
108 def on_draw(self):
109 """ Render the screen. """
110 # Clear all pixels in the window
111 self.clear()
112 self.layers_grid_sprites_one_dim[0].draw()
113
114 def on_update(self, delta_time: float):
115 """ Update the grid """
116
117 # Flip layers
118 if self.cur_layer == 0:
119 layer1 = self.layers_grid_sprites_two_dim[0]
120 layer2 = self.layers_grid_sprites_two_dim[1]
121 self.cur_layer = 1
122 else:
123 layer1 = self.layers_grid_sprites_two_dim[1]
124 layer2 = self.layers_grid_sprites_two_dim[0]
125 self.cur_layer = 0
126
127 # Count the neighbors that are alive
128 for row in range(ROW_COUNT):
129 for column in range(COLUMN_COUNT):
130 live_neighbors = 0
131 # -1 -1
132 if row > 0 and column > 0 \
133 and layer1[row - 1][column - 1].alpha == ALPHA_ON:
134 live_neighbors += 1
135 # -1 0
136 if row > 0 and layer1[row - 1][column].alpha == ALPHA_ON:
137 live_neighbors += 1
138 # -1 +1
139 if row > 0 and column < COLUMN_COUNT - 1\
140 and layer1[row - 1][column + 1].alpha == ALPHA_ON:
141 live_neighbors += 1
142 # 0 +1
143 if column < COLUMN_COUNT - 1 \
144 and layer1[row][column + 1].alpha == ALPHA_ON:
145 live_neighbors += 1
146 # +1 +1
147 if row < ROW_COUNT - 1 \
148 and column < COLUMN_COUNT - 1 \
149 and layer1[row + 1][column + 1].alpha == ALPHA_ON:
150 live_neighbors += 1
151 # +1 0
152 if row < ROW_COUNT - 1 and layer1[row + 1][column].alpha == ALPHA_ON:
153 live_neighbors += 1
154 # +1 -1
155 if row < ROW_COUNT - 1 and column > 0 \
156 and layer1[row + 1][column - 1].alpha == ALPHA_ON:
157 live_neighbors += 1
158 # 0 -1
159 if column > 0 and layer1[row][column - 1].alpha == ALPHA_ON:
160 live_neighbors += 1
161
162 """
163 Implement Conway's game of life rules
164
165 Any live cell with two or three live neighbours survives.
166 Any dead cell with three live neighbours becomes a live cell.
167 All other live cells die in the next generation. Similarly, all other dead cells stay dead.
168 """
169 if layer1[row][column].alpha == ALPHA_ON and (live_neighbors == 2 or live_neighbors == 3):
170 if layer2[row][column].alpha == ALPHA_OFF:
171 layer2[row][column].alpha = ALPHA_ON
172 elif layer1[row][column].alpha == ALPHA_OFF and live_neighbors == 3:
173 if layer2[row][column].alpha == ALPHA_OFF:
174 layer2[row][column].alpha = ALPHA_ON
175 else:
176 if layer2[row][column].alpha == ALPHA_ON:
177 layer2[row][column].alpha = ALPHA_OFF
178
179
180def main():
181 """ Main function - starting point to the program """
182 window = MyGame(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
183 window.center_window()
184 arcade.run()
185
186
187if __name__ == "__main__":
188 main()