Почему замедляется анимация через Clock в SFML

Разрабатываю платформер на SFML. Карта загружается через tinyXML(с помощью TileMapEditor). По какой-то причине, спрайты на втором уровне платформера замедляют свою анимацию. Анимация спрайтов я завязал на объекте clock класса Clock. Создаю переменную float time=clocl.getRelapsedTime... А после этого в зависимости от того, сколько времени прошло перерисовываю спрайт с помощью setTextureRect. При этом, когда запускается новый уровень, переменная time заново инициализируется и проблем быть не должно было. При этом имеется строчка time=time/800, которая как бы делает более плавной анимацию на карте. Эта строчка хорошо работает для первого уровня. Чтобы сделать примерно такую же анимацию на втором уровне нужно поставить примерно time=time/400. Но я так и не понял почему так работает, если clock инициализируется заново. Прилагаю ниже минимальный код... Итак, цикл пока открыто окно занимается отрисовкой всего:

// Для обеспечения большей плавности работаем со временем
// Создадим переменную времени(объект время)
Clock clock;


// Время игры
Clock timeGame;
...
// Цикл, пока окно открыто, обновляем его
while (window.isOpen())
{

    // Передаем в time прошедшее время
    float time = clock.getElapsedTime().asMicroseconds();
    

    // Игровое время в секундах идет
    if (p.life == true)
        timePlayerAlive = timeGame.getElapsedTime().asSeconds();


        // Перезагрузка времени
    clock.restart();
    // Чем больше знаменатель, тем плавнее игра(хотя разница не очень видна :( )
    time = time / 800;

    Event event;
    while (window.pollEvent(event))
    {
        if (event.type == Event::Closed)
            window.close();
        /*
        * В цикле событий именно потому, что если написать
        “если нажат пробел, то стрельнуть” вне цикла событий, то
        будет слишком много пуль, так как нажатие кнопки для компьютера будет
        дольше намного, чем для человека
          */
          //если выстрелили, то создается объект пуля. enum передаем как int 
        
        if (p.isShoot == true)
        {
            p.isShoot = false;
            entities.push_back(new Bullet(BulletImage, "Bullet", lvl, p.x+38, p.y+19, 31, 16, p.state));
            shoot.play();//играем звук пули
            FirstShoot = true;
            timeShootC.restart();
        }

        /* Если оставить обработку нажатия на Tab просто в блоке
        *  обработчиков кнопок, то картинка будет мигать и будет
        *  обновляться только при нажатии повторно на клавишу Tab
        *  причина - неизвестна. Если оставить это в блоке обработчика
        *  самого окна, то все будет работать нормально :)
        */

        //  Обработка события нажатия на кнопку Tab
        if (event.type == Event::KeyPressed)
        {
            if (Keyboard::isKeyPressed(Keyboard::Tab))
            {
                // Выбор, нажата ли уже кнопка или нет
                switch (showMissionText)
                {..........

В том числе в этом цикле обновляется и какая-то картинка(делается анимация). В нее передается постоянно обновляющееся время time, процедура обновления, например, монетки:

void update(float time, float& CurrentFrame2) override
{
    if (name == "Coin") {
        CurrentFrame2 += 0.005 * time;
        if (CurrentFrame2 > 6) CurrentFrame2 -= 6;
        sprite.setTextureRect(IntRect(24 * int(CurrentFrame2), 0, 24, 24));
        sprite.setPosition(x + w / 2, y + h / 2);
    }
    if (name == "Card") {
        CurrentFrame2 += 0.005 * time;
        if (CurrentFrame2 > 8) CurrentFrame2 -= 8;
        sprite.setTextureRect(IntRect(24 * int(CurrentFrame2), 0, 24, 24));
        sprite.setPosition(x + w / 2, y + h / 2);
    }
}

А так происходит запуск уровня. Да, можно вместо возврата bool функции выше сразу вернуть gameOption, потом поправится, я думаю:

// Процедура перезапуска игры, если это необходимо
void gameRunning(RenderWindow &window,int & numberLevel) {
    // если startGame() == true, то вызываем занова ф-цию isGameRunning, 
    // которая в свою очередь опять вызывает startGame() 
    int gameOption = 0;
    bool run = startGame(window, numberLevel, gameOption);
    // gameOption == 1 - рестарт текущего уровня
    // gameOption == 2 - Выход из игры
    // gameOption == 3 -запуск следующего уровня
    if (run==true && gameOption == 1) 
    {   
        
        gameRunning(window,numberLevel); 
    }
    if (run == false && gameOption == 2)
    {
        exit;
    }
    if (run == true && gameOption == 3)
    {
        numberLevel++;
        gameRunning(window, numberLevel);
    }
    
}
int main()
{   

    RenderWindow window(VideoMode(1280, 720), "My Platformer");
    // Сначала загрузка первого уровня
    int numberLevel = 1;
    gameRunning(window,numberLevel);
    return 0;
}

В итоге имеем, что кадры анимации картинки будут прокручиваться как бы быстрее на втором уровне.


Ответы (1 шт):

Автор решения: IvanDx

Итак, причина замедления анимация заключается не совсем в Clock. Как видно из кода, каждому объекту с анимацией, например, объекту класса Money присуще изменение кадров при помощи CurrentFrame. Однако, в текущей версии CurrentFrame является единственным для всех объектов данного класса. Иными словами, обновляя анимацию одного объекта этого класса, обновлялась анимация другого объекта. Поэтому она и ускоряется. Решение: добавить в поле данного класса собственное CurrentFrame, которое будет у каждого объекта. При вызове update обновляется уже собственный CurrentFrame, а не общий для класса

→ Ссылка