I'm currently learning to create my first game ever, and I chose SDL2 to be the game engine. I can make animation for the main character sprite separately. However I figured that it would be ridiculously tedious to control the sprite that way. So I loaded the sprite sheet into a 2 dimensional array hoping that I would be able to control the sprite with all kind of actions with just that one sprite sheet.
#define HOR_FRAMES 16
#define VER_FRAMES 16
// These are for the images and sprites
Sprite catGif;
SDL_Rect catRect[VER_FRAMES][HOR_FRAMES];
bool load()
{
bool success = true;
// Load cat sprite sheets
if (!catGif.loadFromFile("./assets/pets/fighter_cat_sprite/cat_sprite_base_64.png",
sceneRenderer, 0X00, 0x00, 0x00))
{
printf("%s", SDL_GetError());
success = false;
}
else
{
int initX = 0;
int initY = 0;
for (int ver = 0; ver < VER_FRAMES; ver++)
{
for (int hor = 0; hor < HOR_FRAMES; hor++)
{
catRect[ver][hor].x = initX;
catRect[ver][hor].y = initY;
catRect[ver][hor].w = 64;
catRect[ver][hor].h = 64;
initX += 64;
}
initX = 0;
initY += 64;
}
initX = 0;
initY = 0;
}
return success;
}
Then I created a simple enum to define the actions, which is the rows in the sprite sheet
enum Actions{
IDLE,
WALK,
TOTAL
};
After that, in main(), I add the control logic and set the variables in away that I think appropriately for rendering.
#include "init.h"
#include "Sprite.h"
LTexture background(SCREEN_WIDTH, SCREEN_HEIGHT);
SDL_Rect bgRect;
LTexture foreground(SCREEN_WIDTH, SCREEN_HEIGHT);
SDL_Rect fgRect;
int frame = 0;
int maxFrame = 0;
SDL_RendererFlip flipType;
int main(int argc, char* argv[])
{
init();
load();
int action;
bool quitFlag = false;
SDL_Event event;
while (!quitFlag)
{
action = IDLE;
while (SDL_PollEvent(&event) != 0) // Handle events in queue
{
if (event.type == SDL_QUIT ||
event.key.keysym.sym == SDLK_ESCAPE)
quitFlag = true;
}
const Uint8* states = SDL_GetKeyboardState(NULL);
if (states[SDL_SCANCODE_A])
{
maxFrame = 8;
action = WALK;
flipType = SDL_FLIP_HORIZONTAL;
catGif.moveLeft();
}
else if (states[SDL_SCANCODE_D])
{
maxFrame = 8;
action = WALK;
flipType = SDL_FLIP_NONE;
catGif.moveRight();
}
else
{
maxFrame = 4;
action = IDLE;
}
// Drawing
background.clipRender(0, 0, sceneRenderer, &bgRect);
foreground.clipRender(0, SCREEN_HEIGHT / 2, sceneRenderer, &fgRect);
SDL_Rect* currFrame = &catRect[action][frame / maxFrame];
int x = catGif.xGetter();
int y = catGif.yGetter();
catGif.render(x, y, sceneRenderer, currFrame, NULL, 0, flipType);
// Update
SDL_RenderPresent(sceneRenderer);
frame++;
if (frame / maxFrame == maxFrame)
{
frame = 0;
}
}
clean();
return 0;
}
The sprite played smoothly as I pressed the A/D buttons. However, problems appeared after I released the buttons, the sprite sheet continued to play itself through to the end and then the sprite disappeared, even though the "action" variable has been set and there is no way that it can increment itself, I'm pretty sure about that. Please help me to understand how that happened, hopefully I can try to fix it, or take another approach. Thank you. I use code::blocks 16.01 on Fedora linux. And this is the sprite sheet: cat_sprite_sheet