[英]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.