Here’s the first pass I made at a death animation. It’s the simplest thing I could think of that would look OK: the scene fades to black, the player explodes into bits, and you’re prompted to continue. All it’s really missing is a nice exploding sound and a change in music. Have a look below:
I realized after the fact that I accidentally captured the audio of the music I was listening to in the background, and I’m too lazy to re-record it.
The bit where you actually continue doesn’t work yet; prior to this, there was never a point in the game simulation where the player object didn’t exist, so large parts of the game code simply puke their pants when this happens. Now to fix that.
I’ve been back from my international vacation for a couple days, but because of a combination of jetlag and a nasty cold we brought back from abroad, I haven’t had it in me to do any meaningful work. But I’m back, and ready to start crushing this noise. Here is a picture of me chilling next to a sea turtle about 50 feet underwater.
Turtles tear the shit out of reefs and nobody calls them on it
I spent quite a bit of time during this trip relaxing, doing nothing more than thinking. And a lot of the time, I was thinking about the game. For really the first time, I was thinking about not just how I would implement various features, but about how the game world would fit together, and how the lock-and-key semantics that are crucial to the genre will function in that world. To that end, I finalized the list of upgrades the player will collect in the world and assembled a rough map of the major game areas:
The biome / robot manufactory might be combined. We’ll see.
Having this rough plan, and understanding roughly where to create various game areas and what collectible items will allow access to them, will enable me to start building the world map in a serious fashion. I plan to do so using some very basic tiles I found, just to differentiate the various moods and themes of the game world without any attempt at graphical detail. This way I can let my wonderful artistic collaborators catch up to me.
Lots of little bricks make for quick and dirty level design.
The biggest surprise (to me, anyway) is abandoning the traditional “missile” weapon upgrade. You’ll still get a couple firepower upgrades to make your basic weapon more powerful, but unlike in Super Metroid (for example), you won’t have a supply of secondary projectiles (missiles, super missiles, ice missiles, etc.) at your disposal. Instead, I opted for a very powerful but very short-lived beam weapon which travels instantaneously and absolutely liquefies anything in its path, but takes ammo that is very scarce. The weapon fires continuously, and each ammo upgrade will enable it to fire for an additional fraction of a second. By the end of the game, if you manage to find all the upgrades, you’ll be able to shoot it non-stop for a few seconds. Of course, if you’re more judicious with it, it will go a lot farther. To me, this is a lot more interesting of a play dynamic than “just another projectile weapon.”
My proximate goal is to enable player death. I have a prototype of that working, but there are some kinks to iron out. After that, I’ll be crafting the first mini-boss encounter. Hopefully at some point someone volunteers to create some better enemy art for me; it’s gonna look pretty kindergarten-level in the meantime.
It’s a twelve-hour flight from Seattle to Seoul, so I tried to make the most of it by tackling some thorny issues in the game. Even though it’s a situation I wouldn’t usually put myself in willingly, there’s something really nice about being trapped in a seat for twelve hours with no internet access. It makes it easier to stay focused on really stubborn issues like the ones I was determined to solve. And working on my laptop, somewhat less beefy than my desktop at home, is a great way to expose performance issues that I didn’t know I had.
As a first step, I decided it was past time to implement a debug teleportation system, so that I could quickly place myself anywhere on the map. The value of this feature for play testing should be self-evident. Here it is in action:
As you can see, the game doesn’t normally draw anything outside the current room, but when you manually move the viewpoint outside the room it catches on and draws the rest of the world.
One thing that might be hard to notice is that the transition between rooms is quite a bit smoother than it used to be. The room is the fundamental unit of the game world, and room changes are the very important in the simulation. To make physics simulation reasonably fast, only objects in the current room actually exist — when you move between rooms, the game destroys all the simulated bodies in the old room and creates the ones in the new room. On my desktop, this happened fast enough that it wasn’t really noticeable, but on the laptop there was a noticeable stutter every time I went through a door. To address this lag, I changed the room transition code to run in a separate thread so that the camera can move smoothly while it’s occurring. It was a conceptually simple change that was challenging to get right in all the details, but it definitely works a lot better now.
Sadly, I spent most of my time on the long flight dealing with a bug I had recently noticed when destroying a bunch of the landscape, visible in this video:
Around 45 seconds, notice how the character appears to be jumping and landing constantly? That’s because the ground is being created and destroyed under his feet every time a block disappears or reappears. Sadly, Box2d just doesn’t do a very good job managing collisions when bodies are being created and destroyed constantly, and since it’s a continuous floating point simulation it’s inherently unpredictable. The problem above is caused by the game engine erroneously reporting that the character is no longer standing on solid ground, causing him to go into his “falling” animation. As I discovered over the course of long hours debugging at 40,000 feet, the root cause seems to be that the method I was using to determine whether the character is making contact with the ground, involving examining the contacts with his feet, fails about one time in ten when the object he’s standing on didn’t exist in the previous simulation frame. As far as I can tell, there simply is no reliable way to get this information out of Box2d by examining contacts on a body. Ray casting, however, is reliable as ever, and that’s what I eventually gave up and used.
Another subtle bug that I noticed while fixing this one, also visible in the video, is much more mysterious. See how when the character ducks, sometimes he ends up above the ground a bit? As I discovered by painstakingly stepping through this process frame by frame using another debugging utility I built into the game, the problem seems to occur because when the character’s body is resized to its ducking height. Apparently Box2d interprets this change as movement towards the ground, and since the character’s bottom edge is resting against the ground it concludes that there’s a collision that it needs to correct by rebounding the non-static body (the character) upwards. This bug is annoying, but doesn’t seem to be particularly harmful, so I’m considering leaving it alone. I’m tempted to attempt to fix it by destroying and recreating the character’s simulated body instead of resizing it, except I seem to remember that I already tried that and it led to really pernicious bugs like falling through the landscape. Yeah, gonna leave it alone for now.
Next up I’m working on the next major game event, a run-in with the first mini-boss, an automated sentry robot. I have another long flight coming up on Saturday, which will be a good opportunity to get some more work done.
I’ve been corresponding with a couple fine gentlemen who answered the call for pixel artists, and I’m completely blown away how they have stepped up to the challenge. Between the two of them they have basically redrawn the tiles for the entire game — and I haven’t even found a home for some of Kyle’s cave tiles yet. Take a tour of the newly spruced up ship and planet surface:
It looks like a completely new game. It’s kind of unbelievable what a difference a little quality time with some artists makes. I never thought I would get such high quality work from volunteers! Thanks a ton, contributors!
I also filled in the bottom surface of the ship, and you can see how it settled into the rocky terrain when it crash landed.
Tomorrow I’m going on a two-week trip to Seoul and Indonesia, so except for long plane rides I’ll be out of touch with game work. Let’s hope I can get a few updates in on the road!
Thanks to Kevin Fishburne for these rocky tiles! I think they look pretty great!
The only real issue with these tiles is the lack of an “interior corner” tile to handle convex corners in the terrain, illustrated below:
It would also be great to have some interior (non surface) tiles to make the inside of rock formations a bit more dynamic, but fading into black is doable as well, and I should really quit looking this gift horse in the mouth.
Just a quick video showing the map work I was experimenting with today. There’s a good size mountain to climb over, but it can be tunneled through as well.
I also finally took the time to compose an artwork contribution page so that people who want to get up all up in my grill saying they can make better artwork than me can prove themselves right, much to everyone’s vast relief. Seriously, come show me how much better my game would look if you were drawing the tiles. PLEASE.
It’s also worth noting that I scrapped at least a half week’s work of detailed camera fiddling in favor of a far simpler algorithm that performs better anyway. I really hope that was the last time I need to mess with the camera system, but I know it won’t be.
I suck so bad at it that I’m still at the phase where I can hardly know where to begin. Finally I decided to kickstart the process and appropriated some artwork from OpenGameArt.org. It’s a very pixelated terrain tileset with an 8×8 base resolution. It looks like this:
Sadly, the author packaged it with 2 pixels of padding between tiles, which means that my own tileset padder can’t work with it. It also can’t be imported for editing with PyxelEdit. This is a perfect example of how everything always takes longer than you think it will, even when you know that everything will always take longer than you think it will.
I had a few options to get the tileset into the game:
Modify the tileset padder tool to accept a padding argument. This seemed like a lot of work for such a small task.
Edit the image in a paint program, eliminating the padding. This too seemed way too complicated.
Import the individual sprites one by one into PyxelEdit, then import all those .pyxel files into one merged tileset.
The last option was tedious, but still way faster than either of the other two. But I have a feeling in another few weeks I’ll have to do this again and I’ll wish I had modified the tool in the first place.
Anyway, I finally got the tiles imported into the map, and you can see them in action below:
I must say, I’m kind of liking the super pixelated look of this tileset! But I’m torn. The tiles I drew for the ship have an effective 16×16 base resolution, or 4 times the ones outside. Keep in mind that the game uses a 64×64 tile size, so it’s the difference between an effective 4X pixelation factor and an 8X pixelation factor. It’s a huge difference, and something I probably need to standardize on to avoid any jarring contrast. Any thoughts on which resolution is better? Let me know in the comments!
I’m excited to really start filling the world in and populating it with enemies. It’s still so small!
But it looks even smaller in the context of the game world’s scope. Each of the boxes in the map below represents one screen width and height of the game world.
I thought it was high time I finally recorded some gameplay video with the newly functional music system working, so I did that. It turned into a six-minute intro to what the first moments of the game will look like, with all the opening cutscene dialog at a readable speed. The music definitely makes a big difference in setting the scene. Have a look below:
Thanks to Roark Brewster and Max Cheswick for the featured musical tracks. The mixing is still a little out of whack — the sound effects are too loud relative to the music. That’s work I can put off for the moment, though. Next up, it’s time to get down to serious business drawing up some maps for the first area of the game outside the ship.
I worked on the background music system today, since I didn’t have it in me to dive back into pixel art again quite yet — and I got all the hard bits figured out. But since “now there is music playing” is an uninteresting video, I made one of the improved item collection announcement. See it below:
I also wrote a bunch more NPC dialog and fixed several nasty bugs, but those likewise don’t make for interesting watching.
Streaming music with XNA is pretty easy to do and hard to figure out, like a lot of things in XNA. Here are the basic steps:
Convert your music mp3s to raw .wav files. That’s right, XNA streaming supports only WAV files, and you’re far too lazy to write your own audio streaming library. I found this free mp3 decoder to be quite adequate.
Next, you’re going to want to run the Cross Platform Audio Creation Tool (XACT) that comes with XNA. It’s in there, trust me. Dig. Then skim your way through this video to learn the basics of the tool.
Then, in order to listen to any of the audio files in XACT, start up the XACT Auditioning Utility, a separate service that also comes with XNA.
Finally, after swatting down the inevitable errors in the XNA content pipeline configuration, you’re ready to start where the XNA docs on this subject begin. Don’t worry, the sample project code doesn’t compile, so you won’t be distracted.