Awesome, thanks for sharing
Making our own Sprite System on the Gameboy
Hi my name is Paul and I'm the programmer on team Coria. When we started developing Coria, we set out to make a modern style GameBoy game. Part of that vision was to push the GameBoy graphics to their limits while still maintaining the retro feel of the old hardware. So we opted for a nice middle ground between the old school graphics of a game like Mario Land and something that's more like a tech demo than anything else.
As you might know, Coria is entirely written in Assembly and uses a custom built Engine for pretty much everything. This allowed us to create our own tools and rendering routines. One of the most limiting factors of older consoles like the NES or the GameBoy are sprite size and sprite count.
The GameBoy allows up to 40 sprites, which sounds like a lot especially on the tiny 160x144 pixel screen. Additionally you are limited to 10 sprites per scanline. So what does that mean?
A scanline is one horizontal line of pixels on a screen and dates back to the days of CRT monitors when an actual beam of electrons "scanned" along the screen to make up the image. so that means we can only render a maximum of 10 per horizontal line on the monitor. Any additional graphics are just ignored by the hardware.
So 10 sprites doesn't sound to bad, it means 10 images per scanline and 40 images in total. Even 10 enemies on screen will make for good fun game play and get you a long way even in modern games. But there is another caveat: the sprite size. The size is limited to 8x8 pixels per sprite (there is a 8x16 pixel mode, more on that later) which is, as you might know from the PICO-8, not a lot. So we resort to so called metasprites, which is stitching multiple sprites together to form a bigger sprite. This comes with another advantage as well, which is memory optimization. If you split your sprites into chunks, chances are you can reuse parts of those chunks for multiple parts of the animations. Our colleagues at Morphcat have created a great video on Metasprites.
Beyond the grid
As you might have noticed, many games put their 8x8 sprites on an internal grid. Pokemon and Links Awakening for example use a 2x2 grid to form a 16x16 pixel metasprite. This has the advantage that no pixel is wasted and it's pretty easy to implement. We opted to go one step further and let the sprites be placed freely. This allows us to create many more in-between frames and smooth animations by shifting without adding more sprite images to the limited video ram. It's similar to tools like Spine where you split your graphics into different chunks that can move freely to create smooth motion. This allowed us to put all of corias animations (including weapons) in just 48 8x8 pixel chunks.
While we are bound to the old 8 bit hardware when running our game, we can luckily rely on modern tools when it comes to development. So I've created multiple tools to make our lives a lot easier. One of those tools is a Spine-like editor for creating animations. It's written in c# and runs on our good ol' Windows 10 machines. This makes creating sprites and animations for the game a lot easier.
Another thing that is super important to our workflow is a pixel art editor. So I sat down and coded... Hold up! That wouldn't be a good idea. While it might be a nice exercise to create a pixel art tool from scratch, there are already many good tools out there. Our team consists of several artists, all with their own favorite tools and preferences. So I had to find some common language between all of them. Instead of writing an export plugin or something fancy like that I relied on existing tech and the wonderful format named .png . Pretty much every graphic editor out there can export to png and it is super well documented. so I just wrote a converter from png to the gameboy sprite format. This allows everyone to stay in their comfort zone and use the tools are familiar with.
I might write up a post about the whole conversion process later, so stay tuned for the next blogpost.
Until then, stay safe and healthy,