2D Game Engine 만들기 – tutorial with SDL
2.SDL Coordinates and Bliting
Tim Jones | October 25th, 2007
Using the
first tutorial as our base, we'll delve more into the world of SDL surfaces.
As I attempted to explain in the last lesson, SDL Surfaces are basically images
stored in memory.
Imagine we have a blank 320x240 pixel surface. Illustrating the SDL coordinate
system,
we have something like this:
우리의 기초로 첫 번째 자습서를 사용하여, 우리는 SDL surface 세계로 좀 더 탐구한다(뒤진다).
지난 단원에서 설명를 시도했지만, SDL surface는 기본적으로 메모리에 이미지를 저장한다.
빈 320 x 240 픽셀 서피스를 상상해 보세요.
SDL 좌표계를 보여주자면,
우리는 이것처럼 뭔가를 갖는다:
|
This coordinate system is quite different than the normal one you are familiar
with.
Notice how the Y coordinate increases going down, and the X coordinate
increases going right.
Understanding the SDL coordinate system is important in order to properly draw
images on the screen.
이 좌표 시스템은 당신에게 익숙한 일반적인것들과는 매우 다르다.
Y좌표에서 증가 하는 방법이 아래로 내려가는 것이고, 오른쪽으로 X좌표가 증가하는 것을 알것이다.
SDL 좌표계를 이해하는 것은 제대로 화면에 이미지를 그리기 위해 중요하다.
Since we already have the main surface (Surf_Display) setup and ready,
we are going to need a way to draw images on it.
This process is called Blitting, where we basically transfer one image onto
another.
But before we can do that, we have to have a way to load these images into
memory.
SDL offers a simple function to do this called SDL_LoadBMP.
Some pseudocode might look like this:
(우리는) 이미 주요 서피스 (Surf_Display) 설치
및 준비를 했으며,
(우리는) 그것에 이미지를 그리는 방법이 필요하다.
이 프로세스는, (우리는) 기본적으로 다른 하나의
이미지를 다른 곳으로 전송 하는, Blitting 라고 합니다.
그러나 우리가 그렇게 할 수 있기 전에, (우리는) 이러한
이미지를 메모리로 로드 하는 방법이 있어야 한다.
SDL는 SDL_loadbmp라 불리는 간단한 함수를
제공 합니다.
일부 의사 코드는 다음과 같이 나타날 수 있습니다 :
1 2 3 4 5 |
SDL_Surface* Surf_Temp; if((Surf_Temp
= SDL_LoadBMP("mypicture.bmp"))
== NULL) { //Error! } |
It's
rather simple, SDL_LoadBMP takes a
single argument, the file you want to load, and returns a surface.
If the functions returns NULL, either the file is not found, corrupted, or some
other error.
Unfortunately, for the sake of effeciency, this method is not enough.
Often the image loaded will be in a different pixel format than the display.
Thus, when we draw an image to the display we can incurr performance loss, lose
image colors, and the like.
But, thanks to SDL, it offers a quick solution around this, SDL_DisplayFormat.
This function takes a surface already loaded, and returns a new surface using
the same format as the display.
그것은 오히려 간단 하다, SDL_LoadBMP은 단일 인수을 갖고,
로드 하려는 파일과 서피스를 반환 합니다.
만약 함수가 NULL을 반환하면, 혹은 파일
없거나, 손상, 또는 일부 다른 오류 이다.
불행히도, 성과의 이익을 위해, 이
방법은 충분 하지 않다.
자주 로드되는 이미지는 디스플레이 보다 다른 픽셀 형식이다.
따라서,(우리가) 디스플레이에 이미지를 그릴
때, (우리) 성능 손실,이미지
색상 손실과 같은 손실이 발생한다.
그러나, SDL 덕분에, 그것은 SDL_DisplayFormat이
주위에 빠른 솔루션을 제공합니다.
이 함수는 이미 로드된 표면을 받아서, 디스플레이와 같은 형식을 사용하여 새 표면을 반환합니다.
Let's take this process and throw it into a reusable class.
Use SDL Tutorial 1 as the basis for you code,
and add the following two new files: CSurface.h, CSurface.cpp.
Open up CSurface.h and add the following:
이 과정을 가지고, 재사용
가능한 클래스로 그것을 던져 보자.
당신 코드를 기초로 해서 SDL 자습서 1을
사용하고, ( CApp.h ,
CApp.cpp )
다음 두 개의 새 파일 추가: CSurface.h, CSurface.cpp.
CSurface.h 열고 아래 부분을 추가:
1 2 3 4 5 6 7 8 9 10 11 12 |
#ifndef
_CSURFACE_H_ #define
_CSURFACE_H_ #include
<SDL.h> class CSurface
{ public: CSurface(); public: static SDL_Surface*
OnLoad(char* File); }; #endif |
We've
created a simple static function, OnLoad, that will load a surface for us.
Now open
CSurface.cpp:
우리는 우리에게 표면을 로드하는 간단한 정적 기능, OnLoad,를 만들었습니다.
지금CSurface.cpp를 열려면 :
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#include
"CSurface.h" CSurface::CSurface()
{ } SDL_Surface* CSurface::OnLoad(char* File) { SDL_Surface*
Surf_Temp = NULL; SDL_Surface*
Surf_Return = NULL; if((Surf_Temp = SDL_LoadBMP(File))
== NULL) { return NULL; } Surf_Return = SDL_DisplayFormat(Surf_Temp); SDL_FreeSurface(Surf_Temp); // free(old surface ) return Surf_Return; } |
There are
a couple of important things to note here.
Firstly, always remember that when you make a pointer to set it to NULL, or 0.
Many problems can come along later if you fail to do this.
Secondly,
notice how SDL_DisplayFormat returns
a new Surface, and doesn't overwrite the original.
This important to remember because since it creates a new surface, we have to
free the old one.
Otherwise, we have a surface floating around in memory.
여기서 주의해야할 중요한 몇 가지가 있습니다.
첫째, 항상 기억 해야 하는 것은 NULL 또는 0으로 설정하는 포인터를 만들 때이다.
이렇게 하지 않는 경우, 나중에 많은 문제가 따라 올 수 있다다.
둘째, 어떻게
SDL_DisplayFormat가 새 서피스를 반환하고, 원본을 덮어쓰기 하지
않는 것을 주의하는 것이다.
이 새 서피스를 생성했기 때문에, 예전것을 해제해야 하는 것을 기억하는 것이 중요하다.
그렇지 않으면, 우리는
메모리에 떠 있는(메모리 누수) 표면을 갖는다.
Now that we have a way of loading surfaces into memory,
we are also going to need a way to draw them onto other surfaces.
Just like SDL offers a function to load images, it also offers a
function to draw (blit) images: SDL_BlitSurface.
Unfortunately,
this function is not as easy to use as the SDL_LoadBMP,
but nonetheless, it's simple enough.
Open back up CSurface.h and add the following function prototype:
이제는 메모리에 서피스들을 로딩하는 방법을 갖는다,
우리는 또한 다른 서비스들위에 그것들을 그리는 방법을 필요해진다.
마치 SDL이
이미지를 로딩하는 함수를 제공하듯이, 그것은 이미지들을 그리는(blit)
함수를 제공한다: SDL_BlitSurface.
불행히도, 이
함수는 SDL_loadbmp만큼 사용 하기 쉽지 않습니다,
하지만 그럼에도 불구하고, 그것은 충분히 간단하다.
CSurface.h을 다시 열고, 다음 함수 프로토타입을 추가:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#ifndef
_CSURFACE_H_ #define
_CSURFACE_H_ #include
<SDL.h> class CSurface
{ public: CSurface(); public: static SDL_Surface*
OnLoad(char* File); // SDL_LoadBmp() static bool OnDraw(SDL_Surface*
Surf_Dest, SDL_Surface*
Surf_Src, int X, int Y); // SDL_BlitSurface() }; #endif |
Now, open
back up CSurface.cpp, and add the following:
지금,
CSurface.cpp, 다시 열어 및 다음 추가:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
#include
"CSurface.h" CSurface::CSurface()
{ } SDL_Surface* CSurface::OnLoad(char* File) { SDL_Surface*
Surf_Temp = NULL; SDL_Surface*
Surf_Return = NULL; if( ( Surf_Temp = SDL_LoadBMP(File
) ) == NULL ) { return NULL; } Surf_Return = SDL_DisplayFormat(Surf_Temp); SDL_FreeSurface(Surf_Temp); return Surf_Return; } bool CSurface::OnDraw(SDL_Surface* Surf_Dest, SDL_Surface*
Surf_Src, int X, int Y) { if(Surf_Dest == NULL ||
Surf_Src == NULL) { return false; } SDL_Rect
DestR; DestR.x = X; DestR.y = Y; SDL_BlitSurface(Surf_Src, NULL, Surf_Dest, &DestR); return true; } |
First of
all, look at the arguments being passed to the OnDraw function.
We have two surfaces, and two int variables.
The first surface is the destination surface, or the surface we are going to
draw on.
The second surface is the source surface, or the surface we going to use to
draw on another surface.
Basically, we are putting Surf_Src on top of Surf_Dest.
The X, Y variables is the position on the Surf_Dest where we are drawing this
surface to.
우선, OnDraw 함수로 전달되어지는 인자들을 살펴보세요.
두 가지 표면과, 두가지
정수 변수를 갖는다.
첫 번째 표면은 대상 표면이고, 또는 우리가 위에 그리려는 하는 표면이다.
두 번째 표면은 소스 표면이고, 또는 우리가 다른 표면에 그리는 데 사용할 표면이다.
기본적으로, 우리는 Surf_Dest 위에 Surf_Src을 올려 놓은다.
X는 Y 변수는 우리가 이 표면을 드로잉하는
Surf_Dest위의 좌표이다.
-----
The start
of the function makes sure we have valid surfaces, if we don't, return false.
Next, we find SDL_Rect.
This is a SDL structure that basically has four members: x, y,
w, h.
This, of course, creates the dimensions for a rectangle.
We are only worried about where we are drawing to, not the size.
So we assign X, Y coordinates to the destination surface.
If you are wondering what NULL is within SDL_BlitSurface,
it's another parameter for a SDL_Rect.
We'll get to this later on in this lesson.
(우리가) 거짓 반환하지 않는 경우, 함수의 시작, (우리가) 유효한 표면을 가지고
있는지 확인합니다.
다음, 우리는 SDL_Rect을 찾으십시오. X, Y, W, H. :
이것은 기본적으로 네 멤버가 SDL 구조입니다
이것은 물론, 사각형에 대한 치수를 만듭니다.
우리는 오직 (우리는) ,크기가 아니라, 어디에 그리기를 해야 하는 것이 걱정입니다.
그래서 (우리는) X, Y좌표를 대상의 표면에
할당한다.
당신은 SDL_BlitSurface안에 NULL이 궁금 하다면, 그것은 SDL_Rect에 대해 다른 매개 변수이다.
(우리는) 이 수업에서 나중에 얘기하자.
Lastly, we actualy call the function to draw the image, and then return true.
마지막으로, 우리는
실제로 이미지를 그릴 수 있는 함수를 호출하고 TRUE를 반환한다.
Now, to make sure all of this works, let's create a test surface.
Open up CApp.h, and create a new surface, and include the new created
CSurface.h:
자, 이 작업의
전부를 확인하기 위해, 시험 표면을 생성해 보자.
CApp.h를 열고 새로운 표면을 만들고, 새로운 생성
CSurface.h을 포함 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
#ifndef
_CAPP_H_ #define
_CAPP_H_ #include
<SDL.h> #include
"CSurface.h" class CApp { private: bool Running; SDL_Surface*
Surf_Display; SDL_Surface*
Surf_Test; public: CApp(); int OnExecute(); public: bool OnInit(); void OnEvent(SDL_Event* Event); void OnLoop(); void OnRender(); void OnCleanup(); }; #endif |
Also,
initialize the surface to NULL in the constructor:
또한, 생성자에서 NULL로 표면 초기화:
1 2 3 4 5 6 |
CApp::CApp() { Surf_Test = NULL; Surf_Display = NULL; Running = true; } |
And,
remember to cleanup:
그리고, 정리를
기억:
1 2 3 4 5 6 7 |
#include
"CApp.h" void CApp::OnCleanup() { SDL_FreeSurface(Surf_Test); SDL_FreeSurface(Surf_Display); SDL_Quit(); } |
Now, lets
actually load an image.
Open up CApp_OnInit.cpp, and add the
code to load a surface:
이제 이미지를로드 실제로 수 있습니다.
CApp_OnInit.cpp을 열고 표면을 로드하는 코드를 추가 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#include
"CApp.h" bool CApp::OnInit() { if(SDL_Init(SDL_INIT_EVERYTHING) < 0) { return false; } if((Surf_Display = SDL_SetVideoMode(640,
480, 32, SDL_HWSURFACE
| SDL_DOUBLEBUF))
== NULL) { return false; } if((Surf_Test = CSurface::OnLoad("myimage.bmp"))
== NULL) { return false; } return true; } |
Be sure
to replace "myimage.bmp" with an actual bitmap image you have.
If you don't have one, open mspaint and draw something real quick,
and save
it in the same folder where your executable goes.
Now that we have the image loaded, lets actually draw it.
Open up CApp_OnRender.cpp and add
the following:
당신이 가진 실제 비트맵 이미지 "myimage.bmp"을 대체해야합니다.
갖고 있는게 없는 경우, mspaint 열고 신속하게
실제 무언가를 그리고,
실행되는 동일한 폴더에 저장합니다.
우리가 이미지를 로드 했으므로, 실제로 그것을 그릴
수 있습니다.
CApp_OnRender.cpp를 열고 다음을 추가 :
1 2 3 4 5 6 7 |
#include
"CApp.h" void CApp::OnRender() { CSurface::OnDraw(Surf_Display, Surf_Test, 0, 0); SDL_Flip(Surf_Display); // double buffering } |
Notice a
new function here SDL_Flip.
This basically refreshes the buffer and displays Surf_Display onto the screen.
This is called double buffering.
It's the process of drawing everything into memory, and then finally drawing
everything to the screen.
If we didn't do this, we would have images flickering on the screen.
Remember the SDL_DOUBLEBUF flag? This
is what turns double buffering on.
새로운 여기에 기능을 SDL_Flip를 확인합니다.
이것은 기본적으로 새로 고쳐 화면에 버퍼와 표시 Surf_Display.
이것은 이중 버퍼링이라고합니다.
그것은 메모리에 모든 그림의 과정, 그리고 마지막으로 화면에 모든 그림.
우리가 이렇게하지 않았다면, 우리는 화면에 깜박임 이미지 것입니다.
SDL_DOUBLEBUF
플래그를 기억해? 이것은 이중에서 버퍼링 요소다.
Compile your code, and make sure everything works correctly.
You should see your image on the top left hand corner of the screen.
If so, congratulations, you are one step closer to an actual game.
If not, make sure you have the myimage.bmp in the same folder as your
executable.
Also insure it's a valid bitmap file.
코드를 컴파일하고 모든 것을 올바르게 작동 하는지 확인 합니다.
화면의 왼쪽 상단 모서리에 귀하의 이미지를 보아야 한다.
그렇다면, 축 하, 당신은 실제 게임에 한 걸음
더 가까이 있다.
그렇지 않은 경우에 실행 파일 같은 폴더에 있는 myimage.bmp를가지고 있는지 확인
하십시오.
또한 보험은 유효한 비트맵 파일입니다.
Now lets take this process a little bit further.
While it's nice and all to draw images to the screen,
often
we'll need to draw only parts of an image.
Take, for example, a tileset:
지금, 조금
더, 이 과정을 걸린다.
그러나 그것은 이미지를 화면에 그리는 훌륭하며 전부이고,
종종 하나의 이미지의 어떤 부분의 그리는 것이 필요하다.
예를 들어,보자면, 한개의 tileset:
Though this is one single image, we only want to draw a part of it.
Open back up CSurface.h, and add the following code:
이것은 하나의 단일 이미지, 비록 우리만 그것의 부분을 그릴 합니다.
백업 Csurface.h을 열고 다음 코드를 추가:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#ifndef
_CSURFACE_H_ #define
_CSURFACE_H_ #include
<SDL.h> class CSurface
{ public: CSurface(); public: static SDL_Surface*
OnLoad(char* File); static bool OnDraw(SDL_Surface*
Surf_Dest, SDL_Surface*
Surf_Src, int X, int Y); static bool OnDraw(SDL_Surface*
Surf_Dest, SDL_Surface*
Surf_Src, int X, int Y, int X2, int Y2, int W, int H); }; #endif |
Open back
up CSurface.cpp, and add the following function:
백업
Csurface.cpp을 열고 다음 함수를 추가:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
bool CSurface::OnDraw(SDL_Surface* Surf_Dest, SDL_Surface*
Surf_Src, int X, int Y, int X2, int Y2, int W, int H) { if(Surf_Dest == NULL ||
Surf_Src == NULL) { return false; } SDL_Rect DestR; DestR.x = X; DestR.y = Y; SDL_Rect SrcR; SrcR.x = X2; SrcR.y = Y2; SrcR.w = W; SrcR.h = H; SDL_BlitSurface(Surf_Src, &SrcR, Surf_Dest, &DestR); return true; } |
Notice
that it's basically the same function as our first one, except we've added
another SDL_Rect.
This source rect allows use to specify what pixels from the source to copy over
to the destination.
If we specified 0, 0, 50, 50 as parameters for X2...H,
it would only draw upper left part of the surface (a 50x50 square).
인지해야 하는 것은
우리는 다른 SDL_rect을
추가하는 것을 제외하고, 기본적으로 우리의 첫 번째와 동일한 기능이다.
이 원본 rect 사용 허용 대상을 통해 복사할 원본에서 어떤 픽셀을 지정 하려면.
,X 2에 0, 0, 50, 50를 매개 변수로 지정하는 경우...H,
그것은 이라고 만 (50 x 50 평방) 서피스의
상단 왼쪽된 부분을 그립니다.
|
Lets also test this new function out, open back up CApp_OnRender.cpp,
and add
the following:
또한, 이 새로운
기능을 테스트 CApp_OnRender.cpp 백업 열고
다음을 추가할 수 있습니다 :
1 2 3 4 5 6 7 8 |
#include
"CApp.h" void CApp::OnRender() { CSurface::OnDraw(Surf_Display, Surf_Test, 0, 0); CSurface::OnDraw(Surf_Display, Surf_Test, 100, 100, 0, 0, 50, 50); SDL_Flip(Surf_Display); } |
You
should notice that your image is drawn at 100, 100 and only part of it is being
displayed.
You should take special care understanding how these functions work,
and how the SDL coordinate system is setup, you will be using this quite
a bit.
당신의 이미지가 100, 100에 그려지고, 그것의 일부만 표시되는 것을 확인할 수 있습니다.
이러한 함수가 작동하는 방법은 (당신은) 특별한
주의의 이해를 해야하며,
SDL 좌표 시스템이 설치하는 방법을, 당신이 잘 사용하는 것입니다.
Jump on over to the next SDL
tutorial, where we'll look more at SDL
events,
and how to make that process a whole lot simpler.
다음 SDL의 튜토리얼에 넘어가서, 우리가 SDL 이벤트에 더 살펴 볼게요,
그 과정이 훨씬 간단하게 하는 방법.
'온라인게임' 카테고리의 다른 글
하복 Havok - 물리 엔진 (0) | 2011.10.16 |
---|---|
2011한·일 게임이용자 조사보고서 (0) | 2011.10.14 |
DATEADD(Transact-SQL) (0) | 2011.10.12 |
인생게임 Man's Life Game (0) | 2011.10.12 |
1. SDL Tutorial Basics (0) | 2011.10.11 |