Ejemplo n.º 1
0
    // 根据长和宽找到房间大小比较大的 ,
    // todo 需要限定宽高比,否则将会选择长条状
    // todo random 使用seed;
    private static List <RoomForCircle> GetMainRoom(List <RoomForCircle> roomList, float threshold)
    {
        List <RoomForCircle> mainRoomList = new List <RoomForCircle>();

        for (int i = 0; i < roomList.Count; i++)
        {
            RoomForCircle item = roomList[i];
            if (item.rigidBody.Simualeted != false)
            {
                roomList.Remove(item);
                Destroy(item.gameObject);
                i--;
                continue;
            }
            // Debug.Log(item.size.Sum());
            if (item.size.Sum() >= threshold)
            {
                if (item.sprite != null)
                {
                    item.sprite.color = Color.yellow;
                }
                mainRoomList.Add(item);
                item.roomType = RoomType.MainRoom;
            }
        }
        return(mainRoomList);
    }
Ejemplo n.º 2
0
    private static RoomForCircle GenerationRoom(Transform parent, Vector2 position, Vector2 size, Sprite testSprtie = null)
    {
        GameObject newGo = new GameObject("room");

        newGo.transform.position = position;
        newGo.transform.rotation = Quaternion.identity;
        newGo.transform.parent   = parent;
        RoomForCircle temp = newGo.AddComponent <RoomForCircle>();

        temp.size        = size;
        temp.boxCollider = newGo.AddComponent <BoxCollider2D>();
        temp.rigidBody   = newGo.AddComponent <RoomRigidBody>();
        temp.sprite      = newGo.AddComponent <SpriteRenderer>();
        if (testSprtie != null)
        {
            temp.sprite.size     = size;
            temp.sprite.sprite   = testSprtie;
            temp.sprite.drawMode = SpriteDrawMode.Sliced;
        }
        return(temp);
    }
Ejemplo n.º 3
0
    // todo 尝试使用异步完成
    public IEnumerator GenerationRooms()
    {
        UnityEngine.Random.InitState(seed);
        int   currentFinishCount = 0;
        float roomAverage        = 0;

        //设置当前状态
        isGenerating = true;
        for (int i = 0; i < RoomCount; i++)
        {
            // todo 将tilesize设定成参数。
            // 生成房间初始位置
            Vector2 pos = getRandomPointInEllipse(GenerateRadius, GenerateRadius, 1);
            // Debug.Log("pos : " + pos);
            // 房间大小可以使用随机也可以使用预制的房间
            Vector2 size = getRandomSizeInCircle(RoomRadius, 2);
            // Debug.Log("size : " + size);
            roomAverage += size.Sum();
            // 根据大小和初始位置生成房间
            RoomForCircle temp = GenerationRoom(this.transform, pos, size, testSprtie);
            roomList.Add(temp);
            temp.transform.localScale = new Vector3(1, 1, 1);
            // 设置物体碰撞完成时的callback回调
            temp.rigidBody.onSimualtedFinishCallback += () => { currentFinishCount++; };
            //延迟
            yield return(new WaitForFixedUpdate());
        }
        // todo 可以自行调用来完成碰撞,减少随机性。可以通过随机来控制
        float timer = 0;

        while (timer < maxWaitTime && currentFinishCount < RoomCount)
        {
            yield return(new WaitForFixedUpdate());

            timer += Time.fixedDeltaTime;
        }
        // 获取主要房间
        roomAverage /= roomList.Count;
        mainRoomList = GetMainRoom(roomList, roomAverage * mainRoomThreshold);
        foreach (var room in mainRoomList)
        {
            // todo 可定制的主房间,使用代理
            DrawRoomInTilemap(floorTilemap, wallTilemap, floorTile, wallTile, room.transform.position.ToVector2(), room.size);
        }
        // 通过三角剖分获取主要房间之间的联通路
        List <Vector2>  mainRoomPos = mainRoomList.ToPosition();
        List <Triangle> triangles   = Polygon2D.DelaunayTriangulation(mainRoomPos);

        roadList = triangles.GetEdges();
        foreach (var r in roadList)
        {
            Debug.DrawLine(mainRoomPos[r.indexA], mainRoomPos[r.indexB], Color.green, 1f);
        }
        // 使用最小生成树算法生成真实路径,
        List <Edge> mainRoadList = GetMainRoad(roadList, mainRoomPos);

        foreach (var r in mainRoadList)
        {
            Debug.DrawLine(mainRoomPos[r.indexA], mainRoomPos[r.indexB], Color.red, 1f);
        }
        // 算法思路:
        // 将两个房间确定一个矩形范围,在范围中确定一个点,用作折现点。
        foreach (var road in mainRoadList)
        {
            RoomForCircle roomA = mainRoomList[road.indexA];
            RoomForCircle roomB = mainRoomList[road.indexB];
            // todo 可定制的path 使用代理
            // 获取房间之间的路径点, 获取的路径点头和尾分别是房间A和房间B的门口
            Vector2[]  PathPoints = GetPathsBetweenRoom(roomA, roomB);
            GameObject pA         = new GameObject("point0" + roomA.GetHashCode());
            pA.transform.parent   = this.gameObject.transform;
            pA.transform.position = PathPoints[0];
            for (int i = 0; i < PathPoints.Length - 1; i++)
            {
                Debug.DrawLine(PathPoints[i] + new Vector2(0.5f, 0.5f), PathPoints[i + 1] + new Vector2(0.5f, 0.5f), Color.white, 1f);
                GameObject temp = new GameObject("point" + i);
                temp.transform.parent   = pA.transform;
                temp.transform.position = PathPoints[i + 1] + new Vector2(0.5f, 0.5f);
            }

            // 对连线之间的房间进行选取,映射到tilemap中
            // todo 可选的判断方法,间隔一个距离使用raycast 进行判断,减少性能消耗。
            // BUG 房间内有概率出现走廊。
            // BUG side房间的判断有时候有问题
            for (int i = 0; i < PathPoints.Length - 1; i++)
            {
                RaycastHit2D[] result = new RaycastHit2D[mainRoadList.Count];// todo 这里的数量可以动态调整
                int            n      = Physics2D.RaycastNonAlloc(
                    PathPoints[i] + new Vector2(0.5f, 0.5f),
                    (PathPoints[i + 1] - PathPoints[i]).normalized,
                    result, Vector2.Distance(PathPoints[i + 1], PathPoints[i]));
                for (int j = 0; j < n; j++)
                {
                    RaycastHit2D  temp = result[j];
                    RoomForCircle room = temp.collider.gameObject.GetComponent <RoomForCircle>();
                    if (room.roomType == RoomType.NoneRoom)
                    {
                        room.roomType     = RoomType.SideRoom;
                        room.sprite.color = Color.red;
                        // todo 可定制的side房间,使用代理
                        DrawRoomInTilemap(floorTilemap, wallTilemap, floorTile, wallTile, room.transform.position, room.size);
                    }
                }
            }
            DrawHallwayInTilemap(floorTilemap, wallTilemap, floorTile, wallTile, PathPoints);
        }



        isGenerating = false;
        this.gameObject.SetActive(false);
    }
Ejemplo n.º 4
0
    // 返回的是一个ve2的数组,头和尾是房间的门口
    private static Vector2[] GetPathsBetweenRoom(RoomForCircle roomA, RoomForCircle roomB)
    {
        float          AxorBx = UnityEngine.Random.value;
        List <Vector2> list   = new List <Vector2>();
        Vector2        TurnPoint;
        Vector2        pointA;
        Vector2        pointB;

        // todo 这一段看上去冗余
        if (AxorBx >= 0.5f)//AXBY
        {
            Vector2 RedCenter = new Vector2(roomA.transform.position.x, roomB.transform.position.y);
            //   -2 是防止处于墙壁边缘。
            Vector2 RedSize = new Vector2(roomA.size.x - 2, roomB.size.y - 2);
            // 转折点
            TurnPoint = getRandomPointInBox(RedSize, RedCenter);
            // 判断消减方向,确定门的位置
            float dir = (TurnPoint.y - roomA.transform.position.y);// 缩小方向已经确定 正 + 负 -
            pointA = new Vector2(
                TurnPoint.x, roomA.transform.position.y +
                (((dir > 0) ? (roomA.size.y / 2) - 1 : -(roomA.size.y / 2)))
                );
            dir    = (TurnPoint.x - roomB.transform.position.x); // 正 + 负数 -
            pointB = new Vector2(
                roomB.transform.position.x +
                (((dir > 0) ? (roomB.size.x / 2) - 1 : -(roomB.size.x / 2))), TurnPoint.y
                );
        }
        else//BXAY
        {
            Vector2 RedCenter = new Vector2(roomB.transform.position.x, roomA.transform.position.y);
            Vector2 RedSize   = new Vector2(roomB.size.x - 2, roomA.size.y - 2);
            TurnPoint = getRandomPointInBox(RedSize, RedCenter);
            float dir = (TurnPoint.x - roomA.transform.position.x);
            pointA = new Vector2(roomA.transform.position.x + (((dir > 0) ? (roomA.size.x / 2) - 1 : -(roomA.size.x / 2))), TurnPoint.y);
            dir    = (TurnPoint.y - roomB.transform.position.y); // 正 + 负数 -
            pointB = new Vector2(TurnPoint.x, roomB.transform.position.y + (((dir > 0) ? (roomB.size.y / 2) - 1 : -(roomB.size.y / 2))));
        }
        // 如果转折点在房间中
        if (CheckInBox(TurnPoint, roomA.transform.position, roomA.size - new Vector2(2, 2)))
        {
            Vector2 dir = (pointB - TurnPoint);
            if (dir.x != 0)
            {
                float offset = roomA.size.x / 2 - ((dir.x > 0) ?1:-1) * (TurnPoint.x - roomA.transform.position.x);
                TurnPoint += ((dir.x > 0) ? offset - 1 : -offset) * Vector2.right;
            }
            else
            {
                float offset = roomA.size.y / 2 - ((dir.y > 0) ?1:-1) * (TurnPoint.y - roomA.transform.position.y);
                TurnPoint += ((dir.y > 0) ? offset - 1 : -offset) * Vector2.up;
            }
            list.Add(TurnPoint);
            list.Add(pointB);
        }
        else if (CheckInBox(TurnPoint, roomB.transform.position, roomB.size - new Vector2(2, 2)))
        {
            Vector2 dir = (pointA - TurnPoint);
            if (dir.x != 0)
            {
                float offset = roomB.size.x / 2 - ((dir.x > 0) ?1:-1) * (TurnPoint.x - roomB.transform.position.x);
                TurnPoint += ((dir.x > 0) ? offset - 1 : -offset) * Vector2.right;
            }
            else
            {
                float offset = roomB.size.y / 2 - ((dir.y > 0) ?1:-1) * (TurnPoint.y - roomB.transform.position.y);
                TurnPoint += ((dir.y > 0) ? offset - 1 : -offset) * Vector2.up;
            }
            list.Add(pointA);
            list.Add(TurnPoint);
        }
        else// 转折点在房间外
        {
            list.Add(pointA);
            list.Add(TurnPoint);
            list.Add(pointB);
        }
        return(list.ToArray());
    }