I've been working on this for quite some time looking for solutions in various places. I've used Nick Gravelyn's style of storing animations into a text file and am simply incrementing an index to change frames. The trouble I'm having is looping an animation once and only once, but for some reason the way that I know should work isn't working the way I thought it would. I can't for the life of me figure out why, unless it's very specific to how XNA works.
Here is my code:
private void UpdateAttack(KeyboardState current, KeyboardState last, GameTime gameTime)
{
if (current.IsKeyDown(Keys.S) && last.IsKeyUp(Keys.S))
{
neutralStandingKick(gameTime);
}
}
private void neutralStandingKick(GameTime gameTime)
{
//timeSinceLastFrame += gameTime.ElapsedGameTime.Milliseconds; //Framerate control
//if (timeSinceLastFrame > millisecondsPerFrame) //Framerate control
//{
//timeSinceLastFrame -= millisecondsPerFrame; //Framerate control
if (mCurrentState != State.Kicking)
{
mCurrentState = State.Kicking;
Position.Y = 200;
loopOnce(25, 30); //Starts at frame 25, ends at 30
}
//}
}
private void loopOnce(int min, int max)
{
if (currentImageIndex > max || currentImageIndex < min) //Checks to see if index out of range of current animation
currentImageIndex = min; //Starts at the beginning of the animation
for (int i = min; i < max; i++) //Uses the range to determine when to stop
{ currentImageIndex++; } //Increments index each iteration that passes
}
Edit: Here is the Draw method of this particular class
public void Draw(SpriteBatch spriteBatch)
{
//Get the name of the current sprite to draw
string spriteName = possibleImages[currentImageIndex];
//Use that to get the source rectangle
Rectangle source = spriteSourceRectangles[spriteName];
//Send rectangle to a function to set the framesize for bounds checking
getFrameSize(source);
spriteBatch.Draw(theSpriteSheet, Position, source, Color.White);
}
private void getFrameSize(Rectangle frame)
{
frameSize = frame; //For bounds checking
}
Why wouldn't this work?
New Code (Gavin's Suggestion):
private void UpdateAttack(KeyboardState current, KeyboardState last, GameTime gameTime)
{
const int min = 22;
const int max = 30;
timeSinceLastFrame += gameTime.ElapsedGameTime.Milliseconds; //Framerate control
if (current.IsKeyDown(Keys.S) && mCurrentState != State.Kicking)
{
mCurrentState = State.Kicking;
currentImageIndex = min;
}
if (mCurrentState == State.Kicking)
{
if (timeSinceLastFrame > millisecondsPerFrame) //Framerate control
{
timeSinceLastFrame -= millisecondsPerFrame; //Framerate control
currentImageIndex++;
}
}
if (currentImageIndex == max)
mCurrentState = State.Idle;
}
Method that calls UpdateAttack:
public void Update(GameTime theGameTime, Game game)
{
KeyboardState aCurrentKeyboardState = Keyboard.GetState();
UpdateMovement(aCurrentKeyboardState);
UpdateJump(aCurrentKeyboardState);
UpdateAttack(aCurrentKeyboardState, mPreviousKeyboardState, theGameTime);
UpdateStageBounds(game);
mPreviousKeyboardState = aCurrentKeyboardState;
}
It will loop the animation on holding the keyboard key "s" down. But it will not loop all 7 frames in 1 key press like it's supposed to.