Проблема зацикливания анимации в стиле файтинга XNA - PullRequest
1 голос
/ 11 июля 2010

Я уже давно работаю над этим, ища решения в разных местах. Я использовал стиль хранения анимации Ника Грейвлина в текстовом файле и просто увеличиваю индекс для смены кадров. Проблема в том, что я зацикливаю анимацию один раз и только один раз, но почему-то способ, который, как я знаю, должен работать, работает не так, как я думал. Я не могу понять, почему, если только это не очень зависит от того, как работает 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 нажатие клавиши, как положено.

1 Ответ

0 голосов
/ 11 июля 2010

Из того, что я вижу, код, который вы разместили, просто нарисует последний кадр анимации удара, поскольку цикл for в методе LoopOnce зацикливает все кадры и рисует только последний.Это связано с тем, что метод draw вызывается один раз для каждого обновления.

Сначала XNA вызывает метод update, а затем после вызова draw.Таким образом, в вашем методе обновления вы устанавливаете текущий кадр анимации на максимальный кадр, затем он переходит к методу рисования, где вы затем рисуете текущий кадр, который в данный момент является последним кадром.

Длячтобы это работало, вам нужно будет только увеличивать кадр, который вы хотите нарисовать, на единицу для каждого вызова для обновления.

У меня нет XNA на этом компьютере, поэтому я не могу проверить это, и он, вероятно, не будет компилироваться без исправления синтаксических ошибок, но чтобы дать вам представление, что-то вроде этого должно сделать это

private void UpdateAttack(KeyboardState current, KeyboardState last, GameTime gameTime)
        {
           if (current.IsKeyDown(Keys.S) && last.IsKeyUp(Keys.S))
           {
             mCurrentState =State.Kicking;
             currentImageIndex=25;
           }
           if(mCurrentState ==State.Kicking)
               neutralStandingKick(gameTime);              
        }

   private void neutralStandingKick(GameTime gameTime)
    {
           currentImageIndex++;
            if(currentImageIndex==30) mCurrentStart = State.SomeOtherState;
    } 

Удалите ваш метод один раз.Вам нужно заменить State.SomeOtherState на его состояние, когда объект не пинается.Вы, вероятно, также захотите поменять местами жестко закодированные номера кадров с константами.Ваш метод рисования не должен быть изменен, чтобы эта анимация работала.Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...