2014-01-11 5 views
3

현재 SDL을 배우고 있으며 Pacman 게임을 만들려고합니다. 엄청난 양의 코드로 인해 수렁에 빠지지 않도록 단계별로 시도하고 있습니다.SDL에서 움직이지 않는 이미지 렌더링

지금까지 빈 창을 만들고 그 위에 Pacman 이미지를 렌더링했습니다. 나는 화살표 키를 누르고 Pacman을 창 주위로 움직일 수있다. 저는 Pacman 이미지가 RenderCopy를 사용하여 창에 blit하는 SDL_Texture로 저장되도록 설정했습니다. 사용자가 화살표를 누를 때마다 이미지의 좌표를 이동하고 전체 이미지를 다시 렌더링합니다. 이것은 잘 작동합니다. 그러나 이제 팩맨이 먹을 수있는 점들을 화면에 표시하고 싶습니다. 그러나 도트 이미지를로드하여 팩맨과 함께 화면에 blit하는 새로운 텍스처로 저장할 경우 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; 
} 

EDIT 그것을 지적하는 사람을 이해할 것 : 대답에서 RASER의 의견에, 여기에 내가 PollEvent의 예를 볼 수있는 링크입니다 : 사용 http://wiki.libsdl.org/SDL_CreateRenderer?highlight=%28%5CbCategoryAPI%5Cb%29%7C%28SDLFunctionTemplate%29

+0

어떻게 점을 렌더링하고 있습니까? – raser

+0

도트 이미지를로드하고 새 텍스처에 저장했습니다. 그런 다음 동일한 렌더러를 사용하여 두 번째 RenderCopy (RenderCopy 직후에 Pacman 이미지에 사용한)를 호출했지만 도트 텍스처를 렌더링하고 다른 targetRect를 사용했습니다. 코드에서 이미 가지고있는 동일한 RenderPresent 함수를 유지했습니다. 도트와 팩맨을 렌더링하십시오. – wgrenard

+0

허. 나는 지금 그렇게 할 수 있는지를보기 위해 시험을 썼다. 팩맨이 점들 또는 점들과 함께 깜박입니까? – raser

답변

0

위의 방법은 팩맨을 렌더링하면 화면에 점을 렌더링하는 데 실제로 잘 작동합니다. 점에 대한 이미지를 새 텍스처에 저장하고이 텍스처를 유지하는 SDL_Rect를 만든 다음 SDL_CreateRenderer를 사용하여 도트 이미지를 Pacman과 함께 화면에 렌더링합니다. 프레임 속도를 늦추려면 SDL_Delay와 같은 것을 사용하지 않는 한 렌더링 사이에 점의 깜박임이 없음을 알아야합니다.