The Game Boy Advance has a 240x160px screen with 15-bit RGB color support. Setting the color for each pixel manually would require updating 38,400 pixels per frame, or 2,304,000 pixels per second at 60 fps.
With a 16 MHz processor, this means calculating 1 pixel every 8 clock cycles, which is pretty much impossible.
he Game Boy Advance provides two ways to easily put pixels on the screen: tiles and sprites.
Sprites are stored in a special area of video memory called the 'Object Attribute Memory' (OAM).
OAM has space for the 'attributes' of the sprites, such as their location, whether or not they are visible, and which tile to use, but it does not store the actual pixel data.
The pixel data is stored in video RAM (VRAM).
This split allows multiple sprites to refer to the same tiles in VRAM, which saves space and allows for more objects on screen than would be possible by repeating them.
Since RAM is in short supply and expensive, the tile data is stored as indexed palette data.
Instead of storing the full color data for each pixel in the tile, the Game Boy Advance stores a 'palette' of colors, and the tiles that make up the sprites are stored as indexes to the palette.
Each sprite can use a maximum of 16 colors out of the total sprite palette of 256 colors.
`agb` has excellent support for the [aseprite](https://www.aseprite.org/) sprite editor which can be bought for $20 or you can compile it yourself for free.
This contains 5 `16x16px` sprites: the end cap for the paddle, the center part of the paddle, which could potentially be repeated a few times, and the ball with various squashed states.
The aseprite file defines tags for these sprites: "Paddle End," "Paddle Mid," and "Ball."
This uses the `include_aseprite` macro to include the sprites in the given aseprite file.
Now, let's put this on screen by firstly creating the object manager and then creating an object, this will also involve the creation of the main entry function using the `entry` macro.
The signature of this function takes the `Gba` struct and has the never return type, this means Rust will enforce that this function never returns, for now we will achieve this using a busy loop.
Using the `Gba` struct we get the [`ObjectController` struct](https://docs.rs/agb/latest/agb/display/object/struct.ObjectController.html) which manages loading and unloading sprites and objects.
The GBA renders to the screen one pixel at a time a line at a time from left to right.
After it has finished rendering to each pixel of the screen, it briefly pauses rendering before starting again.
This period of no drawing is called `vblank`, which stands for the 'vertical blanking interval'.
There is also a 'horizontal blanking interval', but that is outside of the scope of this book.
You should `.commit()` your sprites only during this `vblank` phase, because otherwise you may end up moving a sprite during the rendering which could cause tearing of your objects[^hblank].
`agb` provides a convenience function for waiting until the right moment called `agb::display::busy_wait_for_vblank()`.
You shouldn't use this is a real game (we'll do it properly later on), but for now we can use this to wait for the correct time to `commit` our sprites to memory.
In this section, we covered why sprites are important, how to create and manage them using the `ObjectController` in `agb` and make a ball bounce around the screen.
[^hblank]: Timing this can give you some really cool effects allowing you to push the hardware.
However, `agb` does not by default provide the timing accuracy needed to fully take advantage of this, erring on the side of making it easier to make games rather than squeezing every last drop of performance from the console.