using UnityEngine; public class TargetCursor : MonoBehaviour { public GameManager gameManager; public GameObject cursorVisual; private bool isShootingInProgress = false; public bool isPlacingShips = false; public GamePole ownField; private int x = 4; private int y = 4; private int width = 10; private int height = 10; private Direction currentDirection = Direction.Right; private PlayerKeySet player1Keys = new PlayerKeySet { Up = ButtonPinMapping.up1, Down = ButtonPinMapping.down1, Left = ButtonPinMapping.left1, Right = ButtonPinMapping.right1, Fire = ButtonPinMapping.action1, TurnLeft = ButtonPinMapping.turnLeft1, TurnRight = ButtonPinMapping.turnRight1 }; private PlayerKeySet player2Keys = new PlayerKeySet { Up = ButtonPinMapping.up2, Down = ButtonPinMapping.down2, Left = ButtonPinMapping.left2, Right = ButtonPinMapping.right2, Fire = ButtonPinMapping.action2, TurnLeft = ButtonPinMapping.turnLeft2, TurnRight = ButtonPinMapping.turnRight2 }; private PlayerKeySet activeKeys; // Текущий квадрант камеры: 0=вперёд, 1=вправо, 2=назад, 3=влево private int cameraQuadrant = 0; // Возвращает физическую кнопку которую нужно нажать чтобы сдвинуть курсор в нужном направлении // dx,dy — логическое направление движения курсора на поле private ButtonPinMapping GetKeyForDirection(int dx, int dy) { // Поворот камеры на 90° вправо: физическая ось поворачивается // q=0: вперёд=вверх, вправо=вправо, назад=вниз, влево=влево // q=1: вперёд=вправо, вправо=вниз, назад=влево, влево=вверх // q=2: вперёд=вниз, вправо=влево, назад=вверх, влево=вправо // q=3: вперёд=влево, вправо=вверх, назад=вправо, влево=вниз int rotDx = dx; int rotDy = dy; for (int i = 0; i < cameraQuadrant; i++) { // Поворот вектора на -90° (камера повернулась вправо — вектор поворачиваем влево) int tmp = rotDx; rotDx = rotDy; rotDy = -tmp; } // Теперь rotDx/rotDy — это какую физическую кнопку нажать if (rotDx == 0 && rotDy == -1) return activeKeys.Up; if (rotDx == 0 && rotDy == 1) return activeKeys.Down; if (rotDx == 1 && rotDy == 0) return activeKeys.Right; if (rotDx == -1 && rotDy == 0) return activeKeys.Left; return activeKeys.Up; // fallback } // кнопочки (только fire и поворот корабля — они не зависят от камеры) private ButtonPinMapping fireKey; private ButtonPinMapping turnLeftKey; private ButtonPinMapping turnRightKey; public Transform cameraPivot; public float rotateSpeed = 90f; private int playerId; private int enemyId; public void Initialize(GameManager gm, int playerId = 1, bool isPlacingShips = false) { this.isPlacingShips = isPlacingShips; gameManager = gm; if (isPlacingShips) ownField = gm.playerField; else ownField = gm.enemyField; BindKeys(playerId); if (cameraPivot == null) { cameraPivot = gameManager.cameraPivot; // SetParent НЕ делаем здесь — этим управляет MoveCameraSmoothly // чтобы не конфликтовать с корутиной перемещения камеры } // всегда настраиваем контроллер var camCtrl = cameraPivot.GetComponent(); if (camCtrl == null) camCtrl = cameraPivot.gameObject.AddComponent(); camCtrl.Setup( gameManager, cameraPivot, turnLeftKey, turnRightKey, rotateSpeed, this // аргумент есть в сигнатуре, но внутри не используется ); enemyId = gameManager.opponentManager.playerId; this.playerId = playerId; Debug.Log("Родился"); UpdateCursorPosition(); } private void BindKeys(int playerId) { activeKeys = (playerId == 1) ? player1Keys : player2Keys; // Направления (up/down/left/right) не копируем — они вычисляются через MapKey + cameraQuadrant fireKey = activeKeys.Fire; turnLeftKey = activeKeys.TurnLeft; turnRightKey = activeKeys.TurnRight; } public void SwitchButton(Vector3 rotate) { if (activeKeys == null) return; // защита от вызова до Initialize float y = rotate.y; if (y > 180) y -= 360; Debug.Log($"Y rotation = {y}"); if (y >= -45 && y < 45) cameraQuadrant = 0; // вперёд else if (y >= 45 && y < 135) cameraQuadrant = 1; // вправо else if (y >= 135 || y < -135) cameraQuadrant = 2; // назад else cameraQuadrant = 3; // влево } void Update() { if (isShootingInProgress) return; if (gameManager.currentInputMode == GameManager.InputMode.UI) return; // --- Поворот корабля в режиме расстановки --- if (isPlacingShips) { if (In.GetButtonDown(turnLeftKey)) { // вращаем влево (против часовой) currentDirection = (Direction)(((int)currentDirection + 3) % 4); UpdateCursorPosition(); } else if (In.GetButtonDown(turnRightKey)) { // вращаем вправо (по часовой) currentDirection = (Direction)(((int)currentDirection + 1) % 4); UpdateCursorPosition(); } } // --- Только в свой ход --- if (!isPlacingShips && (gameManager.currentState != GameState.Playing || !gameManager.isPlayerTurn)) return; // --- Движение курсора --- bool moved = false; if (In.GetButtonDown(GetKeyForDirection( 0, -1))) { MoveCursor( 0, -1); moved = true; } if (In.GetButtonDown(GetKeyForDirection( 0, 1))) { MoveCursor( 0, 1); moved = true; } if (In.GetButtonDown(GetKeyForDirection( 1, 0))) { MoveCursor( 1, 0); moved = true; } if (In.GetButtonDown(GetKeyForDirection(-1, 0))) { MoveCursor(-1, 0); moved = true; } if (moved) UpdateCursorPosition(); // --- Выстрел / установка --- if (In.GetButtonDown(fireKey)) { if (!isPlacingShips) TryShoot(); else TryPlaceCurrentShip(); } } void UpdateCursorPosition() { Cell targetCell = ownField.GetCell(x, y); if (targetCell != null) { cursorVisual.transform.position = targetCell.transform.position + Vector3.back * 0.1f; } if (isPlacingShips) { ownField.ClearGhost(); ownField.ShowShipGhost(x, y, currentDirection); } } void TryShoot() { if (isShootingInProgress) return; if (ownField.PoleShot[x, y] != 0) return; isShootingInProgress = true; if (gameManager.gameMode == GameMode.PlayerVsPlayer) { gameManager.opponentManager.enemyBattery.FireShot( gameManager.opponentManager.playerField, x, y, (wasHit, wasShipDestroyed) => { // мистр кастыль gameManager.opponentManager.ProcessShotResult(wasHit, false, wasShipDestroyed); }); } gameManager.battery.FireShot(gameManager.enemyField, x, y, (wasHit, wasShipDestroyed) => { gameManager.ProcessShotResult(wasHit, true, wasShipDestroyed); if (!wasHit)gameManager.EndPlayerTurn(); isShootingInProgress = false; }); } void TryPlaceCurrentShip() { bool placed = ownField.PlaceShipManual(x, y, currentDirection); if (placed) gameManager.AddShipPlayer(); } void RotateDirection() { currentDirection = (Direction)(((int)currentDirection + 1) % 4); } void MoveCursor(int dx, int dy) { if (isPlacingShips) { x += dx; y += dy; if (x < 0) x = width - 1; if (x >= width) { x = width - 1; gameManager.SetInputMode(GameManager.InputMode.UI); return; } if (y < 0) y = height - 1; if (y >= height) y = 0; return; } else { x += dx; y += dy; if (x < 0) x = width - 1; if (x >= width) x = 0; if (y < 0) y = height - 1; if (y >= height) y = 0; } } } [System.Serializable] public class PlayerKeySet { public ButtonPinMapping Up; public ButtonPinMapping Down; public ButtonPinMapping Left; public ButtonPinMapping Right; public ButtonPinMapping Fire; public ButtonPinMapping TurnLeft; public ButtonPinMapping TurnRight; }