2016-09-27 8 views
1

У меня есть короткий вопрос. Я изучаю SFML, и я сделал несколько приложений, используя его. Когда-нибудь я узнал об использовании фиксированного шага во время игры с кодированием, и было бы здорово, если бы это сработало. НО. Несмотря на то, что я делаю простой проект, как квадрат, перемещающийся слева направо от окна - он отстает! Что может быть причиной этой проблемы? Это мой код:SFML + фиксированный шаг времени = отставание?

#include <SFML/Graphics.hpp> 

int main() 
{ 
    sf::RenderWindow window(sf::VideoMode(800, 600), "Window"); 
    window.setVerticalSyncEnabled(true); 
    sf::Event event; 
    sf::Clock clock; 
    sf::Time accumulator = sf::Time::Zero; 
    const sf::Time timePerFrame = sf::seconds(1.f/60.f); 
    sf::RectangleShape square; 
    square.setSize(sf::Vector2f(32, 32)); 
    square.setOrigin(16, 16); 
    square.setPosition(400, 300); 
    square.setFillColor(sf::Color::Red); 
    int direction = 1; 
    int speed = 300; 
    while(window.isOpen()) 
    { 
     while(window.pollEvent(event)) 
     { 
      if(event.type == sf::Event::Closed) 
      { 
       window.close(); 
      } 
     } 
     while(accumulator >= timePerFrame) 
     { 
      if(square.getPosition().x <= 16 || square.getPosition().x >= 784) direction *= (-1); 
      square.move(sf::Vector2f(speed * direction * timePerFrame.asSeconds(), 0)); 
      accumulator -= timePerFrame; 
     } 
     accumulator += clock.restart(); 
     window.clear(sf::Color::Black); 
     window.draw(square); 
     window.display(); 
    } 
    return 0; 
} 

Как вы можете видеть, я знаю о вертикальной синхронизации, но это не помогает. Является ли мой фиксированный временной шаг неправильным? Любая помощь приветствуется!

+0

Вам не нужно осуществить это самостоятельно 'SF :: Window'has метод под названием' setFramerateLimit' – DogeAmazed

+0

Спасибо за быстрый ответ. Я читал, что использование этой функции не рекомендуется. –

+0

Игнорировать мои последние комментарии, ответ Босслара просветил меня. –

ответ

1

Вы не пытались включить вертикальную синхронизацию? Как вертикальная синхронизация, так и время, которое вы внедрили, могут мешать друг другу, одновременно пытаясь контролировать частоту кадров в одно и то же время. На SFML tutorial page для окон они заявляют:

«Никогда не используйте оба setVerticalSyncEnabled и setFramerateLimit в то же время они будут плохо смешивать и делать вещи хуже!».

Как вы можете видеть здесь из исходного кода для SFML:

void Window::setFramerateLimit(unsigned int limit) 
{ 
    if (limit > 0) 
     m_frameTimeLimit = seconds(1.f/limit); 
    else 
     m_frameTimeLimit = Time::Zero; 
} 

void Window::display() 
{ 
    // Display the backbuffer on screen 
    if (setActive()) 
     m_context->display(); 

    // Limit the framerate if needed 
    if (m_frameTimeLimit != Time::Zero) 
    { 
     sleep(m_frameTimeLimit - m_clock.getElapsedTime()); 
     m_clock.restart(); 
    } 
} 

setFramerateLimit функция SFML осуществляается во многом таким же образом, как и вашем временном шаге, и, таким образом, я не считаю, что ситуация будет отличаться Вот.

После проверки кода на моей машине я увидел небольшую задержку на квадрате, однако отключение вертикальной синхронизации устранило проблему.

Редактировать: Оказалось, что эта проблема сложнее, чем я изначально думал (и я также упускал из виду очевидную потребность в vsync, если есть разрывание). После нескольких дней исследований и возиться с кодом, я узнал несколько вещей, фиксирующих вопрос:

  • Отключение VSYNC (хотя, конечно, мы уже знаем это)
  • Запись программы с Fraps
  • Вызов glFinish() после window.display()
  • Создание окна в любом полноэкранном режиме или без полей (с С.Ф. :: Стиль :: None) в том же размере, что и рабочий стол
  • Отключение Windows Aero тема (хотя, конечно, это относится только к Windows)

Все, кроме первого, исправят его, даже если vsync включен. Основная проблема здесь заключается в том, что vsync работает некорректно в оконном режиме, видимо, это ограничение из-за того, как программа должна совместно использовать пространство экрана с другими программами, которые не обязательно поддерживают vsync.

Поэтому мое предложение:

  • Использование glFinish() после каждого display() вызова при использовании оконного режима, хотя это наказание, он останавливает процессор и синхронизирует его с GPU и мониторинга, когда он может быть обработка асинхронно и бесперебойный, но если ваша программа не особенно интенсивенна для CPU, это не должно быть большой проблемой. В SFML вы можете включить «SFML/OpenGL.hpp», чтобы получить доступ к этой функции.Хотя, если вы используете Windows (Vista и 7, я считаю, что я не знаю, как это работает 8 или 10), то при использовании темы Aero vsync, по-видимому, автоматически активируется, и вы, возможно, не имеете разрыва, чтобы начать. Какую операционную систему ты используешь?
  • Используйте полноэкранный режим и просто соглашайтесь с тем, что в оконном режиме будет заикание. Это может быть даже не заметно в реальной игре или другом графическом приложении, в отличие от жесткого высококонтрастного квадрата, непрерывно движущегося вперед и назад на пустом фоне. Я знаю, что в игре, над которой я работаю прямо сейчас, у меня такая же проблема, но я почти никогда ее не замечал.
  • Прочитайте эту проблему и посмотрите, сможете ли вы найти истинное исправление. По общему признанию использование glFinish является чем-то вроде kludge, и дело с заиканием или разрывом в оконном режиме может быть неприемлемым. Я не совсем уверен, как glFinish удается устранить заикание, и, как правило, никогда не рекомендуется называть эту функцию в любом случае.

Некоторое дальнейшее чтение:

+0

Было ошибкой не читать, как эта функция была реализована. Спасибо, теперь я уверен, что я не должен использовать фиксированный временной шаг с вертикальной синхронизацией в одно и то же время. Но есть еще одна вещь, и это разрывает экран. Если вертикальная синхронизация отключена, визуальные артефакты становятся видимыми. Я нашел видео на youtube, которое показывает ту же проблему: [link] (https://www.youtube.com/watch?v=Kvgz_hQCkZ4). Любое предложение? –

+0

На самом деле вы можете как можно больше обновить свою физику, логику и по-прежнему делать на 60 или 30 кадров в секунду. Это отличное чтение об этом: http://gafferongames.com/game-physics/fix-your-timestep/ – Zouch

+0

@Zouch Проблема, которую я вижу здесь, заключается в том, как vsync должен быть включен для исправления разрыва экрана, а также для сохранения гладкая анимация, так как здесь кажется, что vsync вызывает необычное заикание. Я не могу говорить за меня, но я играл с примерами, приведенными на этом посту, и это, похоже, не устраняет проблему (хотя мне, вероятно, нужно больше времени, чтобы все разобраться). Я тоже честно теряю сейчас. – Bosslard

 Смежные вопросы

  • Нет связанных вопросов^_^