public void Run() { //todo move into IEnumerator CubeCoords playerCoords = HexMath.Pix2Hex(_player.Transform.localPosition.x, _player.Transform.localPosition.y, HexSize); if (_map.LastCoords.x != playerCoords.x || _map.LastCoords.y != playerCoords.y) { UnrenderRing(_map.LastCoords, Fow + 1); RenderRing(playerCoords, Fow); _map.LastCoords = playerCoords; } for (int i = 0; i < _collisionEvents.EntitiesCount; i++) { CubeCoords coords = HexMath.Pix2Hex(_collisionEvents.Components1[i].ObstacleTransform.position, HexSize); } for (int i = 0; i < _triggerForegroundEvents.EntitiesCount; i++) { CubeCoords coords = HexMath.Pix2Hex(_triggerForegroundEvents.Components1[i].ObstacleTransform.position, HexSize); HexForegroundComponent hexComponent = _map.MapF[coords.x, coords.y]; switch (hexComponent.ForegroundType) { case ForegroundTypes.Diamond: _player.Exp += hexComponent.Value; RemoveFore(hexComponent, coords); break; default: break; } } }
public static OffsetCoords ConvertToOffset(CubeCoords cube) { var col = cube.X + ((cube.Z - (cube.Z & 1)) / 2); var row = cube.Z; return(new OffsetCoords(col, row)); }
public static HexNode[] GetNeighbors(HexNode currentNode, IEnumerable <HexNode> nodes) { var currentCubeCoords = currentNode.CubeCoords; var directions = HexHelper.GetOffsetClockwise(); var neighborCoords = new List <CubeCoords>(); for (var i = 0; i < 6; i++) { var dir = directions[i]; var pos = new CubeCoords(dir.X + currentCubeCoords.X, dir.Y + currentCubeCoords.Y, dir.Z + currentCubeCoords.Z); neighborCoords.Add(pos); } var list = new List <HexNode>(); var nodeDictionary = nodes.ToDictionary(x => x.CubeCoords, x => x); for (var i = 0; i < 6; i++) { var neighborCoord = neighborCoords[i]; if (nodeDictionary.TryGetValue(neighborCoord, out var neighborNode)) { list.Add(neighborNode); } } return(list.ToArray()); }
/// <summary> /// Рассчитывает интерполяцией и добавляет в общий список ячейку шестигранного поля. /// </summary> /// <param name="a">Начальное значение. В t=0.0.</param> /// <param name="b">Конечное значение. В t=1.0.</param> /// <param name="list">Существующий список координат.</param> /// <param name="t">Параметр интерполяции.</param> private static void AddPointToList(CubeCoords a, CubeCoords b, List <CubeCoords> list, float t) { LerpCube(a, b, t, out float cubeX, out float cubeY, out float cubeZ); var point = RoundCube(cubeX, cubeY, cubeZ); list.Add(point); }
private static CubeCoords RoundCube(float x, float y, float z) { var rx = Math.Round(x); var ry = Math.Round(y); var rz = Math.Round(z); var xDiff = Math.Abs(rx - x); var yDiff = Math.Abs(ry - y); var zDiff = Math.Abs(rz - z); if (xDiff > yDiff && xDiff > zDiff) { rx = -ry - rz; } else if (yDiff > zDiff) { ry = -rx - rz; } else { rz = -rx - ry; } var cube = new CubeCoords((int)rx, (int)ry, (int)rz); return(cube); }
public HexNode(OffsetCoords coords) { OffsetCoords = coords; var x = coords.X; var y = coords.Y; CubeCoords = HexHelper.ConvertToCube(x, y); }
private void RenderFull(CubeCoords playerCoords, int radius) { RenderHexBackground(playerCoords); RenderHexForeground(playerCoords); for (int i = 1; i <= radius; i++) { RenderRing(playerCoords, i); } }
/// <summary> /// Проверяет, допустимая ли дистанция для совершения действия. /// </summary> /// <param name="act"> Проверяемое действие. </param> /// <param name="currentCubePos"> Узел, из которого совершается действие. </param> /// <param name="targetCubePos"> Целевой узел. </param> /// <returns>Возвращает true, если дистанция допустима.</returns> public static bool CheckDistance(this ITacticalAct act, CubeCoords currentCubePos, CubeCoords targetCubePos) { var range = act.Stats.Range; var distance = currentCubePos.DistanceTo(targetCubePos); var isInDistance = range.Contains(distance); return(isInDistance); }
private void RenderHexForeground(CubeCoords coords) { if (!_map.MapF.ExistAt(coords) || _map.MapF[coords.x, coords.y].IsNew) { return; } HexForegroundComponent foregroundHexComponent = _map.MapF[coords.x, coords.y]; if (foregroundHexComponent.ForegroundType == ForegroundTypes.Empty) { return; } if (foregroundHexComponent.Parent != null) { return; //_poolForeground.Recycle(foregroundHexComponent.Parent); } foregroundHexComponent.Parent = _map.PoolF.Get(); foregroundHexComponent.Parent.PoolTransform.localPosition = HexMath.Hex2Pix(coords, HexSize); switch (foregroundHexComponent.ForegroundType) { case ForegroundTypes.Empty: foregroundHexComponent.Parent.PoolTransform.GetComponent <SpriteRenderer>().sprite = null; foregroundHexComponent.Parent.PoolTransform.GetComponent <Collider2D>().enabled = false; return; case ForegroundTypes.Enemy: foregroundHexComponent.Parent.PoolTransform.GetComponent <SpriteRenderer>().sprite = Enemy; foregroundHexComponent.Parent.PoolTransform.GetComponent <Collider2D>().enabled = true; foregroundHexComponent.Parent.PoolTransform.GetComponent <Collider2D>().isTrigger = false; break; case ForegroundTypes.Obstacle: foregroundHexComponent.Parent.PoolTransform.GetComponent <SpriteRenderer>().sprite = Obstacle; foregroundHexComponent.Parent.PoolTransform.GetComponent <Collider2D>().enabled = true; foregroundHexComponent.Parent.PoolTransform.GetComponent <Collider2D>().isTrigger = false; break; case ForegroundTypes.Diamond: foregroundHexComponent.Parent.PoolTransform.GetComponent <SpriteRenderer>().sprite = Diamond; foregroundHexComponent.Parent.PoolTransform.GetComponent <Collider2D>().enabled = true; foregroundHexComponent.Parent.PoolTransform.GetComponent <Collider2D>().isTrigger = true; break; case ForegroundTypes.Spawn: //spawn point, dunno why foregroundHexComponent.Parent.PoolTransform.GetComponent <SpriteRenderer>().sprite = null; foregroundHexComponent.Parent.PoolTransform.GetComponent <Collider2D>().enabled = false; break; default: throw new Exception("Null object type"); } foregroundHexComponent.Parent.PoolTransform.gameObject.SetActive(true); }
public void ConvertToCubeTest(int offsetX, int offsetY, int cubeX, int cubeY, int cubeZ) { // ARRANGE var expectedCubeCoords = new CubeCoords(cubeX, cubeY, cubeZ); // ACT var factCubeCoords = HexHelper.ConvertToCube(offsetX, offsetY); // ASSERT factCubeCoords.Should().BeEquivalentTo(expectedCubeCoords); }
/// <summary> /// Возвращает соседние координаты указанной точки. /// </summary> /// <param name="baseCoords"> Опорная точка, для которой возвращаются соседние координаты. </param> /// <returns> Набор соседних координат. </returns> public static CubeCoords[] GetNeighbors(CubeCoords baseCoords) { var offsets = GetOffsetClockwise(); var neighborCoords = new CubeCoords[6]; for (var i = 0; i < 6; i++) { var offset = offsets[i]; neighborCoords[i] = offset + baseCoords; } return(neighborCoords); }
private IEnumerable <IGraphNode> GetNextFromMatrix(int localOffsetX, int localOffsetY, int segmentX, int segmentY, IGraphNode[,] matrix) { var directions = HexHelper.GetOffsetClockwise(); var currentCubeCoords = HexHelper.ConvertToCube(localOffsetX, localOffsetY); for (var i = 0; i < 6; i++) { var dir = directions[i]; var neighborLocalCube = new CubeCoords(dir.X + currentCubeCoords.X, dir.Y + currentCubeCoords.Y, dir.Z + currentCubeCoords.Z); var neighborLocalOffset = HexHelper.ConvertToOffset(neighborLocalCube); var neighborSegmentX = segmentX; var neighborSegmentY = segmentY; if (neighborLocalOffset.X < 0) { neighborSegmentX--; } else if (neighborLocalOffset.X >= _segmentSize) { neighborSegmentX++; } if (neighborLocalOffset.Y < 0) { neighborSegmentY--; } else if (neighborLocalOffset.Y >= _segmentSize) { neighborSegmentY++; } IGraphNode currentNeibour; if (neighborSegmentX == segmentX && neighborSegmentY == segmentY) { currentNeibour = matrix[neighborLocalOffset.X, neighborLocalOffset.Y]; if (currentNeibour == null) { continue; } yield return(currentNeibour); } } }
private static CubeCoords[] GetRandomCoords(int coordRollIndex) { var coords = HexHelper.GetOffsetClockwise(); var count = coords.Length; var shuffledCoords = new CubeCoords[count]; for (var i = 0; i < count; i++) { var coordRollIndexOffset = (coordRollIndex + i) % count; shuffledCoords[coordRollIndexOffset] = coords[i]; } return(shuffledCoords); }
private void HideBack(CubeCoords coords) { if (!_map.MapB.ExistAt(coords)) { return; } HexBackgroundComponent hexComponent = _map.MapB[coords.x, coords.y]; if (hexComponent.Parent == null) { return; } _map.PoolB.Recycle(hexComponent.Parent); hexComponent.Parent = null; }
private void HideFore(CubeCoords coords) { if (!_map.MapF.ExistAt(coords)) { return; } HexForegroundComponent foregroundHexComponent = _map.MapF[coords.x, coords.y]; if (foregroundHexComponent.Parent == null) { return; } _map.PoolF.Recycle(foregroundHexComponent.Parent); foregroundHexComponent.Parent = null; }
private void RenderRing(CubeCoords playerCoords, int radius) { CubeCoords coords = new CubeCoords(playerCoords.x, playerCoords.y + radius); for (int i = 0; i < 6; i++) { for (int j = 0; j < radius; j++) { coords.x += HexMath.Directions[i, 0]; coords.y += HexMath.Directions[i, 1]; RenderHexBackground(coords); RenderHexForeground(coords); } } }
/// <summary> /// Для препятсвий выбираются только те узлы, для которых есть все соседи. /// </summary> private static bool HasAllHeighbors(HashSet <OffsetCoords> coordHash, CubeCoords[] neighborCubeOffsets, CubeCoords cube) { foreach (var neighborCubeOffset in neighborCubeOffsets) { var neighborCube = cube + neighborCubeOffset; var neighborOffsetCoords = HexHelper.ConvertToOffset(neighborCube); if (!coordHash.Contains(neighborOffsetCoords)) { return(false); } } return(true); }
/// <summary> /// Рисует линию в кубических координатах. /// </summary> /// <param name="a"> Начало линии. </param> /// <param name="b"> Конец линии. </param> /// <returns> Набор координат, составляющих линию. </returns> public static CubeCoords[] CubeDrawLine(CubeCoords a, CubeCoords b) { var n = a.DistanceTo(b); var list = new List <CubeCoords>(); for (var i = 0; i <= n; i++) { LerpCube(a, b, 1.0f / n * i, out float cubeX, out float cubeY, out float cubeZ); var point = RoundCube(cubeX, cubeY, cubeZ); list.Add(point); } return(list.ToArray()); }
private void UnrenderRing(CubeCoords playerCoords, int radius) { CubeCoords coords = new CubeCoords(playerCoords.x, playerCoords.y + radius); for (int i = 0; i < 6; i++) { for (int j = 0; j < radius; j++) { coords.x += HexMath.Directions[i, 0]; coords.y += HexMath.Directions[i, 1]; if (HexMath.HexDistance(playerCoords.x, playerCoords.y, coords.x, coords.y) >= Fow) { HideHex(coords); } } } }
private static void DrawLineBetweenNodes(Matrix <bool> matrix, CubeCoords openCubeCoord, CubeCoords unitedCubeCoord) { var line = CubeCoordsHelper.CubeDrawLine(openCubeCoord, unitedCubeCoord); foreach (var lineItem in line) { var offsetCoords = HexHelper.ConvertToOffset(lineItem); matrix[offsetCoords.X, offsetCoords.Y] = true; // Коридоры должны быть размером в Size7. // Поэтому вокруг каждой точки прорываем соседей. var neighborCoords = HexHelper.GetNeighbors(offsetCoords.X, offsetCoords.Y); foreach (var coords in neighborCoords) { matrix[coords.X, coords.Y] = true; } } }
public void RenderHexBackground(CubeCoords coords) { if (!_map.MapB.ExistAt(coords) || _map.MapB[coords.x, coords.y].IsNew) { MapGenRandomNeighbours.GenerateHex(coords, _map.MapB, _map.MapF); } HexBackgroundComponent hexComponent = _map.MapB[coords.x, coords.y]; if (hexComponent.Parent != null) { return; //_poolBackground.Recycle(hexComponent.Parent); } hexComponent.Parent = _map.PoolB.Get(); hexComponent.Parent.PoolTransform.localPosition = HexMath.Hex2Pix(coords, HexSize); switch (hexComponent.BackgroundType) { case BackroundTypes.Grass: hexComponent.Parent.PoolTransform.GetComponent <SpriteRenderer>().sprite = Grass; hexComponent.SpeedDown = 1; break; case BackroundTypes.Water: hexComponent.Parent.PoolTransform.GetComponent <SpriteRenderer>().sprite = Water; hexComponent.SpeedDown = 0.1f; break; case BackroundTypes.Swamp: hexComponent.Parent.PoolTransform.GetComponent <SpriteRenderer>().sprite = Swamp; hexComponent.SpeedDown = 0.02f; break; case BackroundTypes.Forest: hexComponent.Parent.PoolTransform.GetComponent <SpriteRenderer>().sprite = Forest; hexComponent.SpeedDown = 0.5f; break; default: throw new Exception("Null ground type"); } hexComponent.Parent.PoolTransform.gameObject.SetActive(true); }
public static CubeCoords[] CubeDrawLine([NotNull] CubeCoords a, [NotNull] CubeCoords b) { var n = a.DistanceTo(b); var list = new List <CubeCoords>(); // Первую итерацию выполняем отдельно. // В ней всегда берём t=0 AddPointToList(a, b, list, 0); // Последующие итерации начинаем с 1, // т.к. первую итерацию обработали. for (var i = 1; i <= n; i++) { // t принимает значения 0..1. // Мы делим 1 на количество шагов n. // И берём i-тый шаг. var t = 1.0f / n * i; AddPointToList(a, b, list, t); } return(list.ToArray()); }
public HexNode(int x, int y) { OffsetX = x; OffsetY = y; CubeCoords = HexHelper.ConvertToCube(x, y); }
private void HideHex(CubeCoords coords) { HideBack(coords); HideFore(coords); }
private void RemoveFore(HexForegroundComponent hexComponent, CubeCoords coords) { _map.PoolF.Recycle(hexComponent.Parent); _map.MapF.ClearAt(coords); }
/// <summary>Возвращает узлы, напрямую соединённые с указанным узлом.</summary> /// <param name="node">Опорный узел, относительно которого выбираются соседние узлы.</param> /// <returns>Возвращает набор соседних узлов.</returns> public override IEnumerable <IMapNode> GetNext(IMapNode node) { var hexCurrent = (HexNode)node; var offsetCoords = new OffsetCoords(hexCurrent.OffsetX, hexCurrent.OffsetY); var segmentX = offsetCoords.X / _segmentSize; if (offsetCoords.X < 0) { segmentX--; } var segmentY = offsetCoords.Y / _segmentSize; if (offsetCoords.Y < 0) { segmentY--; } var localOffsetX = NormalizeNeighborCoord(offsetCoords.X % _segmentSize); var localOffsetY = NormalizeNeighborCoord(offsetCoords.Y % _segmentSize); var segmentKey = new SegmentKey(segmentX, segmentY); var matrix = _segmentDict[segmentKey]; var directions = HexHelper.GetOffsetClockwise(); var currentCubeCoords = HexHelper.ConvertToCube(localOffsetX, localOffsetY); for (var i = 0; i < 6; i++) { var dir = directions[i]; var neighborLocalCube = new CubeCoords(dir.X + currentCubeCoords.X, dir.Y + currentCubeCoords.Y, dir.Z + currentCubeCoords.Z); var neighborLocalOffset = HexHelper.ConvertToOffset(neighborLocalCube); var neighborSegmentX = segmentX; var neighborSegmentY = segmentY; if (neighborLocalOffset.X < 0) { neighborSegmentX--; } else if (neighborLocalOffset.X >= _segmentSize) { neighborSegmentX++; } if (neighborLocalOffset.Y < 0) { neighborSegmentY--; } else if (neighborLocalOffset.Y >= _segmentSize) { neighborSegmentY++; } IMapNode currentNeibour; if (neighborSegmentX == segmentX && neighborSegmentY == segmentY) { currentNeibour = matrix[neighborLocalOffset.X, neighborLocalOffset.Y]; if (currentNeibour == null) { continue; } yield return(currentNeibour); } } }
private static void LerpCube(CubeCoords a, CubeCoords b, float t, out float x, out float y, out float z) { x = Lerp(a.X, b.X, t); y = Lerp(a.Y, b.Y, t); z = Lerp(a.Z, b.Z, t); }