3
\$\begingroup\$

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; } } 
\$\endgroup\$

2 Answers 2

2
\$\begingroup\$

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.

\$\endgroup\$
7
  • \$\begingroup\$ Can u show me how does Animation next, nextAnimation and currentAnimation work? \$\endgroup\$ Commented Feb 26, 2013 at 0:28
  • \$\begingroup\$ Yes, I've updated the answer. \$\endgroup\$ Commented Feb 26, 2013 at 0:42
  • \$\begingroup\$ 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? \$\endgroup\$ Commented Feb 27, 2013 at 23:25
  • \$\begingroup\$ 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. \$\endgroup\$ Commented Feb 28, 2013 at 0:07
  • \$\begingroup\$ 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. \$\endgroup\$ Commented Feb 28, 2013 at 5:49
1
\$\begingroup\$

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.

\$\endgroup\$
1
  • \$\begingroup\$ Sorry for my misunderstanding. Question updated. \$\endgroup\$ Commented Feb 25, 2013 at 13:58

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.