DX라이브러리2014. 12. 22. 17:09

2.1 이미지 처리 : 응용편


샘플 이미지 두개를 이용하여 진행한다.


 


 


 image/character_00.png

image/character_01.png 


아래의 예제는 character_01.png를 처리한 후 character_00.png를 처리하고 있다.


#include <DxLib.h>


int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){

        ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK );


        int x = 0;

        int Handle00, Handle01;

        Handle00 = LoadGraph( "image/character_00.png" );

        Handle01 = LoadGraph( "image/character_01.png" );


        while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 ){


                DrawGraph( x/2, 0, Handle01, TRUE );

                DrawGraph( x,   0, Handle00, TRUE );

                x++;


        }

        

        DxLib_End();

        return 0;


실행결과




프로그램은 위에서부터 차례대로 실행되기 때문에 character_01.png가 먼저 그려지고 이후 character_00.png가 그려지게된다. 이 때문에 좀더 나중에 그려진 이미지가 먼저 그려진 이미지보다 위에 보이게 된다. 다음 예제는 순서를 바꾸어 본 경우이다.


#include <DxLib.h>


int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){

        ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK );


        int x = 0;

        int Handle00, Handle01;

        Handle00 = LoadGraph( "image/character_00.png" );

        Handle01 = LoadGraph( "image/character_01.png" );


        while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 ){


                DrawGraph( x/2, 0, Handle00, TRUE );

                DrawGraph( x,   0, Handle01, TRUE );

                x++;


        }

        

        DxLib_End();

        return 0;


실행결과




결과에서 보는 것 처럼 character_01.jpg의 이미지에는 투명한 부분이 포함되어있는 이미지다.  DrawGraph함수를 통하여 투명도 적용 여부를 결정 가능하다.


DrawGraph( x/2, 0, Handle00, TRUE );


붉은색 표시된 TRUE를 FALSE로 변경하면 투명부분을 처리하지 않는다.


Posted by 캡슐리어
DX라이브러리2014. 12. 22. 16:40

1.9 게임 프로그램 골격의 완성


#include <DxLib.h>


int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){

        ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK ); //윈도우모두, DX라이브러리 초기화, 백그라운드 처리


        int x = 0;

        int Handle;

        Handle = LoadGraph( "image/character_01.png" );


        // while(이미지 반영, 메세지 처리, 화면 클리어)

        while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 ){


                DrawGraph( x, 100, Handle, TRUE );

                x = x + 2;


        }

        

        DxLib_End();

        return 0;


프로그램은 while문의 내부에서 루프하고 있다. 즉, 게임에서 프레임이 필요한 처리는 붉은색 표시부분만 추가하면 된다는 말이다. 그럼 다음과 같이 표시될 좌표를 세개로 나누어보자.


#include <DxLib.h>


int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){

        ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK );


        int x = 0;

        int Handle;

        Handle = LoadGraph( "image/character_01.png" );


        while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 ){


                DrawGraph( x,   100, Handle, TRUE ); //이미지 처리

                DrawGraph( x/2, 200, Handle, TRUE ); //이미지 처리

                DrawGraph( x/4, 300, Handle, TRUE ); //이미지 처리

                x = x + 2;


        }

        

        DxLib_End();

        return 0;


실행결과




3개의 이미지가 동시에 다른 속도로 움직이는 것을 확인 가능하다. 이처럼 while문 내부에 코딩하는 것으로 게임을 만들어가게 된다. 즉, 필요 최소한의 코드는 다음과 같다.


#include <DxLib.h>


int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){

        ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK );


        while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 ){


                //이곳에 필요한 코딩을 하게된다.


        }

        

        DxLib_End();

        return 0;

}



Posted by 캡슐리어
DX라이브러리2014. 12. 22. 14:34

1.8 소스코드를 간단하게 줄이자



루프 문장의 작동 순서는 다음과 같다.


while(1){

메세지 처리;

화면의 이미지를 삭제;

이미지를 화면에 그릴 수 있도록 준비;

백그라운드에 그려놓은 내용을 포어그라운드에 반영;

}


이 중 붉게 표시된 부분 이외에는 매번 반드시 진행되어야 한다. 루프 구문마다 매번 이 코드를 작성하게 된다면 소스코드가 매우 길어질 수 있기 때문에 간단하게 줄여 쓰도록 한다.


Before

#include <DxLib.h>


int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){

        ChangeWindowMode( TRUE );

        DxLib_Init();

        SetDrawScreen( DX_SCREEN_BACK );


int x = 0;

int Handle;

Handle = LoadGraph( "image/character_01.png" );


while( 1 ){

if( ProcessMessage() != 0 ){

                        break;

                }

                ClearDrawScreen();

                DrawGraph( x, 100, Handle, TRUE );

                x = x + 2;

                ScreenFlip();

}

DxLib_End();

return 0;

}


After

#include <DxLib.h>


int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){

        ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK ); //윈도우모두, DX라이브러리 초기화, 백그라운드 처리


        int x = 0;

        int Handle;

        Handle = LoadGraph( "image/character_01.png" );


        // while(이미지 반영, 메세지 처리, 화면 클리어)

        while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 ){


                DrawGraph( x, 100, Handle, TRUE );

                x = x + 2;


        }

        

        DxLib_End();

        return 0;


while의 조건문에서 호출된 함수들은 공통적으로 에러 발생시 0이외의 값을 반환한다. 때문에 위와 같은 방법으로 코딩 가능하다. 즉, 다음과 같은 코딩이 가능하다. 


초기화 처리;

while(1프레임당 반드시 한번 진행해야 하는 처리){

내용;

}


종료처리;


단, DX라이브러리의 초기화 함수는 반환값이 보이질 않기 때문에 에러가 발생한다고 해도 별다른 변화가 없다. 원래대로라면 아래의 예제와 같이 함수별로 하나하나 반환값이 정상인지 체크하여하 하며 이상 발생시 종료하도록 하는것이 제일 좋다.


#include <DxLib.h>


int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){

        if( ChangeWindowMode(TRUE) != 0 ){

                return 0;

        }

        if( DxLib_Init() != 0 ){

                return 0;

        }

        if( SetDrawScreen( DX_SCREEN_BACK ) != 0 ){

                DxLib_End();

                return 0;

        }


        int x = 0;

        int Handle;

        Handle = LoadGraph( "image/character_01.png" );


        while( 1 ){

                if( ScreenFlip() != 0 ){

                        break;

                }

                if( ProcessMessage() != 0 ){

                        break;

                }

                if( ClearDrawScreen() != 0 ){

                        break;

                }


                DrawGraph( x, 100, Handle, TRUE );

                x = x + 2;


        }


        DxLib_End();

        return 0;


일단 예제가 간단해지기 위해 세세한 처리는 생략하였지만 이후 직접 게임을 제작하게 될 때에는 이 예제와 같이 세세하게 에러를 체크해주는 편이 좋다.

Posted by 캡슐리어
DX라이브러리2014. 12. 22. 13:55

1.7 백그라운드처리를 통한 이미지 움직이기


백그라운드처리는 다음과 같은 단계로 진행된다.


- 이미지를 백그라운드에서 처리하도록 함수를 먼저 호출한다.

- 루프 마지막에 백그라운드를 포어그라운드로 반영시켜주는 함수를 호출한다.


백그라운드 처리를 위한 함수는 SetDrawScreen( DX_SCREEN_BACK ); 이며 이 문장을 추가 함으로써 이미지를 백그라운드에서 포어그라운드로 처리해주는 단계를 자동적으로 처리 해준다. 이후 루프의 마지막에 이미지를 포어그라운드에 반영해주는 ScreenFlip함수를 호출하면 된다. 이 역시 단순히 호출만 하면 되는 작업이라 자세한 설명은 생략한다.


#include <DxLib.h>


int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){

ChangeWindowMode( TRUE );

DxLib_Init();

SetDrawScreen( DX_SCREEN_BACK ); //이미지 백그라운드 처리 설정


        int x = 0;

        int Handle;

        Handle = LoadGraph( "image/character_01.png" );


        while( 1 ){

                if( ProcessMessage() != 0 ){

                        break;

                }

                ClearDrawScreen();

                DrawGraph( x, 100, Handle, TRUE );

                x = x + 2;

                ScreenFlip(); //백그라운드 화면을 포어그라운드 화면에 반영

}

DxLib_End();

return 0;


실행결과




이와 같은 결과를 볼 수 있게 된다. 코딩시에는 반드시 백그라운드 처리를 염두해두고 작업하도록 한다.


지금까지의 내용을 정리하면


while(1){

메세지 처리;

화면의 이미지를 삭제;

이미지를 화면에 그릴 수 있도록 준비;

백그라운드에 그려놓은 내용을 포어그라운드에 반영;

}


와 같은 순으로 정리가 가능하다. 또한 이번 섹션에서의 예제에서는 sleep문이 포함되어있지 않다. 본래대로라면 엄청난 속도로 처리가 되면서 이미지가 움직여야 하지만 ScreenFlip함수는 모니터의 재생빈도에 맞추어 이미지처리를 하게되며 60Hz로 동작하는 모니터에서는 1/60초의 대기 시간을 갖게된다. 때문에 빠른속도로 이동하지 않고 적당한 속도로 이동하는 이미지를 확인 할 수 잇다. 


즉, 위 예제에서는 한번의 루프에 x좌표가 2씩 증가하고 60Hz의 속도로 연산하게되면 1초에 x좌표는 120증가 하는 것을 알 수 있다. 이와같이 1초에 몇 프레임의 처리가 가능한가 하는 "프레임 레이트"를 통하여 이동속도를 유추하는게 가능하다. 일반적인 PC의 재생빈도는 60Hz이며 보통 게임을 제작할 때에도 60FPS라는 전제하에 제작하게 된다.

Posted by 캡슐리어
DX라이브러리2014. 12. 22. 13:06

1.6 백그라운드 처리 없이 이미지 움직이기


이미지를 화면에 표시할 때에는 포어그라운드에서 직접 처리하지 않고 프레임버퍼에서 직접 처리하게 된다면 모니터의 재생빈도(보통 60Hz)와 타이밍이 맞질 않아 잘못된 이미지가 표시된다. 이는 이미지가 깜빡이거나 잔상을 남기거나 하는 오류를 보이게 된다. 때문에 백그라운드에서 미리 처리하여 정상적인 이미지가 완성되었을 때 표시하는 단계를 거쳐야 한다. 단, 이번 섹션에서는 백그라운드 처리가 없는 상태에서는 어떻게 보이는지 확인한다.


#include <DxLib.h>


int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){

        ChangeWindowMode( TRUE ); // 윈도우 모드

        DxLib_Init(); // DX라이브러리 초기화


        int x = 50;

        int Handle; // 이미지 핸들값 저장을 위한 변수 선언

        Handle = LoadGraph( "image/character_01.png" ); // 이미지 로드


        while( 1 ){

                if( ProcessMessage() != 0 ){ // 메시지 처리

                        break;// 윈도우의 x버턴 클릭시 종료

                }

                DrawGraph( x, 100, Handle, TRUE ); //이미지 표시

                x = x + 2; // x(횡좌표)를 2씩 늘림

                Sleep(7); // 한번 루프때마다 7ms씩 슬립

        }

        

        DxLib_End(); // DX라이브러리 종료

        return 0;


실행결과



위 스크린샷처럼 이전에 표시된 프레임을 삭제하지 않고 새로 덧 씌웠기때문에 잔상이 보이게 된다. 디스플레이에 표시된 내용을 지우는 함수는 ClearDrawScreen 함수가 있다. 이 함수역시 단순히 호출하는 것 만으로 작동하기 때문에 특별한 설명은 필요 없다. 루프 시작시에 ProcessMessage함수와 ClearDrawScreen함수가 필요하다고 알고 있으면 되겠다.


#include <DxLib.h>


int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){

        ChangeWindowMode( TRUE ); 

        DxLib_Init(); 


        int x = 50;

        int Handle;     

        Handle = LoadGraph( "image/character_01.png" );


        while( 1 ){

                if( ProcessMessage() != 0 ){ 

                        break;

                }

                ClearDrawScreen(); // 이미지를 지운다

                DrawGraph( x, 100, Handle, TRUE );

                x = x + 2;

                Sleep(7);

        }

        

        DxLib_End();

        return 0;


실행결과




위 실행결과와 같이 부드럽게 움직이지 못하고 어딘가 부자연 스러운 움직임을 볼 수 있다.

Posted by 캡슐리어
DX라이브러리2014. 12. 19. 18:26

1.5 특정 키 입력상태를 감지


CheckHitKey 함수 레퍼런스 (주 : 일본어)


선언 

 int CheckHitKey( int KeyCode ); 

기능

 특정 키 입력을 받는다.

인수

 KeyCode : 입력상태를 확인할 키의 키코드

반환값 

 1 - 입력됐다.

 0 - 입력 안됐다.


사용 예)

while( 1 ){

  if( CheckHitKey( KEY_INPUT_ESCAPE ) == 1 ){

    break;

  }

}

*ESC의 키코드 : KEY_INPUT_ESCAPE

*ESC를 입력하였을 때 while 반복분을 중단



=-=-=- 

예제)

#include <DxLib.h>


int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){

        ChangeWindowMode( TRUE ); // 윈도우모드

        DxLib_Init();   // DX라이브러리 초기화


        int Handle;

        Handle = LoadGraph( "image/character_00.png" );

        DrawGraph( 50, 100, Handle, TRUE );


        while( 1 ){

                if( CheckHitKey(KEY_INPUT_ESCAPE) == 1 ){

                        break;

                }

        }

        

        DxLib_End() ;   // DX라이브러리 종료

        return 0 ;

}


제대로 동작하는 경우도 있지만 대부분은 화면이 멈추거나 응답없음오류가 발생할 것이다.

이때에는 ProcessMessage 함수를 추가해준다.

이 함수는 특히 특정 부분을 루푸하는 문장에 사용하게 될 것이다.


수정 예)

#include <DxLib.h>


int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){

        ChangeWindowMode( TRUE ); // 윈도우모드

        DxLib_Init();   // DX라이브러리 초기화


        int Handle;

        Handle = LoadGraph( "image/character_00.png" );

        DrawGraph( 50, 100, Handle, TRUE );


        while( 1 ){

                ProcessMessage();  //추가된 함수

                if( CheckHitKey(KEY_INPUT_ESCAPE) == 1 ){

                        break;

                }

        }

        

        DxLib_End() ;   // DX라이브러리 종료

        return 0 ;

}


실행결과



ESC키를 통해 프로그램의 종료가 가능하다.



이 외에 윈도우의 x버튼을 클릭했을 때 프로그램을 종료시키는 예제는 다음과 같다.

#include <DxLib.h>


int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){

        ChangeWindowMode( TRUE ); // 윈도우모드

        DxLib_Init();   // DX라이브러리 초기화


        int Handle;

        Handle = LoadGraph( "image/character_00.png" );

        DrawGraph( 50, 100, Handle, TRUE );


        while( 1 ){

                if( ProcessMessage() != 0 ){

                        break;

                }

        }

        

        DxLib_End() ;   // DX라이브러리 종료

        return 0 ;



Posted by 캡슐리어
DX라이브러리2014. 12. 19. 16:50

1.4 이미지를 메모리로 호출하여 표시


1.3에서 언급했던 메모리로 미리 로드하는 방법을 통한 이미지 표시는 두 단계를 거친다.

* 이미지 로드

* 로드한 이미지 표시




이미지 로드 함수


 선언 

 int LoadGraph( char *FileName );

기능

 이미지 파일을 메모리로 로드

인수

 FileName : 로드하려는 이미지, 동영상의 경로의 포인터

반환값

 -1 : 에러발생

 -1이상 : 그래픽 핸들값


이 함수를 통하여 이미지를 메모리로 업로드하면 데이터핸들을 반환하고 이 값은 int형임.


사용 예)

int Handle;

Handle = LoadGraph( "image/character_00.png" );




로드한 이미지 표시


선언 

 int DrawGraph( int x, int y, int GrHandle, int TransFlag );

기능

 메모리에 로드한 이미지를 화면에 표시

인수

 x, y : 좌표

 GrHandle : 표시할 이미지의 데이터핸들

 TransFlag : 투명한 부분의 처리방법 결정


=-=-=-=-

사용 예제


#include <DxLib.h>


int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){

        ChangeWindowMode( TRUE ); // 윈도우모드

        DxLib_Init();   // DX라이브러리 초기화


        int Handle;     // 데이터핸들을 저장하기 위한 변수 선언

        Handle = LoadGraph( "image/character_00.png" ); // 이미지 로드

        DrawGraph( 50, 100, Handle, TRUE ); // 데이터핸들을 통한 화면표시


        WaitKey();     // 키 입력 대기

        DxLib_End();   // DX라이브러리 종료

        return 0;


실행화면



'DX라이브러리' 카테고리의 다른 글

1.6 백그라운드 처리 없이 이미지 움직이기  (0) 2014.12.22
1.5 특정 키 입력상태를 감지  (0) 2014.12.19
1.3 이미지 표시  (0) 2014.12.19
1.2 윈도우 표시  (0) 2014.12.19
1.1 환경구축  (0) 2014.12.19
Posted by 캡슐리어
DX라이브러리2014. 12. 19. 16:00

1.3 이미지표시


#include "DxLib.h"


int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){

        ChangeWindowMode(TRUE);

        DxLib_Init();   


        LoadGraphScreen( 50, 100, "image/character_00.png", TRUE ); 


        WaitKey(); 

        DxLib_End();

        return 0;

}


 LoadGraphScreen( 50, 100, "image/character_00.png", TRUE ); 

이 함수를 통하여 이미지 표시

LoadGraphScreen 함수 레퍼런스


선언

 LoadGraphScreen( int x , int y , char *GraphName , int TransFlag );

기능 

 그림파일을 호출하여 화면에 표시

인수 

 x, y : 호출한 그림을 표시하는 좌표. 그림파일의 좌상 기준

 GraphName : 호출할 그림의 경로 또는 경로가 저장되어있는 포인터

 TransFlag : 그림의 투명한 부분의 처리 방법을 결정



단, 이 함수는 테스트 이외에는 사용하지 않는 것을 추천한다.


이 함수를 사용하여 화면에 이미지를 표시할 때에는 다음과 같은 단계를 거치게 된다.


이는 이미지를 표시할 때마다 하드디스크에 접근하게되고 프로그램 수행을 "엄청나게"느리게 하는 원인이 된다.

때문에 하드디스크에서 메모리로 업로드 후 표시하는 다음과 같은 방식을 사용하게 된다.




'DX라이브러리' 카테고리의 다른 글

1.5 특정 키 입력상태를 감지  (0) 2014.12.19
1.4 이미지를 메모리로 호출하여 표시  (0) 2014.12.19
1.2 윈도우 표시  (0) 2014.12.19
1.1 환경구축  (0) 2014.12.19
DX라이브러리 개요  (0) 2014.12.19
Posted by 캡슐리어
DX라이브러리2014. 12. 19. 15:24

1.2 윈도우 표시


#include "DxLib.h"


int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){

        DxLib_Init();   



        WaitKey();      

        DxLib_End();    

        return 0;

}


int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int)  


메인 함수 호출



DxLib_Init(); 


DX라이브러리 함수를 시작하기위해선 반드시 시작전 이 문장이 들어가야 한다.

이 함수는 윈도우 생성부터 초기화까지 전부 내부에서 처리해준다.



WaitKey();


키 입력을 기다리는 함수



DxLib_End();


DX라이브러리를 종료시킬 때 사용하는 함수




#include "DxLib.h"


int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){

        ChangeWindowMode(TRUE); 

        DxLib_Init();   



        WaitKey();    

        DxLib_End();  

        return 0;

}



메인 함수의 맨 앞 ChangeWindowMode(TRUE);  함수는 윈도우 모드로의 변경을 위한 함수

* TRUE : 윈도우모드

* FALSE : 전체화면모드




'DX라이브러리' 카테고리의 다른 글

1.5 특정 키 입력상태를 감지  (0) 2014.12.19
1.4 이미지를 메모리로 호출하여 표시  (0) 2014.12.19
1.3 이미지 표시  (0) 2014.12.19
1.1 환경구축  (0) 2014.12.19
DX라이브러리 개요  (0) 2014.12.19
Posted by 캡슐리어
DX라이브러리2014. 12. 19. 14:57

1.1 환경 구축


다운로드 받은 압축파일을 해제하면 보이는 GameProg.sln을 실행한다.


* "긖긂깛긤" 폴더 : 사운드 샘플

* "됪몴" 폴더 : 이미지 샘플


만약 어떤 프로그램과도 링크되어있지 않다면 VisualC++ 2010 Express를 설치한다.

제대로 설치된 상태에서 실행하면 다음과 같은 화면을 볼 수 있다.



그 후 "디버그(D) - 디버깅 하지 않고 시작"을 수행했을 때 검은색 화면(아무키나 나오면 빠져나온다.)이 보인다면 준비 완료.


* 솔루션 탐색기의 GameProg하단 트리는 각각 소스파일, 헤더파일, 리소스파일 이라고 적혀있음.



소스파일 하단의 test.cpp파일을 열어보면 위와 같은 소스코드를 확인 가능하다.

이 코드는 DX라이브러리를 이용하여 윈도우를 생성하는 가장 기본적인 코드 되겠다.

'DX라이브러리' 카테고리의 다른 글

1.5 특정 키 입력상태를 감지  (0) 2014.12.19
1.4 이미지를 메모리로 호출하여 표시  (0) 2014.12.19
1.3 이미지 표시  (0) 2014.12.19
1.2 윈도우 표시  (0) 2014.12.19
DX라이브러리 개요  (0) 2014.12.19
Posted by 캡슐리어