/// <summary> /// 処理を実行する /// </summary> protected override IEnumerator <float> ExecuteInternal(TileDataMap prevTildeDataMap) { _splitter = _splitFactory.Create(); MapRect = new MapRectData(); // 全体を一つの区画にする // Width&Heightが20の場合 // (0, 0, 20, 20)になる。 // 区画が (0, 0, 10, 20), (10, 0, 20, 20) // となった場合、引き算するだけで // 10 - 0 = 10 // 20 - 10 = 10 // とマスの幅が求まり // for (int x = 0; x < w; ++x) // とすると区画のループ処理がかける var extra = 3; MapRect.CreateRect(0 + extra, 0 + extra, Width - extra, Height - extra); // 区画を作る var splitEnumerator = _splitter?.SplitRect(_data, MapRect); while (splitEnumerator.MoveNext()) { yield return(splitEnumerator.Current); } // 部屋を作る var roomEnumerator = CreateRoom(); while (roomEnumerator.MoveNext()) { yield return(roomEnumerator.Current); } // 道を作る _roadBuilder = _roadFactory.Create(SplitConst.RoadBuilderType.Simple); var roadEnumerator = _roadBuilder.Build(TileDataMap, MapRect); while (roadEnumerator.MoveNext()) { yield return(roadEnumerator.Current); } // 前マップの下階段の位置に部屋を作成する // 下り階段の場所が部屋なら何もしない if (prevTildeDataMap != null) { var prevRoomEnumerator = CreateEntrance(prevTildeDataMap); while (prevRoomEnumerator.MoveNext()) { yield return(prevRoomEnumerator.Current); } } else { // マップだけ作成しておく TileDataMap.BuildRoomMap(); } // 部屋に対して道が重なっていた場合、その道を取り除く RemoveExtraRoad(); // 下階段を作る var pos = GetRandomRoomCellPos(); TileDataMap.SetStepDownFlag(pos.x, pos.y); }
private IEnumerator <float> CreateEntrance(TileDataMap prevTildeDataMap) { if (prevTildeDataMap == null) { // 部屋のマップを作成する TileDataMap.BuildRoomMap(); yield break; } // 前マップの下階段の位置に部屋を作成する // 下り階段の場所が部屋なら何もしない var stepDownPos = prevTildeDataMap.StepDownPos; var tileData = TileDataMap.GetTile(stepDownPos.x, stepDownPos.y); if (tileData.HasFlag(TileFlag.Floor)) { // 部屋のマップを作成する TileDataMap.BuildRoomMap(); yield break; } // 3マスで部屋を作成 var w = Utility.Random.MaxIncludedRange(1, 1); var h = Utility.Random.MaxIncludedRange(1, 1); // どこかの部屋か道と連結したら終わり var xMin = stepDownPos.x - 1; // - w / 2; var xMax = stepDownPos.x + 1; // + w / 2; var yMin = stepDownPos.y - 1; // - h / 2; var yMax = stepDownPos.y + 1; // + h / 2; bool shouldCreateRoad = true; // 隣接しているかチェック for (int y = yMin; y < yMax; ++y) { for (int x = xMin; x < xMax; ++x) { if (!TileDataMap.InRange(x, y)) { continue; } if (TileDataMap.IsAdjacent(x, y, TileFlag.Floor | TileFlag.Road)) { shouldCreateRoad = false; break; } } } TileDataMap.FillRect(xMin, yMin, xMax, yMax, TileFlag.Floor, tileData_ => { return(true); }); // 部屋のマップを作成する TileDataMap.BuildRoomMap(); // 道を作る必要がある場合作成 if (shouldCreateRoad) { // 部屋マップの値を取得 var roomValue = TileDataMap.GetRoomIndex(stepDownPos.x, stepDownPos.y); // 一番近い部屋か道とつなげる var route = new Route.Tracking(); route.Setup(TileDataMap); // 自分の部屋は1とする。 // 自分以外の部屋か道が見つかったら終わり route.Execute(stepDownPos.x, stepDownPos.y, (tracking_, cellPos_, newValue_, oldValue_) => { // 自分の部屋か if (TileDataMap.EqualRoomMapValue(cellPos_.x, cellPos_.y, roomValue)) { // すでに書き込まれていたらスキップ if (oldValue_ == 1) { return(-1); } // 自分の部屋は 1 として書き込む return(1); } // 自分が2(部屋の外周)じゃないのに部屋の隣りにいるならばだめ if (newValue_ > 2) { if (Utility.Map.CallDirection(cellPos_.x, cellPos_.y, (x_, y_) => { // 自分の部屋があればおわり return(TileDataMap.EqualRoomMapValue(x_, y_, roomValue)); })) { return(-1); } } // 前後左右が自分以外の部屋か道ならおわり Utility.Map.CallDirection(cellPos_.x, cellPos_.y, (x_, y_) => { if (!TileDataMap.InRange(x_, y_)) { return(false); } if (TileDataMap.EqualRoomMapValue(x_, y_, roomValue)) { return(false); } // 部屋か道を見つける var tileFlag = TileDataMap.GetTileFlag(x_, y_); if (tileFlag.HasFlag(TileFlag.Floor) || tileFlag.HasFlag(TileFlag.Road)) { tracking_.ProcessFinish(); return(true); } return(false); }); return(0); }); // ルートを道にする var posList = route.GetRoute(route.ForceFinishPos, useDiagonal: false); foreach (var pos in posList) { // 部屋なら何もしない if (TileDataMap.GetTileFlag(pos.x, pos.y).HasFlag(TileFlag.Floor)) { continue; } TileDataMap.SetTileFlag(pos, TileFlag.Road); } } }