Skip to content

Tutorial) 4. Frames from Spritesheets

Bryce "BtheDestroyer" Dixon edited this page Mar 21, 2017 · 3 revisions

Note: This tutorial is specifically geared towards beginners who have little to no programming experience. Because of this, a lot of simple stuff will be explained. These explanations will become more scarce as the tutorial goes on as every section expects the reader to have read everything prior to it, so repetition is not needed.

4.0. The Purpose of Frames

You may have noticed that the function for rendering sprites in a spritesheet are very long. Making frames from spritesheets allows us to use shorter functions, making our code cleaner. In the next part of the tutorial, we'll also use frames to make animations.

The code you should have when you start this section of the tutorial should be this (The line rendering a sprite of the spritesheet has been removed):

#include <3ds.h>
#include <spritetools.h>
#include <stdio.h>
#include <link_overworld_png.h>

int main(void)
{
  int linkX = 50;
  int linkY = 50;

  ST_Init();
  ST_Splashscreen(2510);
  ST_DebugSetOn();
  ST_DebugAddVar("Link X",(void *)&linkX, INT);
  ST_DebugAddVar("Link Y",(void *)&linkY, INT);
  consoleInit(GFX_BOTTOM, NULL);

  st_spritesheet *link_o_s = ST_SpritesheetCreateSpritesheetPNG(link_overworld_png);

  ST_RenderSetBackground(0x82, 0xE1, 0x11);

  while (aptMainLoop())
  {
    ST_RenderStartFrame(GFX_TOP);

    ST_InputScan();
    if (ST_InputButtonDown(KEY_DUP))
      linkY--;
    if (ST_InputButtonDown(KEY_DDOWN))
      linkY++;
    if (ST_InputButtonDown(KEY_DLEFT))
      linkX--;
    if (ST_InputButtonDown(KEY_DRIGHT))
      linkX++;
    if (ST_InputButtonPressed(KEY_START))
      break;

    ST_DebugDisplay();

    ST_RenderEndRender();
  }

  ST_SpritesheetFreeSpritesheet(link_o_s);
  ST_Fini();
  return 0;
}

4.1. Making a Frame

Before the while loop, we'll make a frame of animation using our spritesheet with the function ST_AnimationCreateFrame(st_spritesheet *spritesheet, unsigned int xleft, unsigned int ytop, unsigned int width, unsigned int height). This function returns an allocated pointer, so we'll have to free it using ST_AnimationFreeFrame(st_frame *frame). Note: Make sure you free the frames before you free the spritesheet. The whole thing should look like this:

/* ...Code... */
st_spritesheet *link_o_s = ST_SpritesheetCreateSpritesheetPNG(link_overworld_png);

st_frame *link_o_standing_s = ST_AnimationCreateFrame(link_o_s, 4, 2, 18, 24);
/* ...Code... */
while (aptMainLoop())
{
  /* ...Code... */
}
ST_AnimationFreeFrame(link_o_standing_s);
ST_SpritesheetFreeSpritesheet(link_o_s);
/* ...Code... */

4.2. Rendering a Frame

Now that we have a frame made, we can render it using one of the following functions:

Function Description
ST_RenderFramePosition(st_frame *frame, int x, int y) Draws a frame at a given position
ST_RenderFrameScale(st_frame *frame, int x, int y, double scale) Draws a scaled frame at a given position
ST_RenderFrameRotate(st_frame *frame, int x, int y, double rotate) Draws a rotated frame at a given position
ST_RenderFramePositionAdvanced(st_frame *frame, int x, int y, double scale, double rotate, u8 red, u8 green, u8 blue, u8 alpha) Draws a scaled, rotated, and blended frame at a given position
int linkX = 50;
int linkY = 50;
st_spritesheet *link_o_s = ST_SpritesheetCreateSpritesheetPNG(link_overworld_png);
st_frame *link_o_standing_s = ST_AnimationCreateFrame(link_o_s, 4, 2, 18, 24);
while (aptMainLoop())
{
  ST_RenderStartFrame(GFX_TOP);
  /* ...Code... */
  ST_RenderFramePosition(link_o_standing_s, linkX, linkY);
  ST_RenderEndRender();
}

Now by making other frames, we can draw them with much shorter functions and much more recognizable names.