I am currently learning SDL and I am trying to create a Pacman game. I'm trying to take it in steps so as not to get bogged down with massive amounts of code.
So far I have created a blank window and rendered a Pacman image onto it. I am able to press the arrow keys and move the Pacman around the window. I have it set up so the Pacman image is stored as an SDL_Texture, which I blit to the window using RenderCopy. Each time the user presses an arrow, I move the coordinates of the image and re render the whole image. This works just fine. Now, however, I want to put some dots on the screen for the Pacman to eat. If I load a dot image and store it as a new texture to blit to the screen along with the Pacman, however, each time I move the Pacman the dot flashes in and out because it is being erased and re rendered along with the Pacman.
My question is, how do I avoid this "flashing"? Can I somehow re render only the Pacman without re rendering the rest of the screen? Or is there another way to do this? I figure I'm also going to have the same problem when I try to create the maze later in the background. How do I make a static background that doesn't flash in and out each time I re render?
Below is my code so far. Forgive me if there is any code of bad form in there. As I said, I am just starting to learn SDL (pretty new to C++ as well), so if there is any glaring "You should never do that!" kind of things in there, I would appreciate anyone pointing it out :)
#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;
}
EDIT: In answer to raser's comment, here is the link where I found the PollEvent example: http://wiki.libsdl.org/SDL_CreateRenderer?highlight=%28%5CbCategoryAPI%5Cb%29%7C%28SDLFunctionTemplate%29