提示コードはダンジョンマップ生成アルゴリズムなのですが参考サイトよりステージを縦横に分割する処理を実装しているのですが乱数のばらまきをもう少し調整したいのですがこの場合どうやって調整するべきなのでしょうか?現状だと提示画像のように6回分割を行っており5以上でエリアの最大値より5小さいという制限をかけて乱数を取得していますが提示画像のように乱数の値がバラバラすぎて区画が大きいのと小さいのとで不揃いになってしまいます。どう調整すればまんべんなく区画を生成できるのでしょうか?
Generate_Dungeon.cpp
ソースファイルのvoid Generate_Dungeon::SetLine_X(int posY)
関数部ですがvoid Generate_Dungeon::setGenerate()
関数で乱数を設定しています。
参考サイト:http://rainbowvortex.blog.fc2.com/blog-entry-127.html
Generate_Dungeon.cpp
cpp
#include "../header/Generate_Dungeon.hpp" #include "../../FrameWork/header/FrameWork.hpp" #include <glm/glm.hpp> // ##################################### コンストラクタ ##################################### Generate_Dungeon::Generate_Dungeon(glm::ivec2 s,glm::ivec2 div = glm::ivec2(0,0)) { setDivisionNum_X(div.x); setDivisionNum_Y(div.y); //printf("%d\n",s.y); allSize = s; stage.resize(s.x * s.y); area.resize(0); area.push_back(Area { s.x * s.y,glm::ivec2(0,0),s }); } // ##################################### ステージ再設定 ##################################### void Generate_Dungeon::setReSetStage(glm::ivec2 s,glm::ivec2 div) { setDivisionNum_X(div.x); setDivisionNum_Y(div.y); allSize = s; stage.resize(s.x * s.y); area.resize(0); area.push_back(Area { s.x * s.y,glm::ivec2(0,0),s }); } // ##################################### 一番大きいエリアを削除 ##################################### void Generate_Dungeon::DeleteMaxArea() { Area map = Area{0,glm::ivec2(0,0),glm::ivec2(allSize.x,allSize.y)}; int i = 0; int num = -1; for(std::vector<Area>::iterator itr = area.begin(); itr != area.end(); itr++) { if(map.size < itr->size) { map = *itr; num = i; // std::cout<<map.size<<std::endl; } i++; } if(num != -1) { area.erase(area.begin() + num); } else { std::cout<< "Error: 削除するエリアがありません。"<<std::endl; } } // ##################################### 一番大きいエリアを取得 ##################################### Generate_Dungeon::Area Generate_Dungeon::GetMaxArea() { Area map = Area{0,glm::ivec2(0,0),glm::ivec2(0,0)}; for(std::vector<Area>::iterator itr = area.begin(); itr != area.end(); itr++) { if(map.size < itr->size) { map = *itr; std::cout<<" map.start.y: " << map.start.y<<std::endl; // std::cout<<map.size<<std::endl; } // std::cout<<" map.start.y: " << map.start.y<<std::endl; } std::cout<<"return map.start.y: " << map.start.y<<std::endl; // std::cout<<std::endl; // std::cout<<std::endl; // std::cout<<std::endl; return map; } // ##################################### エリアに値を設定 ##################################### void Generate_Dungeon::SetArea(glm::ivec2 start,glm::ivec2 size,byte b) { for(int y = start.y; y < start.y + size.y; y++) { for(int x = start.x; x < start.x + size.x; x++) { // std::cout<<((y * allSize.x) + x)<<std::endl; stage.at((y * allSize.x) + x) = b; } } } // ##################################### X軸からYの長さを取得 ##################################### /* 説明 マス目の数を返す */ int Generate_Dungeon::GetCheckLine_Y(glm::ivec2 start,int posX) { //std::cout<<( (allSize.x * start.y) + start.x + posX - 1)<<std::endl; byte b = stage.at( (allSize.x * start.y) + start.x + posX); int y = 0; for(int i = start.y; i < allSize.y; i++) { //std::cout<<( (allSize.x * i + start.x) + posX)<<std::endl; if(stage.at( (allSize.x * i + start.x) + posX) != b) { return y; } y++; } return y; } // ##################################### Y軸からXの長さを取得 ##################################### int Generate_Dungeon::GetCheckLine_X(glm::ivec2 start,int posY) { //std::cout<<"aaaaaaa "<< (allSize.x * (start.y + posY) ) + start.x -1 <<std::endl; byte b = stage.at( (allSize.x * (start.y + posY) ) + start.x - 1); int x = 0; for(int i = start.x; i < allSize.x; i++) { // std::cout<<(allSize.x * posY) + i<<std::endl; if(stage.at( (allSize.x * posY) + i) != b) { return x; } x++; } return x; } // ##################################### ステージに値を設定 ##################################### void Generate_Dungeon::SetStage(glm::ivec2 start,glm::ivec2 pos,byte b) { stage.at((allSize.x * (pos.y + start.y)) + pos.x + start.x) = b; } // ##################################### ステージに値を取得 ##################################### byte Generate_Dungeon::GetStage(glm::ivec2 start,glm::ivec2 pos) { return stage.at((allSize.x * (pos.y + start.y)) + pos.x + start.x); } // ##################################### X軸に分割ラインを引く ##################################### void Generate_Dungeon::SetLine_X(int posY) { // std::cout<<"posY: " << posY<<std::endl; Area map = GetMaxArea(); //一番大きいエリアを取得 DeleteMaxArea(); //一番大きいエリアを削除 // printf("allSize.y: %d\n",posY); int rangeX = GetCheckLine_X(map.start,posY); //X軸のマス目の個数を取得 SetArea(map.start,glm::ivec2(rangeX,posY),flag); //範囲に値を設定 glm::ivec2 s = glm::ivec2(map.end.y - map.start.y,map.end.x - map.start.x); area.push_back(Area{ rangeX * posY,map.start,glm::ivec2(map.start.x + rangeX,map.start.y + posY) }); //エリアを追加 flag++; // std::cout<<"posY: " << posY<<std::endl; int y = GetCheckLine_Y(map.start + glm::ivec2(0,posY),0); //乱数のY軸から範囲の下までの個数を得る std::cout<<"posY: " << posY<<std::endl; std::cout<<"y: " << y<<std::endl; // std::cout<< (map.start + glm::ivec2(rangeX,posY)).x<<std::endl; // std::cout<< (map.start + glm::ivec2(rangeX,posY)).y<<std::endl; SetArea(map.start + glm::ivec2(0,posY),glm::ivec2(rangeX,y),flag); //範囲に値を設定 area.push_back(Area{ s.x * s.y,map.start + glm::ivec2(0,posY),glm::ivec2(map.start.x + rangeX,map.start.y + posY + y - 1) }); //エリアを追加 std::cout<<"map.start.y + posY + y - 1: " << map.start.y + posY + y - 1<<std::endl; //std::cout<<allSize.y<<std::endl; //std::cout<<GetMaxArea().end.y <<std::endl; //std::cout<<GetMaxArea().start.x <<std::endl; flag++; } // ##################################### Y軸に分割ラインを引く ##################################### void Generate_Dungeon::SetLine_Y(int pos) { } // ##################################### ステージを生成 ##################################### void Generate_Dungeon::setGenerate() { //std::cout<<divsion_X<<std::endl; for(int i = 0; i< 6; i++) { Area map = GetMaxArea(); //std::cout<<"map.end.y: " <<map.end.y<<std::endl; //std::cout<<"map.end.X: " <<map.end.x<<std::endl; // std::cout<<map.end.y - map.start.y<<std::endl; //printf("random : %d\n",map.end.y - map.start.y); std::cout<<map.end.y - map.start.y - 5 - 1<<std::endl; if(map.end.y - map.start.y - 5 - 1 < 5) { break; } //std::cout<<map.end.y - map.start.y - 5<<std::endl; //std::cout<<"random: "<< FrameWork::GetRandom(5,map.end.y - map.start.y - 5)<<std::endl; int rand = FrameWork::GetRandom(5,map.end.y - map.start.y - 5 - 1); std::cout<<"Random: "<<rand<<std::endl; SetLine_X(rand); //SetLine_X(29 - 1); //printf("aaaaa\n"); // flag++; /* for(int i = 0; i< divsion_Y; i++) { } */ //SetLine_Y(FrameWork::GetRandom(10,allSize.X)); } }
#####Stage.cpp
cpp
// ##################################### コンストラクタ ##################################### Stage::Stage() { stage.resize( (int)(FrameWork::GetCurrentWindow()->getSize().x / 24) * (int)(FrameWork::GetCurrentWindow()->getSize().y / 24) ); std::fill(stage.begin(),stage.end(),(byte)0x00); sprite = FrameWork::LoadTexture("asset/texture/brickChip.png"); dungeon = std::make_shared<Generate_Dungeon>(glm::ivec2((FrameWork::GetCurrentWindow()->getSize().x / 24),(FrameWork::GetCurrentWindow()->getSize().y / 24)),glm::ivec2(3,3)); dungeon->setGenerate(); //printf("aaaa\n"); stage = dungeon->getStage(); int xNum = (int)(FrameWork::GetCurrentWindow()->getSize().x / 24); int yNum = (int)(FrameWork::GetCurrentWindow()->getSize().y / 24); //std::cout<<"X: " << xNum<<std::endl; //std::cout<<"Y: " << yNum<<std::endl; //std::cout<<"Y * X: " << yNum * xNum<<std::endl; for(int i = 0; i< yNum; i++) { for(int j = 0; j < xNum; j++) { switch(stage.at(xNum * i + j)) { case 0x00: { printf("*"); } break; case 0x01: { printf("A"); } break; case 0x02: { printf("B"); } break; // 文字数の関係で省略 } } printf("\n"); } }
FrameWork::GetRandom
cpp
// ##################################### 乱数 取得 ##################################### int FrameWork::GetRandom(int start, int end) { std::random_device rnd; // 非決定的な乱数生成器を生成 std::mt19937 mt(rnd()); // メルセンヌ・ツイスタの32ビット版、引数は初期シード値 std::uniform_int_distribution<> Rand(start, end); // [start, end] 範囲の一様乱数 return Rand(mt); } ``
まだ回答がついていません
会員登録して回答してみよう