Rogue系のゲームを目指して

アバター
大白定義
記事: 14
登録日時: 14年前
住所: 三重県

Rogue系のゲームを目指して

投稿記事 by 大白定義 » 14年前

Rogueというゲームをご存知でしょうか。
1981年に公開された歴史の古いゲームです。

どんなゲームか? というと、トルネコとか風来のシレンっぽいゲームと言うとピンと来る人がいると思います。
まぁ、トルネコや風来のシレンがローグライクゲーム(Rogue-Like Game)と言うように、Rogueは不思議なダンジョンシリーズなどの元ネタとも言えるゲームです。

最近、このRogueから派生したゲームであるNetHackというゲームをiPhoneで始めました。(Rogueもあるんですけどね)
で、まだ4階くらいで死ぬのですが、このゲームをやっていて、「俺もこういうゲームを作ってみたい」と思うようになりました。
前回の記事はそのための第一歩だったりします。

で、今回の進捗報告。
・ソースを書くのをTeraPadからVisual C++ 2008に変更(強制終了の理由が分からなかったため)
・ダンジョン分割処理が完成
・分割された領域それぞれの左上の座標と右下の座標を取得する処理が完成

気力が続く限りはこの処理の進捗報告を日記でやっていけたらな、と。

流石に時間があまり無いのでダンジョン自動生成だけでも年内に完成させたい所。

(こっそり追記)
とりあえず部屋を作る処理がほぼできたので載せてみます。

CODE:

#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;
}
実行結果

CODE:

..................#......................
...######.........#......................
...######.........#...###########........
...######.........#...###########........
...######.........#...###########........
...######.........#...###########........
...######.........#...###########........
...######.........#...###########........
..................#......................
..................#......................
#########################################
..................#......................
..................#...#############......
..................#...#############......
..................#...#############......
..................#...#############......
..................#...#############......
..................#...#############......
......########....#...#############......
......########....#......................
......########....#......................
......########....#......................
......########....#......................
......########....#......................
..................#......................
..................#......................
..................#......................
最後に編集したユーザー 大白定義 on 2010年12月18日(土) 22:37 [ 編集 1 回目 ]

ISLe
記事: 2650
登録日時: 14年前

Re: Rogue系のゲームを目指して

投稿記事 by ISLe » 14年前

ローグ(クローン)やネットハックはソースが公開されてますよ。
むかしは自分でコンパイルして遊ぶものでしたから。

アバター
大白定義
記事: 14
登録日時: 14年前
住所: 三重県

Re: Rogue系のゲームを目指して

投稿記事 by 大白定義 » 14年前

ローグの方は公開されていたが公開停止したと聞いて諦めていたのですが、改めて探してみるとあっさり見つかりました。
まだmain.cをさらっと読んだだけですが、自分でも読める部分があってなんだか感慨深いです。

自分でコンパイルして遊ぶというのは初耳です。
そこから、ユーザーが自分好みに弄ったりして言った結果、派生した作品ができていった、という感じなんですかねぇ。

ああ
記事: 49
登録日時: 14年前

Re: Rogue系のゲームを目指して

投稿記事 by ああ » 14年前

これは期待が高まりますね!

完成目指して頑張って下さい!!

ISLe
記事: 2650
登録日時: 14年前

Re: Rogue系のゲームを目指して

投稿記事 by ISLe » 14年前

大白定義 さんが書きました:自分でコンパイルして遊ぶというのは初耳です。
いまのCPUはインテルアーキテクチャ一色ですが、むかしはモトローラというライバルがいました。
インテルはリトルエンディアンでモトローラはビッグエンディアンなどまるで違うのでひとつのバイナリで済まないのです。
バイナリをネットで送信しようと思ったら何時間もかかってましたし。
大白定義 さんが書きました:そこから、ユーザーが自分好みに弄ったりして言った結果、派生した作品ができていった、という感じなんですかねぇ。
自分の環境で動くようにソースファイルを改変するのが当たり前でしたし、著作権に対する意識も緩かったですね。
必然的にフリーソフトウェアや、完全に著作権を放棄したPDS(パブリックドメインソフトウェア)になってしまう感じですね。

アバター
大白定義
記事: 14
登録日時: 14年前
住所: 三重県

RE: Rogue系のゲームを目指して

投稿記事 by 大白定義 » 14年前

>NNKさん
飽きない程度に全力で頑張ります。
大体デカいこと言って、大失敗して爆発するのが俺なんですけどねw

>ISLeさん
ISLe さんが書きました:自分の環境で動くようにソースファイルを改変するのが当たり前でしたし、著作権に対する意識も緩かったですね。
今こそPCは一般向けですけど、当時はネットワークも未発達でしたし、PCは技術者向けだったから、
ソースファイル弄るのもできて当然(?)だった、という感じなんですかね。
なんと言いますか、時代を感じます。

ISLe
記事: 2650
登録日時: 14年前

RE: Rogue系のゲームを目指して

投稿記事 by ISLe » 14年前

大白定義 さんが書きました:ソースファイル弄るのもできて当然(?)だった、という感じなんですかね。
ハードウェアやOSの仕様が統一されてなかったのでコンパイルできてもきちんと動かないことがよくありました。
できて当然と言えばそうなんですが、できなければ動かせないので頑張って弄ってたわけです。