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 want to run a animation until it has gone through all the frames, even when the activation key is no longer held. After the animation is completely finished, it goes back to walking state. I also want to force the animation to finish first before the player can trigger the new animation.

     if (mCurrentState == State.Walking)
        {
            action = "stand";
            Update_Stand(gameTime);

            if (aCurrentKeyboardState.IsKeyDown(Keys.Left) == true)
            {
                action = "run";
                feetPosition.X += MOVE_LEFT;
                effect = SpriteEffects.None;

                Update_Run(gameTime);

            }
            else if (aCurrentKeyboardState.IsKeyDown(Keys.Right) == true)
            {
                action = "run";
                feetPosition.X += MOVE_RIGHT;
                effect = SpriteEffects.FlipHorizontally;

                Update_Run(gameTime);
            }

            if (aCurrentKeyboardState.IsKeyDown(Keys.Z) == true)
            {
                mCurrentState = State.Hitting;
            }
        }

        if (mCurrentState == State.Hitting)
        {
            action = "hit";

            Update_Hit(gameTime);

            mCurrentState = State.Walking;
        }

My Update_Hit(GameTime gameTime) method is something like that.

// Amount of time between frames 
TimeSpan frameInterval_Hit; 
// Time passed since last frame 
TimeSpan nextFrame_Hit; 

 public void Update_Hit(GameTime gameTime)
    {
        // Check if it is a time to progress to the next frame
        if (nextFrame_Hit >= frameInterval_Hit)
        {
            // Progress to the next frame in the row
            currentFrame_Hit.X++;

            // If reached end of the row advance to the next row, reset to the first frame 
            if (currentFrame_Hit.X >= sheetSize_Hit.X)
            {
                currentFrame_Hit.X = 0;
                currentFrame_Hit.Y++;
            }

            // If reached last row in the frame sheet, jump to the first row again
            if (currentFrame_Hit.Y >= sheetSize_Hit.Y)
                currentFrame_Hit.Y = 0;

            // Reset time interval for next frame
            nextFrame_Hit = TimeSpan.Zero;
        }
        else
        {
            // Wait for the next frame
            nextFrame_Hit += gameTime.ElapsedGameTime;
        }
    }
share|improve this question

2 Answers 2

up vote 2 down vote accepted

A simple generic approach should work. You should really consider making your animations more generic by making them objects, instead of all that hard coding you're doing now. Once you do, add an attribute to your animations and some simple code for handling animations.

Each animation should have a boolean flag indicating if it requires finishing, like your punching animation. Then when a new animation is requested, you can do a simple check:

public void changeAnimation(Animation next) {
    if(currentAnimation.IsPlaying() && currentAnimation.RequiresFinish())
       nextAnimation = next;
    else
       currentAnimation = next;
}

Then, have some code that handles the transition.

private void onAnimationEnd() {
    if(nextAnimation != null) {
        currentAnimation = nextAnimation;
        nextAnimation = null;
    } else {
        currentAnimation = getIdleAnimation();
    }
}

Where currentAnimation and nextAnimation are instances of a animation class. Something like:

class Animation {
    // Amount of time between frames 
    TimeSpan frameInterval; 
    // Time passed since last frame 
    TimeSpan nextFrameInterval; 
    Vec2 currentFrame;
    Vec2 sheetSize;

    public Animation (Vec2 currentFrame, Vec2 sheetSize) {
        this.currentFrame = currentFrame;
        this.sheetSize = sheetSize;
        this.frameInterval = new TimeSpan();
        this.nextFrameInterval = new TimeSpan();
    }

    public void update(GameTime gameTime) {
        // Check if it is a time to progress to the next frame
        if (nextFrameInterval>= frameInterval)
        {
            // Progress to the next frame in the row
            currentFrame.X++;

            if (currentFrame.X >= sheetSize_Hit.X)
            {
                currentFrame.X = 0;
                currentFrame.Y++;
            }

            // If reached last row in the frame sheet, jump to the first row again
            if (currentFrame.Y >= sheetSize.Y)
                currentFrame.Y = 0;

            // Reset time interval for next frame
            nextFrameInterval = TimeSpan.Zero;
        }
        else
        {
            // Wait for the next frame
            nextFrameInterval+= gameTime.ElapsedGameTime;
        }
    }
}

Using an object like this makes it reusable for other animations, instead of just being used for the hit animation. Now when you want to change animations, you can easily just set the currentAnimation to whatever animation object you want, and use all the same code for updating the animation.

share|improve this answer
    
Can u show me how does Animation next, nextAnimation and currentAnimation work? –  optimisez Feb 26 '13 at 0:28
    
Yes, I've updated the answer. –  Byte56 Feb 26 '13 at 0:42
    
I still not understand about how public void changeAnimation(Animation next) function works. Why assign next to nextAnimation and currentAnimation and what is the purpose of putting else? –  optimisez Feb 27 '13 at 23:25
    
It means that if the current animation is still playing and it's not allowed to be canceled early, then trying to apply a new animation gets applied to next. Otherwise it gets set to the current animation. It's a way of protecting the current animation from being changed if it's still playing. –  Byte56 Feb 28 '13 at 0:07
    
Sorry. I'm happy to answer questions on the site, but if you want my one on one programming support, I charge by the hour. –  Byte56 Feb 28 '13 at 5:49

You could create a bool variable like so

 bool isPunching = false;

then wrap a an if loop around Update_Hit(gameTime);, and a if not loop around your mCurrentState = "walking";

  if (mCurrentState == State.Hitting)
    {
        action = "hit";
        isPunching = true;

        if (isPunching)
        {
            Update_Hit(gameTime);
        }

        if (!isPunching)
        {
            mCurrentState = State.Walking;
        }
    }

now in your Update_Hit() method, at the end of the loop add a

 isPunching = false;

Hope this helped.

share|improve this answer
    
Sorry for my misunderstanding. Question updated. –  optimisez Feb 25 '13 at 13:58

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.