Quick answer: A boolean buffer stores only the most recent input. Replace it with a timestamped array queue, push new inputs on press, expire old entries past the window, and consume the first match when you exit lockout.

Your fighting game has an attack button that should chain into a second attack if pressed during the first animation’s recovery frames. You add a boolean attack_buffered that sets on press and clears on use. Combos still drop inputs. The flag is being overwritten by inputs arriving later in the window, and there’s no record of the original press.

Why Flags Fail

A boolean is a 1-bit buffer. If two inputs arrive in the same window, the second overwrites the first. For combo systems, you need every input in the window, timestamped so you can discard expired ones.

The Queue Pattern

// Create event
input_buffer = [];  // array of {action, frame}
input_buffer_window = 10;  // 10 frames

// Step event: capture input
if (keyboard_check_pressed(vk_space))
    array_push(input_buffer, {action: "attack", frame: current_frame});

// Expire old entries
while (array_length(input_buffer) > 0 &&
       current_frame - input_buffer[0].frame > input_buffer_window) {
    array_delete(input_buffer, 0, 1);
}

// On exit from lockout, consume matching input
if (can_attack) {
    for (var i = 0; i < array_length(input_buffer); i++) {
        if (input_buffer[i].action == "attack") {
            array_delete(input_buffer, i, 1);
            start_attack();
            break;
        }
    }
}

Per-Action Windows

A 10-frame window for everything is rarely right. Jumps need 6 frames (any more feels floaty). Dashes need 3. Special moves can extend to 15 for forgiving input. Store the window with the action or pick it at consumption time:

var window = (action == "jump") ? 6 : (action == "special") ? 15 : 10;

Buffer During Lockout

The whole point of buffering is accepting input during recovery animation. Don’t gate input capture on state — always push to the queue. Gate consumption on state instead. This lets the player feed a combo before the previous attack finishes, which is how fighters feel responsive.

Verifying

Add a debug Draw GUI that shows the current buffer contents. You should see inputs appear, age, and get consumed or expire. If an input appears and immediately disappears, a boolean flag is still in the chain somewhere.

“Input feel is buffer tuning. The difference between a snappy combo and a frustrating miss is usually 4 frames of window.”

Related Issues

For broader event timing, see GameMaker alarm not firing. For touch input buffering, see how to debug touch input bugs.

Always show the buffer on screen during development. You’ll tune window sizes by eye in minutes instead of hours.