1: // 게임 기초
2: // 2011년 10월 10일 작성
3:
4: /* 윈도우즈 프로그래밍 순서 WinMain()
5:
6: WndClass정의
7: ↓
8: 클래스를 등록
9: ↓
10: 메모리상에 윈도우 생성
11: ↓
12: 윈도우를 화면에 출력
13: ↓
14: 메시지 루프 (반복)
15: */
16: #include <windows.h> // 모든 API함수들의 원형과 사용하는 상수들이 정의되어 있음.
17: #include "resource.h"
18:
19: #define BW 30
20: #define BH 30
21:
22: LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); //메시지처리함수
23: HINSTANCE g_hlnst; //핸들 인스턴스
24: LPCTSTR lpszClass = TEXT("GameBasis"); //윈도우 제목으로 사용되는 const char * (문자열)
25:
26:
27:
28: /***************************************************************************************************************************
29: WinMain은 엔트리 포인트(시작함수)
30: APIENTRY는 윈도우즈 표준호출규약 _stdcall(없어도 무방함)
31:
32: WinMain의 인자들...
33: ① hInstance: 프로그램의 인스턴스 핸들
34: ② hPrevInstance: 바로 앞에 실행된 현재 프로그램의 인스턴스 핸들로 16비트와 호환성위한 것이니 무시하자. Win32는 NULL이다.
35: ③ lpszCmdParam: 명령행으로 입력된 프로그램의 인수 (콘솔app에서 argv), 보통 실행직후에 열 파일의 경로가 전달됨.
36: ④ nCmdShow: 프로그램이 실행될 형태이며 최소화, 보통 모양 등이 전달된다.
37: ***************************************************************************************************************************/
38: int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow)
39: {
40: HWND hWnd;
41: MSG Message;
42: WNDCLASS WndClass;
43: g_hlnst = hInstance;
44:
45: /* 윈도우 클래스 정의 */
46: WndClass.cbClsExtra = 0;
47: WndClass.cbWndExtra = 0;
48: WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
49: //WndClass.hbrBackground = (HBRUSH)CreateSolidBrush(RGB(0xFF, 0xFF, 0xEE));
50: //WndClass.hbrBackground = (HBRUSH)CreateHatchBrush(HS_DIAGCROSS, RGB(100, 255, 0));
51: //WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
52: WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
53: WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
54: WndClass.hInstance = hInstance;
55: WndClass.lpfnWndProc = WndProc;
56: WndClass.lpszClassName = lpszClass;
57: WndClass.lpszMenuName = NULL;
58: WndClass.style = CS_HREDRAW | CS_VREDRAW;
59:
60: /* 윈도우 클래스 등록 */
61: RegisterClass(&WndClass);
62:
63: /* 메모리상에 윈도우 생성 */
64: hWnd = CreateWindow(lpszClass, TEXT("소코반"), WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME,
65: CW_USEDEFAULT, CW_USEDEFAULT, 30 * 25 + 6, 30 * 15 + 25, // 6과 25 더하는 이유는 타이틀고 윈도우 경계
66: NULL, (HMENU)NULL, hInstance, NULL);
67:
68: /* 화면에 윈도우 표시 */
69: ShowWindow(hWnd, nCmdShow);
70:
71: while(GetMessage(&Message, NULL, 0, 0)) {
72: TranslateMessage(&Message);
73: DispatchMessage(&Message);
74: }
75:
76: return (int)Message.wParam;
77: }
78:
79: LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
80: {
81: HDC hdc; // hdc는 화면DC
82: HDC MemDC; // 메모리DC
83: PAINTSTRUCT ps;
84: int iRow; // 반복제어변수
85: int iCol; // 반복제어변수
86: static HBITMAP hWall; // 벽
87: static HBITMAP hSpace; // 공간
88: static HBITMAP hHuman; // 졸라맨 '@'
89: static HBITMAP hBox; // 박스
90: static HBITMAP hStorage; // 저장공간
91: static HBITMAP hOldBitmap;
92: static int iX = 11;
93: static int iY = 8;
94: static RECT rt;
95: static unsigned char ucStage[][15][25 + 1] = // +1은 문자열이니 NULL추가
96: { // 0123456789012345678901234 // 화면에 출력하는 그래픽을 1:1대응
97: { "#########################"
98: ,"#########################"
99: ,"###### ################"
100: ,"######O ################"
101: ,"###### O################"
102: ,"#### O O ###############"
103: ,"#### # ## ###############"
104: ,"## # ## ###### ..#####"
105: ,"## O O @ ..#####"
106: ,"###### #### # ## ..#####"
107: ,"###### #############"
108: ,"#########################"
109: ,"#########################"
110: ,"#########################"
111: ,"#########################"
112: }
113: };
114:
115: switch(iMessage) {
116: case WM_CREATE:
117: hWall = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_WALL)); // 벽 비트맵 읽어옴.
118: hSpace = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_SPACE)); // 빈공간 비트맵 읽어옴.
119: hHuman = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_HUMAN)); // 졸라맨 비트맵 읽어옴.
120: hBox = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_BOX)); // 박스 비트맵 읽어옴.
121: hStorage = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_STORAGE)); // 저장공간 비트맵 읽어옴.
122: // GetModuleHandle(NULL) == 이 프로그램의 인스턴스 핸들
123: ucStage[0][iY][iX] = '@';
124: return 0;
125:
126: case WM_KEYDOWN:
127: rt.left = iX * BW;
128: rt.top = iY * BH;
129: rt.right = iX * BW + BW;
130: rt.bottom = iY * BH + BH;
131: ucStage[0][iY][iX] = ' ';
132: InvalidateRect(hWnd, &rt, TRUE);
133:
134: switch(wParam) {
135: case VK_LEFT:
136: if('#' != ucStage[0][iY][iX - 1])
137: {
138: iX = iX - 1;
139: }
140: break;
141: case VK_RIGHT:
142: if('#' != ucStage[0][iY][iX + 1])
143: {
144: iX = iX + 1;
145: }
146: break;
147: case VK_UP:
148: if('#' != ucStage[0][iY - 1][iX])
149: {
150: iY = iY - 1;
151: }
152: break;
153: case VK_DOWN:
154: if('#' != ucStage[0][iY + 1][iX])
155: {
156: iY = iY + 1;
157: }
158: break;
159: }
160:
161: rt.left = iX * BW;
162: rt.top = iY * BH;
163: rt.right = iX * BW + BW;
164: rt.bottom = iY * BH + BH;
165: ucStage[0][iY][iX] = '@';
166: InvalidateRect(hWnd, &rt, TRUE);
167:
168: return 0;
169:
170: case WM_PAINT:
171: hdc = BeginPaint(hWnd, &ps);
172: MemDC=CreateCompatibleDC(hdc);
173:
174: // 가로 10개, 세로10개 출력.
175: for(iRow = 0 ; 15 > iRow ; ++iRow)
176: {
177: for(iCol = 0 ; 25 > iCol ; ++iCol)
178: {
179: switch(ucStage[0][iRow][iCol]) {
180: case '#': // 벽
181: hOldBitmap=(HBITMAP)SelectObject(MemDC, hWall);
182: BitBlt(hdc, iCol * BW, iRow * BH, BW, BH, MemDC, 0, 0, SRCCOPY); //비트맵복사 MemDC -> DC
183: SelectObject(MemDC,hOldBitmap);
184: break;
185: case '@': // 졸라맨
186: hOldBitmap=(HBITMAP)SelectObject(MemDC, hHuman);
187: BitBlt(hdc, iCol * BW, iRow * BH, BW, BH, MemDC, 0, 0, SRCCOPY); //비트맵복사 MemDC -> DC
188: SelectObject(MemDC,hOldBitmap); // 핸들 교체 말고도 MemDC를 여러 개 선언하는 법이 있음.
189: break;
190: case 'O': // 박스
191: hOldBitmap=(HBITMAP)SelectObject(MemDC, hBox);
192: BitBlt(hdc, iCol * BW, iRow * BH, BW, BH, MemDC, 0, 0, SRCCOPY); //비트맵복사 MemDC -> DC
193: SelectObject(MemDC,hOldBitmap); // 핸들 교체 말고도 MemDC를 여러 개 선언하는 법이 있음.
194: break;
195: case '.': // 저장공간
196: hOldBitmap=(HBITMAP)SelectObject(MemDC, hStorage);
197: BitBlt(hdc, iCol * BW, iRow * BH, BW, BH, MemDC, 0, 0, SRCCOPY); //비트맵복사 MemDC -> DC
198: SelectObject(MemDC,hOldBitmap); // 핸들 교체 말고도 MemDC를 여러 개 선언하는 법이 있음.
199: break;
200: case ' ': // 통로
201: hOldBitmap=(HBITMAP)SelectObject(MemDC, hSpace);
202: BitBlt(hdc, iCol * BW, iRow * BH, BW, BH, MemDC, 0, 0, SRCCOPY); //비트맵복사 MemDC -> DC
203: SelectObject(MemDC,hOldBitmap); // 핸들 교체 말고도 MemDC를 여러 개 선언하는 법이 있음.
204: break;
205: default: // 디폴트 처리
206: break;
207: }
208:
209: /*
210: if('#' == ucStage[0][iRow][iCol])
211: {
212: hOldBitmap=(HBITMAP)SelectObject(MemDC, hWall);
213: BitBlt(hdc, iCol * BW, iRow * BH, BW, BH, MemDC, 0, 0, SRCCOPY); //비트맵복사 MemDC -> DC
214: SelectObject(MemDC,hOldBitmap);
215: }
216: else if('@' == ucStage[0][iRow][iCol])
217: {
218: hOldBitmap=(HBITMAP)SelectObject(MemDC, hHuman);
219: BitBlt(hdc, iCol * BW, iRow * BH, BW, BH, MemDC, 0, 0, SRCCOPY); //비트맵복사 MemDC -> DC
220: SelectObject(MemDC,hOldBitmap); // 핸들 교체 말고도 MemDC를 여러 개 선언하는 법이 있음.
221: }
222: */
223: }
224: }
225:
226: DeleteDC(MemDC);
227: EndPaint(hWnd, &ps);
228: return 0;
229:
230: case WM_DESTROY:
231: DeleteObject(hWall); //게임 끝나면 지워야 함.
232: DeleteObject(hSpace);
233: DeleteObject(hHuman);
234: PostQuitMessage(0);
235: return 0;
236: }
237:
238: return(DefWindowProc(hWnd, iMessage, wParam, lParam));
239: }