Я уже давно работаю над этим, ища решения в разных местах. Я использовал стиль хранения анимации Ника Грейвлина в текстовом файле и просто увеличиваю индекс для смены кадров. Проблема в том, что я зацикливаю анимацию один раз и только один раз, но почему-то способ, который, как я знаю, должен работать, работает не так, как я думал. Я не могу понять, почему, если только это не очень зависит от того, как работает XNA.
Вот мой код:
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
}
Редактировать: вот метод Draw этого конкретного класса
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
}
Почему бы не сработать?
Новый код (предложение Гэвина):
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;
}
Метод, который вызывает UpdateAttack:
public void Update(GameTime theGameTime, Game game)
{
KeyboardState aCurrentKeyboardState = Keyboard.GetState();
UpdateMovement(aCurrentKeyboardState);
UpdateJump(aCurrentKeyboardState);
UpdateAttack(aCurrentKeyboardState, mPreviousKeyboardState, theGameTime);
UpdateStageBounds(game);
mPreviousKeyboardState = aCurrentKeyboardState;
}
Он зациклит анимацию при удерживании клавиши «s». Но он не будет зацикливать все 7 кадров за 1 нажатие клавиши, как положено.