Fighting Game Input Buffer Implementation in Unity
unknown
csharp
5 months ago
7.4 kB
11
Indexable
using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using System.Linq; public class FightingGameInputBuffer : MonoBehaviour { // Defines a special move with a name and its required input sequence. [System.Serializable] public class SpecialMove { public string moveName; // Name of the special move. public List<string> inputSequence; // Input sequence to execute the move. } // UI components for displaying special move and input buffer. public Text specialMoveText; public Transform bufferDisplayParent; public GameObject buttonImagePrefab; // Duration for displaying a special move message. public float specialMoveDisplayDuration = 2f; private float specialMoveTimer = 0f; // Sprites representing various input directions and actions. public Sprite upSprite, downSprite, leftSprite, rightSprite; public Sprite lightSprite, mediumSprite, heavySprite, specialSprite; public Sprite upLeftSprite, upRightSprite, downLeftSprite, downRightSprite; // Input buffer and configuration. private List<string> buffer = new List<string>(); private float bufferStoreTime = 0.4f; // Maximum time an input remains in the buffer. private int maxBufferSize = 10; // Maximum size of the input buffer. private List<float> inputTimestamps = new List<float>(); // Timestamps for inputs. // List of all defined special moves. public List<SpecialMove> specialMoves = new List<SpecialMove>(); // Mappings of input strings to their corresponding sprites. private Dictionary<string, Sprite> buttonSprites; // Tracks the state of each input key. private Dictionary<string, bool> keyStates = new Dictionary<string, bool> { { "up", false }, { "down", false }, { "left", false }, { "right", false }, { "upleft", false }, { "upright", false }, { "downleft", false }, { "downright", false }, { "light", false }, { "medium", false }, { "heavy", false }, { "special", false } }; // Initialize button sprite mappings. void Start() { buttonSprites = new Dictionary<string, Sprite> { { "up", upSprite }, { "down", downSprite }, { "left", leftSprite }, { "right", rightSprite }, { "upleft", upLeftSprite }, { "upright", upRightSprite }, { "downleft", downLeftSprite }, { "downright", downRightSprite }, { "light", lightSprite }, { "medium", mediumSprite }, { "heavy", heavySprite }, { "special", specialSprite } }; } // Main update loop to handle inputs, buffer management, and special move detection. void Update() { // Handle individual directional and action inputs. HandleInput("up", "Vertical", 1); HandleInput("down", "Vertical", -1); HandleInput("left", "Horizontal", -1); HandleInput("right", "Horizontal", 1); HandleInput("light", "LightAttack", 1); HandleInput("medium", "MediumAttack", 1); HandleInput("heavy", "HeavyAttack", 1); HandleInput("special", "SpecialAttack", 1); // Handle combined diagonal inputs. HandleDiagonalInput("upleft", 1, -1); HandleDiagonalInput("upright", 1, 1); HandleDiagonalInput("downleft", -1, -1); HandleDiagonalInput("downright", -1, 1); // Remove expired inputs from the buffer. CleanExpiredInputs(); // Check if any special moves are executed. CheckSpecialMoves(); // Update the special move display timer. if (specialMoveTimer > 0) { specialMoveTimer -= Time.deltaTime; if (specialMoveTimer <= 0) { specialMoveText.text = ""; // Clear the display when timer expires. } } } // Tracks input states and adds valid inputs to the buffer. void HandleInput(string button, string axisName, float expectedValue) { bool isButtonPressed = Input.GetAxisRaw(axisName) == expectedValue; if (isButtonPressed && !keyStates[button]) { keyStates[button] = true; // Mark input as pressed. AddToBuffer(button); // Add to buffer. } else if (!isButtonPressed) { keyStates[button] = false; // Reset input state. } } // Handles diagonal input detection by combining vertical and horizontal axes. void HandleDiagonalInput(string button, float verticalExpectedValue, float horizontalExpectedValue) { bool isButtonPressed = Input.GetAxisRaw("Vertical") == verticalExpectedValue && Input.GetAxisRaw("Horizontal") == horizontalExpectedValue; if (isButtonPressed && !keyStates[button]) { keyStates[button] = true; AddToBuffer(button); // Add diagonal input to buffer. } else if (!isButtonPressed) { keyStates[button] = false; } } // Adds an input to the buffer and maintains buffer size. void AddToBuffer(string input) { buffer.Add(input); inputTimestamps.Add(Time.time); // Store timestamp. // Remove the oldest input if buffer exceeds maximum size. if (buffer.Count > maxBufferSize) { buffer.RemoveAt(0); inputTimestamps.RemoveAt(0); } UpdateBufferDisplay(); // Update UI to reflect buffer. } // Removes inputs from the buffer that have expired. void CleanExpiredInputs() { float currentTime = Time.time; for (int i = buffer.Count - 1; i >= 0; i--) { if (currentTime - inputTimestamps[i] >= bufferStoreTime) { buffer.RemoveAt(i); // Remove expired input. inputTimestamps.RemoveAt(i); } } } // Checks the buffer for valid special move sequences. void CheckSpecialMoves() { foreach (var move in specialMoves) { // Compare the buffer's recent inputs with the special move's sequence. if (buffer.Count >= move.inputSequence.Count && buffer.Skip(buffer.Count - move.inputSequence.Count).SequenceEqual(move.inputSequence)) { // Display special move and clear the buffer. specialMoveText.text = move.moveName + " Executed!"; specialMoveTimer = specialMoveDisplayDuration; buffer.Clear(); inputTimestamps.Clear(); break; } } } // Updates the UI to display the current input buffer. void UpdateBufferDisplay() { // Clear existing buffer display. foreach (Transform child in bufferDisplayParent) { Destroy(child.gameObject); } // Instantiate UI elements for each input in the buffer. foreach (var button in buffer) { if (buttonSprites.ContainsKey(button)) { GameObject icon = Instantiate(buttonImagePrefab, bufferDisplayParent); icon.GetComponent<Image>().sprite = buttonSprites[button]; } } } }
Editor is loading...
Leave a Comment