Asteroid Shooter
- 7 Devlogs
- 14 Total hours
Simple asteroid shooter game in Pygame(-ce)
Simple asteroid shooter game in Pygame(-ce)
I have done a lot and decided to just bundle it into one last big devlog, but the work was well worth it!
0.005. This makes it so that asteroids spawn 50% faster by the time the player gets to score 100../src directory last-minute. The hard part about this was that I switched to Linux a few days before making this project, so I didn’t have another machine to compile the Windows version of the release. At first I found a guide that I could do it through Wine, and then I had to install a Docker image of Ubuntu that had it all set up, but it ended up not working. I ended up just setting up a Windows 11 virtual machine using Gnome Boxes (much easier than having to set up QEMU). It took me a while but it should work. It runs as expected on the VM (Windows Defender notification will pop up but that’s a problem with PyInstaller).I’m probably missing some stuff, as this was quite a while, but yeah. The game is finished.
Quite a few improvements, though the codebase gets even more convoluted.
Explosion class, and tracking delta-time against a set lifespan. An explosion will last 1/10th of a second, which I think is good enough.paused that is False by default. I also have the main menu, which is True by default and is only toggled at the beginning. Finally, I have one for the game over screen, which is False by default and only toggles when the player has no more lives left. When any of these are True, the sprites will not update, and the game will only listen for input.Overall, the game is basically done and I just need to polish it. I will likely be redrawing the sprites next.
Lots of improvements!
Game class. This makes it generally easier, as now I don’t have to wire so many variables between functions and all.It’s coming along great!
I made some pretty simple changes to the overall codebase but now it’s much cleaner.
settings.py file, I moved them into attributes of their own classes.__init__ method of their classes. Previously, I was under the impression that this was not possible because you needed to run pygame.init() before you used the .convert() (and similar) methods after loading the image. However, I was putting it outside of the class, so it would always run before running pygame.init(). This overall makes the code much cleaner, as now I don’t have to load in the sprites in the main file. Also, it was getting quite challenging to deal with figuring out ways to pass sprites into functions like player.shoot() so that it would spawn in a Bullet correctly..convert_alpha() instead of .convert(), which allows the sprites to have transparency (as seen in picture 2). I had been saving all of the sprites as .png files, but they had a black background when overlapping with other sprites (as seen in picture 3). With this, it actually allows for transparency and looks much nicer.Bullet class but falling downwards. Pygame has this really nice feature where I can check for all collisions between all sprites from any 2 groups like so. pygame.sprite.groupcollide() takes in 2 sprite groups (pygame.sprite.Group), 2 booleans representing whether to remove the sprite right after, and a callback function. This will be useful later for adding explosions and score. They also spawn at a constant interval regardless of FPS. I did that by using delta-time and adding a counter to get the amount of milliseconds since the last frame. A meteor will spawn every 250 milliseconds. I find that this is a playable amount for now.Next thing to do is to add lives and subtract them when the player gets hit with a meteorite.
I made some pretty drastic changes, but for the better.
Player class have its own .shoot() method, but that required me to pass the sprite Group object, as well as the actual sprite image into the function. I searched for a “better” solution for a while but ultimately couldn’t find one. The shoot() method handles the placement, the creation of the Bullet object, and adding it into the Group.assets folder instead of data, because I won’t be storing anything other than sprites and maybe sounds. Also, I will store the .ase files for the sprites just in case, so that I can fully edit them in Aseprite if there are any layers. The one roadblock I came across here was that the paths to the assets were kind of confusing, but I figured it out quickly.Overall, I think it’s coming along great!
Again it takes longer than I would’ve thought, but I implemented movement. To be honest, the movement part was actually the easiest thing and I spent most of the time fighting with ty (the LSP/type checker).
Player class have a custom update() method. Inside, I check for the currently pressed keys and then use an if-statement to eddit the coordinates there. This makes the whole thing much smoother, as with the former option it would be choppy and wouldn’t let you keep holding down the key. Also, when I add the other entities (asteroids), I can make it have its own update() method, and that can be called as well. I am using this cool feature called pygame.sprite.Group, which lets me have a set of sprites and update and draw them all simultaneously. The player can be moved with the left and right arrow keys or A and D. I made it so that if they are both pressed the player will not move at all.
rect attribute of pygame.sprite.Sprite to pygame.Rect | pygame.FRect | None, which causes ty to throw an error because None has no attributes. First, I tried ignoring all errors of that type by setting them to "ignore" in the ty configuration, but then I figured out I could just set the rect attribute to pygame.Rect | pygame.FRect inside the entity class, and that fixed the issue.It’s a little complex as of right now because of the sort of unique way Pygame projects are structured, but I think it’s coming along very well.
This took somewhat longer than I would’ve expected, but first devlog!