본문 바로가기
코스웨어/15년 스마트컨트롤러

김태현 WinAPI 6일차 업그레이드 전

by 알 수 없는 사용자 2015. 11. 20.
728x90
반응형

#include <windows.h>

#include "smart.h"

#include "resource.h"


LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

HINSTANCE g_hInst;

LPSTR lpszClass = "Push Push";


LRESULT OnDestroy(HWND, WPARAM, LPARAM);

LRESULT OnCreate(HWND, WPARAM, LPARAM);

LRESULT OnPaint(HWND hWnd, WPARAM wParam, LPARAM lParam);

LRESULT OnKeyDown(HWND hWnd, WPARAM wParam, LPARAM lParam);

void LoadMap();


//메세지맵에서 자주쓰는 함수를 위에 위치하는게 좋다(자주쓰는게 뒤에 있으면 while이 자주 도니까)

stMsgMap MsgMap[] = {

{ WM_PAINT, OnPaint },

{ WM_KEYDOWN, OnKeyDown },

{ WM_CREATE, OnCreate },

{ WM_DESTROY, OnDestroy },

{ WM_NULL, 0 },

};


//캐릭터와 지도를 저장할 HBITMAP 전역 변수

static HBITMAP HbmHero;

static HBITMAP HbmFront;

static HBITMAP HbmLeft;

static HBITMAP HbmRight;

static HBITMAP HbmBack;

static HBITMAP HbmGround;

static HBITMAP HbmRoad;

static HBITMAP HbmBox;

static HBITMAP HbmDot;


static HDC MemDC;


//지도의 점을 count할 변수(종료조건)

UINT uiDotNum;

//현재 stage를 가질 변수

UINT uiStage=0;

//이동횟수를 저장할 변수(점수)

UINT uiScore;

WCHAR cTile[200];

//지도 정보를 매핑해서 들고있는 3차원 배열

UCHAR ucStageMap[STAGE][Y_FRAME][X_FRAME + 1] = {

{ "###############"

, "#@            #"

, "#     .  B    #"

, "#   B   .     #"

, "#     B       #"

, "#       ## ## #"

, "#       .     #"

, "# ##   ###### #"

, "#             #"

, "###############"

}

,

{ "###############"

, "#@       #    #"

, "# #####  # #  #"

, "#        # #  #"

, "# ## ## .     #"

, "# ## #######  #"

, "#             #"

, "# ## # # # ## #"

, "#             #"

, "###############"

}

};

//하나의 스테이지 정보를 가지고 있을 2차원 배열

UCHAR ucMap[Y_FRAME][X_FRAME + 1];

//Hero의 위치 정보를 추적하는 변수

int ixPos = 0;

int iyPos = 0;


int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance

, LPSTR lpszCmdParam, int nCmdShow)

{

HWND hWnd;

MSG Message;

WNDCLASS WndClass;

g_hInst = hInstance;


WndClass.cbClsExtra = 0;

WndClass.cbWndExtra = 0;

WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);

WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);

WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);

WndClass.hInstance = hInstance;

WndClass.lpfnWndProc = (WNDPROC)WndProc;

WndClass.lpszClassName = lpszClass;

WndClass.lpszMenuName = NULL;

WndClass.style = CS_HREDRAW | CS_VREDRAW;

RegisterClass(&WndClass);


hWnd = CreateWindow(lpszClass, lpszClass, WS_CAPTION | WS_SYSMENU,

CW_USEDEFAULT, CW_USEDEFAULT, X_WINSIZE, Y_WINSIZE,

NULL, (HMENU)NULL, hInstance, NULL);

ShowWindow(hWnd, nCmdShow);


while (GetMessage(&Message, 0, 0, 0))

{

TranslateMessage(&Message);

DispatchMessage(&Message);

}

return Message.wParam;

}


LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)

{

stMsgMap * stpMap = MsgMap;


//message map 기법을 통해서 switch case 문을 지우고 while문이 모든 함수를 처리한다.

while (WM_NULL != (*stpMap).uiMsg)

{

if (iMessage == (*stpMap).uiMsg)

{

//내부적으로 처리하기 때문에 와일문이 돌면 안되기 때문에 return으로 처리한다.

return (((*stpMap).fp)(hWnd, wParam, lParam));

}

++stpMap;

}

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

}


LRESULT OnDestroy(HWND hWnd, WPARAM wParam, LPARAM lParam)

{

DeleteObject(HbmFront);

DeleteObject(HbmLeft);

DeleteObject(HbmRight);

DeleteObject(HbmBack);

DeleteObject(HbmGround);

DeleteObject(HbmRoad);

DeleteObject(HbmDot);

DeleteObject(HbmBox);

DeleteDC(MemDC);

PostQuitMessage(0);

return 0;

}


LRESULT OnCreate(HWND hWnd, WPARAM wParam, LPARAM lParam)

{

HDC hdc;

hdc = GetDC(hWnd);

MemDC = CreateCompatibleDC(hdc);


HbmFront = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_BITMAP3));

HbmLeft = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_BITMAP4));

HbmRight = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_BITMAP5));

HbmBack = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_BITMAP2));

HbmGround = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_BITMAP1));

HbmRoad = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_BITMAP6));

HbmDot = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_BITMAP7));

HbmBox = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_BITMAP9));


ReleaseDC(hWnd, hdc);

HbmHero = HbmFront;

LoadMap();

return 0;

}


LRESULT OnPaint(HWND hWnd, WPARAM wParam, LPARAM lParam)

{

HDC hdc;

PAINTSTRUCT ps;

int iCntx;

int iCnty;


hdc = BeginPaint(hWnd, &ps);


//maping된 구조체의 정보를 가지고와 지도를 그려주는 for문

for (iCnty = 0; iCnty<10; iCnty++)

{

for (iCntx = 0; iCntx<15; iCntx++)

{

if ('#' == ucMap[iCnty][iCntx])

{

SelectObject(MemDC, HbmGround);

}

else if (' ' == ucMap[iCnty][iCntx])

{

SelectObject(MemDC, HbmRoad);

}

else if ('.' == ucMap[iCnty][iCntx])

{

SelectObject(MemDC, HbmDot);

}

else if ('B' == ucMap[iCnty][iCntx])

{

SelectObject(MemDC, HbmBox);

}

BitBlt(hdc, iCntx*X_TILE,iCnty*Y_TILE , X_TILE, Y_TILE, MemDC, 0, 0, SRCCOPY);

}

}

SelectObject(MemDC, HbmHero);

BitBlt(hdc, ixPos*X_TILE, iyPos*Y_TILE, X_TILE, Y_TILE, MemDC, 0, 0, SRCCOPY);

EndPaint(hWnd, &ps);

//점수와 stage를 프로그램 상단에 찍어준다.

wsprintf(cTile, "Stage : %d     KeyCount: %d", uiStage + 1, uiScore);

SetWindowText(hWnd, cTile);

return 0;

}


LRESULT OnKeyDown(HWND hWnd, WPARAM wParam, LPARAM lParam)

{

UINT uixCnt;

UINT uiyCnt;

UINT uiDotCnt;

RECT stArea;

int iRet;


//hero가 이동할때 hero가 이동한 자리와 이동하기 전만 다시 그려주기 위해서

//현재 hero의 이미지를 저장하기 위한 구조체

stArea.left = ixPos * X_TILE;

stArea.right = (ixPos + 1) * X_TILE;

stArea.top = iyPos * Y_TILE;

stArea.bottom = (iyPos + 1) * Y_TILE;


switch (wParam)

{

case VK_RIGHT:

HbmHero = HbmRight;

//hero가 이동할수 있는곳만 이동하도록 하는 if문

if (' '== ucMap[iyPos][ixPos+1])

{

++ixPos;

stArea.right = (ixPos + 1) * X_TILE;

}

else if ('.' == ucMap[iyPos][ixPos + 1])

{

++ixPos;

stArea.right = (ixPos + 1) * X_TILE;

}

else if ('B' == ucMap[iyPos][ixPos + 1])

{

if (' ' == ucMap[iyPos][ixPos + 2])

{

ucMap[iyPos][ixPos + 2] = ucMap[iyPos][ixPos + 1];

if ('.' != ucStageMap[uiStage][iyPos][ixPos + 1])

{

ucMap[iyPos][ixPos + 1] = ' ';

}

else

{

ucMap[iyPos][ixPos + 1] = '.';

}

++ixPos;

stArea.right = (ixPos + 2) * X_TILE;

}

else if ('.' == ucMap[iyPos][ixPos + 2])

{

ucMap[iyPos][ixPos + 2] = ucMap[iyPos][ixPos + 1];

if ('.' != ucStageMap[uiStage][iyPos][ixPos + 1])

{

ucMap[iyPos][ixPos + 1] = ' ';

}

else

{

ucMap[iyPos][ixPos + 1] = '.';

}

++ixPos;

stArea.right = (ixPos + 2) * X_TILE;

}

}

++uiScore;

break;

case VK_LEFT:

HbmHero = HbmLeft;

if (' ' == ucMap[iyPos][ixPos - 1])

{

--ixPos;

stArea.left = (ixPos-1) * X_TILE;

}

else if ('.' == ucMap[iyPos][ixPos - 1])

{

--ixPos;

stArea.left = (ixPos-1) * X_TILE;

}

else if ('B' == ucMap[iyPos][ixPos - 1])

{

if (' ' == ucMap[iyPos][ixPos - 2])

{

ucMap[iyPos][ixPos - 2] = ucMap[iyPos][ixPos - 1];

if ('.' != ucStageMap[uiStage][iyPos][ixPos - 1])

{

ucMap[iyPos][ixPos - 1] = ' ';

}

else

{

ucMap[iyPos][ixPos - 1] = '.';

}

--ixPos;

stArea.left = (ixPos-2) * X_TILE;

}

else if ('.' == ucMap[iyPos][ixPos - 2])

{

ucMap[iyPos][ixPos - 2] = ucMap[iyPos][ixPos - 1];

if ('.' != ucStageMap[uiStage][iyPos][ixPos - 1])

{

ucMap[iyPos][ixPos - 1] = ' ';

}

else

{

ucMap[iyPos][ixPos - 1] = '.';

}

--ixPos;

stArea.left = (ixPos- 2) * X_TILE;

}

}

++uiScore;

break;

case VK_UP:

HbmHero = HbmBack;

if (' ' == ucMap[iyPos-1][ixPos])

{

--iyPos;

stArea.top = (iyPos - 1) * Y_TILE;

}

else if ('.' == ucMap[iyPos-1][ixPos])

{

--iyPos;

stArea.top = (iyPos - 1) * Y_TILE;

}

else if ('B' == ucMap[iyPos-1][ixPos])

{

if (' ' == ucMap[iyPos - 2][ixPos])

{

ucMap[iyPos-2][ixPos] = ucMap[iyPos-1][ixPos];

if ('.' != ucStageMap[uiStage][iyPos-1][ixPos])

{

ucMap[iyPos-1][ixPos] = ' ';

}

else

{

ucMap[iyPos-1][ixPos] = '.';

}

--iyPos;

stArea.top = (iyPos - 2) * Y_TILE;

}

else if ('.' == ucMap[iyPos - 2][ixPos])

{

ucMap[iyPos - 2][ixPos] = ucMap[iyPos - 1][ixPos];

if ('.' != ucStageMap[uiStage][iyPos - 1][ixPos])

{

ucMap[iyPos - 1][ixPos] = ' ';

}

else

{

ucMap[iyPos - 1][ixPos] = '.';

}

--iyPos;

stArea.top = (iyPos - 2) * Y_TILE;

}

}

++uiScore;

break;

case VK_DOWN:

HbmHero = HbmFront;

if (' ' == ucMap[iyPos + 1][ixPos])

{

++iyPos;

stArea.bottom = (iyPos + 1) * Y_TILE;

}

else if ('.' == ucMap[iyPos + 1][ixPos])

{

++iyPos;

stArea.bottom = (iyPos + 1) * Y_TILE;

}

else if ('B' == ucMap[iyPos + 1][ixPos])

{

if (' ' == ucMap[iyPos + 2][ixPos])

{

ucMap[iyPos + 2][ixPos] = ucMap[iyPos + 1][ixPos];

if ('.' != ucStageMap[uiStage][iyPos + 1][ixPos])

{

ucMap[iyPos + 1][ixPos] = ' ';

}

else

{

ucMap[iyPos + 1][ixPos] = '.';

}

++iyPos;

stArea.bottom = (iyPos + 2) * Y_TILE;

}

else if ('.' == ucMap[iyPos + 2][ixPos])

{

ucMap[iyPos + 2][ixPos] = ucMap[iyPos + 1][ixPos];

if ('.' != ucStageMap[uiStage][iyPos + 1][ixPos])

{

ucMap[iyPos + 1][ixPos] = ' ';

}

else

{

ucMap[iyPos + 1][ixPos] = '.';

}

++iyPos;

stArea.bottom = (iyPos + 2) * Y_TILE;

}

}

++uiScore;

break;

case VK_HOME:

iRet = MessageBox(hWnd, "다시 하시겠습니까?", "알림", MB_YESNOCANCEL);

if (IDYES == iRet)

{

LoadMap();

InvalidateRect(hWnd, NULL, TRUE);

}

return 0;

}


InvalidateRect(hWnd, &stArea, FALSE);

uiDotCnt = 0;

for (uiyCnt = 0; uiyCnt<Y_FRAME; ++uiyCnt)

{

for (uixCnt = 0; uixCnt<X_FRAME; ++uixCnt)

{

if (ucMap[uiyCnt][uixCnt] == 'B')

{

if (ucStageMap[uiStage][uiyCnt][uixCnt] == '.')

{

++uiDotCnt;

}

}

}

}

if (uiDotCnt == uiDotNum)

{

MessageBox(hWnd, "클리어!", "알림", MB_OK);

if (uiStage >= STAGE)

{

MessageBox(hWnd, "게임이 끝났습니다.", "알림", MB_OK);

SendMessage(hWnd, WM_DESTROY,0,0);

return 0;

}

++uiStage;

LoadMap();

InvalidateRect(hWnd, NULL, TRUE);

return 0;

}

return 0;

}

//판마다 맵을 불러올

void LoadMap()

{

int iCntx;

int iCnty;

uiDotNum = 0;

uiScore = 0;

//memcopy가 아니고 for문을 돌리는 이유는 hero가 어디있는지 찾아서 rode로 바꿔주기 위해서

for (iCnty = 0; iCnty<10; iCnty++)

{

for (iCntx = 0; iCntx<15; iCntx++)

{

//지도안의 dot의 갯수를 샌다.

if ('.' == ucStageMap[uiStage][iCnty][iCntx])

{

++uiDotNum;

}

if ('@' == ucStageMap[uiStage][iCnty][iCntx])

{

//@는 Hero의 초기 위치만 잡아주고 필요없기 때문에 rode로 대체한다.

ixPos = iCntx;

iyPos = iCnty;

ucMap[iCnty][iCntx] = ' ';

continue;

}

ucMap[iCnty][iCntx]=ucStageMap[uiStage][iCnty][iCntx];

}

}

return;

}


조금씩 정리되는데로 추가하기

728x90