こんばんは、夜遅くにごめんなさい。
「ダンジョン自動生成アルゴリズム」の文献は読み漁ったのですが、
コーディングできません。
どなたか、教えていただけませんでしょうか。
ダンジョン自動生成アルゴリズムのコーディング
Re: ダンジョン自動生成アルゴリズムのコーディング
まず,アルゴリズムをここに書いて下さい.
書かないと,アルツハイマーさんが読んだアルゴリズムが何かなんて誰にも分かりません.
書かないと,アルツハイマーさんが読んだアルゴリズムが何かなんて誰にも分かりません.
Re: ダンジョン自動生成アルゴリズムのコーディング
↓最近は、ここのサイトです。↓beatle さんが書きました:まず,アルゴリズムをここに書いて下さい.
書かないと,アルツハイマーさんが読んだアルゴリズムが何かなんて誰にも分かりません.
http://racanhack.sourceforge.jp/rhdoc/index.html
ただ、↑のサイトのコードをいじってみたのですが、
正常に動きません。
※スペースがないのに部屋を作ったり
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: ダンジョン自動生成アルゴリズムのコーディング
今のコード見ないとなんとも言えないのでcodeタグを使って今のコードをここに貼りつけて下さい。投稿前にプレビューで動作を確認した上でお願いします。
http://dixq.net/board/board.html#k10 ← 詳しくはここに。
http://dixq.net/board/board.html#k10 ← 詳しくはここに。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: ダンジョン自動生成アルゴリズムのコーディング
softya(ソフト屋) さんが書きました:今のコード見ないとなんとも言えないのでcodeタグを使って今のコードをここに貼りつけて下さい。投稿前にプレビューで動作を確認した上でお願いします。
http://dixq.net/board/board.html#k10 ← 詳しくはここに。
#include "DxLib.h" //Dxライブラリ ヘッダー
#include "main.h" //main ヘッダー
#include "keyboard.h" //keyboard ヘッダー
#include "graphics.h" //graphics ヘッダー
#include <stdlib.h> //メモリー操作 ヘッダー
#define Rand( min, max ) GetRand( max ) + min ///乱数の範囲取得(int型)
#define WHITE GetColor( 255, 255, 255 ) ///白色の取得
#define MAX_RECT_COUNT 4 ///区間の最大数
#define MIN_RECT_SIZE 8 ///区間の最小サイズ
#define MIN_ROOM_SIZE 4 ///部屋の最小サイズ
#define MAP_WIDTH 50 ///マップの幅
#define MAP_HEIGHT 50 ///マップの高
int map[ MAP_WIDTH ][ MAP_HEIGHT ]; ///マップ配列
typedef struct{
int x, y, w, h;
} s_room; ///部屋の構造体 定義
typedef struct {
int x, y, w, h;
s_room room;
} s_rect; ///区間の構造体 定義
int roomCount = 0; ///部屋リスト数
s_room *room_list = NULL; ///部屋リスト
int rectCount = 0; ///区間リスト数
s_rect *rect_list = NULL; ///区間リスト
//部屋リストに追加
void roomList_append(s_room room)
{
roomCount++;
room_list = (s_room *)realloc( room_list, sizeof( s_room ) * roomCount );
room_list[ roomCount - 1 ].x = room.x;
room_list[ roomCount - 1 ].y = room.y;
room_list[ roomCount - 1 ].w = room.w;
room_list[ roomCount - 1 ].h = room.h;
}
//部屋の追加
s_room room_add( int x, int y, int w, int h )
{
s_room room;
room.x = x;
room.y = y;
room.w = w;
room.h = h;
roomList_append(room);
return room;
}
//部屋の生成
void room_make( )
{
s_rect rect; ///参照用
int x, y, w, h; ///結果用
for( int i = 0; i < rectCount; i++ )
{
rect = rect_list[ i ];
w = Rand( MIN_ROOM_SIZE, rect.w - 3 );
h = Rand( MIN_ROOM_SIZE, rect.h - 3 );
x = Rand( rect.x + 2, rect.x + rect.w - w - 1 );
y = Rand( rect.y + 2, rect.y + rect.h - h - 1 );
rect_list[ i ].room = room_add( x, y, w, h );
}
}
//区間リストに追加
void rectList_append(s_rect rect)
{
rectCount++;
rect_list = (s_rect *)realloc( rect_list, sizeof( s_rect ) * rectCount );
rect_list[ rectCount - 1 ].x = rect.x;
rect_list[ rectCount - 1 ].y = rect.y;
rect_list[ rectCount - 1 ].w = rect.w;
rect_list[ rectCount - 1 ].h = rect.h;
}
//区間の追加
s_rect rect_add( int x, int y, int w, int h )
{
s_rect rect;
rect.x = x;
rect.y = y;
rect.w = w;
rect.h = h;
rectList_append(rect);
return rect;
}
//区間の生成
void rect_split( s_rect rect_parent )
{
s_rect rect_child;
if( ( rect_parent.h <= MIN_RECT_SIZE * 2 ) ||
( rect_parent.w <= MIN_RECT_SIZE * 2 ) ||
rectCount > MAX_RECT_COUNT)
return;
rect_child = rect_add( rect_parent.x, rect_parent.y, rect_parent.w, rect_parent.h );
int split_coord;
if( Rand( 0, 2 ) == 0 ){
split_coord = Rand( rect_parent.y + MIN_RECT_SIZE, rect_parent.y + rect_parent.h - MIN_RECT_SIZE );
rect_parent.h = split_coord - rect_parent.y;
rect_child.y = split_coord;
rect_split( rect_parent );
rect_split( rect_child );
return;
} else{
split_coord = Rand( rect_parent.x + MIN_RECT_SIZE, rect_parent.x + rect_parent.w - MIN_RECT_SIZE );
rect_parent.w = split_coord - rect_parent.x;
rect_child.x = split_coord;
rect_split( rect_parent );
rect_split( rect_child );
return;
}
}
//マップの生成
void mapCreate( void )
{
int i, j, k;
for ( j = 0; j < MAP_HEIGHT; j++)
for ( i = 0; i < MAP_WIDTH; i++)
map[ i ][ j ] = -1;
rect_list = NULL;
room_list = NULL;
rect_split( rect_add( 0, 0, MAP_WIDTH - 1, MAP_HEIGHT - 1 ) );
// rect_add( 0, 0, MAP_WIDTH - 1, MAP_HEIGHT - 1 );
// room_make( );
s_rect rect;
s_room room;
for( k = 0; k < rectCount; k++ ) {
rect = rect_list[ k ];
for ( i = rect.x, j = rect.y; i <= rect.x + rect.w; i++ ) map[ i ][ j ] = -2;
for ( i = rect.x, j = rect.y + rect.h; i <= rect.x + rect.w; i++) map[ i ][ j ] = -2;
for ( i = rect.x, j = rect.y; j <= rect.y + rect.h; j++) map[ i ][ j ] = -2;
for ( i = rect.x + rect.w, j = rect.y; j <= rect.y + rect.h; j++) map[ i ][ j ] = -2;
room = rect.room;
for ( i = room.x; i <= room.x + room.w; i++ )
for ( j = room.y; j <= room.y + room.h; j++ )
map[ i ][ j ] = 0;
}
// for( k = 0; k < roomCount; k++ ) {
// room = room_list[ k ];
// for ( i = room.x; i <= room.x + room.w; i++ )
// for ( j = room.y; j <= room.y + room.h; j++ )
// map[ i ][ j ] = 0;
// }
}
int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int ){
//ゲームの初期化
MainInit( ); ///メインゲームの初期化
GraphicsInit( ); ///グラフィックの初期化
int l_fontHandle = CreateFontToHandle( "MS ゴシック", 15, -1 );
mapCreate( );
//ゲームの初期化
//メインループ
while( MainLoopCheck( ) ){ ///メインループチェック
for ( int j = 0; j < MAP_HEIGHT; j++)
for ( int i = 0; i < MAP_WIDTH; i++){
if ( map[ i ][ j ] == -1 )
DrawStringToHandle( 15 * i, 15 * j, "■", WHITE,l_fontHandle );
else if ( map[ i ][ j ] == -2 )
DrawStringToHandle( 15 * i, 15 * j, "区", WHITE,l_fontHandle );
else if ( map[ i ][ j ] == 0 )
DrawStringToHandle( 15 * i, 15 * j, "床", WHITE,l_fontHandle );
}
}
//メインループ
//ゲームの終了処理
GraphicsEnd( ); ///グラフィックの終了処理
MainEnd( ); ///メインゲームの終了処理
//ゲームの終了処理
return 0;
}
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: ダンジョン自動生成アルゴリズムのコーディング
すいません。他の部分もないと動かないので他の部分もお願いします。
出来ればダンジョン生成部分にはコメントをお願いします。追いかけるのが結構辛いです。
出来ればダンジョン生成部分にはコメントをお願いします。追いかけるのが結構辛いです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
Re: ダンジョン自動生成アルゴリズムのコーディング
#include "DxLib.h" //Dxライブラリ ヘッダー
#include <stdlib.h> //メモリー操作 ヘッダー
#define Rand( min, max ) GetRand( max ) + min ///乱数の範囲取得(int型)
#define WHITE GetColor( 255, 255, 255 ) ///白色の取得
#define MAX_RECT_COUNT 4 ///区間の最大数
#define MIN_RECT_SIZE 8 ///区間の最小サイズ
#define MIN_ROOM_SIZE 4 ///部屋の最小サイズ
#define MAP_WIDTH 50 ///マップの幅
#define MAP_HEIGHT 50 ///マップの高
int map[ MAP_WIDTH ][ MAP_HEIGHT ]; ///マップ配列
typedef struct{
int x, y, w, h;
} s_room; ///部屋の構造体 定義
typedef struct {
int x, y, w, h;
s_room room;
} s_rect; ///区間の構造体 定義
int roomCount = 0; ///部屋リスト数
s_room *room_list = NULL; ///部屋リスト
int rectCount = 0; ///区間リスト数
s_rect *rect_list = NULL; ///区間リスト
//関数 メインループ継続のチェック
bool MainLoopCheck( void ){
//裏画面を表画面に反映, メッセージ処理, 画面クリア
return ScreenFlip( ) == 0 && ProcessMessage( ) == 0 && ClearDrawScreen( ) == 0;
}
//部屋リストに追加
void roomList_append(s_room room)
{
roomCount++;
room_list = (s_room *)realloc( room_list, sizeof( s_room ) * roomCount );
room_list[ roomCount - 1 ].x = room.x;
room_list[ roomCount - 1 ].y = room.y;
room_list[ roomCount - 1 ].w = room.w;
room_list[ roomCount - 1 ].h = room.h;
}
//部屋の追加
s_room room_add( int x, int y, int w, int h )
{
s_room room;
room.x = x;
room.y = y;
room.w = w;
room.h = h;
roomList_append(room);
return room;
}
//部屋の生成
void room_make( )
{
s_rect rect; ///参照用
int x, y, w, h; ///結果用
for( int i = 0; i < rectCount; i++ )
{
rect = rect_list[ i ];
w = Rand( MIN_ROOM_SIZE, rect.w - 3 );
h = Rand( MIN_ROOM_SIZE, rect.h - 3 );
x = Rand( rect.x + 2, rect.x + rect.w - w - 1 );
y = Rand( rect.y + 2, rect.y + rect.h - h - 1 );
rect_list[ i ].room = room_add( x, y, w, h );
}
}
//区間リストに追加
void rectList_append(s_rect rect)
{
rectCount++;
rect_list = (s_rect *)realloc( rect_list, sizeof( s_rect ) * rectCount );
rect_list[ rectCount - 1 ].x = rect.x;
rect_list[ rectCount - 1 ].y = rect.y;
rect_list[ rectCount - 1 ].w = rect.w;
rect_list[ rectCount - 1 ].h = rect.h;
}
//区間の追加
s_rect rect_add( int x, int y, int w, int h )
{
s_rect rect;
rect.x = x;
rect.y = y;
rect.w = w;
rect.h = h;
rectList_append(rect);
return rect;
}
//区間の生成
void rect_split( s_rect rect_parent )
{
s_rect rect_child;
//生成中止条件
if( ( rect_parent.h <= MIN_RECT_SIZE * 2 ) || //y軸方向のサイズが最小区間サイズの2倍以下
( rect_parent.w <= MIN_RECT_SIZE * 2 ) || //x軸方向のサイズが最小区間サイズの2倍以下
rectCount > MAX_RECT_COUNT) //区間データ数が最大数よりおおきい
return;
//区間(子)の生成
rect_child = rect_add( rect_parent.x, rect_parent.y, rect_parent.w, rect_parent.h );
//分割点
int split_coord;
if( Rand( 0, 2 ) == 0 ){
//縦の分割
split_coord = Rand( rect_parent.y + MIN_RECT_SIZE, rect_parent.y + rect_parent.h - MIN_RECT_SIZE );
rect_parent.h = split_coord - rect_parent.y;
rect_child.y = split_coord;
rect_split( rect_parent );
rect_split( rect_child );
return;
} else{
//横の分割
split_coord = Rand( rect_parent.x + MIN_RECT_SIZE, rect_parent.x + rect_parent.w - MIN_RECT_SIZE );
rect_parent.w = split_coord - rect_parent.x;
rect_child.x = split_coord;
rect_split( rect_parent );
rect_split( rect_child );
return;
}
}
//マップの生成
void mapCreate( void )
{
int i, j, k;
//マップの初期化
for ( j = 0; j < MAP_HEIGHT; j++)
for ( i = 0; i < MAP_WIDTH; i++)
map[ i ][ j ] = -1;
rect_list = NULL;
room_list = NULL;
//区間の生成
rect_split( rect_add( 0, 0, MAP_WIDTH - 1, MAP_HEIGHT - 1 ) );
// rect_add( 0, 0, MAP_WIDTH - 1, MAP_HEIGHT - 1 );
//部屋の生成
room_make( );
s_rect rect;
s_room room;
//描画のための処理
for( k = 0; k < rectCount; k++ ) {
rect = rect_list[ k ];
//「区」の処理
for ( i = rect.x, j = rect.y; i <= rect.x + rect.w; i++ ) map[ i ][ j ] = -2;
for ( i = rect.x, j = rect.y + rect.h; i <= rect.x + rect.w; i++) map[ i ][ j ] = -2;
for ( i = rect.x, j = rect.y; j <= rect.y + rect.h; j++) map[ i ][ j ] = -2;
for ( i = rect.x + rect.w, j = rect.y; j <= rect.y + rect.h; j++) map[ i ][ j ] = -2;
room = rect.room;
//「床」の処理
for ( i = room.x; i <= room.x + room.w; i++ )
for ( j = room.y; j <= room.y + room.h; j++ )
map[ i ][ j ] = 0;
}
}
int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int ){
//ゲームの初期化
ChangeWindowMode( TRUE ); //TRUE・・・ウィンドウモード FALSE・・・フルスクリーン
SetGraphMode( 1024 , 768, 16 ); //1024×768のサイズで解像度16bitに設定
DxLib_Init( ); //DXライブラリ初期化
SetDrawScreen( DX_SCREEN_BACK ); //描画先を裏画面に設定
int l_fontHandle = CreateFontToHandle( "MS ゴシック", 15, -1 );
mapCreate( );
//ゲームの初期化
//メインループ
while( MainLoopCheck( ) ){ ///メインループチェック
for ( int j = 0; j < MAP_HEIGHT; j++)
for ( int i = 0; i < MAP_WIDTH; i++){
if ( map[ i ][ j ] == -1 )
DrawStringToHandle( 15 * i, 15 * j, "■", WHITE,l_fontHandle );
else if ( map[ i ][ j ] == -2 )
DrawStringToHandle( 15 * i, 15 * j, "区", WHITE,l_fontHandle );
else if ( map[ i ][ j ] == 0 )
DrawStringToHandle( 15 * i, 15 * j, "床", WHITE,l_fontHandle );
}
}
//メインループ
//ゲームの終了処理
DxLib_End( ); //DXライブラリ終了
//ゲームの終了処理
return 0;
}
Re: ダンジョン自動生成アルゴリズムのコーディング
添付されたプログラムを実行してみました。
わかりやすいように色をつけましたが。
うまくいかないのはどの部分ですか?
床は、わかるけど、■と区はどういう意味ですか?
わかりやすいように色をつけましたが。
うまくいかないのはどの部分ですか?
床は、わかるけど、■と区はどういう意味ですか?
non
Re: ダンジョン自動生成アルゴリズムのコーディング
返事がいただけないので、自分でプログラムを読みました。
特に、w,hの考え方がオリジナルと違っており、その考え方ではマズイのではないだろうかと思います。
特に、w,hの考え方がオリジナルと違っており、その考え方ではマズイのではないだろうかと思います。
non
Re: ダンジョン自動生成アルゴリズムのコーディング
では、オリジナルに沿って作ってみようと思います。non さんが書きました:返事がいただけないので、自分でプログラムを読みました。
特に、w,hの考え方がオリジナルと違っており、その考え方ではマズイのではないだろうかと思います。
Re: ダンジョン自動生成アルゴリズムのコーディング
再帰呼び出しにおける構造体の引数も、ポインタ渡しでないとマズイです。
#define Rand( min, max ) GetRand( max ) + min
これもマズイです。
#define Rand( min, max ) GetRand( max ) + min
これもマズイです。
non