티스토리 뷰

Games

GBA 게임 만들기

알 수 없는 사용자 2008. 3. 23. 23:40

GBA 하드웨어스펙
GBA Hardware Specification

Item Description
CPU ARM7TDMI
Memory 외부 RAM 256KB / 내부 RAM 64KB / I/O 레지스터 / VRAM / 팔레트 RAM / OAM / 세이브용 RAM 64KB
Screen 240 x 160 dot
Color 32768 color
Graphics mode Mode 0~5 (0~2 mode : Tile Mode,  3~5 mode : Bitmap Mode)
Background Tile Mode
  16색 x 16팔레트 or 256색 x 1팔레트
  Background 최대 4개, BG 사이즈 : 128x128 ~ 1024x1024
  Tile character 정의 수 : 1BG 당 최대 1024까지
Bitmap Mode
  256색 x 1팔레트 or 32768 color 직접 사용.
  BG Double Buffer 또는1개만사용
  BG Size : 240 x 160
Sprite 최대 128개 / 사이즈 : 8x8 ~ 64x64 / 팔레트 : 16색 x 16팔레트 or 256색 x 1팔레트
1D Mapping or 2D Mapping
Sound GB호환 4-Channel Direct Sound 2-Channel
Effect Background 와 Sprite 확대, 축소(Scale), 회전(Rotate), Window 2개, 모자이크 처리, 알파블랜드(투명), fade out,
Layer 순서지정(0~3), X/Y 대칭(flip)
Key 상, 하, 좌, 우, A, B, L, R, Start, Select<
Timer Timer(0~3) 4단계의 주기
DMA DMA(0~3) 4-Channel
Interrupt Vblank, Hblank, Vcount, Timer, DMA, Key, Communication, Cartrage
Communication 최대 4명, Multiboot
Bios Call 43개

GBA게임을 만들자.
GBA용 게임을 직접 만들 수 있다면 좋겠다는 생각을 하는 분들은 그 길이 열려있으니 노력해보기 바란다. GBA프로그래밍이 가능하다는 것은 반드시 게임이 아니라도 GBA를 이용한 무한한 가능성을 펼칠 수 있을 것이다.
GBA개발의 기본은 컴파일러와 그것을 직접 실행할 수 있는 도구다.
1. 개발할때 중간 확인은 에뮬레이터를 통해서 할 수 있다.
대표적인 에뮬레이터는 visualBoyAdvance로 여러가지 기능을 지원해 개발시 가장 좋은 파트너라할만하다. 무료소프트웨어라는 점도 장점이다.
2. 컴파일러는 실제 실행코드를 생성해내는 핵심적인 프로그래밍도구다.
현재 닌텐도에서는 수천만원에 이르는 겜보이 개발환경프로그램을 판매하고 있지만 그런걸 사서 취미를 즐길 미친넘이 몇명이나 있을까나..
무료! 역시 무료로 구할 수 있는 컴파일러가 있다. DevkitAdvance 이넘이다.
이 넘은 c,c++ 컴파일러로 상당히 유연한 모양을 하고 있는 커맨드툴이다.
그외에 GBA전용 헤더파일과 파일컨버터등도 필요하다. 모두 무료로 구할 수 있다.
3. 메모장으로 프로그래밍을 하기란 어렵다! 따라서 적당한 툴이 있어야한다. 개인적으로 좋아하는 acroeditor나 ultraeditor의 경우는 문법강조가 될 뿐만 아니라 커스텀툴 설정을 통해 dos모드의 툴을 연계해서 사용할 수 있기 때문에 아주 편리하다.
4. 에뮬로만 돌리면 재미가 없다. 짜피 pc에서 돌 프로그래밍이라면 어렵게 gba프로그래밍할 필요가 없기 때문이다. 역시 gba용으로 만들었으면 그것은 겜보이에서 돌려야하지 않겠는가!
여기에 필요한 것은 nand형 메모리매체를 지원하는 겜보이 램팩들이다. 닥터, 울트라 등의 메모리롬팩을 준비하자.
모든 것을 포함해서 4번의 메모리롬팩은 10만원정도에 구매할 수 있고 나머진 공짜다. 이제 필요한건 열정뿐이다!

----------------------------------------------------------------------------------------

GBA게임만들기 (1) - 개요와 환경셋팅
1. 들어가기에 앞서
본격적으로 GBA게임을 만들기 전에 몇가지 설명을 하고 시작하겠습니다.
먼저 가장 큰 도움을 받은 곳은 아래 주소의 까페입니다.
http://cafe.naver.com/gbastation.cafe
입문자에게 너무나 친절한 설명이 인상적입니다.
두번째로는 GBA개발자의 전당인 아래 주소입니다.
http://devkitadv.sourceforge.net/
여기에서 최신 개발툴을 받을 수 있는데 무료에다가 성능도 쓸만합니다.
다운로드 링크는 아래와 같습니다.
http://sourceforge.net/project/showfiles.php?group_id=67315
그외에도 어느정도 실력이 붙자 외국의 여러 개발자 포럼이나, 프리롬 사이트에서도 많은 도움을 받았습니다. 일본에서 사온 GCC프로그래밍편 특별판 리눅스 - 리눅스에서 각성한 우리들의 게임보이!란 책도 큰 도움이 되었네용. 이책은 리눅스에서 겜보이를 연결할 수 있는 드라이버와 케이블을 제공해주고 있는데 예제로 들어가 있는 소스의 경우 큰 도움이 되었습니다.

2. 환경설정
개발을 하려면 개발환경을 갖춰야합니다. 크게 컴파일러,에디터,에뮬레이터,기타소스 로 나눠서 설명하겠습니다.
- 컴파일러 설치
위의 소스포지의 툴은 바로 겜보이프로그래밍을 위한 컴파일러가 되겠습니다.
일 단 위의 다운로드 링크에서 총 6개의 파일을 모두다 받아서 같은 곳에다가 풀면 한 폴더 밑에 쭉하고 풀리게 됩니다. 일단 컴파일러는 압축을 푸는 것만으로 설치가 완료되는데 좀더 편리하게 사용하기 위해서 환경변수의 path에 압축을 푼 폴더와 그 폴더의 bin폴더를 잡아주는게 좋습니다. 음 그렇게 정리한 zip파일이 아래 있습니다.
devkitadv.zip
- 에디터 설치
비 주얼C같은 경우는 통합개발환경이라고 해서 에디터도 지원해주지만 이 무료툴은 에디터가 없습니다. 물론 메모장같은걸로 작업하고 cmd에서 타이핑으로 컴파일해도 되지만 그게 왠 생노가다 입니까.. 최소한의 에디터환경을 구축하는게 좋죠.
일단 컴파일러도 공짜를 쓰고 있으니 에디터도 공짜를 구합시다.
http://acrosoft.pe.kr/bbs/zboard.php?id=ae_download
위 주소에 가시면 아크로에디터의 최신 버전을 받을 수 있습니다. 아크로에디터는 무료답지 않게 외부컴파일연동이나 코드의 색상강조기능을 갖고 있어서 편리합니다. 아래순서대로 잡아주세요.
      1.일단 저걸 받아서 setup으로 설치하고나서 실행하신 후에 메뉴를 봅니다.
      2.메뉴>도구>사용자도구설정 으로 들어가셔서 '추가'를 누릅니다(두개를 추가할겁니다)
      3.메뉴이름 : GBA(gcc)
         명령 : devkitadv경로bingcc.exe
         인자 : -o %PATH%%NAMEONLY%.elf %FULLNAME% -lm
         작업디렉 : %PATH%
      4.하나 더 추가합니다.
메뉴이름 : GBA(objc)
         명령 : devkitadv경로binobjcopy.exe
         인자 : -O binary %PATH%%NAMEONLY%.elf %PATH%%NAMEONLY%.gba
         작업디렉 : %PATH%
위의 과정을 끝내면 일단 에디터환경도 끝입니다. 이젠 아크로에디터에서 소스입력해서 간단히 컴파일할 수 있게 된거죠. 위의 내용을 입력하기 귀찮으실테니 사용자도구불러오기에서 아래 파일을 불러오셔도 간단히 셋팅됩니다.
GBAtools.aut
- 에뮬레이터 설치
에뮬은 일반적으로 사용되고 있는 Visual Boy Advance를 사용합니다. 근데 홈피가 박살났는지 마땅한 정식링크는 없습니다. 각 자료실등에서 받을 수 있는데 일단 여기에 링크해두겠습니다. 압축을 풀면 설치가 끝입니다.
VisualBoyAdvance-1.7.zip
- 기타소스
위의 세가지를 다 설치해도 아직 할일이 남았습니다. GBA프로그래밍을 위한 헤더와 게임프로그래밍을 위한 BMP변환기, 맵타일생성기등입니다. 각각 아래 링크에 있습니다.
      헤더파일 : GbaHeaderFiles.zip
      BMP변환기 : BMP2HEADER.exe
      맵타일생성기 : MapEditor.exe
3. 개발의 흐름
실제로 개발에 들어가면 위에서 셋팅한 환경을 이용해 다음과 같은 순서로 작업하게 됩니다.
a. acroeditor실행(당연하죠..=.=)
b. 소스입력 및 이미지를 헤더로 변환(BMP변환기나 맵타일생성기 이용)
c. GBA(gcc)를 이용해서 소스로부터 elf생성
d. GBA(objc)를 이용해서 elf로부터 gba생성
e. VisualBoyAdvance를 이용해서 소스테스트
즉 간단히 말해 소스를 만들고 1차컴파일하면 elf가 되고 2차컴파일하면 대망의 gba가 되는겁니다.
이번엔 이정도로 해둘까요. 담엔 직접 개발소스를 정리해가죠.

----------------------------------------------------------------------------------------

GBA게임만들기 (2) - 간단한 샘플프로그램 제작
개발환경이 셋팅되었다면 무엇보다 역시 간단한 샘플을 만들어보는 것이 최고죠.
GBA 환경에서 개발하기 위해서는 기본적으로 C나 C++에 대한 이해가 필요합니다. C와 C++은 비슷한 것 같지만 사실은 완전히 다른 언어에 가깝습니다. 어떤쪽이 더 좋다라고 말하긴 힘들죠(C++이 나온 이유가 C의 불만을 개선하기 위해서라곤 하지만 결국 무식한 쪽도 나쁘지 않더라는 것이죠)
C에서 가장 어렵고 힘든 개념은 아마도 포인터일 겁니다. 초심자들이 힘들어하는 부분이기도 하고 반대로 C가 중급언어로서 강력한 힘을 갖는 이유이기도 합니다. C++은 역시 상속과 관련된 클래스컨트롤입니다. 객체디자인 자체가 어려운 일이죠. 이 프로그래밍언어 자체를 모르는 것은 어떻게 해결해야하는가 하면, 예제를 따라가면서 점점 공부해가는 방법밖엔 없습니다.
즉 영어로 얘기하자면 단어공부, 문법공부를 다 한뒤에 독해를 하는게 아니라 독해를 해가면서 모르는 단어를 찾아보고, 문장이 이해가 안되면 문법책을 뒤져보는 식의 공부죠. 사람마다 공부하는 방식이 있겠지만 프로그래밍을 배울때는 이런 방법이 나쁘지 않습니다.
밑에 샘플은 그저 카피해서 컴파일하는 훈련을 위한 소스입니다.
그저 카피해서 아크로에디터에서 컴파일 해봅시다 ^^
소스원문


#include "gba.h"
#include "bg.h"
void WaitForVsync(void){
   while(*(volatile u16*) 0x4000006 >= 160){};
   while(*(volatile u16*) 0x4000006 < 160){};
}
int main(void) {
   u16 *palette = MEM_BG_PAL;
   u16 *tiles = MEM_BG_CHAR(0);
   u16 *bgmap = MEM_BG_MAP(28);
   u8 x = 5;
   u8 y = 5;
   u8 z = 29;
   SetMode( MODE_0 | BG0_ENABLE );
   REG_BG0CNT = ( BG_SIZEA_256_256 | BG_COLOR_256 | BG_CHARBASE(0) | BG_MAPBASE(28) );
   palette[0] = RGB(10,20,30);
   palette[1] = RGB(31,22,10);
   u16 i;
   for( i = 0 ; i < 32 ; i++ ) tiles[i] = 0 + ( 0 << 8 );
   for( i = 32 ; i < 64 ; i++ ) tiles[i] = 1 + ( 1 << 8 );
   bgmap[0] = 1;
   bgmap[5] = 1;
   bgmap[32*y+x] = 1;
   bgmap[32*y+z] = 1;
   while(1) WaitForVsync();
   return 0;
}


위의 소스가 어떤 의미인지 전혀 설명할 생각은 없습니다. 위 소스는 주크님이 네이버의 '포터블 Game' 까페에 연재하시는 글에서 발췌했습니다(주크님이 작성하신 저 예제파일을 최초의 소스로 선택한 이유는 짧아서입니다. 죄송^^; )
이번 강좌에서 오직 해볼 실습은 컴파일입니다. 다음의 순서로 컴파일을 해보죠.
1. 위 소스 원문을 카피하여 아크로에디터에서 빈문서를 열고 붙여넣기를 한다.
2. test.c로 적당한 폴더에 저장한다.
3. test.c를 저장한 폴더에 1회강좌에서 기타준비물에 있던 gba관련헤더압축파일속에 있는 gba.h와 bg.h를 카피한다.
4. 아크로에디터에서 도구 > 사용자도구 > GBA(gcc) 를 실행한다.
5. 이어서 도구 > 사용자도구 > GBA(objc) 를 실행한다.
6. test.c를 저장한 폴더를 열어보면 해당폴더에 test.gba를 발견할 수 있습니다. 에뮬로 실행해보세요.
위 의 순서대로 진행하여 에뮬레이터에 이상없이 파란바탕에 오렌지 점이 몇개 찍혀있으면 성공한 겁니다. 이번 강좌는 소스를 작성하고 컴파일하는 연습을 하는 것이기 때문에 충분히 연습해보고 향후 개발시에 이러한 순서와 내용을 숙지하면 충분합니다(코드를 작성하고 헤더를 모아서 컴파일을 두번한다라는..)

----------------------------------------------------------------------------------------

GBA게임만들기 (3) - 컴파일러 공부
이제 워밍업은 이쯤으로 하고 진짜로 공부를 해보겠습니다(즉 이젠 제대로 읽고 이해를 하고, 외워야한다는 뜻입니다^^)
현재 겜보이용 프로그램을 만들 수 있는 툴은 몇가지가 나와있습니다. 그 중에 제 강좌에서 다루고 있는 devkit advance도 있습니다만, ham툴도 있고 arm사에서 직접 배포하는 툴도 있습니다.
즉 간단히 하고 싶은 말은 툴은 많이 있다는 겁니다. 일단 본 강좌는 설치가 가장 간단한(압축을 풀면 끝나니까) devkit advance로 진행하고 있는 겁니다. 따라서 이 툴을 먼저 공부하지 않으면 프로그래밍을 해도 그걸 어떻게 겜보이용 프로그램으로 바꿀지가 막막해지는거죠(아까부터 '툴(tool)'이라고만 했는데 정확하게는 컴파일러를 지칭하고 있습니다-c 또는 c++이란 언어의 형식으로 씌여진 문서를 겜보이가 이해할 수 있는 기계어의 집합으로 번역해주는 프로그램이라고 이해하시면 간단하겠네요)
그럼 이제 본격적인 devkit advance의 설명을 드리겠습니다.
일 단 devkit은 오픈소스그룹인 gnu에서 누구나 사용할 수 있는 프리컴파일러인 gcc를 기반으로 만들어졌습니다. 현재 http://gcc.gnu.org 에서 배포하는 gcc는 인텔계열 cpu에 최적화 되어있는데 반해 devkit은 겜보이의 cpu인 ARM7TDMI에 최적화 되어있습니다(어짜피 컴파일러라는게 cpu가 이해할 수 있는 언어로 c를 번역하는것이라 그 cpu가 무엇이냐에 따라 다른 컴파일러가 필요한거죠. 따라서 일반적인 c컴파일러를 구해서 프로그래밍해도 겜보이에서 돌지 않습니다. devkit이 아니라도 정확하게는 ARM7TDMI용 컴파일러가 필요한 것이죠)
그 외의 특징이나 제공되는 툴은 전부 gcc의 규격에 따르고 있습니다. 따라서 gcc를 공부하는 것이 devkit advance를 공부하는 지름길입니다.
사실 gcc는 리눅스나 유닉스 사용자라면 대부분 어느정도 사용법을 알고 있습니다.
일단 제가 강좌를 위해서 참고한 사이트는 아래 주소입니다.
http://junjaewoo.com/kldp/Gcc_and_Make-KLDP-html/gcc_and_make.html#toc2
아래 사이트에서 직접 공부하셔도 되고 제가 간단히 정리한 아래글을 보셔도 됩니다 ^^
단 위 링크에서 공부하시는 경우 devkit의 gcc와 옵션에서 약간 차이가 날 수 있으니 유의하세요.
1. gcc.exe
gcc.exe 는 이름 그대로 gcc의 핵심적인 기능입니다. 하지만 많은 분들이 착각하시는데 gcc는 c컴파일러가 아니라 중앙에서 소스를 통제하고 관장하는 프로그램입니다. 코드를 보고 c컴파일러가 필요한가, c++컴파일러가 필요한가도 판단하고, 링크도 하지만 실제적인 컴파일은 다른 프로그램이 하게됩니다(신경쓸 필요는 없지만요)
따라서 gcc를 공부한다는 것은 gcc의 링크기능과 컴파일 통제기능을 공부한다고 볼 수 있습니다.
일단 gcc의 모든 옵션을 간단히 살펴보고 사용예제를 통해 익혀보겠습니다.
-pass-exit-codes : 이 길다란 옵션은 컴파일중에 심각한 오류가 발생하면 탈출하란겁니다.
--help : 도움말을 표시
--target-help : 특정명령어에 대한 도움말을 표시(--v-help 이런식으로 쓰이죠)  
-dumpspecs : 스펙문자열안에 있는 모든 빌트를 표시
-dumpversion : 컴파일러 버전을 표시
-dumpmachine : 컴파일러의 타겟 프로세서를 표시
-print-search-dirs : 컴파일러가 패스로 잡은 폴더를 표시
-print-libgcc-file-name : 컴파일러의 동료라이브러리 이름을 표시
-print-file-name=[lib] : 라이브러리의 전체경로를 표시
-print-prog-name=[prog] : 컴파일컴포넌트의 전체경로를 표시
-print-multi-directory : gcc라이브러리 버전이 있는 루트폴더를 표시
-print-multi-lib : 커맨드라인오셥과 라이브러리폴더간의 매핑을 표시
-print-multi-os-directory : OS라이브러리에 잡힌 상대경로를 표시
-Wa,[options] : 어셈블러에 대해 컴마 구분자를 무시
-Wp,[options] : 전처리기에 대해 컴마 구분자를 무시
-Wl,[options] : 링커에 대해 컴마 구분자를 무시
-Xlinker [arg] : 링커에게를 무시
-save-temps : 임시파일을 지우지 않음
-pipe : 임시파일 보단 파이프를 사용함
-time : 각 서버프로세스 실행시간
-specs=[file] : [file]컨텐츠의 빌트인스펙을 오버라이드함
-std=[standard] : 입력소스를 [standard]로 간주함
-B [directory] : 컴파일러 검색 패스에 [directory]를 추가함
-b [machine] : [machine]을 위해 gcc를 실행함
-V [version] : [version]의 gcc를 실행함
-v : gcc버전을 표시함
-E : 컴파일이나 어셈블, 링크를 하지 않고 전처리만 함
-S : 어셈블이나 링크를 하지않고 컴파일만 함
-c : 링크를 하지 않고 어셈블과 컴파일만 함
-o [file] : [file]로 컴파일될 파일을 출력
-x [language] : 컴파일러가 인지할 파일이름에 대해서 언어를 명시한다.
옵션이 많지만 실제로 사용되는게 그렇게 많지는 않습니다. 일단 상단에 설명에 표시로 끝나는 넘들은 표시하는 넘들이라 컴파일과 상관은 없고 그냥 궁금할때 써보면 됩니다.
예 를들어 'gcc -print-search-dirs' 이렇게 명령을 내리면 gcc가 기본적으로 잡고 있는 모든 패스를 보여줍니다. 여기에 헤더나 라이브러리가 위치하지 않는다면 -B 옵션을 이용해서 잡아줘야합니다. 또 한가지 예를 들자면, 'gcc -dumpmachine' 이라고 명령을 내려보면 'arm-agb-elf' 라고 뜹니다. 즉 devkit의 gcc는 arm프로세스를 위한 컴파일러라는 뜻이죠.
일단 디스플레이 옵션들은 그렇다고 치고 핵심적인 옵션들은 아래쪽에 있는 옵션들입니다.
test.c라는 c소스가 있다고 가정하고 차근차근 설명해보겠습니다.
1단계 : 그냥 친다.
'gcc test.c' 라고 아무런 옵션도 없이 명령하면 결과는 'a.out'이라는 미리 약속된 이름의 실행파일을 만들어냅니다. 컴파일상으로 완전하지만, 저런 이름으로 출력되길 원하지는 않을 겁니다.
2단계 : 출력파일의 이름을 준다.
'gcc -o test.elf test.c' 라고 치면 컴파일의 결과로 test.elf가 만들어집니다. 저 명령을 잘보면 '-o test.elf' 여기까지가 한셋트고 그걸 제외하면 'gcc test.c'가 되어 1번과 같은 명령입니다. 옵션은 뒤에 붙여도 무방하니까 'gcc test.c -o test.elf'라고 써도 동일합니다. 이 -o옵션은 test.c파일을 컴파일한 후에 어떤 이름을 붙일지를 결정해줍니다.
3단계 : 여러개의 파일을 모아서 컴파일한다.
test.c외에도 test2.c, test3.c 라는 파일이 더 있고 이것들을 한꺼번에 모아서 컴파일해야할 경우가 생깁니다. 이런 경우는 2번에서 파일이름만 확장해주면 됩니다.
'gcc -o test.elf test.c test2.c test3.c' 이렇게 됩니다.
4단계 : 컴파일만 하기
실 제로 c어플리케이션은 여러개의 파일로 구성해서 하나의 파일이 그러한 여러개의 c파일을 통합하는 방식이 됩니다. 이런 경우 각각의 모듈들을 미리 컴파일 해두면 나중에는 그것을 묶기만 하면됩니다. 따라서 하나의 모듈이 완성되면 그것을 미리 컴파일만 해두고 싶은데 그럴때 사용하는 옵션이 -c옵션입니다. 'gcc -c test.c' 이렇게 하면 약속된 이름인 'test.o'가 생성됩니다.
3번단계에서 'gcc -o test.elf test.c test2.c test3.c' 이렇게 하면 컴파일러는 그 시점에서 세개의 c파일을 컴파일해야하지만 미리 'gcc -c test.c','gcc -c test2.c','gcc -c test3.c'를 해두어서 test.o, test2.o, test3.o 를 생성해두었다면,
'gcc -o test.elf test.o test2.o test3.o' 라는 명령을 통해 간단히 링크하는 과정으로 생성할 수 있습니다.
5단계 : 추가적인 패스를 지정한다.
4 번까지의 예제에서 test2.c 또는 test2.o가 같은 폴더에 있다고 가정하고 있습니다만 사실은 다른 폴더에 있을 수도 있죠. 이런 경우 명시적으로 컴파일러가 파일을 검색할 폴더를 지정해줘야합니다. 그것은 -B옵션으로 가능합니다. 가령 test2.o가 c:test라는 폴더 밑에 있다면
'gcc -o test.elf test.o test2.o test3.o -B c:test' 라는 명령을 통해서 해당폴더를 검색하게 할 수 있습니다.
일단 GCC는 여기까지 살펴보고 다음은 make.exe를 공부해보겠습니다.
2. make.exe
make 란 말그대로 만들어내는 프로그램입니다. 위의 gcc를 이용해서 복잡한 파일이 연결된 프로젝트를 컴파일하려면 매번 귀찮은 일이기도 하거니와, 타이핑 중에 실수도 유발하게 됩니다. 따라서 이러한 과정을 하나의 파일에 저장해서 스크립트로 만들어두고 사용하면 편리하겠죠. 바로 그러한 기능을 수행하는 것이 make.exe입니다. 따라서 make.exe의 옵션도 배워야하고 make.exe가 인식할 수 있는 컴파일 스크립트도 배워야합니다.
헥헥..너무 길어서 나중에 마저 작성..

----------------------------------------------------------------------------------------

RPG제작타일샘플
block.psd
Book1.xls
test.fla

----------------------------------------------------------------------------------------

퍼지로직 샘플
그러면 실제로 제가 슈팅 게임에 사용한 적 캐릭터의 움직임을 제어하는 룰베이스를 한번보죠.  
#define PURSUIT 0 // 추적 모드
#define ATTACK 1 // 공격 모드
#define RUN 2 // 회피 모드
char rule_base_x[3][3][5] = // ML SL 0 SR MR
{
  -3, -3, -2, 0, 2, // LEFT
  -3, -2, 0, 2, 3, // 0
  -2, 0, 2, 3, 3, // RIGHT
  -3, -3, -4, 3, 2,
  -4, -2, 0, 2, 4,
  -2, -3, 4, 3, 3,
  0, 2, 3, -3, -2,
  0, 3, 4, -3, 0,
  2, 3, -3, -2, 0
};
char rule_base_y[3][3][5] = // MU SU 0 SD MD
{
  -4, -3, -2, 0, 2, // UP
  -3, -2, -2, 0, 2, // 0
  -3, -2, -2, 3, 2, // DOWN
  -4, -3, -4, 0, 0,
  -3, -2, -4, 0, 2,
  -3, -3, -4, 0, 2,
  2, 2, 3, -3, 0,
  0, 3, -4, -3, 0,
  0, 3, -3, -2, -2
};  
< 하나는 X, 하나는 Y 에 대한 rule base 입니다. >
위에서 각각의 인덱스의 의미는 다음과 같습니다.
첫째 : 동작 모드 선택
둘째 : 플레이어 캐릭터의 움직임
세째 : 적 캐릭터에서 본 플레이어 캐릭터의 떨어진 거리
< 주석으로 표기된 어림수 기호의 의미는 예컨데 SL 이라면 왼쪽으로 조금 떨어졌다는 것입니다. >  
각 캐릭터의 위치는 프로그램 상에서
X = X + DX ;
Y = Y + DY ;
라는 식으로 갱신 되므로, 각 각의 배열 요소의 값은 적캐릭터의 DX 와 DY 값이 됩니다.
그러니까 시시 각각 변화하는 플레이어의 동작을 적절한 인덱스 값으로 바꾸어서, 그 인덱스에 해당하는 rule base 값을 적 캐릭터의 DX 와 DY 값으로 이용하면 되는 겁니다.
동작모드의 경우는 여러개를 준비해 두고 게임의 적절한 상황에 맞게 인덱스를 지정해 주면 다양한 적의 움직임을 만들수 있습니다.
그러면 실제로 rule base 는 어떻게 정해 주어야 할까요?
두 가지 방법이 있습니다.
하나는 경험적인 방법이고, 하나는 시행착오법입니다.
제가 위에서 사용한 룰베이스의 값들은 제가 게임 중에 캐릭터를 어떻게 조작하는지를 모방해서 만든 것입니다.
그러니까 룰베이스의 데이타를 제공하는 사람의 경험능력에 달려 있는 경험적인 방법이죠.
저 같이 게임을 제대로 못하는 사람이 만들면 잘 해야 만든 사람 정도 실력 밖에 구현이 안되죠.
반면에 시행착오법은 최적의 룰베이스를 시행착오를 통해서 컴퓨터가 스스로 찾도록 하는 것입니다.
요즈음 신경망 인공지능을 이용해서 퍼지 룰 베이스를 찾아내는 연구가 활발하게 이루어지고 있는 것으로 알고 있습니다.
---------------------------------------------------------------
그러면 실제로 적 캐릭터를 움직이는 함수입니다.
void type_move(void)
{
  byte b, i, j, k ;
  int delta_x, delta_y, bm = 0 ;
  delta_x = character[thunder].x - character[type01].x ;
  delta_y = character[thunder].y - character[type01].y ;
  if ( delta_x > 45 )
    torp_fire(character[type02].x, character[type02].y) ;
  for (b = 0 ; b < MAXNO ; b++)
  {
    if(beam[b].energy==0)
      continue ;
    bm++ ;
  }
  if ( character[type01].energy >= character[thunder].energy )
    i = ATTACK ;
  else if ( bm && abs( delta_x ) < 60 )
    i = RUN ;
    else i = PURSUIT ;
  if (abs(delta_x) < 20)
    bullet_fire(character[type01].x, character[type01].y+5) ;
  switch(character[thunder].dx)
  {
    case -3 :
        j=0 ;
        break ;
    case 0 :
        j=1 ;
        break ;
    case 3 :
        j=2 ;
        break ;
  }
  if ( abs(delta_x) < 5 )
    k = 2 ;
  else if ((delta_x) <= -5 && (delta_x) > -30)
    k = 1 ;
  else if (delta_x <= -30)
    k = 0 ;
  else if ((delta_x) >= 5 && (delta_x) < 30)
    k = 3 ;
  else if (delta_x >= 30)
    k = 4 ;
character[type01].dx = rule_base_x[i][j][k] ;
character[type01].x+ = character[type01].dx ;
  switch(character[thunder].dy)
  {
    case -3 :
        j = 0 ;
        break ;
    case 0 :
        j = 1 ;
        break ;
    case 3 :
        j = 2 ;
        break ;
  }
  if ( abs(delta_y) < 15 )
    k = 2 ;
  else if ((delta_y) <= -15 && (delta_y) > -60)
    k = 1 ;
  else if (delta_y <= -60)
    k = 0 ;
  else if ((delta_y) >= 15 && (delta_y) < 60)
    k = 3 ;
  else if (delta_y >= 60)
    k = 4 ;
  if ( random(5)==0 )
  {
    character[type01].dy = rule_base_y[i][j][k] ;
    character[type01].y+ = character[type01].dy ;
  }
}  
세세 하게 설명 하지 않아도 차근히 살펴 보시면 이해 하 실 수 있을겁니다.
의외로 간단하죠.
마지막에 if ( random(5)==0 ) 으로 한 건 100% 적용하면 제가 도저히 이길 수가 없으므로 y에 대해서는 1/5 만 적용되도록 한 겁니다.
어디 게시판에 보니까 '로드 런너'라는 애플시절의 게임을 아이비엠 용으로 만드는데, 게임의 상황에 따라서 미묘하게 변화하는 적 캐릭터의 동작 속도를 구현하기 어렵다고 하는데, 퍼지를 이용하면 간단하게 될 것 같네요.

출처 : http://pda.actionfilter.com

'Games' 카테고리의 다른 글

Mabinogi Official Opening  (0) 2008.05.26
MStar  (0) 2008.05.26
Hearts and Other Trick-Taking Games  (0) 2008.02.20
Casino Games  (0) 2008.02.20
바카라 게임방법  (1) 2008.02.20