> For the complete documentation index, see [llms.txt](https://aeriform.gitbook.io/hucc/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://aeriform.gitbook.io/hucc/getting-started/working-with-sprites.md).

# Working with Sprites

## Displaying Sprites

This is the sprite (and frames) we are going to show.

<figure><img src="/files/QP4zad2TyjiV0zKozWMw" alt=""><figcaption></figcaption></figure>

To start we need to use the following directives for HuCC to load and process our sprite. Do this at the beginning of the file.

```c
#incspr(logo, "logo.png", 0, 0, 2, 12)
#incpal(logo_pal, "logo.png")
```

{% hint style="info" %}
Because our sprite is 32pixels wide and has 6 frames, it is a 'double sprite', so the values 2, and 12 are important here.
{% endhint %}

Set up our `main` function to load sprite into VRAM, and the palette.

```c
void main() {
    load_palette(16, logo_pal, 1);
    load_vram(0x5000, logo, 0x800);
}
```

With that done, let's break this down because it can get complicated the first time.

Inside the `main` function, first we have to initialise the Sprite Attribute Table (SATB). We need to do this before we can do anything with displaying sprites.

```c
init_satb();
```

Next we set which sprite we want to modify, `0` in this case as it is the first.

```c
spr_set(0);  
```

Now set the default position of where we want the sprite to be displayed.

```c
spr_x(0);
spr_y(0);
```

For the attributes of the sprite we need to set its data that loaded into VRAM at address `0x5000` .

Then the `spr_ctrl` that defines the sprite size, in this case 32x32, and not not flipped.

```c
spr_pattern(0x5000);
spr_ctrl(FLIP_MAS|SIZE_MAS, NO_FLIP|SZ_32x32);
```

Set the palette we want to use, again `0` as it is the first, and the priority also to `0` for now.

```c
spr_pal(0);
spr_pri(0);
```

Finally we need to tell the SATB to update.

```c
satb_update();
```

With all that done you should now see the sprite on the screen:

<figure><img src="/files/T7NShLVyyNaLchrBP0ud" alt=""><figcaption></figcaption></figure>

If you need to check, here is the complete code for showing the sprite up to this point:

<details>

<summary>Complete code for displaying a sprite</summary>

<pre class="language-c"><code class="lang-c"><strong>#include &#x3C;huc.h>
</strong>
#incspr(logo, "logo.png", 0, 0, 2, 12)
#incpal(logo_pal, "logo.png")

void main() {

    load_palette(16, logo_pal, 1);
    load_vram(0x5000, logo, 0x800);

    init_satb();

    spr_set(0);
    spr_x(0);
    spr_y(0);
    spr_pattern(0x5000);
    spr_ctrl(FLIP_MAS|SIZE_MAS, NO_FLIP|SZ_32x32);
    spr_pal(0);
    spr_pri(0);

    satb_update();
}
</code></pre>

</details>

## Animating a Sprite

With our sprite displayed on screen, let's have some fun with it.

We'll want to make it bounce around the screen and change frame when it hits a side of the screen.

Let's add some constants and variables in our `main` above where we draw the sprite:

```c
#define SCREEN_WIDTH 232
#define SCREEN_HEIGHT 184

int speedx = 1;  // X velocity
int speedy = 1;  // Y velocity
int logox = 100; // Starting x position
int logoy = 100; // Starting y position
int frame = 0;   // Current animation frame
```

Following the last line of drawing the sprite we need a `while` loop and some conditions:

```c
    while(1) {
        // Update position
        logox += speedx;
        logoy += speedy;

        // Bounce off screen edges
        if(logox <= 0 || logox >= SCREEN_WIDTH-8) {
            speedx = -speedx;
            frame = (frame + 1) % 6;
        }
        if(logoy <= 0 || logoy >= SCREEN_HEIGHT+8) {
            speedy = -speedy;
            frame = (frame + 1) % 6;
        }

        // Update sprite
    }
```

This is fairly basic stuff that adds the velocity to the position of the sprite so that it moves , then checks if it has collided with the bounds of the screen.

{% hint style="info" %}
We're adjusting the screen height and width by 8, to account for the sprite.
{% endhint %}

This line is how we update the frame of the animation, using a modulo to ensure that the number never exceeds the maximum number of frames, 6 in this case.

```c
frame = (frame + 1) % 6;
```

Now in the `while` loop we need to pass this to update the sprite.

First, again we need to say which sprite we are updating:

```c
spr_set(0);
```

Then set the x and y positions of the sprite again:

```c
spr_x(logox);
spr_y(logoy);
```

Here we update the data in the sprite pattern based on the frame, from the data in VRAM.

```c
spr_pattern(0x5000 + (frame * 0x100));
```

Now update the sprite:

```c
satb_update();
```

Finally, we need to add a `vsync()` so that we lock the rendering to 60fps.

Compile and run:

<figure><img src="/files/PMJVG2QYNNi8Kq0r6BRo" alt=""><figcaption></figcaption></figure>

And there we have our sprite moving, bouncing and changing colour!

{% file src="/files/QP4zad2TyjiV0zKozWMw" %}
You can download the sprite used in this example here
{% endfile %}

<details>

<summary>Complete code for this example</summary>

```c
#include <huc.h>

#incspr(logo, "logo.png", 0, 0, 2, 12)
#incpal(logo_pal, "logo.png")

void main() {
    #define SCREEN_WIDTH 232
    #define SCREEN_HEIGHT 184

    int speedx = 1;  // X velocity
    int speedy = 1;  // Y velocity
    int logox = 100; // Starting x position
    int logoy = 100; // Starting y position
    int frame = 0;   // Current animation frame

    init_satb();

    // Initialize sprite 0
    spr_set(0);
    spr_x(logox);
    spr_y(logoy);
    spr_pattern(0x5000);
    spr_ctrl(FLIP_MAS|SIZE_MAS, NO_FLIP|SZ_32x32);
    spr_pal(0);
    spr_pri(1);

    // Load sprite data and palette
    load_palette(16, logo_pal, 1);
    load_vram(0x5000, logo, 0x800);
    satb_update();

    while(1) {
        // Update position
        logox += speedx;
        logoy += speedy;

        // Bounce off screen edges
        if(logox <= 0 || logox >= SCREEN_WIDTH-8) {
            speedx = -speedx;
            frame = (frame + 1) % 6;
        }
        if(logoy <= 0 || logoy >= SCREEN_HEIGHT+8) {
            speedy = -speedy;
            frame = (frame + 1) % 6;
        }

        // Update sprite
        spr_set(0);
        spr_x(logox);
        spr_y(logoy);
        spr_pattern(0x5000 + (frame * 0x100));

        satb_update();
        vsync();
    }
}
```

</details>
