gpt4 book ai didi

c++ - SDL_Texture 移动动画

转载 作者:搜寻专家 更新时间:2023-10-31 01:43:38 24 4
gpt4 key购买 nike

我想为我的小游戏做插值。有 2 个 SDL_Textures,当我点击第一个然后再点击第二个时,它们的位置被交换,但没有移动动画。那么如何为 SDL_Textures 制作动画位置交换?

void MainLoop() {

SDL_Event Event;

float t = 0.0f;
float dt = 0.1f;

float currentTime = 0.0f;
float accumulator = 0.0f;

while (Running)
{
while(SDL_PollEvent(&Event)) {
OnEvent(&Event);
}
const float newTime = SDL_GetTicks();
float frameTime = newTime - currentTime;
const Uint32 maxFrameTime = 1000; // 1 sec per frame is the slowest we allow
if( frameTime > maxFrameTime) {
frameTime = maxFrameTime;
}
currentTime = newTime;
accumulator += frameTime;
while( accumulator >= dt )
{
this->UpdatePositions(); // simulate a "frame" of logic at a different FPS than we simulate a frame of rendering
accumulator -= dt;
t += dt;
}

Render();
}

主要渲染方法:

void Puzzle::Render() const {
SDL_RenderClear(renderer);
for (int i = 0; i < blocksNum; ++i)
{
Rectangle texRect = normalizeTexCoords(blockRect(blocks[i]));
Rectangle scrRectOrigin = blockRect(i);

DrawRect(scrRectOrigin, i, texRect);
}

SDL_RenderPresent(renderer);
}


void DrawRect(const Rectangle& screenCoords, int textureId, const Rectangle& textureCoord) {
SDL_Texture *texture = blockTexture(blocks[textureId]);
renderTexture(texture, renderer, (int)screenCoords.left, (int)screenCoords.top, (int)blockWidth, (int)blockHeight);
//SDL_DestroyTexture(texture2);
}

void renderTexture(SDL_Texture *tex, SDL_Renderer *ren, int x, int y, int w, int h) {
// Destination rectangle position
SDL_Rect dst;
dst.x = x; dst.y = y; dst.w = w; dst.h = h;
SDL_RenderCopy(ren, tex, NULL, &dst);
}

在我的 UpdatePosition 方法中,我想让我的 SDL_Textures 移动,但它仍然在没有动画的情况下交换。

void Puzzle::UpdatePositions()
{
if (secondSwappedBlock != -1) {
Rectangle firstRect = blockRect(blocks[firstSwappedBlock]);
firstRect.left += speed * deltaTime;
firstRect.right += speed * deltaTime;

SDL_Texture *texture = blockTexture(blocks[firstSwappedBlock]);
renderTexture(texture, renderer, (int)firstRect.left, (int)firstRect.top, (int)blockWidth, (int)blockHeight);
}
}


void Puzzle::SwapBlocks(const int first, const int second) const
{
if (first != second)
{
const int t = blocks[first];
blocks[first] = blocks[second];
blocks[second] = t;
}
}

最佳答案

这是一个最小的(但完全有效的)示例:

#include "SDL.h"
#include <assert.h>

/* linear interpolation between {start.x; start.y} and {end.x; end.y} */
static void rect_lerp(SDL_Rect *out, const SDL_Rect *start, const SDL_Rect *end, float f) {
float t = 1.0f - f;
out->x = (float)start->x * t + (float)end->x * f;
out->y = (float)start->y * t + (float)end->y * f;
}

int main(int argc, char **argv) {
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER);

SDL_Window *window = SDL_CreateWindow("example",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
640,
480,
SDL_WINDOW_SHOWN);
assert(window);
SDL_Renderer *renderer = SDL_CreateRenderer(window, 0, SDL_RENDERER_ACCELERATED);
assert(renderer);

int quit = 0;
int animate = 0;
Uint32 animation_start_time;

/* whole animation will play in e.g. one seconds */
const Uint32 animation_time_total = 1000;

SDL_Rect rect0 = {
.x = 0, .y = 0, .w = 128, .h = 128
};
SDL_Rect rect1 = {
.x = 256, .y = 256, .w = 128, .h = 128
};

while(!quit) {
/* time of current frame */
Uint32 tcurrent = SDL_GetTicks();

SDL_Event event;
while(SDL_PollEvent(&event)) {
if(event.type == SDL_KEYUP) {
if(event.key.keysym.sym == SDLK_ESCAPE) {
quit = 1;
break;
} else if(event.key.keysym.sym == SDLK_SPACE) {
animate = 1;
animation_start_time = tcurrent;
}
}
}

SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);

SDL_Rect r0 = rect0, r1 = rect1;
/* if not within animation - leave coordinates as they are */
if(animate) {
if(tcurrent > animation_start_time + animation_time_total) {
/* animation ends by now */
/* swap rect0 and rect1 and stop animation */
SDL_Rect t = rect0;
rect0 = rect1;
rect1 = t;
animate = 0;

/* need to update r0 and r1 too */
r0 = rect0;
r1 = rect1;
} else {
/* animation is incomplete - interpolate coordinates */
/* calculate current animation percentage - in range [0; 1] */
float factor = ((float)(tcurrent - animation_start_time)) / animation_time_total;
rect_lerp(&r0, &rect0, &rect1, factor);
rect_lerp(&r1, &rect1, &rect0, factor);
}
}

/* r0 and r1 now have correct coordinates, draw */
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_RenderDrawRect(renderer, &r0);

SDL_SetRenderDrawColor(renderer, 255, 0, 255, 255);
SDL_RenderDrawRect(renderer, &r1);

SDL_RenderPresent(renderer);
}

SDL_DestroyWindow(window);
SDL_Quit();

return 0;
}

为了简单起见,它绘制了矩形而不是纹理,但这可以很容易地改变。

如您所见,在该示例中,只要动画不完整,我就会保留旧坐标,并且仅在它完全消失时才固定它。这很容易允许重放并且没有精度问题;但是 - 如果您在动画已经播放时尝试按空格键,它只会重新开始。

另一种方法是在每个动画步骤上更新坐标(可能有不同的更新频率然后重绘);在这种情况下,您将需要保留当前坐标、目标坐标(动画完成后您将到达的坐标),可能还有起始坐标(以消除精度问题)。

关于c++ - SDL_Texture 移动动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24793748/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com