GBDK set sprite prop

From GbdevWiki
Jump to: navigation, search

Introduction

This tutorial seeks to describe, with examples, how to make precise changes to a sprite's state, without requiring any previous knowledge of binary or bitwise operators. The set_sprite_prop function, found in gb.h, sets properties of a sprite.

TL;DR:

The property argument is a byte and can be combined using bitwise operators (ways to combine binary sets) to pass several properties at once: property1 | property2 | ... | propertyn to send multiple properties, existingProperties | property to leave everything the same but turn property on, existingProperties & ~property to leave everything the same but turn property off.

Definitions

gb.h includes some property definitions:

  • #define S_PALETTE 0x10U
  • #define S_FLIPX 0x20U
  • #define S_FLIPY 0x40U
  • #define S_PRIORITY 0x80U

The problem with setting these is that any will obliterate any other properties.

Sprite property flags

The flags are stored in binary like this:

Bit 0 0 0 0 0 0 0 0
Feature Relative to background Flip Y Flip X DMG palette GBC Tile bank Color Color Color
0 In front Don't flip Don't flip Monochrome palette 0 Bank 0 0+ 0+ 0
1 Behind Flip vertically Flip horizontally Monochrome palette 1 Bank 1 1+ 1+ 1

set_sprite_prop

Using the defined shorthand, you can call

set_sprite_prop(spriteNumber, S_FLIPY);

which sets the properties to 01000000 (40 in hexadecimal, 64 in decimal), and

set_sprite_prop(spriteNumber, S_FLIPX);

which sets the properties to 00100000 (20 in hexadecimal, 32 in decimal)

but if you do both, the entire set is overwritten with the latest set, so the bit that is flipped gets flipped back.

Bitwise operators

So how do you do both? With bitwise operators! We're specifically interested in & (and), | (or), and ~ complement. & adds two bit sets together but only carries over 1s that existed in both previous sets (1100 & 1011 is 1000). | carries over any 1s that existed in either (1000 | 1011 is 1011). ~ gives the complement of a single set, effectively flipping each bit to its opposite, regardless of its position (~1011 is 0100).

So how do we put this into practice?

OR

Well, we know that S_FLIPY is 01000000 and S_FLIPX is 00100000. To turn both on in one move, you'd use OR: |, and get 01100000:

set_sprite_prop(spriteNumber, S_FLIPY | S_FLIPX);

get_sprite_prop

That's great! But it ignores the existing states of the other bits, for example a color palette, or priority relative to the background. Perhaps you want to flip the sprite on its axes independently of each other. For that, you can feed get_sprite_prop directly into set_sprite_prop (or set it to a variable and feed that in) and use the | operator:

set_sprite_prop(spriteNumber, get_sprite_prop(spriteNumber) | newProp);

A real example: set_sprite_prop(0, get_sprite_prop(0) | S_FLIPX);

AND and NOT

Now how do you switch a bit off? Here's where the & and ~ operators come into play.

With &, we know that only 1s found in both sets get carried over. Any set & a set full of 1s will result in that set. Any 0 in either set will result in a 0 in the resulting set. So we need to & combine the existing property set with a set full of 1s and a 0 in the position of the bit we want to switch off. We can get the latter with the complement operator ~ and any single or collective setting we want turned off.

An example:

The existing state of properties on a sprite is 00100011 (see #get_sprite_prop)(flipped horizontally, set to color palette 3), and we want to revert the mirrored effect. So:

00100011 & ~00100000

Breaking this down completely, let's apply the NOT first and flip the latter set:

11011111

Now let's combine them using AND:

00100011

11011111

making:

00000011

We've successfully retained all previous bit states except for the one we switched off.

Here's a real-world example:

set_sprite_prop(0, get_sprite_prop(0) & ~S_FLIPX);

Takeaway

Hopefully you can now apply any changes to a sprite's properties without a lot of hassle or trial and error.