- 음악과 나 -/『 짬 통 』

다이렉트 X 게임 만들기 good81(전영란)

noon2dy 2006. 4. 17. 13:51

 

기쁨 API, Direct X를 이용한 그림 띄우기 (분류:프로그래밍)
2005-10-09 오후 7:49:14

 

 

먼저 VC++에서 Alt + F7을 눌러 링크에 ddraw.lib, dxguid.lib를 추가시켜 준비를 마춘다.

 

설명은 다음에 하겠습니다. 몸이 불편하여 ㅡㅡ;

 

#include

 

#include

 

#include "ddutil.h"

 

 

 

#define MAX 256 //미사일의 최대 개수

 

 

 

//키보드의 정보를 담을 버퍼

 

BOOL NowKeyState[256];

 

//전역으로 사용될 윈도우 핸들

 

HWND GlobalWnd;

 

LPDIRECTDRAW7 lpDirectOBJ; //LPDIRECTDRAW7의 객체

 

 

 

LPDIRECTDRAWSURFACE7 lpPrimarySurface; //Primary Surface의 객체를 생성

 

LPDIRECTDRAWSURFACE7 lpBackSurface; //Back Surface 객체를 생성합니다.

 

LPDIRECTDRAWSURFACE7 lpPlayer; //플레이어 그림 객체

 

LPDIRECTDRAWSURFACE7 lpEnermy;//적기 그림 객체

 

LPDIRECTDRAWSURFACE7 lpPMissile;//미사일 그림 객체

 

LPDIRECTDRAWSURFACE7 lpBoom; // 충돌시 출력 이미지 객체

 

LPDIRECTDRAWSURFACE7 lpBackGround;//배경 그림 객체

 

 

 

int Frame = 0; //프레임의 초기값 설정

 

int inc =0 ; // 증가값

 

int PPlaneX =500, PPlaneY=500; // 플레이어 시작 위치

 

 

 

int PMX[MAX], PMY[MAX]; // 미사일 좌표.

 

int PMissileState;//미사일 증가 값 0~255

 

int PMOn[MAX], PMCount[MAX]; //PMOn[MAX]는 미사일 온, 오프, PMCount[MAX]는 출려되는 미사일 갯수.

 

int Total = 0; // 미사일의 전체적인 증가값

 

int Bx =0 ,By =0; // 미사일그림 출발 좌표값

 

 

 

//에러 메시지를 출력해 줌

 

BOOL ErrorMessage(HWND hwnd, char *str)

 

{

 

    MessageBox(hwnd, str, "연산실패", MB_OK);

 

    DestroyWindow(hwnd);

 

 

 

    return FALSE;

 

}

 

 

 

//#########################################################

 

//  용도 : 생성한 객체를 모두 삭제한다.

 

//  연결 관계 : MsgProc 부분에서 메시지가 종료될 때

 

//              그 부분에서 호출되어 윈도우와 동시에 삭제된다.

 

//##########################################################

 

void DeleteAll(void)

 

{

 

    //Primary Surface를 소멸시킨다.

 

    if(lpPrimarySurface != NULL)

 

    {

 

        lpPrimarySurface ->Release();

 

        lpPrimarySurface = NULL;

 

    }

 

 

 

    if(lpBackGround != NULL)

 

    {

 

        lpBackGround ->Release();

 

        lpBackGround = NULL;

 

    }

 

 

 

    if(lpEnermy!= NULL)

 

    {

 

        lpEnermy ->Release();

 

        lpEnermy = NULL;

 

    }

 

 

 

    if(lpBoom != NULL)

 

    {

 

        lpBoom ->Release();

 

        lpBoom = NULL;

 

    }

 

    

 

    //화면 객체로 사용한 그림을 삭제한다.

 

    if(lpPMissile != NULL)

 

    {

 

        lpPMissile->Release();

 

        lpPMissile = NULL;

 

    }

 

 

 

    if(lpPlayer != NULL)

 

    {

 

        lpPlayer->Release();

 

        lpPlayer = NULL;

 

    }

 

 

 

    //LPDIRECTDRAW7 객체를 삭제한다.

 

    if(lpDirectOBJ != NULL)

 

    {

 

        lpDirectOBJ ->Release();

 

        lpDirectOBJ = NULL;

 

    }

 

}

 

 

 

//###################################################

 

//  용도 : 윈도우에서 발생하는 메시지의 처리

 

//  연결관계 : 메시지를 처리할 부분에서 사용된다.

 

//###################################################

 

long FAR PASCAL WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

 

{

 

    switch(message)

 

    {

 

    case WM_KEYDOWN: //키가 눌렸을 때의 처리

 

        NowKeyState[wParam] = TRUE;

 

        break;

 

 

 

    case WM_KEYUP: //키가 놓여졌을 때의 처리

 

        NowKeyState[wParam] = FALSE;

 

        break;

 

 

 

    case WM_TIMER: //타이머가 호출될 때마다 한프레임씩 증가한다.

 

        if(Frame

 

        {

 

            Frame = Frame + 1;

 

        }

 

        else

 

        {

 

            Frame = 0;

 

        }

 

 

 

        break;

 

 

 

    case WM_DESTROY:

 

        DeleteAll(); //종료 시 생성한 객체를 모두 삭제한다.

 

        KillTimer(GlobalWnd, NULL);

 

        PostQuitMessage(0);

 

        break;

 

    }

 

    return DefWindowProc(hWnd, message, wParam, lParam);

 

}

 

 

 

//################################################################

 

//  용도 : 윈도우 생성을 초기화 한다.

 

//  연결관계 : 윈도우를 처음 생성 시에 메인에서 호출하여 생성한다.

 

//################################################################

 

BOOL InitWindow(HINSTANCE hInstance, int nCmdShow)

 

{

 

    WNDCLASS wc; //윈도우 클래스의 선언

 

 

 

    wc.style = CS_HREDRAW | CS_HREDRAW | CS_DBLCLKS;

 

    wc.lpfnWndProc = WindowProc;

 

    wc.cbClsExtra = 0;

 

    wc.cbWndExtra = 0;

 

    wc.hInstance = hInstance;

 

    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);

 

    wc.hCursor = LoadCursor(NULL, IDC_ARROW);

 

    wc.hbrBackground = GetStockBrush(BLACK_BRUSH);

 

    wc.lpszMenuName = NULL;

 

    wc.lpszClassName = "EXAM3_1";

 

    RegisterClass(&wc);

 

 

 

    //윈도우의 생성

 

    GlobalWnd = CreateWindowEx (0, "EXAM3_1", NULL, WS_POPUP, 0, 0, GetSystemMetrics(SM_CXSCREEN),

 

                                GetSystemMetrics(SM_CXSCREEN), NULL, NULL, hInstance, NULL);

 

 

 

    //생성에 실패하였을 경우

 

    if ( !GlobalWnd) return FALSE;

 

 

 

    //윈도우를 업데이트하는 부분

 

    SetFocus(GlobalWnd);

 

    ShowWindow(GlobalWnd, nCmdShow);

 

    UpdateWindow(GlobalWnd);

 

    ShowCursor(FALSE);

 

 

 

    return TRUE;

 

}

 

 

 

//################################################################

 

//  용도 : 다이렉트 드로우를 초기화 하는 부분

 

//  연결관계 : 다이렉트 드로우상의 실질적인 작업을 할 수 있게 한다.

 

//################################################################

 

BOOL InitDirectDraw(int x, int y, int bpp)

 

{

 

    HRESULT hr; //결과값을 담을 변수

 

    DDSURFACEDESC2 ddsd; //표면을 담을 객체

 

    DDSCAPS2 ddscaps; //표면의 정보를 저장한다

 

    LPDIRECTDRAW pdd; //다이렉트 드로우의 객체를 생성한다.

 

    

 

    //다이렉트 드로우들 생성한다.

 

    hr = DirectDrawCreate(NULL, &pdd, NULL);

 

    if (hr !=DD_OK)

 

        return ErrorMessage(GlobalWnd, "DirectDrawCreate의 실패"); //버전 검사하기

 

    

 

    hr = pdd->QueryInterface (IID_IDirectDraw7, (LPVOID * ) &lpDirectOBJ);

 

    if (hr !=DD_OK)

 

        return ErrorMessage(GlobalWnd, "QueryInterface의 실패"); //협력수준을 검사합니다.

 

 

 

    hr = lpDirectOBJ->SetCooperativeLevel(GlobalWnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);

 

    if (hr != DD_OK) return ErrorMessage(GlobalWnd, "SetCooperativeLevel의 실패");

 

 

 

    //화면보드를 설정합니다.

 

    hr = lpDirectOBJ ->SetDisplayMode(x,y,bpp,0,0);

 

    if (hr != DD_OK)

 

        return ErrorMessage(GlobalWnd, "SetDisplayMode의 실패");

 

 

 

    //Primary Surface를 만들어 정보를 담는다.

 

    memset(&ddsd,0,sizeof(ddsd));

 

    ddsd.dwSize = sizeof(ddsd);

 

    ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;

 

    ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;

 

    ddsd.dwBackBufferCount = 1;

 

 

 

    //담겨진 정보를 가지고 실질적인 표면을 생성한다.

 

    hr = lpDirectOBJ -> CreateSurface(&ddsd, &lpPrimarySurface, NULL);

 

    if (hr != DD_OK)

 

        return ErrorMessage(GlobalWnd, "CreateSurface의 실패");

 

 

 

    //Back Surface 표면을 생성하기 위한 표면의 저장을 저장한다.

 

    memset(&ddscaps, 0, sizeof(ddscaps));

 

    ddscaps.dwCaps = DDSCAPS_BACKBUFFER;

 

 

 

    //후위면과 Primary Surface와의 연결을 설정한다.

 

    hr = lpPrimarySurface -> GetAttachedSurface(&ddscaps, &lpBackSurface);

 

    if (hr != DD_OK)

 

        return ErrorMessage(GlobalWnd, "GetAttachedSurface의 실패 ");

 

    return TRUE;

 

}

 

 

 

//#########################################################################

 

//  용도 : 출력할 그림을 모두 불러오는 기능.

 

//  연결관계 : DD초기화후 그림이미지를 불러와 화면으로 그림출력.

 

//#########################################################################

 

BOOL InitGraphicLoad(void)

 

{

 

    //그림 이미지를 로드 하는 작업

 

    lpBackGround = DDLoadBitmap(lpDirectOBJ, "Surface\\BackGround.BMP",0,0);

 

    lpPlayer = DDLoadBitmap(lpDirectOBJ, "Surface\\play.BMP",0,0);

 

    lpBoom = DDLoadBitmap(lpDirectOBJ, "Surface\\Boom.BMP",0,0);

 

    lpEnermy = DDLoadBitmap(lpDirectOBJ, "Surface\\enermy.BMP",0,0);

 

    lpPMissile= DDLoadBitmap(lpDirectOBJ, "Surface\\missile.BMP",0,0);

 

 

 

    DDSetColorKey(lpPlayer,RGB(0,255,0));   

 

    DDSetColorKey(lpBoom,RGB(0,255,0));

 

    DDSetColorKey(lpEnermy,RGB(0,255,0));   

 

    DDSetColorKey(lpPMissile,RGB(0,255,0));     

 

    return TRUE;

 

}

 

 

 

//#########################################################################

 

//  용도 : 매 프레임임마다 다른 그림을 출력할 수 있는 역할

 

//  연결관계 : 화면 갱신

 

//#########################################################################

 

void FrameMove(void)

 

{

 

    RECT BackRect = {0, 0, 1280, 800}; //후위면의 영역 설정

 

    RECT BackGroundRect = {0,0, 1024, 768};

 

    RECT PlayerRect = {0, 0, 36, 62};

 

    RECT EnermyRect = {0,0, 100,89};

 

    RECT PMissileRect = {0, 0, 21, 18};

 

    RECT BoomRect = {0,0,45,40};

 

    RECT ;

 

    //Back Surface로 이미지를 로드한다.

 

    lpBackSurface -> Blt( &BackRect, lpBackGround, &BackGroundRect, DDBLT_WAIT | DDBLTFAST_NOCOLORKEY,NULL );

 

//////////////////////////////////////////플레이어 조정 부분//////////////////////////

 

    if(NowKeyState[VK_RIGHT])

 

    {

 

        PPlaneX = PPlaneX + 10;

 

    }

 

    else if(NowKeyState[VK_LEFT])

 

    {

 

        PPlaneX = PPlaneX - 10;

 

    }

 

 

 

    if(NowKeyState[VK_UP])

 

    {

 

        PPlaneY = PPlaneY -10;

 

    }

 

    else if(NowKeyState[VK_DOWN])

 

    {

 

        PPlaneY = PPlaneY +10;

 

    }

 

    lpBackSurface -> BltFast(PPlaneX,PPlaneY, lpPlayer, &PlayerRect, DDBLTFAST_WAIT | DDBLTFAST_SRCCOLORKEY);

 

//////////////////////////////////////////////////////////////////////////////////////////////

 

    lpBackSurface -> BltFast(500,300,lpEnermy, &EnermyRect, DDBLTFAST_WAIT | DDBLTFAST_SRCCOLORKEY);

 

///////////////////////////////////////////플레이어 미사일 부분/////////////////////////////

 

    

 

    if(NowKeyState[VK_SPACE])

 

    {

 

        PMissileState ++;

 

        Total ++;

 

        if(PMissileState >MAX-1 && Total > MAX-1)

 

        {

 

            PMissileState = 0;

 

            Total = 0;

 

        }

 

        PMOn[Total] = 1;

 

        PMCount[Total] = 0;

 

        if(PMOn[Total] == 1)

 

        {

 

            PMX[Total] = PPlaneX;

 

            PMY[Total] = PPlaneY;   

 

            PMOn[Total] =0;

 

        }

 

    }

 

    

 

    for(PMissileState =0 ; PMissileState < MAX ; PMissileState++)

 

    {  

 

        PMY[PMissileState] = PMY[PMissileState] - 10;

 

        //적기와 미사일의 충돌 처리//

 

        if(PMY[PMissileState] < 389 && PMX[PMissileState] > 490 && PMX[PMissileState] < 600)

 

        {

 

            By=PMY[PMissileState] ;

 

            Bx=PMX[PMissileState] ;

 

            PMY[PMissileState] = -389;        

 

        }

 

        lpBackSurface -> BltFast(Bx,By,lpBoom, &BoomRect, DDBLTFAST_WAIT | DDBLTFAST_SRCCOLORKEY);

 

        lpBackSurface -> BltFast(PMX[PMissileState],PMY[PMissileState],lpPMissile, &PMissileRect, DDBLTFAST_WAIT | DDBLTFAST_SRCCOLORKEY);

 

    }

 

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

 

    //프리핑을 통한 화면으로의 고속복사를 시도한다.

 

    lpPrimarySurface -> Flip (NULL, DDFLIP_WAIT);

 

}

 

//#########################################################################

 

//  용도 : 메인으로 모든 연산을 처리한다.

 

//  연결관계 : 모든연산을 묶어서 처리하는 메인부분

 

//#########################################################################

 

int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)

 

{

 

    MSG msg;

 

    

 

    if(!InitWindow(hInstance, nCmdShow)) return FALSE; //윈도우를 초기화 한다

 

    if(!InitDirectDraw(1280,800,32)) return FALSE; //다이렉트 드로우를 초기화헌다.

 

    if(!InitGraphicLoad() ) return FALSE; //그림을 로드하는 일을 한다.

 

 

 

    SetTimer(GlobalWnd, NULL,10, NULL); //타이머로 화면을 갱신한다.

 

 

 

    while ( !NowKeyState[VK_ESCAPE]) //ESC키가 눌렸는지 확인한다.

 

    {

 

        if (PeekMessage(&msg, GlobalWnd,0,0,PM_NOREMOVE))

 

        {

 

            if(!GetMessage(&msg, GlobalWnd, 0,0)) return msg.wParam;

 

 

 

            TranslateMessage(&msg);

 

            DispatchMessage(&msg);

 

        }

 

        else

 

        {

 

            FrameMove(); //변화된 프레임을 출력한다.

 

        }

 

    }

 

 

 

    DestroyWindow(GlobalWnd);

 

    

 

    return TRUE;

 

}

 

... devpia에서

'- 음악과 나 - > 『 짬 통 』' 카테고리의 다른 글

CMapEditor..  (0) 2006.04.17
4월 17일.. 디다.  (0) 2006.04.17
충돌체크  (0) 2006.04.17
[스크랩] 게임프로그래밍/게임기획 게임제작의 기술..  (0) 2006.04.17
소스 세이프.  (0) 2006.04.17