Time for another update. It’s starting to become a recurring theme, but progress has been slow again. Besides a full-time job and a social life, I’ve recently started taking Japanese classes, which means I don’t spend a whole lot of time behind a computer when at home these days. Nevertheless, I managed to put together a very simple framework for sprite-based rendering of entities together.
Sprite rendering
I made a conscious decision not to use an already-existing sprite-based framework such as SpriteKit or Cocos2D, and instead write everything related to rendering from scratch. The main reason for this decision is that DIY is more fun, but it also means I can keep things as concise and simple as possible.
To render game entities using sprites, I first created a simple
sprite atlas class, K14SpriteAtlas
. A sprite atlas
represents a set of sprite frames as a single image, somewhat like a collage of
sprite frame images. A texture is created from the atlas image, and when
rendering an entity, it can change its sprite frame by just using different
texture coordinates into the atlas image, instead of having to create a single
texture for every sprite frame and binding it on every draw call.
The sprite atlas class is simple but effective: it’s created with a frame
size and a number of rows and columns of frames, and on construction it
will allocate a bitmap context large enough to accomodate
the requested number of sprite frames. Sprite frames can then be added to
the atlas using a string-type key, and a UIImage
containing the frame
image, which is pasted into the bitmap context using UIImage drawInRect
.
I chose to use one sprite atlas for each entity type, which is initialized and
uploaded to the GPU by the renderer before the game loop is started. A static
singleton property spriteFrameImages
was added to K14Entity
and its
descendants, which returns a dictionary from sprite frame names to UIImage
instances, which are loaded from PNG files in the application bundle the first
time the property is accessed. To limit creating texture atlases to only those
entities that a are actually used by the active planet, a property
usedEntityClasses
was added to K14Planet
, which returns the class names of
all used entity types.
The code inside the renderer class that sets up the atlas images for all entity types used on the active planet looks like this:
_spriteTextures = [NSMutableDictionary new];
_spriteTextureAtlases = [NSMutableDictionary new];
// Create texture atlases for used entity types
for (NSString *entityClass in planet.usedEntityClasses)
{
Class cls = NSClassFromString(entityClass);
K14SpriteAtlas *sprite_atlas = [[K14SpriteAtlas alloc] initWithRows:4 columns:4 frameWidth:128 frameHeight:128];
for (NSString *frame_name in [cls spriteFrameImages])
{
[sprite_atlas addSpriteFrameWithName:frame_name image:sprite_frames[frame_name]];
}
_spriteTextureAtlases[entityClass] = sprite_atlas;
_spriteTextures[entityClass] = [GLKTextureLoader textureWithCGImage:sprite_atlas.image.CGImage
options:@{ GLKTextureLoaderApplyPremultiplication : @(YES) }
error:nil];
}
Result
To test sprite rendering I cobbled together some vector drawings for the entities of the test planet. I used Sketch 3 by Bohemian Coding, which isn’t cheap but makes it so easy to create vector drawings like this, that it’s easily worth the investment. Here’s a video of the test planet using sprite rendering for entities:
Note that I made no effort whatsoever to make the sprites look good yet, they are all single-colored and their proportions are a little off compared to the original game. None of the sprites are animated yet either, but the supporting code to animate them is all there: animating a sprite is just a matter of creating the necessary sprite frames and swapping them by setting the entity sprite frame name when necessary.
Next steps
I’m not quite sure what feature I want to add next, most likely it will be one of the following: a simple main menu and scene transitions to allow getting in and out of different planets, or hooking up input handling to actual working controls (on-screen or accelerometer) so the game can be ‘played’ on a real device. The combination of these 2 things would allow recording more elaborate action replays, which will come in handy as test inputs when I start working on the actual game logic and win-lose conditions and such.
Development scoreboard
I spent about 4 hours on the sprite atlas classes, and another 2 creating the sprites. The total development time is now at about 97 hours. SLOC count is now 1353.