繁体   English   中英

SDL 2.0 如何在一切之上生成纹理?

[英]SDL 2.0 How to generate texture on top of everything?

我正在做这个 Frogger 类型的游戏,当玩家接近“胜利”位置时,我想在某些坐标上显示纹理。 这是游戏的样子: 我的游戏

红色圆圈中是青蛙玩家到达该位置后应渲染“胜利”纹理的空间(只是“ok拇指”的纹理)。 此外,这个纹理应该保持在“胜利”位置直到游戏结束,两个选项:-> 直到玩家失去所有 3 个生命 -> 直到玩家占据所有 5 个“胜利”位置 现在,一些代码。 这是来自 main(),包含所有渲染内容的部分:

                SDL_SetRenderDrawColor(gRenderer, 2, 100, 64, 1);
                SDL_RenderClear(gRenderer);
                SDL_RenderCopy(gRenderer, plansza, NULL, &otherRect[2]);
                renderMovingObjects(enemiesRect, alliesRect);
                SDL_RenderCopy(gRenderer, frog, NULL, &otherRect[0]);
                renderHearts(lives);
                checkIfWon(&otherRect[0], &lives, &play, &places);
                //renderWonPosition(300, 500); //explanation below
                SDL_RenderPresent(gRenderer);

这是 checkIfWon() 函数,它只是检查玩家是否处于“获胜”位置,如果是 - 它应该生成“获胜”纹理,然后重置玩家位置以在 gameOver() 函数内继续游戏。

void checkIfWon(SDL_Rect* frogRect, int* lives, bool* play, int *places)
{
static bool pos1 = false, pos2 = false, pos3 = false, pos4 = false, pos5 = false;
if (*places == 0)
    pos1 = pos2 = pos3 = pos4 = pos5 = false;
if (frogRect->y == 50 + (SCREEN_HEIGHT % 100))
{
    if (frogRect->x > 29 && frogRect->x < 61)
    {   
        checkIfPositionWon(&pos1, places, lives);
        renderWonPosition(frogRect->x, frogRect->y);  //HERE should render "win" texture
        gameOver(frogRect, lives, play, places);
    }
    else if (frogRect->x > 169 && frogRect->x < 201)
    {
        checkIfPositionWon(&pos2, places, lives);
        renderWonPosition(frogRect->x, frogRect->y);   // it's pretty much same else if's 5 times
        gameOver(frogRect, lives, play, places);       // for 5 different positions
    }
    else if (frogRect->x > 309 && frogRect->x < 341)
    {
        checkIfPositionWon(&pos3, places, lives);
        renderWonPosition(frogRect->x, frogRect->y);
        gameOver(frogRect, lives, play, places);
    }
    else if (frogRect->x > 449 && frogRect->x < 481)
    {
        checkIfPositionWon(&pos4, places, lives);
        renderWonPosition(frogRect->x, frogRect->y);
        gameOver(frogRect, lives, play, places);
    }
    else if (frogRect->x > 589 && frogRect->x < 621)
    {
        checkIfPositionWon(&pos5, places, lives);
        renderWonPosition(frogRect->x, frogRect->y);
        gameOver(frogRect, lives, play, places);
    }
    else
    {
        printf("LOST LIFE!\n");
        gameOver(frogRect, lives, play, places);
    }

    if (*places == 5) //the player occupied all five "win" positions and the game ends
        gameOver(frogRect, lives, play, places);
}
}

这是在特定坐标上呈现“win”纹理的函数:

void renderWonPosition(int x, int y)
{
  SDL_Rect wonPosition = { x, y, 50, 50 };
  SDL_RenderSetViewport(gRenderer, &wonPosition);
  SDL_RenderCopy(gRenderer, ok, NULL, NULL);
  SDL_Rect undoView = { 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT };
  SDL_RenderSetViewport(gRenderer, &undoView);
}

现在...
我的问题是,此功能不会永久渲染纹理,仅用于第二个快照左右。 我对此进行了调试,并且在 renderWonPosition() 内部传递的值没问题。 我担心的是,为什么当我使用一些随机 int 参数在 main() 内部调用相同的 renderWonPosition() 函数时,这会起作用并呈现“win”纹理,但是当在 checkIfWon() 内部调用此函数时,纹理仅保留一个第二?

它正在消失,因为您只为角色赢得的一个实例/帧渲染它。 现在大多数渲染都是在某种帧缓冲区上完成的。 这就是用户最终在屏幕上看到的内容。 帧缓冲区可以有不同的格式用于不同的用途,但通常只是一个缓冲区。 在一般情况下,它是一个表示 2D 像素图像的缓冲区。

发生的情况是您不会每次都绘制到相同的缓冲区,或者如果您每次都将其清除为单一的静态颜色。 正如您在发布的代码中看到的那样。

        SDL_SetRenderDrawColor(gRenderer, 2, 100, 64, 1);

        SDL_RenderClear(gRenderer); // <---- this clears the buffer to a solid color

        SDL_RenderCopy(gRenderer, plansza, NULL, &otherRect[2]);
        renderMovingObjects(enemiesRect, alliesRect);
        SDL_RenderCopy(gRenderer, frog, NULL, &otherRect[0]);
        renderHearts(lives);
        checkIfWon(&otherRect[0], &lives, &play, &places);
        //renderWonPosition(300, 500); //explanation below
        SDL_RenderPresent(gRenderer);

所以现在的问题是checkIfWon只会调用 renderWonPosition() 一次。 那是当玩家处于该位置时。 我会假设gameOver()在重置游戏时将玩家移出该位置是否正确? 所以现在这个循环下次通过renderWonPosition()不会被调用,因为玩家不再处于那个位置。

因此,您必须确保每帧/循环都渲染“Won”纹理。 所以基本上如果你的变量pos1/pos2/etc...是真的,那么你应该调用renderWonPosition()


话虽如此,您绝对可以因此改进 checkIfWon 函数。 我不知道你的其他一些变量是做什么的,但从变量的places来看你做了很多额外的工作,因为你的变量pos1/pos2/...隐藏在checkIfWon()函数中。

你可以这样做:

#include <vector>

struct WinningPosition {
    // used to check the bounds if the frog is in this position
    // frog->x > this->x && frog->x < this->x + Width
    static constexpr int Width = 32;

    // the x, y position that the frag can be in to win
    int x;
    int y;
    bool won = false;
};

void renderWonPosition(int x, int y) {
    // todo render
}

void handleWinningPositions(SDL_Rect* frogRect, std::vector<WinningPosition>& positions) {
    // we loop through all the possible positions
    for (auto& pos : positions) {
        // if the position is already won then we render it
        // to the screen and continue as we don't need to check it again
        if (pos.won) {
            renderWonPosition(pos.x, pos.y);
            continue;
        }


        // this might need to be looked at, I just took it from your code
        // but checking an exact position might not be the best approach
        // for example, if the frog can move more than 1 pixel at a time
        // assuming that frogRect->y is measured in pixels
        if (frogRect->y == 50 + (SCREEN_HEIGHT % 100))
        {
            if (frogRect->x > pos.x && frogRect->x < pos.x + WinningPosition::Width)
            {
                pos.won = true;
            }
        }
    }

    // Here you could check if the game is over,
    // if all the above positions are set to true or if no
    // lives remaining

    // checkIfPositionWon(&pos2, places, lives);
    // gameOver(frogRect, lives, play, places);

}


// ...

    // here we simply store all the positions that are winnable
    // we set which this position is to be rendered or 
    // where the frog needs to be in order for it to be considered a win
    std::vector<WinningPosition> winningPositions = {
        WinningPosition{ 29, 50 /* you'd need to calcluate the Y position */ },
        WinningPosition{ 169, 50 },
    };

    handleWinningPositions(frogPos, winningPositions);

// ...

无论如何,游戏很难编程。 它们变得非常复杂,游戏的许多组件都需要相互了解。 我只能看到你拥有的代码的一小部分,所以我不知道其他一切是如何运作的。 希望这能给你更多关于你能做什么的想法。 通过这种方式,添加更多位置真的很容易,而且您不太可能在确定青蛙是否处于获胜位置的逻辑中犯错误。 最终,您编写的代码更少,维护工作也更少:)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM