NewGRF을 제작하기 위해서는 기본적인 제작 프로그램이 있어야 합니다.
크게 GRFMaker를 이용하는 방법과 NML, NFO 방식으로 프로그래밍하는 방법 등이 있습니다.
하지만 GRFMaker는 TTD 시절에 이용되던 프로그램이라
OpenTTD 최신 버전과는 잘 맞지 않는 단점이 있고,
NFO 방식은 저급 프로그래밍 언어
[1]라 배우기가 어렵습니다.
그래서 제 경우에는 (배우기는 그래도 어렵지만)
고급 프로그래밍 언어
[2]인 NML 방식을 이용해서 NewGRF을 제작하고 있습니다.
이번 기회에 부족한 실력이지만 제가 배운 NML을 알려드리고자 팁을 작성합니다.
* 읽기 전에
하늘색 부분은 여러분이 마음대로 이름을 정할 수 있는 부분입니다.
분홍색 부분은 정해진 문자열이나 값을 찾아서 지정해주어야 하는 부분입니다.
1. NML 컴파일러 준비하기
NML 방식은 NewGRF을 '프로그래밍'하는 방식입니다.
따라서 소스 코드인 *.nml 파일을 *.grf 파일로 변환하기 위한 '컴파일러'가 필요합니다.
이 컴파일러가 바로 nmlc.exe 파일입니다.
http://bundles.openttdcoop.org/nml/nightlies/LATEST에서 다운로드할 수 있습니다.
(들어가서 파일 이름이
nml-XXXXX-windows-win32.zip 으로 되어있는 것 다운로드)
압축을 풀면 여러 개의 파일이 뜨지만,
우리가 사용할 것은
nmlc.exe 실행파일 단 하나입니다.
nmlc.exe 파일이 있는 폴더 경로를 잘 기억하십시오.
[시작]-[실행]을 눌러 입력창에
cmd (XP 기준)를 입력하고 엔터를 치면
옛날에 본 듯한 도스창(명령 프롬포트)이 뜹니다.
방금 전에 nmlc.exe 파일이 있는 폴더로 이동(cd 폴더명)한 뒤,
명령창에
nmlc 를 입력하면 다음과 같이 안내문이 뜹니다.
sage: nmlc [options] <filename>
Where <filename> is the nml file to parse
Options:
\--version show program's version number and exit
-h, \--help show this help message and exit
-d, \--debug write the AST to stdout
-s, \--stack Dump stack when an error occurs
\--grf=<file> write the resulting grf to <file>
\--md5=<file> Write an md5sum of the resulting grf to <file>
\--nfo=<file> write nfo output to <file>
-M output a rule suitable for make describing the
graphics dependencies of the main grf file (requires
input file or --grf)
\--MF=<file> When used with -M, specifies a file to write the
dependencies to
\--MT=<file> target of the rule emitted by dependency generation
(requires -M)
-c crop extraneous transparent blue from real sprites
-u save uncompressed data in the grf file
\--nml=<file> write optimized nml to <file>
-o <file>, \--output=<file> write output(nfo/grf) to <file>
-t <file>, \--custom-tags=<file> Load custom tags from <file> [default: custom_tags.txt]
-l <dir>, \--lang-dir=<dir> Load language files from directory <dir> [default: lang]
-a <dir>, \--sprites-dir=<dir> Store 32bpp sprites in directory <dir> [default: sprites]
\--default-lang=<file> The default language is stored in <file> [default: english.lng]
\--start-sprite=<num> Set the first sprite number to write (do not use except when
you output nfo that you want to include in other files)
-p <palette>, \--palette=<palette> Force nml to use the palette <pal> [default: ANY].
Valid values are 'DOS', 'WIN', 'ANY'
--quiet Disable all warnings. Errors will be printed normally.
영어로 되어있어 무슨 소리인지 모르겠지만 일단은 그러려니 하고 넘어갑니다.
어차피 우리가 사용할 명령어는 몇 개 없습니다.
2. 프로젝트 폴더 만들기
이제 NewGRF을 만들기 위해 프로젝트 폴더를 하나 만듭니다.
nmlc.exe 파일이 있는 폴더 안에 아래와 같이 적당히 폴더를 하나 만듭니다.
이번 강좌에서는
my_newgrf 이라고 해보겠습니다.
그 폴더 안에 또다시
lang 이라는 폴더를 만듭니다.
최종적으로 아래와 같은 구조가 될 것입니다. (폴더는 기울임 표시하였습니다.)
(...)
└nmlc.exe
└
my_newgrf
├
lang
└ (본체 파일이 들어갈 곳)
3. 가장 기초적인 NewGRF 만들기 : 언어파일
NML의 가장 큰 장점 중 하나가 바로 '번역을 손쉽게 지원할 수 있다'는 점입니다.
방금 만드신
lang 폴더에 언어 파일(*.lng)을 제작해서 넣으시면 됩니다.
하지만 기본적으로 영어 언어 파일(english.lng)은 반드시 있어야 합니다.
만약 한국어 번역을 지원하고 싶다면
english.lng 파일과 korean.lng 파일을 만들어서
아래와 같이 위치시키시면 됩니다. (굵은 글씨)
(...)
└nmlc.exe
└
my_newgrf
├
lang
│├
english.lng
│└
korean.lng
└ (본체 파일)
언어 파일은 다음과 같이 작성합니다.
#grflangid {{#ef007c <number>}}
{{#00b0a2
<string-name> :<text>
<string-name> :<text>
}}...
하나 하나 설명하겠습니다.
```##grflangid
<number>
##grflangid 는 이 언어 파일이 어떤 언어를 나타내는지 알려주는 부분입니다.
{{#ef007c <number>}} 부분에 언어에 대한 코드값을 입력해주어야 합니다.
영어는 00, 한국어는 3A 입니다.
단, 이 코드값은 16진수값이므로, 입력시 앞에 0x 를 붙여주어야 합니다.
ex) 영어: ##grflangid 0x00
한국어: ##grflangid 0x3A
다른 언어의 코드값은 [[[http://newgrf-specs.tt-wiki.net/wiki/NML:Language_files]]]의 가장 하단에 있는 표에서 참고할 수 있습니다.
<string-name>: <text>
<string-name>은 문자열 이름입니다.
아래 소스 코드 본체에서 사용될 부분입니다.
<text>는 그 문자열 이름에 해당하는 문자열입니다.
이 둘을 콜론(:)으로 구분하여 입력하면 됩니다.
<string-name>은 <text> 이다 라고 생각하시면 편하겠네요.
백번 설명하는 것보다 직접 보여드리는 게 낫겠지요.
이번에 만들 NewGRF에서 쓸 언어 파일 코드입니다.
따라해보세요.
'''[영어 언어 파일 (english.lng)]'''
##grflangid 0x00
STR_MY_NEWGRF_NAME :My First NewGRF
STR_MY_NEWGRF_DESC :This is my first NewGRF. This is a description.
'''[한국어 언어 파일 (korean.lng)]'''
##grflangid 0x3A
STR_MY_NEWGRF_NAME :내 첫 번째 NewGRF
STR_MY_NEWGRF_DESC :내가 만든 첫 번째 NewGRF입니다. 이건 설명입니다.
'''4. 가장 기초적인 NewGRF 만들기 : 소스 코드 본체'''
이제 정말 기초적인 NewGRF을 만들어보겠습니다.
지금 만들 NewGRF은 어떤 기능도 하지 않고,
그저 NewGRF 목록에 이름만 올리는 용도입니다.
하지만 내가 만든 GRF이 게임 상에서 그 이름을 표시한다는 게 꽤 뿌듯하답니다.
본체 파일은 확장자가 .nml 이며,
여기에 코드를 작성하여 컴파일하는 방식입니다.
메모장이나 기타 텍스트 편집 프로그램을 열고 다음과 같이 코드를 작성합니다.
{{#951015 NML은 C 계열의 프로그래밍 언어처럼 줄 끝에 항상 세미콜론(;)을 붙여야 합니다.}}
(참고: 주석도 C 계열을 따라갑니다. //, /* */ 사용 가능)
grf {
grfid: "ABCD";
name: string(STR_MY_NEWGRF_NAME);
desc: string(STR_MY_NEWGRF_DESC);
version: 0;
min_compatible_version: 0;
}
하나 하나 설명을 해보겠습니다.
grf { ~ }
중괄호로 묶인 하나의 영역을 '''블록'''이라고 합니다.
grf 블록은 NewGRF의 기본적인 정보를 선언해줍니다.
중괄호 안에 있는 grfid, name 같은 것들은 속성값입니다.
grfid: "
ABCD";
grfid 속성은 NewGRF의 고유한 ID를 지정하는 부분입니다.
4바이트 고정 문자열로 되어있습니다. (더도말고 덜도말고 딱 4글자라는 말입니다.)
{{#00b0a2 ABCD}} 부분을 고치시면 됩니다. 숫자를 써도 괜찮습니다.
하지만 이럴 경우 다른 NewGRF과 중복될 수도 있기 때문에,
이를 피하기 위해 '''16진수 방식'''으로도 입력할 수 있습니다.
1글자(1바이트)는 2글자의 16진수로 되어있습니다.
뒤에 오는 숫자가 16진수임을 표시하기 위해 자를 앞에 덧붙입니다.
예를 들면 A = 65, 0 = 48 등입니다. (ASCII 코드표 참조)
예를 들어 자기 이름이 '홍길동'이고 1번째로 만드는 NewGRF이라면
grfid 속성을 'HGD1' 이라고 지정하는 습관을 들이는 것도 좋습니다.
(1이 1글자임)
name: string(
STR_MY_NEWGRF_NAME);
name 속성은 게임 상에서 나타날 NewGRF의 이름입니다.
string({{#00b0a2 STR_MY_NEWGRF_NAME}}) 은 위 '언어 파일' 부분에서 나온 <string-name>입니다.
STR_MY_NEWGRF_NAME 이라는 문자열을 읽어오겠다는 뜻입니다.
나중에 STR_MY_NEWGRF_NAME에 '나의 첫번째 NewGRF' 등의 문자열을 넣으면 됩니다.
desc: string(
STR_MY_NEWGRF_DESC);
desc 속성은 이 NewGRF의 설명(description) 부분을 지정합니다.
마찬가지로 {{#00b0a2 STR_MY_NEWGRF_DESC}}?라는 문자열을 지정합니다.
version: 0;
version 속성은 이 NewGRF의 버전을 나타냅니다.
숫자 0부터 시작하여 NewGRF을 수정할 때마다 1씩 올리는 방식입니다.(소숫점 불가)
0을 포함한 자연수로 값을 입력하셔야 합니다. (마지막에 세미콜론 붙이는 것도 잊지 마세요.)
min_compatible_version: 0;
min_compatible_version 속성은 처음 만들 때에는 version과 같이 값이 0입니다.
하지만 NewGRF을 수정하고 수정하다 구 버전과 호환이 안되게 될 경우,
이 min_compatible_version 속성을 수정하면 됩니다.
호환이 가능한 가장 낮은 version 값을 지정해주면 됩니다.
백문이불여일견이라고 실제 이번 강좌에서 만들 NewGRF의 NML 소스를 확인해봅시다.
샘플 소스에서는 주석을 어떻게 사용하는 지에 대해서도 적어두었습니다.
이 소스 파일을 '''{{#00b0a2 my_newgrf}}.nml''' 이라고 저장하겠습니다.
아래와 같은 위치에 만드시면 됩니다.(굵은 글씨)
(...)
└nmlc.exe
└''{{#00b0a2 my_newgrf}}''
├''lang''
│├english.lng
│└korean.lng
└ '''{{#00b0a2 my_newgrf}}.nml'''
/*
이런 형태로 주석을 사용할 수 있습니다.
이 형식의 주석은 여러 줄의 설명을 달 수 있습니다.
*/
// 이런 형태의 주석도 사용 가능합니다.
// NewGRF 기본 정보 선언
grf {
grfid : "HGD1"; // 홍길동(HGD)의 첫 번째(1) NewGRF
name : string(STR_MY_NEWGRF_NAME);
desc : string(STR_MY_NEWGRF_DESC);
version : 0;
min_compatible_version : 0;
}
'''5. 컴파일하여 .grf 파일로 만들기'''
이제 모든 준비가 끝났습니다.
최종적으로 다음과 같은 파일/폴더 구조가 되어야 합니다.
(...)
└nmlc.exe
└''{{#00b0a2 my_newgrf}}''
├''lang''
│├english.lng
│└korean.lng
└ my_newgrf.nml
이제 [시작]-[실행]을 누릅니다.
입력창에 '''cmd''' (XP기준)를 입력하면 명령 프롬프트(도스창)가 뜹니다.
'''''dir''''' (폴더 목록 나열/검색)과 '''''cd''''' (폴더 이동)명령어를 이용해
nmlc.exe 파일이 있는 폴더까지 들어갑니다.
입력줄에 '''nmlc'''를 쳐봤을 때 아까 봤던 긴 영어 안내문이 나오면 됩니다.
이제 입력줄에 다음과 같이 입력합니다.
nmlc -l ./
my_newgrf/lang/ ./
my_newgrf/
my_newgrf.nml
명령어를 해석하자면 이렇게 되겠네요.
nmlc : 컴파일해주세요.
-l ./my_newgrf/lang/ : 언어 파일은 ./my_newgrf/lang/ 폴더에 있어요.
./my_newgrf/my_newgrf.nml : 본체 소스 파일은 ./my_newgrf/my_newgrf.nml 입니다.
```
이제
my_newgrf 폴더로 들어가보면 전에 없던
my_newgrf.grf 파일이 생성된 것을 볼 수 있습니다.
이제 이 파일을 OpenTTD가 설치된 폴더 내에 있는
newgrf 폴더에 넣어볼까요?
와우! 게임에 내가 만든 NewGRF이 뜨는군요!
아까 언어파일에서 입력한 문자열도 잘 뜹니다.
게임 전체 언어를 영어로 바꾸어도 잘 뜨네요.
* 마치며
이번에 만든 NewGRF은 추가해서 적용해도 게임 상에 아무런 영향을 끼치지 않는 것입니다.
grf 블록으로 NewGRF의 기본적인 정보만 지정해주었을 뿐,
그 이후에 아무 것도 코딩하지 않았기 때문입니다.
이후 자동차, 전차, 기차 등을 만들기 위해서는 추가적인 문법을 더 공부해야 합니다.
일단은 오늘은 여기서 만족하도록 하지요. :)
댓글