Composable Sprites Part 1
Right, so this was one of those weeks that something that has been brewing in my head has been materialised to code, and it works, and it's amazing and it's definitely the way forward. I'm talking about composable sprites, which are sprites that really consist of a number of layers, in order to make a unique looking sprite. A few examples here, of a sprite with different equipment:
Motivation
The player characters that I'm using from the Oryx tileset (first five rows here) are a bit problematic:
- They've been reused too many times. The sprites are frequently recognizable, so that's not good if you're trying to make something new.
- They are not flexible, as each is a unique combination of race and equipment. There's no soldier wielding a staff, or a mage wielding an axe. For a proper RPG or roguelike game, where characters can equip lots of things, we want the visual representation to show that too.
Desired outcome
The solution is of course to use composable sprites (not sure if there's a more appropriate name for these things). Effectively, we split a sprite into multiple layers, e.g. naked body, pants, head, left hand equipment, right hand equipment, etc. When the character wields a sword in their right hand, we overlay a sword sprite at the appropriate location. When the character wields a shield in their left hand, as a separate process, we overlay the relevant sprite too. So we can generate the proper sprite given all the individual components. This all sounds reasonable, and it's not groundbreaking, it just implies quite a bit of work, part of it is art-related. And this is where things get funky.
Below are some problems and associated solutions.
Exact attachment placement
To put a shield to the hands of a sprite, we need two things: location of the hands, and location of the shield handle. So, these need to be marked in advance, and when it's the time to do the composition, we align the sprites using this information
Hands visible or not
Holding some equipment at a certain hand results in the hand being visible or not. E.g. holding a sword, we can see the hand. But while holding a shield, we can't see anything besides the shield. So each piece of equipment needs to be marked if it hides the hand or not.
Separating the layers from existing sprites.
This is a no brainer, but it's also manual labour. For certain character sprites, I have to extract the layers manually, which means pixel work. Thankfully this has to be done just once.
Weapon and equipment sprites.
This is the major problem that had to be solved. I need weapon/shield sprites of appropriate size to attach to character hands. Since characters are 24x24 pixels, that means that weapons/shields should be about 12-16 pixels large. Now this is a problem, as while 16px sprites are common, 12 are surely not. And I dare you to simply resize a sprite from 16 to 12 pixels and see what happens. Disaster. To add insult to the injury, I like silhouettes in my sprites, and silhouettes are also getting destroyed by transformations. I even tried that RotSprite algorithm but the results are also abysmal at such low resolutions. The solution? Deceptively simple: use xBRZ a few times, then rotate, then nearest-neighbour downsample to desired resolution. Extra trick: before the transformations, detect and remove silhouette, and after the transformations, add it back again.
45-degree sprite rotation
A hyper-specific solution to a problem that maybe nobody cares about (except me?). So, you know all these endless sprite packs where the weapon icons are along the main diagonal? That's great, and they do it for the extra real-estate, but the problem is that my sprites never hold weapons at such an angle (because they also obstruct the face). Look at the first image. On the "left" (as we see it) hand, there's only space to put a weapon that extends upwards. On the right hand, the held weapon can either extend upwards (tangential to ground), either fully to the left (parallel to ground), or a bit angled (almost parallel to ground, but weapon tip slightly higher). So this means that diagonally-oriented weapons would need to be rotated either +45 degrees, or -45 degrees, or about 30 degrees. So, what do we do? Well I developed a really simple transformation that works just for 45 degrees, and is not destructive at all. Here's an example, and needless to say, I'm super happy with the results!
So this was just proof of concept. How does fit together with the game? To be continued...