Tuesday, 2 May 2017

Teach Yourself Game Programming in 21 Days - Day 4

Annoying, this chapter is named Getting Sprite to the Point. It is an important one, though.

"Admittedly, a sprite is well-known to be a little elven creature from mythology." Yeah, good start. This is where the library development starts to get serious. Not only does it deal with moving graphics around the screen, it also contains code for loading the hilariously old PCX graphics format.

Dealing with PCX files is a little annoying, because they use run-length encoding to compress their data. BMP files can do this too (an early Windows graphics format) but it's optional, whereas pretty much every PCX file out there is going to be encoded. It's not a particularly difficult task to decode them, but it's there. Still, this does introduce the idea of having to process files from common design formats to use in a game. An engine which really cares about loading time would save this post-processed format as its own file, for more speed.

Here's what makes a sprite, according to André:
Most of the fields should be self-explanatory, but he comments them anyway. It will take a long time for the book to use all of these. Still, almost everything you could think of is doable with this base definition, and everything else could be attached to that extra_data field if you need to. As a side note, I don't like the whole "define a pointer typedef" thing, I'd rather just see sprite*. Ho hum.

"Unless you want to algorithmically generate images for your games, [...]" Haha! Before I go on, it's worth talking about this. There aren't all that many games out there that generate images algorithmically, but it's incredibly common to run into so-called roguelite games these days; randomly generated dungeons and items and so on have found their way into blockbusters like Diablo and The Binding of Isaac. Spore is an example of a game which generates models algorithmically, which is pretty neat.

Anyway. "[...] you'll have to draw them using some kind of bit-map paint program that works with mode 13h. My favourite is Deluxe Paint (Dpaint) and Deluxe Animation (DA), both from Electronic Arts." Wow, remember when Electronic Arts made things other than FIFA games? I remember Dpaint because I used to have it on the Amiga, but I've never used the DOS version. Seeing as I'm missing the companion CD, I had to make my own (terrible) graphics, and I used Usenti, which can save to PCX for some reason. Possibly because it's easy to import into games. 8)

Next, the author explains how to use an image as a sprite-sheet, a useful technique which is still used today in pretty much every 2D game. Essentially, parts of the image are separated into (usually) equal-sized cells. These cells are then used in sequence to form animations; this also mirrors the physical animation technique.

There's a whole bunch of boilerplate code here also for creating and deleting sprite structures. While boring, this also properly teaches how to dispose of unused resources. Of course, higher level languages take care of this for you now, but that garbage collection brings its own problems. André doesn't discuss such things - I don't know a great deal about how modern engines account for this. I imagine they just expose some garbage collector call, so you can just run it in your loading screen or something.

There's a treatment of transparency and not smearing the background under the sprite. Interestingly, there's also an unimplemented discussion of something called "transparency encoding", which I hadn't thought about before. I'll let the author enlighten you:
"When we wrote the sprite-drawing function Draw_Sprite(), we uncovered an unfortunate fact: the function had to be able to implement transparency, and the only way to do this was test each pixel before it was drawn. This was time-consuming; a simple calculation showed that 256 ifs would be executed for a simple 16x16-pixel bit map. There's got to be a faster way to draw sprites that somehow deals with transparency better, right?"

The written solution is to essentially run through the sprite once with RLE beforehand, taking note of when there's a drawable pixel or not. This information is then saved over the original buffer. Then, upon writing the sprite to the screen, it uses control information encoded into the buffer to skip runs of transparent bytes, instead of if-ing every one. This is a reasonable speed-up (during the main game loop) at the cost of a bit more loading time (only happens once per sprite).

And of course, collision detection! "Most of a video game is just testing whether you hit something or it hit you!" Wise words; as such, he uses a very fast algorithm for this, checking for bounding box overlap. As a responsible developer, the author then explains why bounding boxes suck, and recommends you shrink them slightly so that you get less false positives. My optimisation brain tells me this is the kind of information that could also be stored in the sprite structure, rather than having to calculate the size a few times every frame.

The chapter rounds off with a thrilling game called Attank!!! Spoilers, it's not thrilling. It could be decent with a finished AI, and a fire button, and... well, that's the point of the book. Make it a good game!

All the code listings can be found in the appropriate directory in my code repository. I haven't done any of the exercises for this one, because I could barely even spend the time to write this post. One day! I also had a vague idea of somehow making these demos run inside the browser using Emscripten or some kind of custom interpreter/engine. Aaaaah! Why do I never run out of ideas for coding that will take months of my life?

No comments:

Post a Comment