Allegro/STL Tutorial Ch.3 Study+more

Chapter 3

3. Game Basics

3.1 The Backdrop

Now that our palette is ready, let's start to get some actual graphics onto the screen. We will first create a backdrop bitmap. First we must create a bitmap with create_bitmap(), then we can draw onto it, and finally we will blit it onto the screen. Here is the code that does this.
자 이제 팔레트도 준비되었으니, 그림을 화면에 출력해 보자. 우리는 배경 비트맵을 생성할 것이다. 우선 create_bitmap()을 이용해서 비트맵을 생성하자, 그러면 그 비트맵에 그림을 그릴수 있다. 마지막으로 그 비트맵을 화면에 출력(blit) 할수있다. 다음의 소스코드를 참조하자.
#include <allegro.h>
#include "tutorial.h"

#define MIN_Y 8

DATAFILE* data;
BITMAP* backdrop;

int main()
{
  allegro_init();
  install_keyboard();

  data=load_datafile("tutorial.dat");

  set_gfx_mode(GFX_VGA,320,200,0,0);

  set_palette((RGB*)data[TUT_GAMEPAL].dat);

  // create 320x192 backdrop
  backdrop=create_bitmap(320,192);
  for (int Y=0; Y<128; Y++) hline(backdrop,0,Y,319, (Y/2)+128);
  for (int Y=128; Y<192; Y++) hline(backdrop,0,Y,319, ((Y-128)/2)+192);

  blit(backdrop,screen,0,0,0,MIN_Y,320,200);

  readkey();
  return 0;
}
As you should know, #define is a preprocessor directive used to create a symbolic alias for something else. Here, we use MIN_Y to decide at what Y position the game screen starts, which we preset to be at Y=8, leaving us sufficient room for a status bar at the top later on. We have also defined the global variable backdrop to be a pointer to a BITMAP. We use create_bitmap() to allocate a 320x192 bitmap, then use a couple of for loops to fill every scanline of it with an appropriate color, using hline() to draw each of the horizontal lines onto the backdrop bitmap. Finally, we use blit() to copy the backdrop onto the screen at the appropriate position. We now have the game background ready. (You are of course free to modify the colors as you see fit.)
당신이 물론 알겠지만, #define은 어떤 '무언가'에 대한 심볼릭 링크를 생성할때 사용되는 지시어 이다. 우리는 MIN_Y를 게임 화면의 시작 Y좌표를 의미하는 심볼을 만들었고, 나중에 상태바 출력을 위한 공간을 제외한 8을 할당했다. 우리는 또한 배경 비트맵 메모리를 가리키는 전역 변수도 선언했다. 우리는 create_bitmap() 함수를 사용해서 320*192 비트맵을 할당받을 수 있고, 몇개의 for 루프에 hline() 함수를 사용해서 배경 비트맵을 채울 수 있다. 마지막으로 blit() 함수를 사용해서 배경을 원하는 좌표의 화면에 출력할 수 있다. 이렇게 해서 우리는 게임의 배경 준비를 마쳤다. (뭐, 필요하다면 색상은 feel 가는대로 수정하시던지..- .-)

3.2 Double Buffering

In our game, we are going to use the animation technique known as "double buffering". This means that for each frame (animation snapshot), we will build the displayed image in an off-screen buffer, then blit it onto the screen. This is necessary since if we drew everything sprite by sprite directly onto the screen, it would flicker badly.
우리 게임에서, '더블 버퍼링'이라는 애니메이션 테크닉을 사용할 것이다. 이것은 각 프레임(애니메이션 컷)을 메모리 버퍼에 쓰고, 버퍼의 내용을 화면에 뿌리는 것이다. 이것은 반드시 필요한 것인데, 만약 당신이 모든 스프라이트-프레임-들을 화면에 직접 뿌리면 심하게 '깜빡' 거릴 것이다.
(The technique known as "page flipping" is a similar solution but builds the frame in a part of video memory that isn't shown, and then tells the graphics card to show that part of video memory. In this context, each screenful of data in video memory is known as a page, and page flipping alternates between two pages. If there's a lot of overdraw or special effects, double buffering will be faster, but if there isn't much to draw page flipping is faster. However, in the standard VGA 320x200 256-color graphics mode, there can only be one page, so page flipping is not possible.)
('페이지 플리핑'이라는 테크닉이 상당히 비슷한데, 이것은 비디오 메모리의 출력되지 않는 부분에 쓰는것이다. 그리고 그래픽카드에 해당 부분을 보여달라고 요청하는 것이다. 이때, 비디오 메모리에 있는 각 화면을 '페이지'라고 부른다. 또한 페이지 플리핑이라는것은 두개의 페이지를 서로 바꾸는것이다. (보이는 페이지를 안보이는 페이지로, 안보이는 페이지를 보이는 페이지로) 만약 그려야 할 양이 많다거나 특수효과들이 많이 사용되었다면 더블 버퍼링이 더 빠르다, 그러나 그 외의 경우에는 페이지 플리핑이 빠르다. 하지만, VGA 320x200 256컬러 그래픽 모드에서는 단 하나의 페이지만 있다. 따라서 페이지 플리핑 테크닉은 쓰고 싶어도 쓸수가 없다.)

To illustrate this technique, we will now make our game using double buffering to move the helicopter across the screen until you hit a key.
테크닉을 써먹기 위해서, 우리는 더블 버퍼링을 써서 키보드 입력이 있을때까지 헬리콥터를 횡으로 움직이게 만들것이다.

#include <allegro.h>
#include "tutorial.h"

#define MIN_Y 8

DATAFILE*data;
BITMAP*backdrop,*framebuf;

int main()
{
  allegro_init();
  install_keyboard();

  data=load_datafile("tutorial.dat");

  set_gfx_mode(GFX_VGA,320,200,0,0);

  set_palette((RGB*)data[TUT_GAMEPAL].dat);

  // create 320x192 backdrop
  backdrop=create_bitmap(320,192);
  for (int Y=0; Y<128; Y++) hline(backdrop,0,Y,319, (Y/2)+128);
  for (int Y=128; Y<192; Y++) hline(backdrop,0,Y,319, ((Y-128)/2)+192);

  // create 320x200 double buffer
  framebuf=create_bitmap(320,200);
  clear(framebuf);

  for (int X=0; X<320; X++) {
    // build frame
    blit(backdrop,framebuf,0,0,0,MIN_Y,320,200);
    draw_rle_sprite(framebuf,(RLE_SPRITE*)data[TUT_CHOPPER].dat,X,100);
    // display frame
    vsync();
    blit(framebuf,screen,0,0,0,0,320,200);
  }
  readkey();
  return 0;
}
Here, we create the framebuf bitmap to use as our double buffer, clear it so that where our planned status bar is supposed to be doesn't contain garbage. For each frame in that for loop, we blit the backdrop onto the buffer, then draw the helicopter sprite on top of this. Then we vsync() and then blit the buffer onto the visible screen.
위 소스에서, 우리는 더블버퍼링을 하기 위해서 프레임버퍼 비트맵을 생성했다. 배경이 출력되지 않는 빈 공간-상태바가 출력될 자리-에 쓰레기 데이터(...)가 포함되지 않도록 해당 버퍼를 클리어했다. 루프마다 버퍼에 배경화면을 출력하고 그 위에 헬리콥터 스프라이트를 출력했다. 그리고 vsync()를 호출하고 실제 모니터에 버퍼에 있는 데이터를 뿌렸다.
The vsync() call waits for the vertical retrace, that is when the electron beam that illuminates every pixel on your monitor has finished the frame and is beginning to retrace back to the top of the image to begin a new screen refresh (typically 60 times per second). The best place to update the video memory is in exactly this small retrace period, because if you change the image while the electron beam is busy displaying it, you may get unwanted artifacts. This isn't serious, just doesn't always look good, and besides, there isn't much reason to update the image more often than it can be displayed.
vsync() 함수를 호출하면 수직 retrace를 대기한다. 수직 retrace란 모니터 필셀이 위에서 바닥까지 모두 출력된 다음에 다시 상단 출력 준비까지를 의미한다. (보통 초당 60회 반복한다) 비디오 메모리를 갱신하기 위한 최적의 타이밍은 retrace 기간이다. 왜냐하면 전자빔이 화면에 출력하느라 바쁠때 이미지를 갱신하면 사이드 이팩트가 발생하기 때문이다. 뭐, 사실 크리티컬한 문제는 아니다 다만, 보기에 좋지 않고 굳이 미친듯이 자주 화면을 갱신할 이유가 없기 때문이다. (...- .-)

3.3 User Input

Making a chopper cruise across the screen over a cool shaded background is all fine and well, but what we want to do is to make a game, that means that the user should have at least some control of what he's doing, otherwise he could just as well rent a video. So, to show how this can be done, we will let the user steer the chopper around the screen using the keyboard or joystick.
헬리콥터가 간지나는 배경화면을 가로질러 날아가는데 까지는 무난히 완성했다. 하지만 우리가 만들려는것은 게임다. 게임에 부합할려면 최소한 컨트롤은 되야하지 않을까? 그렇지 않다면 비디오를 틀어놓는것과 뭐가 다르단 말이냐? 그래서 이번에는 키보드나 조이스틱을 이용해서 헬리콥터를 컨트롤 하도록 해 보겠다.

#include <allegro.h>
#include "tutorial.h"

#define MIN_Y 8

DATAFILE*data;
BITMAP*backdrop,*framebuf;
int X=0,Y=100;

int main()
{
  allegro_init();
  install_keyboard();
  initialise_joystick();

  data=load_datafile("tutorial.dat");

  set_gfx_mode(GFX_VGA,320,200,0,0);

  set_palette((RGB*)data[TUT_GAMEPAL].dat);

  // create 320x192 backdrop
  backdrop=create_bitmap(320,192);
  for (int Y=0; Y<128; Y++) hline(backdrop,0,Y,319, (Y/2)+128);
  for (int Y=128; Y<192; Y++) hline(backdrop,0,Y,319, ((Y-128)/2)+192);

  // create 320x200 double buffer
  framebuf=create_bitmap(320,200);
  clear(framebuf);

  while (!key[KEY_ESC]) {
    // build frame
    blit(backdrop,framebuf,0,0,0,MIN_Y,320,200);
    draw_rle_sprite(framebuf,(RLE_SPRITE*)data[TUT_CHOPPER].dat,X,Y);
    // display frame
    vsync();
    blit(framebuf,screen,0,0,0,0,320,200);
    // get user input
    poll_joystick();
    if (key[KEY_LEFT]||joy_left) X--;
    if (key[KEY_RIGHT]||joy_right) X++;
    if (key[KEY_UP]||joy_up) Y--;
    if (key[KEY_DOWN]||joy_down) Y++;
  }
  return 0;
}
This is not very advanced, it does not do any bounds-checking or anything, it is only meant to show how the Allegro keyboard and digital joystick subsystems can be used to control an object. However, we won't do it exactly this way in our actual game, we will be somewhat more ambitious in our game control design.
뭐, 그렇게 어려운것도 없다. 이건 화면 벗어나는것에 대한 제약따위도 없다. 단지 알레그로 키보드와 조이스틱 시스템을 이용해서 오브젝트 컨트롤이 가능함을 보여준것 뿐이다. 하지만, 우리는 실제 게임에서 이 루틴을 그대로 사용하지는 않을거다. 우리는 좀더 빡세고 간지나도록 코드를 짤것이다. : )
To learn more, proceed to the next chapter
우훗, 더 배우고 싶다면 다음 챕터를 보도록 하장. : )

refer: http://www.ping.uio.no/~ovehk/allegro/tut3.html

트랙백

이 글과 관련된 글 쓰기 (트랙백 보내기)
TrackbackURL : http://handmade.egloos.com/tb/5068933 [도움말]

덧글

덧글 입력 영역