用二维数组 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;
...
}
错误存在是因为 ==
检查你的帧增量。如果当前 frame
是 40
并且您释放 A/D,maxFrame
将设置回 4
。 frame / maxFrame
= 40 / 4 = 10 > 4
,所以它永远不会等于maxFrame
,而frame
一直在增加,从而使你的精灵在[frame / maxFrame]
消失时消失边界。将 frame
重置为 0 将解决此问题。
我目前正在学习创建我的第一款游戏,我选择了 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;
...
}
错误存在是因为 ==
检查你的帧增量。如果当前 frame
是 40
并且您释放 A/D,maxFrame
将设置回 4
。 frame / maxFrame
= 40 / 4 = 10 > 4
,所以它永远不会等于maxFrame
,而frame
一直在增加,从而使你的精灵在[frame / maxFrame]
消失时消失边界。将 frame
重置为 0 将解决此问题。