Hold Buffers
My favorite kind of input buffer by far is a hold buffer.
How does it work?
The idea is pretty simple. Once you press a button, that buttons is buffered. It stays buffered until:
- It results in an action, or
- You release the button press.
Here are the benefits to this kind of buffer system over a normal 5 frame buffer for example:
- Players can buffer moves for longer if they want to, making the game easier to control.
- If the player doesn't know how this buffer system works, then they'll naturally have a roughly 4-5 frame buffer, because that's how long players tend to hold a button press for normally.
- If a player wants to, they can cancel their buffer early. So they'll never have the disadvantages that normally come with long buffer times, where a move will come out that they feel like they didn't want.
- For any player who's ever buffered anything out of hitstop, this will already feel natural.
- It's by far the easiest buffer system to implement in my opinion.
Implementation Overview
The easiest way to implement this in my opinion is to keep a list of buffered buttons, or a dictionary of button names with Booleans for whether they're buffered or not. Then you define the following two functions:
First is a "handle buffer" function that runs each frame and does the following for each pressable button your game has (for example ABCD or LMH):
- If the button is not currently held, clear it from the buffer.
- If the button is held, but it was also held last frame, do nothing.
- If the button was pressed this frame, add it to the buffer.
Then a "check buffer" function which takes a button as input:
- If the button is in the buffer, remove it and return
True. - If the button is not in the buffer, return
False.
Then whenever you want to check for a button press for an attack, you use the check buffer function. Just make sure you check all the other requirements for the attack first so you don't eat any inputs.
Technical Implementation
The following is an example of how you implement a hold buffer in Python. In this case self.Buffer, InputsThisFrame, and self.InputsLastFrame are all dictionaries with the keys being button names, and the values being Booleans.
def HandleBuffer(self,InputsThisFrame):
# Inputs is a dictionary here
for ButtonName in InputsThisFrame:
if not InputsThisFrame[ButtonName]:
# If we're not holding the button, unbuffer it
self.Buffer[ButtonName]=False
continue
if self.InputsLastFrame[ButtonName]:
# If we were already holding it, don't change the buffer
continue
# If we pressed it this frame, add it to the buffer
self.Buffer[ButtonName]=True
def CheckBuffer(self,ButtonName):
if self.Buffer[ButtonName]:
# Remove it from the buffer now that it's been used
self.Buffer[ButtonName]=False
return True
else:
return False
Addendum: Adding a time limit
Some games prefer to add a time limit so the buffer doesn't last forever even if you hold the button forever. The fix for this is very simple.
- Instead of storing only true or false, store 0 and 1.
- If the button is held down and buffered, but not pressed this frame add one to the buffer.
- If the buffer is above whatever timer your want, set it to 0.