1981年に公開された歴史の古いゲームです。
どんなゲームか? というと、トルネコとか風来のシレンっぽいゲームと言うとピンと来る人がいると思います。
まぁ、トルネコや風来のシレンがローグライクゲーム(Rogue-Like Game)と言うように、Rogueは不思議なダンジョンシリーズなどの元ネタとも言えるゲームです。
最近、このRogueから派生したゲームであるNetHackというゲームをiPhoneで始めました。(Rogueもあるんですけどね)
で、まだ4階くらいで死ぬのですが、このゲームをやっていて、「俺もこういうゲームを作ってみたい」と思うようになりました。
前回の記事はそのための第一歩だったりします。
で、今回の進捗報告。
・ソースを書くのをTeraPadからVisual C++ 2008に変更(強制終了の理由が分からなかったため)
・ダンジョン分割処理が完成
・分割された領域それぞれの左上の座標と右下の座標を取得する処理が完成
気力が続く限りはこの処理の進捗報告を日記でやっていけたらな、と。
流石に時間があまり無いのでダンジョン自動生成だけでも年内に完成させたい所。
(こっそり追記)
とりあえず部屋を作る処理がほぼできたので載せてみます。
#include
#include
#include
#define MAP_MIN_SIZE_X 20
#define MAP_MAX_SIZE_X 30
#define MAP_MIN_SIZE_Y (MAP_MIN_SIZE_X * 2)
#define MAP_MAX_SIZE_Y (MAP_MAX_SIZE_X * 2)
#define DIVISOR_MIN_NUM 1
#define DIVISOR_MAX_NUM 3
#define DIVISOR_MIN_SIZE 7
#define ROOM_MAX_SIZE 5
struct field_data{
int kind; //マスの種類(壁か、否か等)
int flag; //プレイヤーが存在しているかどうか
};
struct map_data{
struct field_data *field; //フィールドの領域
int size; //サイズ
int width; //横幅
int height; //縦幅
};
//動的に確保した配列の位置を算出する
int getArrayNum(int width, int x, int y){
return x + (y * width);
}
//範囲を限定した乱数を生成する
int getRandomRange(int min, int max){
if((max - min) == 0) return max;
else return rand() % (max - min) + min;
}
//範囲を限定した、指定した以上の差がある乱数を生成する
int getRandomRangeDiff(int sample, int dif, int min, int max){
int x;
if(max-min == dif) return max;
do{
x = getRandomRange(min, max);
printf("max %d min %d\n", max, min);
printf("%d - %d = %d\n", sample, x, x-sample);
if(max-min height;
y1 = left_up / map->height;
x2 = right_down % map->height;
y2 = right_down / map->height;
//塗りつぶし開始
for(i = left_up; i height;
y3 = i / map->height;
//始点より斜め下で終点より斜め上なら塗る
if(x3 = x1){
if(y3 = y1){
map->field[i].kind = 1;
}
}
}
}
//部屋の生成
void makeRoom(struct map_data *map, int div_num_ver, int div_num_hor, int div_place_ver[], int div_place_hor[]){
int i, j, k;
int x1, y1, x2, y2, x3, y3;
//部屋の定義
struct room_data{
int left_up; //部屋の右上の座標
int right_down; //部屋の左下の座標
} *div_room, *set_room;
//分割した部屋の数を得る
int div_size = (div_num_ver+1) * (div_num_hor+1);
//分割した領域を部屋として扱う
div_room = (struct room_data *)malloc(sizeof(struct room_data) * div_size);
//セットする部屋
set_room = (struct room_data *)malloc(sizeof(struct room_data) * div_size);
//分割した領域の左上と右下の座標を獲得
k = 0;
for(i = 0; i height, x1, y1);
if(i == div_num_ver) y1 = map->width - 1;
else y1 = div_place_ver[i] - 1;
if(j == div_num_hor) x1 = map->height - 1;
else x1 = div_place_hor[j] - 1;
div_room[k].right_down = getArrayNum(map->height, x1, y1);
k++;
}
}
//各領域の一部から、部屋の始点と終点をランダムで決める
k = 0;
for(i = 0; i height;
y1 = div_room[i].left_up / map->height;
x2 = div_room[i].right_down % map->height;
y2 = div_room[i].right_down / map->height;
//ランダムで部屋となる領域の始点を決定
x3 = getRandomRange(x1 + 1, x2 - (ROOM_MAX_SIZE+1));
y3 = getRandomRange(y1 + 1, y2 - (ROOM_MAX_SIZE+1));
set_room[k].left_up = getArrayNum(map->height, x3, y3);
//ランダムで部屋となる領域の終点を決定
x3 = getRandomRange((set_room[k].left_up % map->height) + ROOM_MAX_SIZE, x2 - 1);
y3 = getRandomRange((set_room[k].left_up / map->height) + ROOM_MAX_SIZE, y2 - 1);
set_room[k].right_down = getArrayNum(map->height, x3, y3);
k++;
}
//塗りつぶし処理
for(i = 0; i width / 2; //縦
int half_size_hor = map->height / 2; //横
int i, j; //ループ変数
int buf; //記憶用
for(i=0,buf=0; i width - buf) / 2);
}
for(i=0,buf=0; i height - buf) / 2);
}
//分割された場所を壁にする
for(i=0; i size; i++){
//iと縦の長さの余りがx座標になる
buf = i % map->height;
for(j=0; j field[i].kind = 1;
}
}
//iと縦の高さを割った数がy座標になる
buf = i / map->height;
for(j=0; j field[i].kind = 1;
}
}
}
//部屋作成処理に飛ぶ
makeRoom(map, div_num_ver, div_num_hor, div_place_ver, div_place_hor);
//動的に取得した部分の開放
free(div_place_ver);
free(div_place_hor);
}
//フィールドの初期化
void initField(struct map_data *map){
int i;
for(i=0; i size; i++){
map->field[i].kind = 0;
map->field[i].flag = 0;
}
}
//フィールドの表示。rogueっぽく
void drawField(struct map_data *map){
int i;
for(i=0; i size; i++){
switch(map->field[i].kind){
case 0:
printf(".");
break;
case 1:
printf("#");
break;
default:
printf("%d",map->field[i].kind);
break;
}
if(i % map->height == map->height - 1) printf("\n");
}
}
int main(void){
//ダンジョンデータの宣言
struct map_data map;
//乱数の初期化
srand((unsigned int)time(NULL));
//フィールドのサイズを乱数で生成
map.height = getRandomRange(MAP_MIN_SIZE_Y, MAP_MAX_SIZE_Y);
map.width = getRandomRange(MAP_MIN_SIZE_X, MAP_MAX_SIZE_X);
map.size = map.width * map.height;
//フィールドの領域を取得
map.field = (struct field_data *)malloc(sizeof(struct field_data) * map.size);
//フィールドを初期化
initField(&map);
setDivision(&map);
//フィールドを描画
drawField(&map);
//フィールドを開放
free(map.field);
//入力待ちにすることで結果を確認できるようにする
getchar();
return 0;
}
..................#......................
...######.........#......................
...######.........#...###########........
...######.........#...###########........
...######.........#...###########........
...######.........#...###########........
...######.........#...###########........
...######.........#...###########........
..................#......................
..................#......................
#########################################
..................#......................
..................#...#############......
..................#...#############......
..................#...#############......
..................#...#############......
..................#...#############......
..................#...#############......
......########....#...#############......
......########....#......................
......########....#......................
......########....#......................
......########....#......................
......########....#......................
..................#......................
..................#......................
..................#......................