C++ 在SDL中绘制静止图像
我目前正在学习SDL,我正在尝试创建一个吃豆人游戏。我正试图分步实施,以免陷入大量代码的泥潭 到目前为止,我已经创建了一个空白窗口,并在其上渲染了一个Pacman图像。我可以按箭头键,在窗口周围移动吃豆人。我已经设置好了,所以Pacman图像被存储为SDL_纹理,我使用RenderCopy将其显示到窗口。每次用户按下箭头时,我都会移动图像的坐标并重新渲染整个图像。这个很好用。现在,我想在屏幕上画一些点,让吃豆人吃。如果我加载一个点图像并将其存储为一个新纹理,与Pacman一起闪烁到屏幕上,但是,每次我移动Pacman时,点都会闪烁,因为它会随着Pacman一起被擦除和重新渲染 我的问题是,如何避免这种“闪现”?我是否可以只重新渲染Pacman而不重新渲染屏幕的其余部分?还是有其他方法可以做到这一点?我想当我稍后在背景中尝试创建迷宫时,我也会遇到同样的问题。如何使静态背景在每次重新渲染时不闪烁 下面是到目前为止我的代码。如果里面有任何形式不好的代码,请原谅我。正如我所说的,我刚刚开始学习SDL(对C++来说也是相当新的),所以如果有任何明显的“你永远不应该那样做”的话,我会感激任何人指出:C++ 在SDL中绘制静止图像,c++,sdl,blit,pacman,C++,Sdl,Blit,Pacman,我目前正在学习SDL,我正在尝试创建一个吃豆人游戏。我正试图分步实施,以免陷入大量代码的泥潭 到目前为止,我已经创建了一个空白窗口,并在其上渲染了一个Pacman图像。我可以按箭头键,在窗口周围移动吃豆人。我已经设置好了,所以Pacman图像被存储为SDL_纹理,我使用RenderCopy将其显示到窗口。每次用户按下箭头时,我都会移动图像的坐标并重新渲染整个图像。这个很好用。现在,我想在屏幕上画一些点,让吃豆人吃。如果我加载一个点图像并将其存储为一个新纹理,与Pacman一起闪烁到屏幕上,但是,
#包括
#包括
使用名称空间std;
窗内常数=480;
const int WINDOW_WIDTH=640;
const int MOVE_WIDTH=10;
int main(int argc,const char*argv[]
{
SDL_Window*mainWindow=NULL;//用于保存主窗口
SDL_Renderer*Renderer=NULL;//保存渲染器
SDL_Rect targetlect;//将向其绘制pacman图像的矩形
SDL_Surface*bmpSurface=NULL;//用于保存bmp图像
SDL_纹理*bmpTexture=NULL;//用于保存bmp图像
//初始化SDL并检查错误
if(SDL_Init(SDL_Init_EVERYTHING)!=0)
{
cout用于渲染Pacman的上述方法实际上可以很好地将点渲染到屏幕上。只需将点的图像存储在新纹理中,创建一个SDL_Rect来保存此纹理,然后使用SDL_CreateRenderer将点图像与Pacman一起渲染到屏幕上。您应该注意到点不会闪烁即使渲染,只要你没有使用SDL_延迟之类的东西来降低帧速率。你是如何渲染点的?我加载了点图像并将其存储在新的纹理中。然后我调用了第二个RenderCopy(就在我用于Pacman图像的RenderCopy之后)使用相同的渲染器,但渲染点纹理并使用不同的targetRect。然后我只保留了代码中已有的相同的RenderPresent函数来渲染点和吃豆人。嗯,我刚刚编写了一个测试,看看它是否会这样做。吃豆人是随着点闪烁还是仅仅是点闪烁?我想问题可能出在您处理事件的方式上。通常会调用SDL_PollEvent,直到它返回0为止,因此您不会得到事件的累积。我在SDL_CreateRenderer函数的文档中找到了PollEvent示例。我只是再次检查了它,它看起来像我的代码。无论如何,我只是将一些代码放在一起为您和这个点不再闪烁了。我想我发现了我的问题。在中间的某个地方,我试图添加一些动画(Pacman上的一个打开和关闭的嘴),所以我在它们之间呈现了两个不同的Pasman图像,SDLyDelphi(90)。渲染之间的延迟必须是正在发生的事情。事后看来非常愚蠢。
#include <iostream>
#include <SDL2/SDL.h>
using namespace std;
const int WINDOW_HEIGHT = 480;
const int WINDOW_WIDTH = 640;
const int MOVE_WIDTH = 10;
int main(int argc, const char * argv[])
{
SDL_Window* mainWindow = NULL; //To hold the main window
SDL_Renderer* renderer = NULL; //To hold the renderer
SDL_Rect targetRect; //Rectangle to which pacman image will be drawn
SDL_Surface* bmpSurface = NULL; //To hold bmp image
SDL_Texture* bmpTexture = NULL; //To hold bmp image
//Initialize SDL and check for errors
if ( SDL_Init(SDL_INIT_EVERYTHING) != 0 )
{
cout << "ERROR: could not initialize SDL." << endl;
}
//Create a window
mainWindow = SDL_CreateWindow("BAM", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WINDOW_WIDTH, WINDOW_HEIGHT, 0);
if (mainWindow == NULL)
{
cout << "ERROR: could not initialize mainWindow." << endl;
}
//Initialize renderer
renderer = SDL_CreateRenderer(mainWindow, -1, SDL_RENDERER_ACCELERATED);
//Load image and store in an SDL_Surface
bmpSurface = SDL_LoadBMP("/Users/billgrenard/Desktop/Programs/SDL/SDL_KeyPresses/SDL_KeyPresses/pacman_closed.bmp");
if ( bmpSurface == NULL )
{
cout << "ERROR: could not load bmp file." << endl;
}
//Convert surface to texture for rendering
bmpTexture = SDL_CreateTextureFromSurface(renderer, bmpSurface);
if ( bmpTexture == NULL )
{
cout << "ERROR: could not convert bmp surface." << endl;
}
SDL_FreeSurface(bmpSurface);
//Define rectangle where pacman image is to be blitted
targetRect.w = 30;
targetRect.h = 30;
targetRect.x = (WINDOW_WIDTH/2) - (targetRect.w/2);
targetRect.y = (WINDOW_HEIGHT/2) - (targetRect.h/2);
//Main game loop
while (1)
{
SDL_Event e;
if (SDL_PollEvent(&e))
{
//Quit when user x's out the window
if (e.type == SDL_QUIT)
{
break;
}
//If user presses a key enter switch statement
else if( e.type == SDL_KEYDOWN )
{
switch ( e.key.keysym.sym ) {
//If user presses up arrow and the resulting move is inside the window, then move the Pacman's position
case SDLK_UP:
if ( targetRect.y - MOVE_WIDTH > 0 )
{
targetRect.y -= MOVE_WIDTH;
}
break;
//If user presses down arrow and the resulting move is inside the window, then move the Pacman's position
case SDLK_DOWN:
if ( targetRect.y + MOVE_WIDTH < (WINDOW_HEIGHT - targetRect.w) )
{
targetRect.y += MOVE_WIDTH;
}
break;
//If user presses right arrow and the resulting move is inside the window, then move the Pacman's position
case SDLK_RIGHT:
if ( targetRect.x + MOVE_WIDTH < (WINDOW_WIDTH - targetRect.w) )
{
targetRect.x += MOVE_WIDTH;
}
break;
//If user presses left arrow and the resulting move is inside the window, then move the Pacman's position
case SDLK_LEFT:
if ( targetRect.x - MOVE_WIDTH > 0 )
{
targetRect.x -= MOVE_WIDTH;
}
break;
default:
break;
}
}
}
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, bmpTexture, NULL, &targetRect);
SDL_RenderPresent(renderer);
}
SDL_DestroyWindow(mainWindow);
SDL_DestroyTexture(bmpTexture);
SDL_DestroyRenderer(renderer);
SDL_Quit();
return 0;
}