In addition to working on fixing and improving the AI, I’m currently working on adding carrying corpses. Beyond the programming involved with that, it also entails a new set of animations and a bunch of character sprites for these animations.
When I first started working on Hidden Asset, making these character sprites took a looooong time. At least a couple of weeks were spent making the thousands of sprites just for the walking animation. Since then, I’ve automated a lot of this process so it now only takes a few days. I thought I’d run through the process of making the sprites for a single animation set and how I’ve automated as much as I could to speed it all up…
Every character animation I make always starts in Poser. Here, I manually animate the default male Poser character. When I’m happy with the animation for him, I then also apply the animation to the female Poser character and correct any issues that crop up due to these two characters not being of the same size and proportions, so the animation from the male character doesn’t fit 100% on the female one.
For the ‘carrying a corpse’ animation I had to animate two characters at once: the player character and the poor guy/gal that’s dead and being carried. When this was done, I rendered out my template animation frames. For this specific animation, it resulted in these 10 frames of animation (here shown in 1 of the 8 movement directions):
These template frames are then animated in the actual game engine, meaning that each frame gets a set of coordinates that tell the game where the sprite should be drawn relative to the tile the character is on. I’m now ready to start rendering the actual sprites for use in game, since these template sprites are never used directly in the game — only for figuring out the relative coordinates for each frame.
Thankfully, Poser offers something called Poser Script, which is short scripts written in Python that can be used to basically automate anything you do in Poser. For my needs, these scripts are used to automatically load and apply clothes and hair and the like to the Poser characters, then rendering out each of these items separately and for each frame and direction of the animation. It doesn’t take much time to write such a script, especially now that I’ve already done this process a bunch of times and can just reuse old scripts. So I set a script to run in Poser and can usually leave the computer for half an hour or so — or work on something else while the sprites render in the background.
When this has been done for all the body parts, clothes, shoes, hairstyles and everything else for the characters, I usually have a few thousand separate sprite images in my folder. For this particular animation, I actually first rendered out the player character, since he’s just a single sprite:
When rendering the sprites for the character being carried, I applied a flat grey material to anything that wasn’t the specific sprite being rendered to mask out anything that’s obscured by the character itself or the player character carrying it. Let’s use a pants sprite as an example. Here’s one of the pants styles for the first frame of the animation:
Before I got clever about automating as much of this as possible, I only rendered the pants themselves, so I had to manually erase everything that was supposed to be obscured. If you have to do that for X thousands of sprites, you can probably imagine why this took so long for the first set of animations I made for the game. Now I’ve just written a small program that automatically reads all the image files in a folder and erases anything in the image with the exact gray color used for the mask. So I just copy this program into the folder containing the image files and run it. It chugs along for a couple of minutes and then everything has been erased just the way I want it:
There are sometimes still a few issues that need to be corrected manually. Sometimes the gray color was also present in another part of the image, so I have to restore the part that shouldn’t have been erased. Or parts of the character was clipping through the sprite and covering it, so I have to patch that area. But it’s negligible compared to the work needed before. I can probably quickly check and fix all the thousands of separate sprites over a day or two.
I do this in GIMP. But I do more than just fix any problem sprites in GIMP — I also shrink the sprites to half size. Whether drawing by hand or modelling and rendering through a 3D program such as Poser, Blender or 3ds Max, it’s always a good idea to make the original artwork in higher resolution than needed and then shrink it. You’ll get more detail in the final artwork/sprite like that. Also, in my particular case, the jagged edges left behind when the gray areas were deleted become more smooth when the image is shrunk:
In keeping with my attempt to automate as much as possible, I’ve written a small GIMP script that automatically shrinks all open images to half size and saves them. So I usually have 20-30 images open at a time in GIMP, then quickly check them for issues that need fixing and then just run my script. Quick and easy!
For each of these sprites to be drawn in the right place on screen when running the game, the engine needs to know the sprites’ coordinates relative to the template sprites. So when the game is running, these ‘sub-sprites’ (that are each a separate body part or clothing item) are drawn to screen relative to the original template sprites, which were drawn relative to the ingame tile.
To get the coordinates relative to the template sprites, I use another program that I wrote for this purpose. Just as I did with the program that erased all the masked parts, I copy this program into the image folder and run it. This program automatically crops each image and then writes the coordinates of the cropped image’s top left corner (what the coordinates of the cropped image’s top left corner were on the uncropped image) to a text file. This leaves me with thousands of cropped sprite images that are as small as they can possibly be — and a long list with the coordinates for each sprite:
Using a third program I wrote for this specific purpose, these coordinates are then converted into a format that I can copy/past directly into the game’s code. Voila!
All I need to do now is gather all these thousands of sprites into a few sprite sheets and feed the coordinate of each sprite on the sprite sheet into the game’s code. This is also done with my own program that spits out a text file with coordinates that are formatted so they can be copy/pasted directly into code.
And there you have it. There are quite a few steps involved, but automating as much as possible has made what was once the biggest bottleneck when developing Hidden Asset almost a breeze!