public void GetNeighborBorderNodes_TopLeft_ReturnsTopRight() { // ARRANGE const int REGION_SIZE = 20; // У нас есть 2 региона, расположенных по соседству. var regionSchemeMock = new Mock <ILocationScheme>(); var regionScheme = regionSchemeMock.Object; var currentRegion = new GlobeRegion(REGION_SIZE); FillRegion(REGION_SIZE, regionScheme, currentRegion); // Берём правую верхнюю точку для перехода. var currentNode = currentRegion.Nodes.OfType <GlobeRegionNode>().Single(node => node.OffsetX == 0 && node.OffsetY == 0); var currentTerrainCell = new TerrainCell() { Coords = new OffsetCoords(1, 0) }; var targetRegion = new GlobeRegion(REGION_SIZE); FillRegion(REGION_SIZE, regionScheme, targetRegion); var expectedTransitionNodes = new[] { targetRegion.Nodes.OfType <GlobeRegionNode>().Single(node => node.OffsetX == REGION_SIZE - 1 && node.OffsetY == 0), targetRegion.Nodes.OfType <GlobeRegionNode>().Single(node => node.OffsetX == REGION_SIZE - 1 && node.OffsetY == 1) }; var targetRegionBorders = targetRegion.Nodes.OfType <GlobeRegionNode>().Where(node => node.IsBorder); var targetTerrainCell = new TerrainCell() { Coords = new OffsetCoords(0, 0) }; // ACT var factTransitionNodes = RegionTransitionHelper.GetNeighborBorderNodes(currentNode, currentTerrainCell, targetRegionBorders, targetTerrainCell); // ASSERT factTransitionNodes.Should().BeEquivalentTo(expectedTransitionNodes); }
private async void Start() { //TODO Разобраться, почему остаются блоки от перемещения при использовании перехода _commandBlockerService.DropBlockers(); if (_globeManager.Globe == null) { if (!_progressStorageService.LoadGlobe()) { var globeGenerationResult = await _globeGenerator.GenerateGlobeAsync(); _globeManager.Globe = globeGenerationResult.Globe; _globeManager.GlobeGenerationHistory = globeGenerationResult.History; var startCell = _globeManager.Globe.StartProvince; _player.Terrain = startCell; var createdRegion = await CreateRegionAsync(_globeManager.Globe, _player.Terrain, _globeGenerator, _progressStorageService); await CreateNeighborRegionsAsync(_player.Terrain.Coords, _globeManager, _globeGenerator, _progressStorageService); _globeManager.Regions[_player.Terrain] = createdRegion; var startNode = createdRegion.RegionNodes.Single(x => x.IsStart); _player.GlobeNode = startNode; startNode.ObservedState = GlobeNodeObservedState.Visited; _globeModalManager.ShowHistoryBookModal(); } else { _globeManager.GlobeGenerationHistory = new GlobeGenerationHistory(); if (!_progressStorageService.LoadPlayer()) { var startCell = _globeManager.Globe.StartProvince; _player.Terrain = startCell; } } } var currentGlobeCell = _player.Terrain; if (!_globeManager.Regions.TryGetValue(currentGlobeCell, out var currentRegion)) { var createdRegion = await CreateRegionAsync(_globeManager.Globe, currentGlobeCell, _globeGenerator, _progressStorageService); _globeManager.Regions[_player.Terrain] = createdRegion; } // Создание соседних регионов await CreateNeighborRegionsAsync(_player.Terrain.Coords, _globeManager, _globeGenerator, _progressStorageService); Debug.Log($"Current: {currentGlobeCell}"); Debug.Log($"Current: {_globeManager.Globe.HomeProvince}"); _region = currentRegion; // Создание визуализации узлов провинции. _locationNodeViewModels = new List <MapLocation>(100); foreach (GlobeRegionNode globeRegionNode in _region.Nodes) { var worldCoords = HexHelper.ConvertToWorld(globeRegionNode.OffsetX + _player.Terrain.Coords.X * 20, globeRegionNode.OffsetY + _player.Terrain.Coords.Y * 20); var locationObject = _container.InstantiatePrefab(LocationPrefab, transform); locationObject.transform.position = new Vector3(worldCoords[0], worldCoords[1], 0); var locationViewModel = locationObject.GetComponent <MapLocation>(); locationViewModel.Node = globeRegionNode; locationViewModel.ParentRegion = _region; _locationNodeViewModels.Add(locationViewModel); locationViewModel.OnSelect += LocationViewModel_OnSelect; locationViewModel.OnHover += LocationViewModel_OnHover; } // Создание коннекторов между узлами провинции. var openNodeViewModels = new List <MapLocation>(_locationNodeViewModels); while (openNodeViewModels.Any()) { var currentNodeViewModel = openNodeViewModels[0]; openNodeViewModels.Remove(currentNodeViewModel); var neighbors = _region.GetNext(currentNodeViewModel.Node); var neighborViewModels = openNodeViewModels.Where(x => neighbors.Contains(x.Node)).ToArray(); foreach (var neibourNodeViewModel in neighborViewModels) { CreateConnector(currentNodeViewModel, neibourNodeViewModel); } } // Создание визуализаций соседних провинций var currentRegionBorders = _region.RegionNodes.Where(x => x.IsBorder).ToArray(); // TODO в открытые можно помещать только бордюр для экономии. openNodeViewModels = new List <MapLocation>(_locationNodeViewModels); var currentBorderNodes = currentRegion.Nodes.OfType <GlobeRegionNode>().Where(x => x.IsBorder).ToArray(); for (var offsetX = -1; offsetX <= 1; offsetX++) { for (var offsetY = -1; offsetY <= 1; offsetY++) { if (offsetX == 0 && offsetY == 0) { // Это нулевое смещение от текущего элемента. // Пропускаем, т.к. текущий элемент уже есть. continue; } var terrainX = _player.Terrain.Coords.X + offsetX; var terrainY = _player.Terrain.Coords.Y + offsetY; if (_globeManager.Globe.Terrain.GetLowerBound(0) <= terrainX && terrainX <= _globeManager.Globe.Terrain.GetUpperBound(0) && _globeManager.Globe.Terrain[0].GetLowerBound(0) <= terrainY && terrainY <= _globeManager.Globe.Terrain[0].GetUpperBound(0)) { var terrainCell = _globeManager.Globe.Terrain[terrainX][terrainY]; var neighborRegion = _globeManager.Regions[terrainCell]; // Ищем узел текущей провинции, являющийся соседним с узлом соседней провинции. var neighborBorderNodes = neighborRegion.Nodes.OfType <GlobeRegionNode>().Where(x => x.IsBorder); foreach (var neighborBorderNode in neighborBorderNodes) { var transitionNodes = RegionTransitionHelper.GetNeighborBorderNodes(neighborBorderNode, terrainCell, currentRegionBorders, _player.Terrain); if (!transitionNodes.Any()) { // Этот узел соседней провинции не имеет переходов в текущую. // Соответственно, из текущей провинции никто не будет иметь переходов в этот узел соседней провинции. // Значит его можно вообще не отрисовывать. continue; } var worldCoords = HexHelper.ConvertToWorld(neighborBorderNode.OffsetX + terrainX * 20, neighborBorderNode.OffsetY + terrainY * 20); var locationObject = _container.InstantiatePrefab(LocationPrefab, transform); locationObject.transform.position = new Vector3(worldCoords[0], worldCoords[1], 0); var locationViewModel = locationObject.GetComponent <MapLocation>(); locationViewModel.Node = neighborBorderNode; locationViewModel.ParentRegion = neighborRegion; locationViewModel.OtherRegion = true; _locationNodeViewModels.Add(locationViewModel); locationViewModel.OnSelect += LocationViewModel_OnSelect; locationViewModel.OnHover += LocationViewModel_OnHover; // Создаём коннекторы от всех пограничных узлов, // имеющий переходв в текущий узел соседней провинции. var openTransitionNodes = openNodeViewModels.Where(x => transitionNodes.Contains(x.Node)); foreach (var openTransitionNode in openTransitionNodes) { CreateConnector(openTransitionNode, locationViewModel); } } } } } if (_player.MainPerson == null) { if (!_progressStorageService.LoadPerson()) { _player.MainPerson = _humanPersonFactory.Create(); } } var playerGroupNodeViewModel = _locationNodeViewModels.Single(x => x.Node == _player.GlobeNode); var groupObject = _container.InstantiatePrefab(HumanGroupPrefab, transform); _groupViewModel = groupObject.GetComponent <GroupVM>(); _groupViewModel.CurrentLocation = playerGroupNodeViewModel; groupObject.transform.position = playerGroupNodeViewModel.transform.position; Camera.Target = groupObject; Camera.GetComponent <GlobalFollowCamera>().SetPosition(groupObject.transform); var nodes = _locationNodeViewModels.Select(x => x.Node); var centerLocationNode = GlobeHelper.GetCenterLocationNode(nodes); var centerLocationNodeViewModel = _locationNodeViewModels .Single(nodeViewModel => nodeViewModel.Node.OffsetX == centerLocationNode.OffsetX && nodeViewModel.Node.OffsetY == centerLocationNode.OffsetY); MapBackground.transform.position = centerLocationNodeViewModel.transform.position; _player.GlobeNodeChanged += HumanPlayer_GlobeNodeChanged; MoveGroupViewModel(_player.GlobeNode); }