using UnityEngine;
///
/// Реализация системы ввода с клавиатуры для тестирования и разработки.
/// Эмулирует работу периферийной платы через стандартные клавиши клавиатуры.
///
///
/// Соответствие клавиш и пинов:
/// - Игрок 1: WASD + Space
/// - Игрок 2: Стрелки + RightControl
/// - Служебные: 1, 2, 3, F5
/// - Датчики хопера: O, P
///
public class KeyboardInput : InputSource
{
private int currentPlayer = 1;//ПЕРЕОПРЕДЕЛИТЕ ОПРЕДЕЛЕНИЕ ТЕКУЩЕГО ИГРОКА ПОД СВОЮ СИСТЕМУ.
//private GameManager gm;//я получаю кто сейчас ходит через этого менеджера. Если у вас другое, допишите.
/// Проверяет состояние кнопки по её физическому пину через клавиатуру
public override bool GetButton(ButtonPinMapping button) => Input.GetKey(getKeyCode(button));
/// Проверяет нажатие кнопки по пину в текущем кадре через клавиатуру
public override bool GetButtonDown(ButtonPinMapping button) => Input.GetKeyDown(getKeyCode(button));
/// Проверяет отпускание кнопки по пину в текущем кадре через клавиатуру
public override bool GetButtonUp(ButtonPinMapping button) => Input.GetKeyUp(getKeyCode(button));
//----------------------------------------------------------------------------------
/// Проверяет состояние кнопки по числовому индексу пина через клавиатуру
public override bool GetButton(int pinIndex) => Input.GetKey(getKeyCode(pinIndex));
/// Проверяет нажатие кнопки по индексу пина в текущем кадре через клавиатуру
public override bool GetButtonDown(int pinIndex) => Input.GetKeyDown(getKeyCode(pinIndex));
/// Проверяет отпускание кнопки по индексу пина в текущем кадре через клавиатуру
public override bool GetButtonUp(int pinIndex) => Input.GetKeyUp(getKeyCode(pinIndex));
//----------------------------------------------------------------------------------
/// Проверяет состояние действия для текущего игрока (всегда игрок 1 для клавиатуры)
public override bool GetButtonCurrentPlayer(PlayerAction button) => GetButton(GetButtonForCurrentPlayer(button));
/// Проверяет начало действия текущим игроком в текущем кадре
public override bool GetButtonDownCurrentPlayer(PlayerAction button) => GetButtonDown(GetButtonForCurrentPlayer(button));
/// Проверяет завершение действия текущим игроком в текущем кадре
public override bool GetButtonUpCurrentPlayer(PlayerAction button) => GetButtonUp(GetButtonForCurrentPlayer(button));
//----------------------------------------------------------------------------------
/// Проверяет состояние действия для любого из игроков (игрок 1 ИЛИ игрок 2)
public override bool GetButtonAnyPlayer(PlayerAction button) => CheckBothPlayers(button, GetButton);
/// Проверяет начало действия любым игроком в текущем кадре
public override bool GetButtonDownAnyPlayer(PlayerAction button) => CheckBothPlayers(button, GetButtonDown);
/// Проверяет завершение действия любым игроком в текущем кадре
public override bool GetButtonUpAnyPlayer(PlayerAction button) => CheckBothPlayers(button, GetButtonUp);
//----------------------------------------------------------------------------------
///
/// Инициализирует клавиатурный ввод. Всегда возвращает true так как клавиатура всегда доступна.
///
/// Всегда true
public override bool Initialize() => true;
// ================================================================================
// ВСПОМОГАТЕЛЬНЫЕ МЕТОДЫ
// ================================================================================
///
/// Определяет кнопку текущего игрока для указанного действия.
/// Для клавиатуры всегда возвращает кнопку первого игрока.
///
private ButtonPinMapping GetButtonForCurrentPlayer(PlayerAction button)
{
var buttons = _buttonByAction(button);
return currentPlayer == 1 ? buttons.player1button : buttons.player2button;
}
///
/// Проверяет действие для обоих игроков используя указанную функцию проверки.
///
private bool CheckBothPlayers(PlayerAction action, System.Func buttonFunc)
{
var buttons = _buttonByAction(action);
return buttonFunc(buttons.player1button) || buttonFunc(buttons.player2button);
}
///
/// Возвращает соответствие между игровыми действиями и физическими кнопками игроков.
///
private (ButtonPinMapping player1button, ButtonPinMapping player2button) _buttonByAction(PlayerAction playerAction) =>
playerAction switch
{
PlayerAction.up => (ButtonPinMapping.up1, ButtonPinMapping.up2),
PlayerAction.down => (ButtonPinMapping.down1, ButtonPinMapping.down2),
PlayerAction.left => (ButtonPinMapping.left1, ButtonPinMapping.left2),
PlayerAction.right => (ButtonPinMapping.right1, ButtonPinMapping.right2),
PlayerAction.action => (ButtonPinMapping.action1, ButtonPinMapping.action2),
PlayerAction.rotateLeft => (ButtonPinMapping.turnLeft1, ButtonPinMapping.turnLeft2),
PlayerAction.rotateRight => (ButtonPinMapping.turnRight1, ButtonPinMapping.turnRight2),
_ => throw new System.ArgumentException($"Unknown player action: {playerAction}")
};
///
/// Преобразует физический пин в соответствующую клавишу клавиатуры.
///
private KeyCode getKeyCode(ButtonPinMapping button)
{
return button switch
{
ButtonPinMapping.up1 => KeyCode.W,
ButtonPinMapping.right1 => KeyCode.D,
ButtonPinMapping.down1 => KeyCode.S,
ButtonPinMapping.left1 => KeyCode.A,
ButtonPinMapping.action1 => KeyCode.Space,
ButtonPinMapping.up2 => KeyCode.UpArrow,
ButtonPinMapping.right2 => KeyCode.RightArrow,
ButtonPinMapping.down2 => KeyCode.DownArrow,
ButtonPinMapping.left2 => KeyCode.LeftArrow,
ButtonPinMapping.action2 => KeyCode.RightControl,
ButtonPinMapping.turnLeft1 => KeyCode.LeftShift ,
ButtonPinMapping.turnRight1 => KeyCode.RightShift,
ButtonPinMapping.secret1 => KeyCode.F5,
ButtonPinMapping.hasPrize1 => KeyCode.O,
_ => KeyCode.None,
};
}
///
/// Преобразует числовой индекс пина в соответствующую клавишу клавиатуры.
/// Используется для методов с прямым доступом по индексу.
///
private KeyCode getKeyCode(int pinIndex)
{
return pinIndex switch
{
0 => KeyCode.W, // up1
1 => KeyCode.D, // right1
2 => KeyCode.S, // down1
3 => KeyCode.A, // left1
4 => KeyCode.Space, // action1
5 => KeyCode.UpArrow, // up2
6 => KeyCode.RightArrow, // right2
7 => KeyCode.DownArrow, // down2
8 => KeyCode.LeftArrow, // left2
9 => KeyCode.RightControl, // action2
10 => KeyCode.LeftShift, // startOnePlayer
11 => KeyCode.RightShift, // startTwoPlayers
12 => KeyCode.F5, // secret
14 => KeyCode.O, // hasPrize
15 => KeyCode.P, // prizeGiven
_ => KeyCode.None, // невалидный индекс
};
}
}