이니셜 B
GNEX 환경에서 개발한 일본 만화 이니셜D를 컨셉으로 하는 장애물 피하기 장르의 모바일 게임
| 구분 | 내용 |
|---|---|
| 플랫폼 | GNEX |
| 개발 도구 및 사용 언어 | GNEX SDK, Mobile C |
| 개발 기간 | 2004년 9월 ~ 2004년 10월 |
1. 프로그램 소개
당시 한창 재미있게 보고 있던 만화 이니셜D를 페러디 하여 만든 종스크롤 장애물 피하기(일명 똥피하기) 게임.
부스터를 적절하게 사용하여 장애물들을 피해 최대한 빠른 시간 내에 목적지에 도달 하면 된다.
조작 방법 설명
- 방향키 : 각 화살표 키 또는 Num2, Num8, Num4, Num6 숫자 버튼
- 확인, 가속 키 : OK키, 또는 Num5 숫자 버튼
플레이어 차량 선택
북악산의 최고속으로 불리우는 AE86 Tureno의 오너 A군과 관악산의 과도한 드리프트라 불리우는 FD3S의 오너 B군이 등장한다.
물론 위 설명은 모두 가상의 설정 이다.
게임 속 등장 인물들은 학과 동기들로써 이 작품 이후 부터 본인의 자작 게임 내에 자주 등장하게 된다.
친구들의 프라이버시를 존중하여 이름과 사진은 모자이크 처리 하였다.
게임 플레이
맞은편에서 오는 차량들을 피하며 목적지 까지 당도하면 된다.
부스트 모드
부스트를 작동하면 가속으로 한 번에 이동하는 거리가 늘어나는 만큼 차량의 제어와 회피가 어려워 진다.
우습게도 적 차량의 이동 속도와 맵 스크롤의 속도 또한 그만큼 증가하기 때문에 당시 친구들로 부터 전혀 쓸데 없는 기능이라는 혹평을 받았다.
게임 오버
마주오는 차량과 부딪치면 게임 오버 된다.
2. 프로그램 구조 개요
전체적으로, while문 안에서 무한 루프를 돌며 루프문 내부에 있는 switch 문에 의해 현재 상태 값에 따라 프로그램 상태가 분기 및 변화하는 구조이다.
이 같은 구조를 기본 골격으로 하여 각각 프로그램의 상태에서 호출되는 함수 내의 하위 로직들로 하여금 게임을 위한 여러 기능들이 수행 되도록 한다.
개략적인 개요는 다음과 같다.
1) 매크로문으로 정의해 놓은 프로그램의 상태값들
1
2
3
4
5
6
7
8
9
10
11
#define PROLOGUE_STATE 1000
#define MENU_STATE 1001
#define PLAYER_SELECTION_STATE 1002
#define GAME_EXPLAIN_STATE 1003
#define CONTROL_EXPLAIN_STATE 1004
#define GAME_STAGE_STATE 1005
#define MAX_STAGE 3
#define FIRST_STAGE 0
#define SECOND_STAGE 1
#define THIRD_STAGE 2
2) 루프문 내에서의 프로그램의 상태 변화
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
while(1)
{
switch(nGame_State) {
case PROLOGUE_STATE :
프롤로그();
break;
case MENU_STATE :
메뉴();
nCurrent_Stage = FIRST_STAGE;
break;
case PLAYER_SELECTION_STATE :
차량선택();
break;
case GAME_EXPLAIN_STATE :
게임설명();
break;
case CONTROL_EXPLAIN_STATE :
키조작법();
break;
case GAME_STAGE_STATE :
게임모드();
break;
}
}
3) 실제 게임의 전체적인 로직
배경 화면인 도로 이미지의 스크롤 작업과 게임 진행 정도의 척도가 되는 거리 값은 각각 독립적으로 구성 되어져 다루어 진다.
이와 관련된 주요 변수들에는 다음과 같은 것들이 있으며 보면 알겠지만 각종 변수나 함수들이 전역으로 선언 되어져 있음에도 굳이 파라미터를 따로 받아 지역 스택 공간을 낭비하는 등의 비효율적인 모습들을 보여준다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
int nCurrent_Stage_Num; //현재 진행중인 스테이지의 번호
int nStage_Distance[MAX_STAGE]; //스테이지별 총 거리 값
int nCurrent_Distance; //게임 진행 정도의 척도가 되는 유저가 현재 까지 이동한 거리
int nUser_Boost_Distance; //부스트 모드시 유저 차량의 추가적인 이동 거리
int nEnemy_Boost_Distance; //부스트 모드시 장애물 차량의 추가적인 이동 거리
int nDefault_Scroll_Unit; //백그라운드의 기본 스크롤 단위
int nBoost_Scroll_Unit; //부스트 모드시 백그라운드의 추가적 스크롤 단위
bool bBoost_Mode; //부스트 모드 사용 유무
bool bGameOver; //게임 오버 유무
bool bStageClear; //스테이지 클리어 유무
struct COORD{
int nX; //좌표 x
int nY;
};
struct CAR{
int nObjectCode; //차량 이미지 번호(ex: 0:유저1, 1:유저2, 2:적1, 3:적2)
COORD nCoord; //차량의 거리상 현재 위치를 나타내는 좌표값
int nDefault_Moving_Distance; //유저가 제어하는 차량 및 장애물 차량의 기본 이동 거리
bool bStageNum[MAX_STAGE];
//출현 스테이지 번호 ex:
//1번 스테이지에 등장 : bStageNum[0] = true;
//2번 스테이지에 등장 : bStageNum[1] = false;
//3번 스테이지에 등장 안함 : bStageNum[2] = true;
COORD nInintCoord[MAX_STAGE]; //스테이지 별 초기 위치 값
};
플레이어와 장애물 차량 오브젝트 선언:
1
2
CAR Player;
CAR Enemies[MAX_ENEMY];
게임내 로직 흐름:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
스테이지_초기화(nCurrent_Stage);
while(1) {
배경화면_스크롤_처리(nDefault_Scroll_Unit + (bBoost_Mode * nBoost_Scroll_Unit));
차량들의_좌표_계산(Enemies); //충돌 체크 및 게임 오버 유무 체크는 이 함수 내부에서 이루어 진다.
현재까지의_누적_이동거리_계산(Player.nDefault_Moving_Distance, nStage_Distance[nCurrent_Stage], &nCurrent_Distance);
차량_이미지_출력();
스테이지_클리어_&_게임오버_처리();
최종_화면_출력();
}
주요 함수 개요:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
스테이지_초기화(int p_nCurrent_Stage)
{
nCurrent_Distance = 0;
bStageClear = false;
bGameOver = false;
Player.nCoord.nX = START_X;
Player.nCoord.nY = START_Y;
for(int cnt = 0; cnt < MAX_ENEMY; cnt++)
{
if(Enemies[cnt].bStageNum[p_nCurrent_Stage]) {
Enemies[cnt].nCoord.nX = Enemies[cnt].nInitCoord[p_nCurrent_Stage].nX;
Enemies[cnt].nCoord.nY = Enemies[cnt].nInitCoord[p_nCurrent_Stage].nY;
}
}
}
배경화면_스크롤_처리(int p_nScroll)
{
배경화면_버퍼에_뿌리기(스크린의_x좌표, 스크린의_y좌표 + p_nScroll);
}
차량들의_좌표_계산(CAR* p_Enemies)
{
for(int cnt = 0; cnt < MAX_ENEMY; cnt++)
{
if(p_Enemies[cnt].bStageNum[p_nCurrent_Stage]) {
p_Enemies[cnt].nCoord.nY -= p_Enemies[cnt].nDefault_Moving_Distance;
if(충돌_체크(&Player, &Enemies[cnt]))
게임오버_세팅();
}
}
}
현재까지의_누적_이동거리_계산(int p_nMoving_Distance, int p_nStage_Distance, int* p_pCurrent_Distance)
{
*p_pCurrent_Distance += p_nMoving_Distance;
if(p_nStage_Distance >= *p_pCurrent_Distance) {
스테이지_클리어_세팅();
}
}
부스트 모드의 구현 개요
부스트 모드의 경우 장애물 차량의 이동 거리와 게임 진행 정도의 척도가 되는 플레이어의 현재 까지의 이동 거리 값과 배경 화면 스크롤 속도 제어를 위한 값을 부스터 모드에 따른 증가 값을 동일하게 적용시켜 증가하는 방식으로 구현 되어 있다.
부스트 작동시 사용 제한 시간은 max 값에서 부터 0값 까지 시간에 따라 순차적으로 차감 되어 지며 부스트의 사용 제한 시간은 비 부스터 모드시에 초당 10%씩 충전 된다.




