You are browsing as a guest. Sign up (or log in) to start making projects!

Game of Life

  • 9 Devlogs
  • 9 Total hours

Conway's Game of Life implementation in Pygame

Ship #1

I implemented Conway's Game of Life in pygame(-ce). This took me quite a while because it is my first time working in pygame. I added features like controlling the flow of the simulation (pausing, going forward one generation, unpausing, speed), and themes. There is a statusline showing the current generation, speed, etc. There is a window showing the keybinds. Both can be toggled. I learned about the basics of Pygame, Pyinstaller, UI/UX design, and general programming.

  • 9 devlogs
  • 9h
  • 11.70x multiplier
  • 105 Stardust
Try project → See source code →
Open comments for this post

48m 19s logged

Just added a new thing to allow shift+left clicking, because dragging right click wouldn’t work on my laptop. This kind of took a while to implement because Pygame is weird, but I got it and now it works on laptops too! I don’t know if this is specific to only mine, but it’s also just easier to play the game on a laptop now. Also, I figured out how to package it into an executable. Pyinstaller is a pain to work with, and it took me a while too, but I got it. At first it was 50 megabytes but I got it to ignore some of the libraries from Pygame so now it’s 15-25, which seems to be normal.

0
0
4
Open comments for this post

20m 6s logged

I think this is the final devlog! I added a (relatively) small message to show the keybinds. It’s on by default, for new users. I also made the text bigger and changed the statusline from “updates/sec” to “gens./sec.” (abbreviated).

0
0
4
Open comments for this post

1h 32m 8s logged

Ok… The scope gets even bigger. I did A LOT of work this time, in very small but meaningful changes. Tl;dr: I improved the code, made the project look nicer, changed some of the keybinds, and made it much better to use.

  • Various code improvements: The code is generally cleaner now. I took the time to go over the if-statements and such, and then remove unnecessary things. I also split it up into several different files. As of right now, I have one to store the main Board class (board.py), one for the themes (themes.py), and then the main.py file stores the main while loop.
  • Visual changes: I made some visual changes that I think make the project nicer.
    • Instead of the gray bar at the bottom, I put the status line at the top left corner and made it toggleable by a keybind. I think I might put a rectangle behind it to make it look cooler and distinguish it from the white cells in the default theme (at the moment if there are squares there you won’t be able to see the text.
    • I changed the title bar. This was fairly straightforward, only 2 lines of code. I made screenshots of the glider in all the different themes, so now it will pick a random one for the icon at startup.
  • Performance improvements: I wasn’t really sure what to name this category, though the project probably won’t be the most performant thing ever… On a slightly older laptop it took ~10% of the CPU (Ryzen 5 5500U) and 100MB ram. Anyways, the main thing here is that the FPS is now separate from the speed of the simulation. I had to do this because the dragging was very choppy and would skip a lot of cells when the FPS was low. To fix this, I started tracking the delta-time (the amount of time since the clock tick at the end of the main while loop last updated). I was then able to add it to a counter variable every time the while loop ran. By comparing that counter value to my set interval, I am able to control how many times per second the simulation is ran. Thus, I set the FPS to 120, which is pretty smooth and not as resource-intensive as 256 (small difference, but eh). By default, the simulation will run 8 times per second.
  • Keybind changes:
    • The s key toggles the statusline.
    • The n key runs the simulation for one generation.
    • The c key clears the board (did I mention that before?).
    • The + and - keys have been unbound. I felt they weren’t that necessary.
    • Keys 1-7 change the presets from 1 generation/second, and doubling until 64/s. I felt any more than that was unnecessary and it wouldn’t refresh anyways because the FPS is 120. Could let the user change it in the future.

I’ve been telling myself that I am close to finishing the project, but I keep adding new things. I’m sure I’ll find a new feature to add.

0
0
4
Open comments for this post

1h 8m 41s logged

Quite a bit done here, but a lot of progress, and I think I’m almost ready to ship.

  • I added a counter for the generation. It isn’t very useful, but still nice to have.
  • I found the idea of a menu to be unnecessary, so I made a little 10-pixel tall statusline that shows the running status, current generation, and FPS. Quite easy to make, I just added 10 to the window height and then wrote a function to put text on that strip.
  • I added some new keybinds:
    • The g key can be pressed to toggle the grid (forgot to show it in the video, unfortunately).
    • The t key can be pressed to change the theme.
  • I added themes! Because the Board.draw() method was already flexible, this was very straightforward. First, I got ChatGPT to generate a list of themes (nothing more). Then, I made a new variable to keep track of the current theme index. That variable gets increased when the t key is pressed, and then the keys of the theme are bassed to the Board.draw() method.

To conclude, I think I am very close to finally shipping this small project! I will continue to make some more small changes and improvements.

0
0
3
Open comments for this post

29m 8s logged

This was fairly straightforward. I added a bunch of quality of life features for the simulation.

  • Clearing the screen (c) fills the board with the same 2-dimensional array filled with False as the default board.
  • Speed up (+) and down (-) set the FPS up or down 1 and then it is passed into clock.tick() at the end of the main while loop.
    • Speed presets (1-9) set the FPS to the corresponding index of an array of settings. As of right now, it’s just a sequence of powers of 2 from 1 to 256, but I might change it to something more ergonomic. I like this one because I use one if statement to handle all 9 keys.
  • Pausing (space) as promised earlier. This just toggles a variable that is False by default, and then I am checking if it’s True later.

Next I am going to add a small menu that will display important information like the number of the generation, as well as the presets. I want it to be hideable so as to not block it, but I also want the board to be the whole screen, so it’s going to be a small window. Then, maybe, tapping into the flexibility of my custom draw() function and adding preset colorschemes?

P.S.: Here is a better recording that showcases the simulation… The last post didn’t do it very much justice…

0
0
1
Open comments for this post

2h 35m 52s logged

I got the rules working! This was probably the hardest part yet, honestly.

  • First, the function to count the live neighbors of a cell took an embarrassingly long amount of time. After a bunch of iterations, I settled on looping through a list of tuples representing offsets for the x and y “coordinates” of the cell. I had to check for the bounds, too, since there are cells on the edges and it will fail if I count those as neighbors too.
  • The function to actually run the simulation, or making a cell live or die based on the rules, was less hard. I implemented the rules fairly quickly from the Wikipedia page on the game, though the wording was kind of tricky. There was this bug early on where the cells would glitch out and not update correctly, and I was able to fix it by creating a copy of the grid and changing that instead, then “pushing” it to the screen all at once.

Overall, I think the project is turning out nicely. Next, I will implement a pause feature so that I can draw stuff and see how it plays out instead of hardcoding it for testing.

0
0
2
Open comments for this post

57m 47s logged

I implemented clicking and dragging! This was somewhat more complicated than I thought it would be, but not hard in retrospect.

The clicking itself was quite easy. It was just a matter of listening for the click event, and then I implemented a function to find the position of the cell under the mouse position and toggle it.

The dragging was a bit harder, though. When I first got it working (shown in the second video), it was choppy. The main issues that I saw were:

  • I can drag but it’s generally interrupted;
  • dragging just a little bit repeatedly toggles the cell;
  • and I can move my cursor off the window and, it will still toggle the cells but sort of wrapped around.

Interestingly, the last one only seemed to happen when I was dragging my cursor and then moved the mouse out of the window but only on the right side.

I ended up solving the issue by adding some checks and making dragging only make the cells alive. This resulted in the first video, which is much cleaner.

I like how this is turning out!

1
0
4
Open comments for this post

48m 53s logged

I changed it to use a main class for the whole board.

The class contains a 2-dimensional array of booleans. This lets me access a specific cell from a coordinate like pygame’s coordinates, where x goes right and y goes down, as shown in the picture attached.

I also changed the draw function to be much more versatile. First, I am now using the rectangle function, which will let me color specific cells much easier. Also, I have some future customizability options with the colors of the borders, as well as either state of the cell.

0
0
4
Open comments for this post

17m 49s logged

This is my first time using pygame. I was able to get a very basic window with a grid. For the grid, I used a simple for loop that draws a horizontal line and a vertical line.

0
0
6

Delete project?

Are you sure you want to permanently delete this project? This action cannot be undone.

All devlogs, followers, and associated data will be removed.

Followers

Loading…