I am working on an action platformer using Pygame.

My player sprite has three melee attacks. Let's call them SLASH_1, SLASH_2, and SLASH_3. Each of these attacks has, let's say, 2 animation frames, the same hit box, and results in the same amount of damage.

I want the mechanics of my game to be such that if the user presses the attack button three times in quick succession, the sprite will do each attack in turn (regardless of whether there's an enemy around). For an example of what I'm talking about, see here.

I have currently implemented this in the following way:

I have an empty list called "attack_queue" into which I insert attack animation frames when the user presses the attack button. If they press it quick enough, the second and third attacks are added into the list. On each iteration of my game loop, I animate the first frame of the attack_queue (if it's non-empty). The animation code also generates hit boxes for each attack as well as checks for whether the attacks land on an enemy. Once a frame has been animated, it is removed from the attack_queue.

Here's some pseudo-code to give you a better idea:

now = get_current_time()

attack_queue = []
    if attack_button pressed:
        if now - last_attack > 50 ms:
        n = 0
        add attack_animations[n] to attack_queue
        last_attack = now
    else if now - last_attack < 50 ms:
        n += 1        
        add attack_animations[n mod 3] to attack_queue
        last_attack = now       


This works okay for the time being, but I doubt it's the most elegant way of implementing attack chains. (One problem I am having is that this method results in a bit of input lag, since the player is able to press the attack button a third time before the second attack animation has finished.)

My questions are:

  1. In general, what are some other methods of implementing attack chains?
  2. Specifically for Pygame, what are the best ways of implementing attack chains?

A similar question is addressed on Reddit here, but I am looking for a more fully fleshed out answer.


1 Answer 1


The problem with this approach is that when the player presses attack three times, the player-character is locked into the attack chain and the player can not interrupt it. The player might perceive that as unresponsive controls.

Other options:

  • Have the character cycle through all available attack animations while the player holds down the attack button. When an attack animation ends, check if the player is still holding the attack button. If it's still down, proceed with the next attack animation. When it's not down anymore, go back to the default pose.
  • Alternatively, if you want to maintain the haptic of "three button presses = three attacks", add a short time-window after each attack animation:
    • If the player presses the attack button and the current animation is still playing, do nothing.
    • If the last attack ended less than n milliseconds ago, play the next attack animation.
    • If the last attack ended n or more milliseconds ago or this is the first time the player presses attack, play the first animation.
  • 1
    \$\begingroup\$ The first option seems to me like a good option, but I reckon it would be even more responsive if you check for this press in a longer period around the time when the animation ends as well. Keep in mind that one then also needs to check if the button has been released before this press, otherwise holding the button will also result in a melee chain. \$\endgroup\$
    – dragonfly
    Sep 22, 2017 at 22:41
  • 1
    \$\begingroup\$ @dragonfly I would actually ignore whether or not the player released the attack button during the attack. When the player just tapped it and now taps it again at the end of the attack, the player intention is likely to continue the attack chain. An exception would be if the attacks in the attack chain have mechanical differences. In that case there might be situations where the player wants to repeat the first attack instead of performing an attack chain. Holding vs. mashing could be how the player chooses between these two attack modes. \$\endgroup\$
    – Philipp
    Sep 22, 2017 at 22:52

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .