상세 컨텐츠

본문 제목

Windows API 사각형 회전 시키기

자습

by CASTLELONG 2020. 12. 30. 16:26

본문

대학 1학년때,

동아리에서 각자 자신이 갈 분야를 택해서 멘토 멘티를 정하고 공부를 하는 시간을 가졌다.

나는 뭘 골랐는지 기억이 안나는데, 게임을 택했던 친구는 있었다.

게임 멘토는 친구에게 윈도우 api로 탱크를 회전시키라는 과제를 주셨었다.

나도 같이 지켜봤는데 삼각함수를 이용한 문제였고

결국 그 친구는 포기했고, 나 또한 수포자였다.

 

그래서 이번에 시도해봤다.

1. 삼각함수

삼각함수가 뭐에 쓰는건지 나는 몰랐다.

관심은 있었으나, 배우기에는 산이 너무 높아보였고, 하기 싫었다.

그러던 중 올해 초에 유튜브에서 이런 영상을 봤다.

https://www.youtube.com/watch?v=C_UsgRpyrUM&t=121s

나에게 삼각함수를 단번에 알려주는 레게노 영상이다

 

 

이 영상을 본 기억을 종합해 sin과 cos을 조합하면 원을 그릴 수 있다는 것을 생각했다.

그래서 일단 콤파스마냥 중심점에서 가장자리까지 선을 그어 원을 그려봤다.

2. 회전하는 선 그려보기

switch (wParam) {
		case VK_LEFT:
			ang--;
			break;
		case VK_RIGHT:
			ang++;
			break;
		}
		y = sin(DEG2RAD*ang);
		x = cos(DEG2RAD*ang);
		MoveToEx(hdc, 500, 250, NULL);
		LineTo(hdc, 500 + (250 * sin(DEG2RAD*ang)), 250 + (250 * cos(DEG2RAD * ang)));

이딴식으로 하면 그려진다.

DEG2RAD 는 Pi/180 즉 라디안으로 전처리기로 정의해놓은 값이다.

y와 x는 좌표같지만 sin과 cos이 있으므로 삼각함수 결과 값이다.

그래서 500,250의 좌표에서 250의 길이로 시계바늘 돌아가듯이 선이 그어진다.

 

3. 이제 사각형을 회전시켜보자.

static float ang = 0;
	HDC hdc;
	static float r = 0;
	static int pA[] = { 300,150,0 }, pB[] = { 700,150,0 }, pC[] = { 300, 350,0 }, pD[] = { 700, 350,0 }, mP[] = { 500,250 };
    switch (message)
    {
    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:
        {

			PAINTSTRUCT ps;
			hdc = BeginPaint(hWnd, &ps);
			pA[2] = atan2f(mP[1] - pA[1], mP[0] - pA[0]) * 180 / PI;
			pB[2] = atan2f(mP[1] - pB[1], mP[0] - pB[0]) * 180 / PI;
			pC[2] = atan2f(mP[1] - pC[1], mP[0] - pC[0]) * 180 / PI;
			pD[2] = atan2f(mP[1] - pD[1], mP[0] - pD[0]) * 180 / PI;
			r = sqrt(pow((pC[1] - pA[1]), 2) + pow((pD[0] - pC[0]), 2))/2;
			MoveToEx(hdc, mP[0] + r*cos(DEG2RAD*(pA[2] + ang)), mP[1] + r*sin(DEG2RAD*(pA[2] + ang)), NULL);
			LineTo(hdc, mP[0] + r*cos(DEG2RAD*(pB[2] + ang)), mP[1] + r*sin(DEG2RAD*(pB[2] + ang)));
			LineTo(hdc, mP[0] + r*cos(DEG2RAD*(pD[2] + ang)), mP[1] + r*sin(DEG2RAD*(pD[2] + ang)));
			LineTo(hdc, mP[0] + r*cos(DEG2RAD*(pC[2] + ang)), mP[1] + r*sin(DEG2RAD*(pC[2] + ang)));
			LineTo(hdc, mP[0] + r*cos(DEG2RAD*(pA[2] + ang)), mP[1] + r*sin(DEG2RAD*(pA[2] + ang)));
			EndPaint(hWnd, &ps);
        }
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
	case WM_KEYDOWN:
		
		switch (wParam) {
		case VK_LEFT:
			ang--;
			break;
		case VK_RIGHT:
			ang++;
			break;
		}
		InvalidateRect(hWnd, NULL, TRUE);
		break;

막상 어떻게 해야할지 몰라 일단 4개 점의 x,y좌푯값을 저장하는 배열들을 만들었다.(pA, pB, pC, pD)

그리고 그 배열에는 x,y 좌표 뿐만 아니라 좌표와 중심점(mP) 사이의 처음 각도 또한 저장한다.

그리고 사각형의 대각선은 지름이다. 피타고라스의 공식을 이용해 반지름을 구한다.

이제 중심점 x,y에서

(반지름 * cos(라디안 * (점과 중심점 사이의 각도 + 변화된 각도) ) ) 와

(반지름 * sin(라디안 * (점과 중심점 사이의 각도 + 변화된 각도) ) ) 를 더해주면

점의 좌표가 나온다.

각 꼭짓점의 좌표를 모두 구해 선으로 이어주면

그것이 사각형이 된다.

그리고 왼쪽, 오른쪽 방향키를 누르면 ang값을 올리거나 내려서 위에서 말한 변화된 각도를 줄 수가 있다.

 

뭔가 코드를 더 줄일 수 있을것 같지만,

이대로 올리는 편이

미래의 나에게도 현재의 나에게도 혹시라도 읽게될 누군가에게도

더 쉽게 받아들일 수 있을지도 모르겠다.

열심히 공부하고 있는 나에게 태클은 언제나 환영

'자습' 카테고리의 다른 글

QUICK SORT ALGORITHM with others  (1) 2021.01.09
Windows API 바라보는 방향으로 움직이기  (2) 2021.01.04
HEAP TREE with HEAP SORT ALGORITHM  (0) 2020.12.10
STACK ALGORITHM with LINEAR LIST  (2) 2020.12.07
0.1 + 0.2 != 0.3 (작성중)  (0) 2020.08.19

관련글 더보기

댓글 영역