Issue with input buffer (in fighting games)

i’m working on a 2D fighting game that uses an input buffer similar to that of the Street Fighter series, using this article and that article to help me.

each move has a priority and sequence. special moves override regular moves (your commands and normals), and you can also charge your attacks. this is a basic example of how a move would look like:

          [1] = {
				Name 	 = "Hadoken";
				Priority = 2;
				Sequence = {"Down", "Forward", "Forward", "A"};
			};

special moves have priority set to 2, while regular moves have priority set to 1
the sequence is just a list of inputs that i have to do in order to perform the move

i created a FIFO queue that handles the players inputs and removes them after a certain time. it works as expected, but the problem i’m struggling with is implementing a feature that checks if the player’s inputs and the desired move’s sequence matches.

source code
local ACTION_EXPIRE 	= 0.5
local BUFFER_WINDOW 	= 50
local LAST_MATCH_INDEX	= 0

local Queue				= FIFO.new( { INPUT = "None", TIME = 0} )
local InputSequence 	= {} --this is a list of buttons the player presses
local Moveset			= nil -- the moveset variable is a table, listing the moves a player can do

local Player			= Players.LocalPlayer

-- private functions
local function CheckInput(action, processed)
	if processed then return end
	
	Queue:push( 
		{ 
			INPUT = InputModule.CommandList[action], 
			TIME = os.time() 
		}
	) 
end

local function CheckSequence()

--[[
 this is where i'm stuck.
how do i figure out if the player's inputs and the hadoken's sequence match?
]]
	
end

local function AddToSequence(input)
	table.insert(InputSequence, input)
	CheckSequence()
end

local function TryBufferedInput()
	local length = Queue:length()

	for i = 1, length do
		local obj = Queue:peek(i)
		local oldTime = obj['TIME']

		if ( (os.time() - oldTime ) > ACTION_EXPIRE) then
			Queue:remove(i)
			break -- sometimes the object returned from Queue:peek() is nil
		else
			AddToSequence(obj['INPUT'])
		end
	end
end

thanks in advance.

7 Likes

any form of help is appreciated.

update:

the input buffer finally works now, i just needed to convert this section of code to lua lol

function Buffer:CheckSequence()
	local bufferIndex		= 0
	local lastMatchIndex	= 0
	local matchedInputCount = 0
	

	for moveIndex = 1, #self.PlayerMoveset do
		bufferIndex 	  = ((#self.InputSequence - 1) + 1) --makes sure that it always stays at 1
		matchedInputCount = 0

		for inputIndex = #self.PlayerMoveset[moveIndex].Sequence, 1, -1 do
			
			while (bufferIndex >= 0) do
				if self.PlayerMoveset[moveIndex].Sequence[inputIndex] == self.InputSequence[bufferIndex] then
					matchedInputCount += 1
					break
				end

				bufferIndex -= 1
			end
		end

		if (matchedInputCount == #self.PlayerMoveset[moveIndex].Sequence) then

			lastMatchIndex = moveIndex
			local move = self.PlayerMoveset[lastMatchIndex]

			if InputController:CheckIfMoveIsValid(move) then
				self.Result:Fire(move)
				self.InputSequence = {}
				break
			end
		end
	end
end
7 Likes

Hi, I was wondering how you were able to achieve this?

I’m struggling on understanding your source code and how to implement this within my own games.

2 Likes