예제 #1
0
파일: Builder.cs 프로젝트: Toshizabeth/Ling
        /// <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);
        }
예제 #2
0
파일: Builder.cs 프로젝트: Toshizabeth/Ling
        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);
                }
            }
        }