2014-01-11 46 views
3

我目前在學習SDL,我正在嘗試創建一個Pacman遊戲。我試圖採取措施,以避免陷入大量的代碼。在SDL中渲染無運動圖像

到目前爲止,我已經創建了一個空白窗口,並呈現一個Pacman圖像。我可以按下箭頭鍵並在窗口周圍移動Pacman。我已經設置好Pacman圖像作爲SDL_Texture存儲,我使用RenderCopy將它存儲到窗口中。每次用戶按下箭頭時,我都會移動圖像的座標並重新渲染整個圖像。這工作得很好。不過,現在我想在屏幕上放一些點來讓吃豆子的人吃。如果我加載一個點圖像並將其作爲一個新的紋理與Pacman一起移動到屏幕上,但是,每當我移動Pacman時,點就會閃爍出來,因爲它正在被抹去並與Pacman一起渲染。

我的問題是,我該如何避免這種「閃爍」?我能以某種方式重新呈現Pacman而不重繪渲染屏幕的其餘部分嗎?還是有另一種方法來做到這一點?我想我在後臺嘗試創建迷宮時也會遇到同樣的問題。我如何製作靜態背景,每次渲染時都不會閃爍出來?

以下是我的代碼到目前爲止。請原諒我,如果在那裏有任何不良形式的代碼。正如我所說的,我剛剛開始學習SDL(對於C++來說也很新穎),所以如果有什麼明顯的「你永遠不應該那樣做!」在那裏樣的東西,我將不勝感激有人指點一下:)

#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; 
} 

編輯:在回答RASER的評論,這裏是我發現PollEvent例如鏈接:http://wiki.libsdl.org/SDL_CreateRenderer?highlight=%28%5CbCategoryAPI%5Cb%29%7C%28SDLFunctionTemplate%29

+0

你是如何渲染點? – raser

+0

我加載了點圖像並將其存儲在新紋理中。然後,我使用相同的渲染器調用了第二個RenderCopy(在用於Pacman圖像的RenderCopy之後),但渲染了點紋理並使用了不同的targetRect。然後,我只保留了代碼中已有的RenderPresent函數渲染點和Pacman。 – wgrenard

+0

我剛纔寫了一個測試,看它是否會這樣做,而不是。 pacman是否與點或點一起閃爍? – raser

回答

0

上述方法使用使得Pacman實際上可以很好地將點渲染到屏幕上。只需將點的圖像存儲在新紋理中,創建一個SDL_Rect來保存此紋理,然後使用SDL_CreateRenderer將點圖像與Pacman一起渲染到屏幕上。只要您沒有使用像SDL_Delay這樣的功能來降低幀速率,您應該注意到效果圖之間不會閃爍點。