-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.py
171 lines (127 loc) · 5.13 KB
/
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
import pygame
import random
import time
pygame.init()
#(pygame has 0, 0 at top left)
#colours
BLACK = (0, 0, 0)
DEADCOL = (23, 26, 33)
ALIVECOL = (150, 197, 176)
#environment variables
WIDTH, HEIGHT = 800, 800
TILE_SIZE = 20
GRID_WIDTH = WIDTH // TILE_SIZE
GRID_HEIGHT = HEIGHT // TILE_SIZE
FPS = 60
#init screen
screen = pygame.display.set_mode((WIDTH, HEIGHT))
#clock
clock = pygame.time.Clock()
#generate random positions
def gen(num):
return set([(random.randrange(0, GRID_HEIGHT), random.randrange(0, GRID_WIDTH)) for _ in range(num)])
#draw grid
def draw_grid(positions):
#draw position format: (col, row)
for position in positions:
col, row = position
#top left corner
top_left = (col * TILE_SIZE, row * TILE_SIZE)
pygame.draw.rect(screen, ALIVECOL, (*top_left, TILE_SIZE, TILE_SIZE)) #unpacks top_left and plots TILE_SIZE (X) x TILE_SIZE (Y)
#draw horizontal lines
for row in range(GRID_HEIGHT):
pygame.draw.line(screen, BLACK , (0, row * TILE_SIZE), (WIDTH, row * TILE_SIZE))
#draw vertical lines
for col in range(GRID_WIDTH):
pygame.draw.line(screen, BLACK , (col * TILE_SIZE, 0), (col * TILE_SIZE, HEIGHT))
#updating the grid
def adjust_grid(positions):
#init sets for new cells before replacing old ones
all_neighbours = set()
new_positions = set()
for position in positions:
neighbours = get_neighbours(position) #get neighbours of each position
all_neighbours.update(neighbours) #update all_neighbours with neighbours
neighbours = list(filter(lambda x: x in positions, neighbours)) #filter out neighbours that are in positions
if len(neighbours) in [2, 3]:
new_positions.add(position) #add position to new_positions (keep them) if it has 2 or 3 neighbours
for position in all_neighbours:
neighbours = get_neighbours(position)
neighbours = list(filter(lambda x: x in positions, neighbours))
if len(neighbours) == 3:
new_positions.add(position)
return new_positions
def get_neighbours(pos):
x, y = pos
neighbours = []
for dx in [-1, 0, 1]: #dx = displacement in x
if x + dx < 0 or x + dx > GRID_WIDTH: #if x + dx is out of bounds, skip
continue
for dy in [-1, 0, 1]: #dy = displacement in y
if y + dy < 0 or y + dy > GRID_WIDTH: #if y + dy is out of bounds, skip
continue
if dx == 0 and dy == 0: #if dx and dy are 0, skip
continue
neighbours.append((x + dx, y + dy)) #add neighbour to neighbours
return neighbours
#main loop
def main():
running = True
playing = False
count = 0
update_frequency = 4
start_time = time.time() # Initial start time for the timer
elapsed_time = 0 # Tracks total elapsed time
positions = set() # Init positions as a set
while running:
clock.tick(FPS)
# Only update elapsed time if the game is playing
if playing:
elapsed_time = time.time() - start_time
# Increment count and update the grid if needed
count += 1
if count >= update_frequency:
count = 0
positions = adjust_grid(positions)
# Update the window title with the current game status and timer
pygame.display.set_caption(f"{'Playing' if playing else 'Paused'} - Timer: {int(elapsed_time)} seconds")
# Event handling
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.MOUSEBUTTONDOWN:
x, y = pygame.mouse.get_pos()
col = x // TILE_SIZE
row = y // TILE_SIZE
pos = (col, row)
if pos in positions:
positions.remove(pos)
else:
positions.add(pos)
if event.type == pygame.KEYDOWN:
# Toggle the game state between playing and paused
if event.key == pygame.K_SPACE:
playing = not playing
if playing:
# Resuming: Reset the start time to adjust for the paused period
start_time = time.time() - elapsed_time
else:
# Pausing: Store the current elapsed time
elapsed_time = time.time() - start_time
# Clear positions and reset timer
if event.key == pygame.K_c:
positions = set()
playing = False
start_time = time.time()
elapsed_time = 0
# Generate random positions
if event.key == pygame.K_g:
positions = gen(random.randrange(4, 10) * GRID_WIDTH)
# Drawing and refreshing the screen
screen.fill(DEADCOL) # Fill screen with the background color
draw_grid(positions) # Draws grid after filling screen
pygame.display.update() # Refresh the display
pygame.quit()
#only run main if this file is run
if __name__ == "__main__":
main()