I’ve always had a soft spot in my heart for scrolling space shooters. One of my favorites is Tyrian. I know I’m not alone in exclaiming how good this game is. Heck, any game that allows you to fly around in a “Super Carrot” while shooting hot dog projectiles is a winner in my book. I enjoy them so much that I decided to make one of my own.
If you’re looking for more great Tyrian artwork, do check out Daniel Cook’s blog, Lost Garden. He has put up most of the artwork for free. Our boss ship came from his free graphics dump in his postmortem of Hard Vacuum. Thanks, Daniel!
My favorite shooter of more recent times is Jets’n'Guns by the Czech indie dev team, Rake in Grass. The difficulty level is perfect, the sound is spot-on and the visuals are amazing. It is a game that I keep coming back to no matter how many times I beat it. Do yourself a favor and check it out.
In June of 2008 my friend, Robert, and I started working on what we called PewPew Shooter. We obviously stepped way into clever-creative land with the name. We weren’t setting out to develop anything revolutionary or never-before-seen in the shooter world. We just wanted a space shooter game.
We worked on it in our down-time off and on for about 3 months. We knew early on that we were eager to get something up and running quickly, so we decided to use Microsoft’s XNA Framework to develop it. We were able to get a working demo going within a matter of days. Here is a video of it after just 3 days of work.
Some features of the engine we ended up creating include:
- Geographic Grid Registration
We had the potential to have a large number of entities on the screen and doing collision detection on all of them was costly. We ended up creating a class that would manage the entities for us that grouped entities by where they were on the screen. This saved us a huge amount in iterating over the enemies when checking for collisions. Instead of comparing a player’s shot projectile to all entities we just compared it to all entities in its own and neighboring grid locations.
- Collision Detection
We opted to not do sweep tests for our collision detection. Instead we decided to try to design around needing to do too much work for the collision detection. We chose to not have anything move at so great of a speed that an intersection should occur but would be overlooked because the two object might swap places. We ended up simply testing for collisions after moving everything each frame.
We started out with a simple bounds check but then we started adding shapes that fit the theme of the game better than squares or circles. So we had to check alpha pixels and make sure that the collision wasn’t between two invisible pieces of the objects. This worked fine until we introduced a large meteor object. This meteor was considerably larger than anything we’d put into the game up to that point and we immediately saw a large slow down whenever an object intersected with the rectangle bounds of the meteor.
At the time the algorithm checked every pixel of object A against every pixel of object B to see if they were above a certain threshold. This ensured that transparent pixels didn’t cause a collision. I reworked the algorithm so that it only checked each pixel of the actual overlapped rectangle of each object. This made the game playable with large meteors and increased framerate overall as most object that were getting collision checked were small projectiles against large ships. The most amount of pixels we’d ever have to check was n * n where n is the number of pixels in the smallest object. This is much better than n * m (m>n) where m is the number of pixels in the larger image. In reality, it averaged out to less than n * n as the smaller object wasn’t always completely overlapped by the larger object.
- Local Multiplayer
Multiple players wasn’t something that we thought about early in the development but, as it turned out, it didn’t end up being too dificult to add in. We tried to keep a lot of our functions that involved enemies picking targets and entities tracking entities’ movements pretty generic. This worked out well for us when we added a second player because the functions didn’t have to be modified at all and the enemies automatically started firing at random players (which they were doing all along, except there was just one to choose).
Theoretically we could support an arbitrary amount of players until we hit the max the CPU could process in a frame and the enemies and tracking powerups would work fine. In the end adding multiple players was only a couple hours worth of work. Two players are able to enjoy the game on a single keyboard.
- Particle Engine
I can’t take credit for the particle engine. But it was a very attractive addition. Our early explosion animation was a little kludgy and didn’t look all that great. Once I got JimJams’ Mercury Particle Engine integrated we were able to have attractive explosions and projectile trails. The addition of the particle engine was a nice visual touch.
- Level Editor
I took a day to write a level editor supported saving and loading of levels. It wasn’t fancy, but it made the process of creating a level much easier than the previous method, which was editing an xml file by hand. It also allowed us to somewhat visualize the levels as we were creating them. The best solution would have been to build the editor into the engine, but we didn’t take the time to do that.
We both learned a lot working on this project. More importantly, we had an awesome time developing PewPew. In the end we had to stop production as life stuff came up. If I get some free time I’ll try to figure out what licensing obligations I have by using Mercury and try to get the code put up online.
In the meantime, enjoy some pictures.