이제 프레임워크는 완성됐고, 이 프레임워크를 갖고 게임을 만들면 됩니다.
첫번째 게임은 C언어 게임만들기 강좌에서 나오는 5장-슛골임 게임 만들기입니다.
(전체적인 내용은 위링크의 강좌의 내용이지만 순서나 코드는 제 나름대로 작성하였습니다.)
게임은 간단합니다.
좌우로 움직이는 골대에 플레이어를 좌우로 움직여 제한시간 내에 공을 가능한 많이 넣는 것입니다.
우선 좌우로 움직이는 플레이어 캐릭터를 만든다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | char PLAYER_STR[] = "└─●─┘"; typedef struct Position { int x, y; }Position; typedef struct { Position position; char *strPlayer;// = "└─●─┘";//주인공 캐릭터 int nLength; //주인공 캐릭터 전체 길이 }Player; Player g_Player; | cs |
Player를 조작할 Player 구조를 만듭니다.
Player는 x,y 좌표값, 그려질 텍스트값, 텍스트 길이를 갖고 있습니다.
이 값을 Init()함수에서 초기화 해줍니다.
1 2 3 4 5 6 7 8 9 10 11 | void Init() { InitFPSData(&fpsData); g_Player.position.y = 22; g_Player.position.x = 0; g_Player.nLength = strlen(PLAYER_STR); g_Player.strPlayer = (char*)malloc(sizeof(char)*g_Player.nLength); strcpy(g_Player.strPlayer, PLAYER_STR); } | cs |
다음 초기화한 Player 변수를 화면에 그려줍니다. 그려주는 건 Render()함수 내부에 작성해줍니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 | void Render() { ScreenClear(); DrawFPS(&fpsData); char string[100] = { 0, }; ScreenPrint(g_Player.position.x, g_Player.position.y, g_Player.strPlayer); sprintf(string, "주인공 이동좌표 : %d, %d", g_Player.position.x, g_Player.position.y); ScreenPrint(0, 3, string); ScreenFlipping(); } | cs |
이제 j키로 왼쪽으로 이동, l키로 오른쪽으로 이동하게 처리하면 됩니다.
키처리하는 부분은 입력받은 key값에 따라 처리하는 keyProcess()함수 내부에서 처리하면 됩니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 | void KeyProcess(int key) { int remain; switch (key) { case 'j': g_Player.position.x--; break; case'l': g_Player.position.x++; break; } } | cs |
다시 실행시킨 후 j,l키를 입력해보면 좌우로 움직이는 것을 확인할 수 있습니다.
*이동 시 화면에 잔상이 남을 경우, WaitRender()함수에서 시간을 조정해서 fps를 높여보세요.
또는 ScreenClear()함수의 Clear범위를 늘려주세요.
현재 출력되고 있는 Player는 왼쪽 팔을 기준으로 0,0으로 설정되어져 그려지고 있다.
팔 길이가 다른 캐릭터의 경우 동시에 출력할 경우 팔 길이에 따라 머리는 다른 곳에 위치하게 된다.
(경계에 대한 처리도 다르고 볼 컨트롤 하는 위치 좌표 역시 다르게 된다)
그렇기 때문에 머리좌표를 기준으로 출력하는 중심좌표가 필요하다.
미리 만들어 둔 Player 구조체에 center Position을 추가한 후 Init에서 초기화해준다.
1 2 3 4 5 6 7 | typedef struct { Position position; Position center;// 중심 좌표 char *strPlayer;// = "└─●─┘";//주인공 캐릭터 int nLength; //주인공 캐릭터 전체 길이 }Player; | cs |
Init()
1 2 | g_Player.center.x = 4; g_Player.center.y = 0; | cs |
*중심좌표가 4인 이유는 PLAYER_STR[] = "└─●─┘" 를 strlen()으로 사이즈를 출려해보면 10인 것을 볼 수 있다. 즉, 한 글자당 2컬럼씩의 사이즈를 갖고 있어서 왼쪽 팔 2개 다음에 위치한 머리의 좌표는 4를 갖는다.
Render()
1 2 | int printX = g_Player.position.x - g_Player.center.x; ScreenPrint(printX, g_Player.position.y, g_Player.strPlayer); | cs |
Player를 출력했던 Render()함수에서 center.x만큼 뺀 후 출력하게 되면 중심좌표(머리)를 기준으로 출력하게 된다.
*(4,0)에 위치할 때 실제 출력은 4를 뺀(0,0)에서 출력하므로 머리를 기준좌표로 출력하게 되는 것이다.
클리핑(Clipping) 적용
클리핑이란? 오려낸다는 뜻으로 게임 이미지에서 필요한 부분만을 출력하고 보이지 않는 부분은 출력하지 않는 기법을 말합니다.
이 게임에선 양쪽 경계 끝으로 갔을 때는 경계를 넘어간 만큼 팔은 잘라내고 출력하게 구현하겠습니다.
아래 그림과 같이요.
Render()함수 내부에서 경계를 넘어갔을 경우, 처리해주면 됩니다.
우선 아래와 같이 조건문을 나눕니다.
1 2 3 4 5 6 7 8 9 10 11 | int printX = g_Player.position.x - g_Player.center.x; if (printX < 0) { } else if (g_Player.position.x + g_Player.center.x +1 > 40) { } else { ScreenPrint(printX, g_Player.position.y, g_Player.strPlayer); } | cs |
첫번째 if문 printX<0보다 작을 경우는 왼쪽 팔이 경계를 넘어갔을 경우
두번째 else if문의 경우,
g_Player.position.x(머리좌표)+g_player.center.x(이름이 헷갈리지만 오른쪽팔을 계산) +1(맨끝 Null을 계산) 하여
40(오른쪽 경계선)을 넘는지 체크합니다.
각 경계를 넘억가지 않은 경우 else에서 처리됩니다.
이제 각각 처리되는 경우는 아래와 같이 하면 됩니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | int printX = g_Player.position.x - g_Player.center.x; if (printX < 0) { ScreenPrint(0, g_Player.position.y, &g_Player.strPlayer[printX*-1]); } else if (g_Player.position.x + g_Player.center.x + 1 > 40) { strncat(string, g_Player.strPlayer, g_Player.nLength - ((g_Player.position.x + g_Player.center.x +1)-40)); ScreenPrint(printX, g_Player.position.y, string); } else { ScreenPrint(printX, g_Player.position.y, g_Player.strPlayer); } | cs |
1. 왼쪽 경계를 넘을 경우ScreenPrint(0, g_Player.position.y, &g_Player.strPlayer[printX*-1]);-> 왼쪽을 넘은 경우 -(음수)값에 출력할 수 없으므로 무조건 0에 출력한다. -> g_Player.strPlayer[printX*-1], printX값은 왼편으로 넘어갈때마다 -2,-4... 값으로 줄게 되는데 -1을 곱하여 주인공 string값의 인덱스로 사용한다. : -2(2): ─●─┘, -4(4):●─┘, -6(6):─┘ (각 글자의 칼럼 값은 2이므로..)2. 오른쪽 경계를 넘을 경우strncat(string, g_Player.strPlayer, g_Player.nLength - ((g_Player.position.x + g_Player.center.x +1)-40)); ScreenPrint(printX, g_Player.position.y, string);-> strncat : 지정된 길이만큼 두개의 문자열을 합친다. -> string배열에 오른쪽으로 넘어간 팔의 길이를 제외하고 합친 뒤 출력.이상태로 실행해보면 좌우 경계를 넘었을 때 문작가 깨진 것을 확인할 수 있다.
이는 각 글자의 칼럼은 2이기 때문에 경계를 넘어선 경우엔 2씩 이동해주어야한다. 아래와 같이 경계를 넘어선 경우 2씩 이동되게 해주자.
123456789101112131415161718192021 void KeyProcess(int key){int remain;switch (key){case 'j':g_Player.position.x--;if (g_Player.position.x- g_Player.center.x < 0 || g_Player.position.x + (g_Player.center.x*2) + 1 >40){g_Player.position.x--;}break;case'l':g_Player.position.x++;if (g_Player.position.x+(g_Player.center.x*2)+1 >40||g_Player.position.x - g_Player.center.x < 0){g_Player.position.x++;}break;}}cs 실행시켜 보면 Player 객체를 좌우로 움직여볼 수 있습니다.
'Software Development > C, C++' 카테고리의 다른 글
C언어로 게임만들기 - 5. 첫번째 게임_3)움직이는 골대 만들기 (0) | 2017.03.20 |
---|---|
C언어로 게임만들기 - 5. 첫번째 게임_2)Ball 만들기 (0) | 2017.03.19 |
C언어로 게임만들기 - 4. 코드정리(전체코드) (3) | 2017.03.18 |
C언어로 게임만들기 - 3. 렌더링 기능 구현 (2) | 2017.03.15 |
C언어로 게임만들기 - 2. 게임 프로그래밍 용어 (0) | 2017.03.14 |