Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm not sure if the title is exactly an accurate representation of what I'm actually trying to ask, but that was the best I could think of. I am experiencing an issue with my character class. I have developed a system so that he can perform chain attacks, and something that was important to me was that 1)button presses during the process of an attack wouldn't interrupt the character, and 2) at the same time, button presses should be stored so that the player can smoothly queue up chain attacks in the middle of one so that gameplay doesn't feel rigid or unresponsive.

This all begins when the player presses the punch button. Upon pressing the punch button, the game checks the state of the dpad at the moment of the button press, and then translates the resulting combined buttons into an int which I use as an enumerator relating to a punch method for the character. The enumerator is placed into a List so that the next time the character's Update() method is called, it will execute the next punch in the list. It only executes the next punch if my character is flagged with acceptInput as true. All attacks flag acceptInput as false, to prevent the interruption of attacks, and then at the end of an attack, acceptInput is set back to true. While accepting input, all other actions are polled for, i.e. jumping, running, etc.

In runtime, if I attack, and then queue up another attack behind it (by pressing forward+punch) I can see the second attack visibly execute, which should flag acceptInput as false, yet it gets interrupted and my character will stop punching and start running if I am still holding down the dpad.

Included is some code for context.

This is the input region for my character.

//Placed this outside the if (acceptInput) tree because I want it 
//to be taken into account whether we are accepting input or not.
//This will queue up attacks, which will only be executed if we are accepting input.
//This creates a desired effect that helps control the character in a
// smoother fashion for the player.
if (Input.justPressed(buttonManager.Punch))
{
    int dpadPressed = Input.DpadState(0);

    if (attackBuffer.Count() < 1)
    {
        attackBuffer.Add(CheckPunch(dpadPressed));
    }
    else
    {
        attackBuffer.Clear();
        attackBuffer.Add(CheckPunch(dpadPressed));
    }
}

if (acceptInput)
{

    if (attackBuffer.Count() > 0)
    {
        ExecutePunch(attackBuffer[0]);
        attackBuffer.RemoveAt(0);
    }

    //If D-Pad left is being held down.
    if (Input.DpadDirectionHeld(0, buttonManager.Left))
    {
        flipped = false;
        if (onGround)
        {
            newAnimation = "run";
        }
        velocity = new Vector2(velocity.X - acceleration, velocity.Y);
        if (walking == true && velocity.X <= -walkSpeed)
        {
            velocity.X = -walkSpeed;
        }
        else if (walking == false && velocity.X <= -maxSpeed)
        {
            velocity.X = -maxSpeed;
        }
    }

    //If D-Pad right is being held down.
    if (Input.DpadDirectionHeld(0, buttonManager.Right))
    {
        flipped = true;
        if (onGround)
        {
            newAnimation = "run";
        }
        velocity = new Vector2(velocity.X + acceleration, velocity.Y);
        if (walking == true && velocity.X >= walkSpeed)
        {
            velocity.X = walkSpeed;
        }
        else if (walking == false && velocity.X >= maxSpeed)
        {
            velocity.X = maxSpeed;
        }
    }

    //If jump/accept button is pressed.
    if (Input.justPressed(buttonManager.JumpAccept))
    {
        if (onGround)
        {
            Jump();
        }
    }

    //If toggle element next button is pressed.
    if (Input.justPressed(buttonManager.ToggleElementNext))
    {
        if (elements.Count != 0)
        {
            elementInUse++;

            if (elementInUse >= elements.Count)
            {
                elementInUse = 0;
            }
        }
    }

    //If toggle element last button is pressed.
    if (Input.justPressed(buttonManager.ToggleElementLast))
    {
        if (elements.Count != 0)
        {
            elementInUse--;

            if (elementInUse < 0)
            {
                elementInUse = Convert.ToSByte(elements.Count() - 1);
            }
        }
    }

    //If character is in the process of jumping.
    if (jumping == true)
    {
        if (Input.heldDown(buttonManager.JumpAccept))
        {
            velocity.Y -= fallSpeed.Y;
            maxJumpTime -= elapsed;
        }

        if (Input.justReleased(buttonManager.JumpAccept) || maxJumpTime <= 0)
        {
            jumping = false;
            maxJumpTime = 0;
        }
    }

    //Won't execute abilities if input isn't being accepted.
    foreach (PlayerAbility ability in playerAbilities)
    {
        if (buffer.Matches(ability))
        {
            if (onGround)
            {
                ability.Activate();
            }
            if (!onGround && ability.UsableInAir)
            {
                ability.Activate();
            }
            else if (!onGround && !ability.UsableInAir)
            {
                buffer.Clear();
            }
        }
    }
}

When the attackBuffer calls ExecutePunch(int) method, ExecutePunch() will call one of the following methods:

private void NeutralPunch1() //0
    {
        acceptInput = false;
        busy = true;
        newAnimation = "punch1";
        numberOfAttacks++;
        timeSinceLastAttack = 0;
    }

    private void ForwardPunch2(bool toLeft) //true == 7, false == 4
    {
        forwardPunch2Timer = 0f;
        acceptInput = false;
        busy = true;
        newAnimation = "punch2begin";
        numberOfAttacks++;
        timeSinceLastAttack = 0;

        if (toLeft)
        {
            velocity.X -= 800;
        }

        if (!toLeft)
        {
            velocity.X += 800;
        }
    }

I assume the attack is being interrupted due to the fact that ExecutePunch() is in the same if statement as running, but I haven't been able to find a suitable way to stop this happening.

Thank you ahead of time for reading this, I apologize for it having become so long winded.

share|improve this question
    
When is the first block of code being executed? Every step? –  Anko Jun 16 '12 at 19:56
    
You can't really break out, except with something like a goto but I don't recommend you start using those. You can use return; to leave a function entirely. –  Byte56 Jun 16 '12 at 19:56
    
The first block of code is executed every step within my character's Update() method. I've read about goto's, and understand why I don't want to use that. I'm not sure how I would go about using return;? –  TheBroodian Jun 16 '12 at 19:58
add comment

1 Answer

up vote 2 down vote accepted

Pretty long question, but if I read it correctly: acceptInput could change after you've check it? So check it again:

if (acceptInput)
{
    if (attackBuffer.Count() > 0)
    {
        ExecutePunch(attackBuffer[0]);
        attackBuffer.RemoveAt(0);
    }

    // ## Inserted additional check here
}
if (acceptInput)
{
    // The rest of your code
share|improve this answer
    
See- That's exactly what I thought too, but if I do it that way, it still behaves exactly the same way, which confuses me further yet... –  TheBroodian Jun 16 '12 at 20:12
    
I'd check the code that sets acceptInput back to true, and make sure it's not executing when you don't want it to –  John McDonald Jun 16 '12 at 20:22
    
I will do so, thank you for the advice! –  TheBroodian Jun 16 '12 at 20:42
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.