用二维数组 SDL2 控制精灵

Controlling sprite with 2 dimensional array SDL2

我目前正在学习创建我的第一款游戏,我选择了 SDL2 作为游戏引擎。我可以单独为主角精灵制作动画。但是我认为以这种方式控制精灵会非常乏味。 所以我将精灵 sheet 加载到一个二维数组中,希望我能够只用一个精灵 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;
    }

然后我创建了一个简单的枚举来定义动作,也就是精灵中的行sheet

enum Actions{
    IDLE,
    WALK,
    TOTAL
};

之后,在 main() 中,我添加了控制逻辑并设置了我认为适合渲染的变量。

#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;
}

当我按下 A/D 按钮时,精灵播放流畅。然而,在我松开按钮后问题出现了,精灵 sheet 继续自己播放到最后,然后精灵消失了,即使 "action" 变量已经设置并且没有办法可以增加自己,我很确定。 请帮助我了解这是怎么发生的,希望我能尝试修复它,或者采取其他方法。谢谢你。 我在 Fedora linux 上使用 code::blocks 16.01。 这是精灵 sheet:cat_sprite_sheet

更改动画状态时必须将frame重置为0

{
    maxFrame = ...;
    frame = 0;
    ...
}

错误存在是因为 == 检查你的帧增量。如果当前 frame40 并且您释放 A/D,maxFrame 将设置回 4frame / maxFrame = 40 / 4 = 10 > 4,所以它永远不会等于maxFrame,而frame一直在增加,从而使你的精灵在[frame / maxFrame]消失时消失边界。将 frame 重置为 0 将解决此问题。