- 전체
- 게임 일반 (make game basics)
- 모바일 기획 및 디자인
- GameMaker Studio
- Unity3D
- Cocos2D
- 3D Engine OGRE
- 3D Engine irrlicht
- copperCube
- corona SDK
- Windows Basic Game
- BaaS (Mobile Backend)
- phnegap & cordova
- ionic & anguler
- parse (backend)
- firebase (backend)
- Game Backend Server / Opt
- web assembly
- Smart Makers
- pyGame & Ren'Py
- 머드(MUD) 게임 만들기
- Xamarin(자마린)
- flutter (플루터 앱 개발)
- construct 2 / 3
- pocketbase
- RPG Maker 시리즈
- godot engine
- playmaker(unity)
- react native
머드(MUD) 게임 만들기 무작정 배우는 C언어 머드(MUD)게임 만들기 Part2 게임스랩
2020.10.17 23:52
무작정 배우는 C언어 머드(MUD)게임 만들기 Part2 게임스랩
예제 게임 소스 : MUD_TurtleAdventure(2).zip
안녕하세요. 지난 시간에 이어서 머드게임 만들기를 계속 진행하겠습니다. 아, 이 시점에서 혹시 오해하실수 있어서 말씀드리는데 모든 명령어는 대소문자를 반드시 지켜주셔야합니다. 소문자로 되어있다면 반드시 소문자로만 쓰셔야합니다. 데이터 타입의 경우는 다르지만 일단 넘어가고 대부분의 명령어들은 대소문자를 구분하므로 맞게 사용하세요
지난 시간 마지막 부분에서 함수에 대해서 얘기했었습니다. 우리가 만든 textColor() 함수를 좀 더 활용해 볼 수 있는 코드들을 준비해봤습니다. 일단 결과 화면부터 보겠습니다.

게임의 프롤로그 정도에 해당되는 부분을 이런 식으로 넣어봤습니다. 초록색 글은 NPC로 설정한 것들이고 노란색 글은 주인공입니다. 대사는 모두 흰색이지요. 이 부분들을 표현하기 위해선 우리가 지난 시간에 배운 코드로만 작성한다면 상당히 코드량이 많아지고 복잡해 질것입니다. 왜 그런지 직접 코드를 보겠습니다.
textColor(FOREGROUND_GREEN | FOREGROUND_INTENSITY);
printf("상어 대신");
textColor(FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY);
printf(" : 이보게, 상태는어떠하신가?\n\n");
textColor(FOREGROUND_GREEN | FOREGROUND_INTENSITY);
printf("문어 의원");
textColor(FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY);
printf(" : 가슴을움켜쥐고있는이불가사리를떼어낼려면천년묵은빨간토끼의간이필요합니다.\n\n");
… 생략
대략 저런식으로 모든 대사들을 처리해야 할 것입니다. 우리가 만든 textColor() 함수만을 이용하다면 말입니다. 대사가 많아질수록 엄청나게 코드가 길어지겠지요? 아마도 모두 그렇게 예상될 것입니다. 자, 여기서 한번 집고 넘어갈 것은 바로 함수라는 것입니다. 지난 시간에 우리는 무작정 함수란 것을 만들어 사용했습니다. 함수란 과연 무엇일까요? 여러가지로 정의할 수 있겠습니다만 제가 여기서 말하고 싶은 것은 바로 항상 똑같은 내용을 처리한다는 것입니다. textColor() 함수를 예를 들면 이 함수는 글자의 색을 바꾸는 일을 하는 함수입니다. 오직 그 일만을 합니다. 위 코드에서 보다시피 몇 번씩 글자의 색깔을 바꾸는 행동을 하고 있습니다.
다시 본론으로 돌아와서 상어대신 등의 캐릭터들의 대화를 처리하는 함수를 만들면 우리는 저렇게 긴 코드를 일일이 타이핑할 필요가 없다는 뜻입니다. 다음 코드를 한번 보겠습니다.
void npcDialogue(char* _name, char* _dialogue)
{
textColor(FOREGROUND_GREEN | FOREGROUND_INTENSITY);
printf("%s", _name);
textColor(FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY);
printf(" : %s\n\n", _dialogue);
}
NPC의 대화를 처리하는 사용자 정의 함수를 만들었습니다. 전달인자로는 이름과 대화내용을 지정했습니다. 문자형을 전달인자로 지정 할 때는 char 타입 뒤에 * (포인터)를 추가해줍니다. 포인터 개념은 아주 먼 훗날 설명해드리겠습니다. 지금은 그냥 이렇게 사용하면 되겠구나 라는 정도만 아셨으면 합니다. 그리고 지난 시간에 배웠던 char 타입을 출력할 때 &변수를 사용했던 것을 기억하실 겁니다. 포인터가 추가된 타입은 위 코드처럼 &를 붙이지 않고 _name 과 같이 원래 변수명을 사용합니다. 우리는 무작정 따라 배우는 컨셉이니까 그냥 그렇구나 라고 이해하고 넘어가주시면 감사하겠습니다. 자세한 설명은 때가 되면 하겠습니다. 누누히 제가 이렇게 강조하는 이유는 처음부터 너무 복잡한 개념을 파고 들게 되면 이해도 쉽지 않고 어려워져 자칫 흥미를 잃게 될 수 있기 때문입니다. 그러니 양해해 주세요. ^^
아무튼 저렇게 사용자 함수를 만들고 메인 함수 안에서 이렇게 사용하면
npcDialogue("상어대신", "이보게, 상태는 어떠하신가?");
npcDialogue("문어의원", "가슴을 움켜쥐고 있는 이 불가사리를 떼어 낼려면 천년묵은 빨간토끼의 간이 필요합니다.");
npcDialogue("상어대신", "토끼라면 지상에 사는 것이 아닌가? 우리가 어찌 지상으로 갈 수 있단 말인가?");
처음 화면에서 본것과 같이 자신의 화면에 출력될 것입니다. 어떠세요? 함수에 대해서 좀 더 이해가 되셨나요? 주인공의 경우는 이름이 다른색으로 표현되니 같은 함수로는 처리가 불가능하겠군요. 그래서 비슷한 종류의 함수를 하나 더 만들어서 사용하였습니다. 자세한 코드는 첨부파일을 확인해보시면 되겠습니다.
이제 우리는 제시되는 글만 보는 것이 아니라 처음 우리가 보았던 머드게임처럼 사용자가 직접 명령을 내릴 수도 있기를 바랍니다. 그에 필요한 명령어는 바로 gets(char* s) 입니다. 전달값은 문자열입니다. 사용법을 바로 알아 보겠습니다.
char myInput[128];
gets(myInput);
풀이해 보자면 사용자의 입력된 문자수가 얼마일지 모르므로 넉넉히 128개로 char 을 선언하고 gets 함수로 128개 내의 문자를 처리할 테니 알아둬 라고 전달인자값으로 보내줍니다. 이 명령어가 실행된후에는 입력을 받기 위해 프로그램이 대기를 하고 있을것입니다. 여러분은 키보드로 원하는 글자를 타이핑하시면됩니다. 좀 더 명시적으로 사용자에게 알려주기 위해 다음과 같이 코딩하면 좀 더 좋을거 같습니다.
char myInput[128];
printf(“명령을 기다리고 있습니다. 입력해 주세요. : “);
gets(myInput);
이 코드로 실행하면 마지막 문자 뒤에 커서가 깜빡이고 있을 것입니다. 그럼 위에서 배운 사용자 정의 함수를 통해 저는 입력 처리를 이렇게 바꿔 봤습니다.
void question(char* _question)
{
textColor(FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
printf("%s ", _question);
textColor(FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY);
gets(g_inputBuf);
}
Void main()
{
…생략
question("육지로올라가시겠습니까? <예or 아니오> :");
}

이렇게 우리는 원하는 질문과 대화를 단 두개의 함수를 사용함으로써 좀 더 편하게 코드를 작성해 볼 수 있겠습니다. 그럼 질문에 대한 답변을 했을 때 답변에 따른 상황을 사용자에게 보여줘야 하겠지요? 그럼 사용자가 입력한 내용이 무엇인지 알아야합니다. 그 내용은 바로 gets(g_inputBuf); 에 담겨 있는 g_inputBuf 변수에 있습니다. 내용이 어디 있는지 알았으니 이걸 어떻게 이용할지를 이제 생각하면 되겠습니다. 일단 코드부터 보겠습니다.
while(1)
{
question("육지로올라가시겠습니까? <예or 아니오> :");
if(strcmp(g_inputBuf, "예") == 0)
{
charDialogue(g_playerName, "휴~~, 드디어도착했군. 육지도오랜만인걸?");
charDialogue(g_playerName, "그런데빨간털을가진토끼라... 흰토끼는많이봤지만빨간토끼는어디있는거지? 일단흰토끼를찾아서정보를모아야겠다.");
break;
}
else if(strcmp(g_inputBuf, "아니오") == 0)
{
printf("%s은(는) 바다에서계속헤엄을치며놀고있습니다.(임무를수행해야지! ㅡ.ㅡ;)\n", g_playerName);
}
else
{
printf("잘못된명령입니다.\n");
}
}
새로운 명령어들이 보입니다. while, if, else if, else, strcmp 등입니다. 우선 while 에 대해서 알아보겠습니다. while 은 반복문 중의 하나입니다. 어떤 내용을 반복적으로 수행하기 위한 명령어이지요. while() 에서 () 안에는 조건이 들어갑니다. 예를 들면 이런것입니다.
int num = 10;
while(num < 100) // 조건
{
num = num + 1; //수행할 명령
}
num은 현재 10이고 100보다 작을때까지 num에 1을 더해서 num 에 다시 저장하는 명령을 반복 수행하는 것입니다. 조건을 달성할때까지 num = num + 1; 행위를 반복하죠. 그래서 반복문이라고 부릅니다. 그럼 제가 사용한 while(1) 은 무슨 내용일까요? 여기에 쓰인 개념은 참과 거짓입니다. 데이터 타입중 bool 이라는 논리형 데이터 타입이 있습니다. 1과0만을 표현할 수 있고 1은 참(true) 0은 거짓(false) 으로 정의되어 있습니다. 제가 아는한 거의 모든 프로그래밍 언어에서 이것은 변하지 않습니다. 조건에 1을 넣었다는 것은 while의 조건은 항상 참(조건을 만족한다.) 이다라고 지정한 것입니다. 그래서 무한 반복을 하게됩니다. 보통 무한 반복을 위한 코드로 많이 활용되기도 합니다. 만약 0을 넣었다면 항상 거짓이므로 명령을 수행하지 않고 바로 while문 밖으로 나가서 그 다음 명령을 실행할것입니다.
복잡하게 보일수 있겠지만 위에 제시한 예제 코드를 보시면서 응용해 보시면 금방 감을 잡으실겁니다. 그 다음 보이는 if 는 조건문입니다. 우리말로 풀자면 만약 ~ 라면 이겠죠. 이해를 돕기 위해 다음 예제를 보겠습니다.
int num = 10;
if(num < 100)
{
num = num + 1; //수행할 명령
}
else if(num > 100)
{
num = 10; //수행할 명령
}
else
{
num = 0;
}
만약 num 100보다 작다면 num 에 1을 더해서 num에 다시 저장하라. 라는 뜻입니다. 그 뒤의 else if 는 그게 아니라 만약 ~ 라면 으로 풀이됩니다. else if를 무한대 계속 설정할 수 있습니다. 여러분이 원하는 조건들을 이런식으로 많이 만들수 있다는 것입니다. 마지막의 else 는 위에서 지정한 조건 외의 모든 것 이라고 생각하시면 됩니다. 예제를 각자 적용해 보시면서 이리저리 바꿔보시면 금방 이해가 가실겁니다.
마지막으로 strcmp(문자열, 문자열); 함수에 대해서 이야기하겠습니다. 이 함수는 두개의 문자열을 비교하여 같으면 리턴값으로 0 을. 다르면 0이 아닌 값을 리턴합니다. 이 함수의 반환값은 int 형 입니다. 처음 포스팅때 함수에 대해 얘기했을 때 함수의 반환값 즉 리턴값에 대해 얘기했었습니다. 지금 이 함수는 반환값을 int 형태로 돌려주는것입니다.
if(strcmp(g_inputBuf, "예") == 0)
이 코트에서 보면 입력한 문자열 g_inputBuf 에 있는 문자열과 예 라는 문자열을 비교하는 것입니다. 서로 같다면
{
charDialogue(g_playerName, "휴~~, 드디어도착했군. 육지도오랜만인걸?");
charDialogue(g_playerName, "그런데빨간털을가진토끼라... 흰토끼는많이봤지만빨간토끼는어디있는거지? 일단흰토끼를찾아서정보를모아야겠다.");
break;
}
내용을 수행할 것입니다. 이해를 위해 상세히 풀이하자면 1.“ if “ 만약 , 2.“ strcmp(g_inputBuf, "예") “ 함수를 이용해 비교를 해서 반환값을 주겠죠? 같다면 0을 줄것입니다. 그 값이 3.“ == 0 “ 0과 같다면 이라고 풀이가 되겠습니다. 중간에 나오는 break; 라는 명령어는 반복문에서 강제로 빠져나오는 명령어라고 생각하시면 됩니다.

결과 화면을 보면 위와 같습니다. while문을 이용해 무한 반복을 시킨 이유는 사용자가 올바른 명령을 내릴때까지 gets 를 통한 입력을 지속적으로 받기 위한 것이고 if와 else if등을 사용한 이유는 여러 상황에서 적절한 처리를 하기 위함입니다. 위와 같이 아니오를 했을때의 내용, 선택지에 없는 명령을 했을 경우의 처리, 그리고 예라는 명령을 통해 게임을 진행하게 하는 상황등을 만들기 위해서 필요한 처리였던 것입니다. break; 의 경우 질문지(육지로 올라가시겠니까?)에 해당되는 최종 답변(예)이 다음 진행상황으로 유도되게 만들었기에 더 이상 같은 질문을 할 필요가 없어 break; 문을 이용해 while 을 빠져 나온것입니다.
좀 어려울 수도 있지만 첨부된 소스파일을 보시면서 하나씩 만져보시면 금방 이해하실거라 믿습니다. 마지막으로 여러분이 좀더 게임화면을 자유자재로 사용할 수 있도록 새로운 명령어를 소개합니다.
system("mode con:lines=50 cols=100");
lines=50 의 부분이 세로부분입니다. 50 대신에 원하시는 수를 넣으시면 됩니다.
cols=100 의 부분은 가로부분입니다. 마찬가지로 100 대신에 원하시는 수를 넣으시면 가로 세로 사이즈를 결정하실수 있습니다. 지금까지의 내용으로도 충분히 응용할수있으므로 다음 포스팅때까지 여러분이 게임을 많이 완성시키길 바라면서 이번 포스팅을 끝내겠습니다. 부족한 면이 많지만 다음 3편을 기대해주세요.
ps. 이걸 기반으로 여러분이 만들어 보신 게임을 구경하고 싶네요 ^^ 너무나 궁금합니다.
[출처] https://gameslab.tistory.com/m/76?category=486131
광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.
댓글 0
| 번호 | 제목 | 글쓴이 | 날짜 | 조회 수 |
|---|---|---|---|---|
| 7 |
[flutter (플루터 앱 개발)]Flutter - InAppWebview Communication (인앱웹뷰로 웹과 앱 양방향 통신하기, 자바스크립트 커뮤니케이션)
| 졸리운_곰 | 2024.04.13 | 275 |
| 6 |
[flutter (플루터 앱 개발)] flutter - fvm 적용하기 (Futter Version Management)
| 졸리운_곰 | 2024.04.11 | 189 |
| 5 |
[flutter (플루터 앱 개발)]Using Flutter FVM in Windows & MacOS
| 졸리운_곰 | 2024.04.10 | 294 |
| 4 | [flutter (플루터 앱 개발)] Flutter version management in Visual Studio Code with FVM | 졸리운_곰 | 2024.04.10 | 231 |
| 3 |
[flutter (플루터 앱 개발)] pHp backend with flutter
| 졸리운_곰 | 2024.03.18 | 350 |
| 2 | [flutter (플루터 앱 개발)] [Flutter] fvm으로 Flutter 버전 관리 | 졸리운_곰 | 2024.03.17 | 203 |
| 1 |
[flutter (플루터 앱 개발)] How to use Flutter’s Rest API
| 졸리운_곰 | 2023.03.21 | 349 |

