두더지잡기 게임
1. 두더지잡기 게임을 모티브로 한 원 잡기.
[1] 게임을 진행할 영역을 얻어와야 한다.
[2] 마우스 좌표가 원의 영역내에 있다면 점수가 증가한다.
[3] 1000점이 초과되면 스테이지가 증가한다.
[4] 10스테이지가 되면 메세지가 출력된다.
[5] 원은 1초에 한번씩 좌표가 변경된다.
[6] 스테이지가 올라갈 수록 원의 크기는 줄어든다.
2. 소스
1) 사용자 정의함수
#include<time.h> #include<math.h> void Init(HWND hWnd, LPRECT rect, int *x, int *y, int *r, int *score, int *stage) { srand(time(NULL)); GetClientRect(hWnd, rect); //창 생성 시 화면의 좌표영역을 얻어온다. *x = rand() % rect->right; *y = rand() % rect->bottom; *r = 185; //원의 반지름 *score = 0; *stage = 1; SetTimer(hWnd, 1, 1000, NULL); //1번타이머 = 1초에 한 번씩 WM_TIMER메세지 발생 } void Draw(HDC hdc, LPRECT rect, int *x, int *y, int r, int score, int stage) { TCHAR str[80]; _stprintf_s(str, _T("스테이지 : %d 점수 : %d 좌표 : (%d, %d) 반지름 : %d"), stage, score, *x, *y, r); TextOut(hdc, 400, 5, str, _tcslen(str)); //현재 정보 출력 Rectangle(hdc, 5, 25, rect->right - 5, rect->bottom - 5); // 전체 맵 그리기 SelectObject(hdc, CreateSolidBrush(RGB(255, 0, 0))); // 창의 브러시속성에 빨간색을 부여 Ellipse(hdc, *x - r, *y - r, *x + r, *y + r); //빨간색 원 그리기 } void Timer(HWND hWnd, LPRECT rect, int *x, int *y) { *x = rand() % rect->right; *y = rand() % rect->bottom; //영역 내 원의 좌표 얻어오기 InvalidateRgn(hWnd, NULL, TRUE); } double Length(int x1, int y1, int x2, int y2) { return sqrt((x2 - x1)*(x2 - x1) + (y2 - y1) * (y2 - y1)); //클릭한 마우스의 범위를 구하기 위해 사용하며 원으로부터 거리 반환 } void Mouse(HWND hWnd, LPARAM lParam, LPRECT rect, int *x, int *y, int *r, int *score, int *stage) { int mx = LOWORD(lParam); int my = HIWORD(lParam); //마우스의 좌표 얻어오기 //if (*x - *r < mx && mx < *x + *r && *y - *r < my && my < *y + *r) { if (Length(*x, *y, mx, my) < *r) { //마우스의 좌표가 원의 내부에 있다면? *score += 100; //스코어 증가 *x = rand() % rect->right; *y = rand() % rect->bottom; //새로그리기 위한 원의 좌표 확보 if (1000 < *score) { //점수가 1000점을 초과했다면? (*stage)++; //다음스테이지로 *score = 0; //스코어는 초기화 *r -= 20; //난이도 조절을 위해 원의 반지름은 감소 } if (10 < *stage) { MessageBox(hWnd, _T("WOW!!!"), _T("you are great!!"), MB_OK); // 10스테이지가 넘어가면 메세지 출력 } KillTimer(hWnd, 1); //1번타이머 죽이기 SetTimer(hWnd, 1, 1000, NULL); //1번 타이머 생성 //죽이고 다시 생성하는 이유는 클릭했을 때 기존 원의 위치에서 대기하지 않도록하기위함. InvalidateRgn(hWnd, NULL, TRUE); } }
2) 윈도우 메세지처리함수
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; HDC hdc; static RECT space; //게임영역 static int x; static int y; //원의 좌표 static int r; //반지름 static int stage; //스테이지 static int score; //점수 switch (message) { case WM_CREATE: Init(hWnd, &space, &x, &y, &r, &score, &stage); break; case WM_TIMER: Timer(hWnd, &space, &x, &y); break; case WM_LBUTTONDOWN: Mouse(hWnd, lParam, &space, &x, &y, &r, &score, &stage); break; case WM_COMMAND: { int wmId = LOWORD(wParam); // 메뉴 선택을 구문 분석합니다: switch (wmId) { case IDM_ABOUT: DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } } break; case WM_PAINT: { hdc = BeginPaint(hWnd, &ps); Draw(hdc, &space, &x, &y, r, score, stage); EndPaint(hWnd, &ps); } break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }
3. 시연[1]
- 마우스 클릭 시 점수가 올라가고 1000점 초과 시 스테이지가 올라가고 반지름은 줄어드는 것을 확인할 수 있다.
- 그러나 이렇게 할 경우 9스테이지에서는 원이 거의 보이지 않는다.
4. 시연[2]
1) 치트엔진을 사용하여 10스테이지를 달성하고 메세지의 내용을 확인하려 한다.
- 치트엔진을 실행 후 현재 실행중인 두더지게임을 올린다.
- 현재 점수가 200이므로 메모리 상에 200이라는 값이 있는 주소를 검색한다.
- first scan 시 5개의 메모리주소에 200이라는 값이 들어있다.
- 그러나 이 중 어떤 것이 점수인지 모르므로 점수 점수를 올린다.
- 원을 클릭해서 점수를 300으로 올리고 300을 next scan 한다.
- 점수가 들어있는 주소를 확인하고 이 주소의 값을 1111로 변경하였다.
- 스테이지가 6으로 오른 것을 확인할 수 있다.
- 이렇게 할 경우 여러번 해야해서 번거로우므로 반지름의 사이즈를 변경해보려고 한다.
- 현재 반지름인 85를 first scan한다.
- 스테이지를 올린 후 반지름의 크기에 변화를 주어 65로 next scan한다.
- 반지름이 저장되어 있는 주소를 찾았으므로 1000정도로 변경한다.
- 이 경우 원의 반지름이 커져서 영역 대부분을 차지하므로 수월하게 스테이지를 올릴 수 있다.
- 11스테이지까지 올린 후 출력되는 메세지를 확인할 수 있다.
[1] 변경 불가능하도록 하는 방법
- 출력되는 값을 기준값 + 알파 식으로 부여한다.
ex) 점수의 메모리에 있는 값을 50이라고 잡으면 출력시에는 항상 score - 50을 출력한다.
※ 치트엔진은 휴리스틱을 이용하여 찾는방법을 이용한다.
한 마디로 값만 알면 찾을 수 있기에 실제 값이랑 보여지는 값이랑 다르게 하면 된다.
그러나 리버싱으로 변경하는 것은 단순히 값을 다르게 하는 것만으로는 불가능하며 복잡도와 난독화를 이용해야 한다.
'Programming Language > Windows API' 카테고리의 다른 글
메뉴 및 공용대화상자 (0) | 2018.10.09 |
---|---|
지렁이게임 (0) | 2018.09.30 |
입력된 방향키 확인 (0) | 2018.09.30 |
사각형 그리기 (0) | 2018.09.30 |
도형 자동이동 (0) | 2018.09.30 |
댓글