private MoveDirection ComputeDirection(OperationBluehole.Content.Int2D currentPos, OperationBluehole.Content.Int2D nextPos)
    {
        int xDiff = nextPos.x - currentPos.x;

        if (xDiff != 0)
        {
            if (xDiff > 0)
            {
                return(MoveDirection.Right);
            }
            else
            {
                return(MoveDirection.Left);
            }
        }

        int yDiff = nextPos.y - currentPos.y;

        if (yDiff != 0)
        {
            if (yDiff > 0)
            {
                return(MoveDirection.Up);
            }
            else
            {
                return(MoveDirection.Down);
            }
        }

        return(MoveDirection.Stay);
    }
Пример #2
0
        public bool MovePlayer(Int2D position)
        {
            Int2D newPosition = position;

            // 임시 사용 중
            // 해당 영역에 몬스터 있으면 덮어 쓰지 말고 다르게 처리할 것
            // 전투를 하든가...뭐 그런 식으로

            /*
             * while ( map[position.y, position.x].party != null )
             * {
             *  Int2D tempPosition;
             *  tempPosition.x = newPosition.x + random.Next(-3, 3);
             *  tempPosition.y = newPosition.y + random.Next(-3, 3);
             *
             *  if ( map[position.y, position.x].objectType != MapObjectType.TILE || map[position.y, position.x].party != null )
             *      continue;
             *
             *  newPosition = tempPosition;
             * }
             */
            map[newPosition.y, newPosition.x].party       = map[playerPosition.y, playerPosition.x].party;
            map[playerPosition.y, playerPosition.x].party = null;
            playerPosition = newPosition;

            return(true);
        }
Пример #3
0
        // 맵 생성!
        private void GenerateMap(List <Party> mobs, List <Item> items, Party users)
        {
            // 맵 상의 임의의 영역에 대해서
            // 각 영역은 멤버로 자신이 생성된 방향(horizontal, verical)과 영역좌표(AABB)를 가진다
            // 부모 영역에 대한 참조와 트리에서의 depth정보도 가진다.
            // 만약 자신의 depth가 upper bound보다 작으면 아래의 작업을 수행한다
            // 자신의 반대 방향으로 임의의 위치에서 다시 잘라서 해당 영역을 자식으로 추가
            DungeonTreeNode root = new DungeonTreeNode();

            root.SetRoot(size, random, map, mobs, items, zoneList, userLevel);
            root.GenerateRecursivly();

            // player party와 ring 배치 - 맵 전체를 기반으로
            RingOfErrethAkbe ring = new RingOfErrethAkbe();

            playerPosition = root.RegisterParty(users, true);
            ringPosition   = root.RegisterGameObject(ring);
            items.Add(ring);

            zoneList[map[ringPosition.y, ringPosition.x].zoneId].items.Add(ring);

            // PrintOutMAP();

            // Console.WriteLine( "distance between player and ring" );
            // Console.WriteLine( " :" + Math.Abs( playerPosition.x - ringPosition.x ) + " / "+ Math.Abs( playerPosition.y - ringPosition.y ) );
        }
Пример #4
0
 public int GetZoneId(Int2D position)
 {
     return(zoneList
            .Where(z => z.lowerBoundary.x <= position.x && position.x <= z.upperBoundary.x && z.lowerBoundary.y <= position.y && position.y <= z.upperBoundary.y)
            .Select(z => z.zoneId)
            .First());
 }
Пример #5
0
        public Int2D RegisterParty(Party party, bool isUsers = false)
        {
            Int2D position = new Int2D(-1, -1);

            while (true)
            {
                position = GetRandomInternalPosition();

                if (map[position.y, position.x] != null && map[position.y, position.x].objectType == MapObjectType.TILE &&
                    map[position.y, position.x].party == null)
                {
                    // 플레이어가 아이템 위에서 시작하지 않도록 제어
                    if (map[position.y, position.x].gameObject != null && isUsers)
                    {
                        continue;
                    }

                    map[position.y, position.x].party = party;
                    party.position = position;

                    break;
                }
            }

            return(position);
        }
Пример #6
0
        public DungeonZone(int zoneId, Int2D lowerBoundary, Int2D upperBoundary)
        {
            this.zoneId        = zoneId;
            this.lowerBoundary = lowerBoundary;
            this.upperBoundary = upperBoundary;

            centerPosition.x = (lowerBoundary.x + upperBoundary.x) / 2;
            centerPosition.y = (lowerBoundary.y + upperBoundary.y) / 2;
        }
Пример #7
0
        public void Test()
        {
            Int2D start = new Int2D();
            bool  stop  = false;

            for (int i = 0; i < mapSize; ++i)
            {
                for (int j = 0; j < mapSize; ++j)
                {
                    if (dungeonMaster.GetMapInfo()[i, j].objectType == MapObjectType.TILE)
                    {
                        start.x = j;
                        start.y = i;
                        Teleport(start);
                        Console.WriteLine("start : " + position.x + "," + position.y);
                        stop = true;
                        break;
                    }
                }

                if (stop)
                {
                    break;
                }
            }

            stop = false;
            Int2D end = new Int2D();

            for (int i = mapSize - 1; i >= 0; --i)
            {
                for (int j = mapSize - 1; j >= 0; --j)
                {
                    if (dungeonMaster.GetMapInfo()[i, j].objectType == MapObjectType.TILE)
                    {
                        end.x = j;
                        end.y = i;
                        Console.WriteLine("dest : " + end.x + "," + end.y);

                        var runningTime = Stopwatch.StartNew();
                        MakePath(end);

                        Console.WriteLine("[Simulation : " + runningTime.ElapsedMilliseconds + " ms]");
                        stop = true;
                        break;
                    }
                }

                if (stop)
                {
                    break;
                }
            }
        }
Пример #8
0
        public void Init(Int2D position)
        {
            isRingDiscovered = false;
            this.position    = position;

            // 존 방문 기록도 업데이트하고, 첫 movePath 계산도 해둔다
            currentZoneId = dungeonMaster.GetZoneId(position);
            dungeonZoneHistory.Push(currentZoneId);
            exploredZone.Add(currentZoneId);

            UpdateDestination();
        }
Пример #9
0
        // 조심해!
        // FOR DEBUG!!!!
        public void Teleport(Int2D destination)
        {
            position = destination;

            // 현재 존 정보 업데이트 할 것
            int currentZoneId = dungeonMaster.GetZoneId(position);

            if (currentZoneId != dungeonZoneHistory.Peek())
            {
                dungeonZoneHistory.Push(currentZoneId);
                exploredZone.Add(currentZoneId);
            }
        }
Пример #10
0
        private void AllocateObjects(DungeonZone zone)
        {
            // 아이템과 몹 배치
            int tileCount = (upperBoundary.y - lowerBoundary.y - 1)
                            * (upperBoundary.x - lowerBoundary.x - 1);

            int mobCount = (int)(tileCount * Config.MOB_DENSITY);

            for (int i = 0; i < mobCount; ++i)
            {
                // 몹 생성하고
                mobs.Add(GeneratoMobParty());

                int idx = mobs.Count - 1;

                zone.mobs.Add(mobs[idx]);

                // 등록
                Int2D mobPosition = RegisterParty(mobs[idx]);
            }

            int itemCOunt = (int)(tileCount * Config.ITEM_DENSITY);

            for (int i = 0; i < itemCOunt; ++i)
            {
                // 아이템 생성하고
                Item newItem = new ItemToken();
                ((ItemToken)newItem).GenerateRandomToken(
                    usersLevel + random.Next(
                        (int)(-usersLevel * Config.MOB_REWARD_ITEM_RANGE),
                        (int)(usersLevel * Config.MOB_REWARD_ITEM_RANGE)
                        ), ItemToken.equipTypePool[random.Next(ItemToken.equipTypePool.Length)]);
                items.Add(newItem);
                int idx = items.Count - 1;

                zone.items.Add(items[idx]);

                // 등록
                Int2D itemPosition = RegisterGameObject(items[idx]);
            }
        }
Пример #11
0
        public Int2D RegisterGameObject(GameObject obj)
        {
            Int2D position = new Int2D(-1, -1);

            while (true)
            {
                position = GetRandomInternalPosition();

                if (map[position.y, position.x] != null && map[position.y, position.x].objectType == MapObjectType.TILE &&
                    map[position.y, position.x].gameObject == null)
                {
                    // 조심해!
                    // item에 자신의 idx 기록은 안 해도 되려나...
                    map[position.y, position.x].gameObject = obj;
                    obj.position = position;

                    break;
                }
            }

            return(position);
        }
 public int GetZoneId(Int2D position)
 {
     return(dungeon.GetZoneId(position));
 }
Пример #13
0
 public Int2D(Int2D rhs)
 {
     this.x = rhs.x; this.y = rhs.y;
 }
Пример #14
0
        private void MakePath(Int2D destination)
        {
            // Debug.WriteLine( "start to make the path" );
            // Debug.WriteLine( "start : " + position.x + " / " + position.y );
            // Debug.WriteLine( "dest : " + destination.x + " / " + destination.y );

            // 조심해!!!
            // priority_queue가 없어서 일단 list로 구현
            // List<ExploerNode> openSet = new List<ExploerNode>();
            MinHeap <ExploerNode> openSet = new MinHeap <ExploerNode>();

            for (int i = 0; i < mapSize; ++i)
            {
                for (int j = 0; j < mapSize; ++j)
                {
                    map[i, j].Reset();
                }
            }

            map[position.y, position.x].gScore   = 0;
            map[position.y, position.x].fScore   = map[position.y, position.x].gScore + GetHeuristicScore(position, destination);
            map[position.y, position.x].isOpened = true;
            // openSet.Add( map[position.y, position.x] );
            openSet.Push(map[position.y, position.x]);

            while (openSet.Count > 0)
            {
                // ExploerNode current = openSet.Min();
                ExploerNode current = openSet.Peek();
                // Debug.WriteLine( "current : " + current.position.x + " / " + current.position.y );

                if (current.position.Equals(destination))
                {
                    currentMovePath.Push(currentDestination);   // 최종 목적지를 일단 넣고 그 사이를 채움

                    ReconstructPath(current);
                    currentMovePath.Pop();      // 현재 위치는 빼자
                    break;
                }

                // openSet.Remove( openSet.Min() );
                openSet.Pop();
                current.isClosed = true;

                // 조심해!
                // 배열을 하나 새로 만드는 것이 어색하다
                // 맨 끝 지점들에는 안 가니까 예외 처리는 생략
                List <ExploerNode> neigborNodes = new List <ExploerNode> {
                    map[current.position.y - 1, current.position.x],
                    map[current.position.y + 1, current.position.x],
                    map[current.position.y, current.position.x - 1],
                    map[current.position.y, current.position.x + 1]
                };

                for (int i = 0; i < neigborNodes.Count; ++i)
                {
                    ExploerNode neighbor = neigborNodes[i];

                    if (neighbor.isClosed)
                    {
                        continue;
                    }

                    float gScoreTentative = current.gScore + Math.Abs(destination.x - current.position.x) + Math.Abs(destination.y - current.position.y);

                    if (!neighbor.isOpened || gScoreTentative < neighbor.gScore)
                    {
                        neighbor.cameFrom = current;
                        neighbor.gScore   = gScoreTentative;
                        neighbor.fScore   = neighbor.gScore + GetHeuristicScore(neighbor.position, destination);

                        if (!neighbor.isOpened)
                        {
                            neighbor.isOpened = true;
                            // openSet.Add( neighbor );
                            openSet.Push(neighbor);
                        }
                        else
                        {
                            openSet.DecreaseKeyValue(neighbor);
                        }

                        // openSet.Sort( new NodeComp() );
                    }
                }
            }

            // Debug.WriteLine( "end!!!!" );
        }
Пример #15
0
 private float GetHeuristicScore(Int2D target, Int2D goal)
 {
     return((float)Math.Sqrt(Math.Pow(goal.x - target.x, 2) + Math.Pow(goal.y - target.y, 2)));
     // return Math.Abs( goal.x - target.x ) + Math.Abs( goal.y - target.y );
 }
Пример #16
0
        public bool Move(MoveDiretion direction, GameRecord record)
        {
            switch (direction)
            {
            case MoveDiretion.DOWN:
                position = new Int2D(position.x, position.y + 1);
                break;

            case MoveDiretion.LEFT:
                position = new Int2D(position.x - 1, position.y);
                break;

            case MoveDiretion.RIGHT:
                position = new Int2D(position.x + 1, position.y);
                break;

            case MoveDiretion.UP:
                position = new Int2D(position.x, position.y - 1);
                break;

            default:
                break;
            }

            // 일단 도착했으니까 제거
            if (position.Equals(currentMovePath.Peek()))
            {
                currentMovePath.Pop();
            }

            // 몹이 있는지 확인한다
            // 있으면 일단 전투부터 요청
            Party target = dungeonMaster.GetMapObject(position.x, position.y).party;

            if (target != null && target.partyType == PartyType.MOB)
            {
                if (!dungeonMaster.StartBattle(target))
                {
                    record.lastPosition = position;

                    return(false);
                }
            }

            // 아이템 있는지 확인한다
            Item item = (Item)dungeonMaster.GetMapObject(position.x, position.y).gameObject;

            if (item != null)
            {
                if (item.code == ItemCode.Ring)
                {
                    isRingDiscovered = true;
                }
                else
                {
                    dungeonMaster.LootItem(item, currentZoneId);
                    UpdateDestination();
                }
            }

            // 현재 존 정보 업데이트 할 것
            int newZoneId = dungeonMaster.GetZoneId(position);

            if (currentZoneId != newZoneId)
            {
                // 영역이 바뀌었다!
                currentZoneId = newZoneId;

                UpdateDestination();

                // 처음 가보는 곳이면 일단 스택에도 넣고, 가봤다고 기록도 하자
                if (!exploredZone.Contains(currentZoneId))
                {
                    dungeonZoneHistory.Push(currentZoneId);
                    exploredZone.Add(currentZoneId);
                }
            }

            return(true);
        }