2014-05-09 2 views
3

저는 지난 주 내 게임의 핵심을 만들어 왔으며 렌더링이 단순히 충분하지 않았기 때문에 저는 벽을 때렸습니다. 운동은 육포적이었고, 나는 찢어지고 있었고 일반적으로 많은 지체가있었습니다. 그것을 다시 반복 증가,SFML 렌더링 성능 문제

 sf::RenderWindow window(sf::VideoMode(1024, 768), "Testing"); 
       window.setVerticalSyncEnabled(true); 
     sf::Clock clock; 
     sf::Event event; 
     float elapsed; 
     while(window.isOpen()) 
     { 
       elapsed += clock.restart().asSeconds(); 
       std::cout << 1.f/elapsed << std::endl; 
       while(elapsed > 1.f/60.f) 
       { 
         while(window.pollEvent(event)) 
         { 
           if (event.type == sf::Event::Closed || event.key.code == sf::Keyboard::Escape) 
           { 
             window.close(); 
           } 
         } 
         elapsed -= 1.f/60.f; 
       } 
       window.clear(); 
       window.display(); 
     } 

FPS에는 40에서 시작하여 60까지 이동 한 후 다시 30 폭포 : 나는 매우 간단한 gameloop 렌더링 테스트 그래서 내 게임 엔진의 잘못되지 않을 수 있다고 생각 . VSynct를 false로 설정하면 30-500 fps 사이의 아무 곳이나 구할 수 있습니다. 프레임 속도를 올바르게 테스트하지 않거나 내 nvidia 드라이버에 문제가 있습니다 (변경없이 2 번 재설치했습니다). 어떤 도움을 주셔서 감사합니다!

+0

나는 왜 'elapsed - = 1.f/60.f ;'. 그 뒤에있는 논리는 무엇입니까? 나는 왜 당신이 일정한 것을 빼는 지 알지 못한다. – luk32

+0

이것을 확인하십시오. http://gameprogrammingpatterns.com/game-loop.html – Veritas

답변

1

당신은 나에게 당신과 비슷한 코드를 가진 물질을 지적했지만 당신은 그것을 다르게 썼습니다. 에서

: gameprogrammingpatterns.com/game-loop.html

double previous = getCurrentTime(); 
double lag = 0.0; 
while (true) 
{ 
    double current = getCurrentTime(); 
    double elapsed = current - previous; 
    previous = current; 
    lag += elapsed; 

    processInput(); 

    while (lag >= MS_PER_UPDATE) 
    { 
    update(); 
    lag -= MS_PER_UPDATE; 
    } 

    render(); 
} 

당신은 하나의 변수 모두 elapsed, elapsedlag을 사용하고있는 것으로 보인다. 그것이 나를 당황하게했다. elapsed으로 mangling하면 시간을 측정하는 용도로 사용할 수 없게됩니다. 귀하의 코드는 다음과 같이 보일 것입니다 :

sf::RenderWindow window(sf::VideoMode(1024, 768), "Testing"); 
      window.setVerticalSyncEnabled(true); 
    sf::Clock clock; 
    sf::Event event; 
    float lag; 
    float elapsed; 

    while(window.isOpen()) 
    { 
      lag = elapsed = clock.restart().asSeconds(); 
      std::cout << 1.f/elapsed << std::endl; 
      while(lag > 1.f/60.f) 
      { 
        while(window.pollEvent(event)) 
        { 
          if (event.type == sf::Event::Closed || event.key.code == sf::Keyboard::Escape) 
          { 
            window.close(); 
          } 
        } 
        lag -= 1.f/60.f; 
      } 
      window.clear(); 
      window.display(); 
    } 

정확한지 확실하지 않습니다. 나는 정확히 clock.restart().asSeconds()이 무엇인지 모릅니다. 개인적으로, 필자는 예제와 같이 한 줄씩 구현할 것입니다. 왜 작업 코드를 재 설계해야합니까?

편집 : OP는 "throttling"에 대해 elapsed을 사용하여 시간 측정 변수로서의 목적을 깨고 확인했습니다.

+0

restart() 함수는 경과 시간을 반환하므로 지연 변수를 사용할 필요가 없습니다. 그러나 이처럼 프레임을 세는 데 제대로 작동하지 않을 것이고 나는 그것을 완전히 놓쳤습니다. 나는 지금 60 fps를 일관되게 얻는다, 고마워! – Veritas

+0

그래서 나는 그것을 올바르게 얻었다. 확인해 주셔서 감사합니다. 경과 한 상태에서'+ ='를 사용했기 때문에 정확한지 확신 할 수 없었습니다. 그러나'restart'가 실제로 시계를 다시 시작한다면, 그것을 요약하는 것이 필요하지 않다고 생각합니다. – luk32

1

여기 내가 무엇입니까 이 (가) 발생했습니다. 코드를 올바르게 이해하면 시뮬레이션의 시간 단계를 초당 60 회 일정하게 유지하려고합니다. 루프를 실행해야하는 횟수를 추적하기 위해 일종의 누적기를 사용하고 있습니다. 이와 같은 누산기를 사용할 때의 문제점은 시뮬레이션 루프에 시간이 걸린다는 사실을 기억해야한다는 것입니다. 왜 이것이 문제가되는지 설명하기 위해 몇 가지 사례를 살펴 보겠습니다. 나는 명료성을 위해 16.6666 (1/60 초) 대신 20 밀리 초를 사용하려고합니다. 가정 해 봅시다 :

  1. 시뮬레이션 루프 실행에는 10 밀리 초가 걸립니다. 처음으로 elapsed >= 20, 재설정되고 시뮬레이션 루프가 실행됩니다. 다음에 다시 돌아올 때, elapsed == 10 + c 여기서 c은 작은 것으로 건너 뜁니다. 결국 elapsed >= 20 그리고 다시 반복됩니다. 모든 것이 좋습니다.
  2. 시뮬레이션 루프를 실행하는 데 정확히 20 밀리 초가 걸립니다. elapsed은 20이되고 내부 루프는 실행하려면 20 밀리 초가 걸립니다. 다음에 루프를 실행할 때 elapsed == 20. 그것은 반복됩니다. 모든 것은 기본적으로 괜찮습니다.
  3. 시뮬레이션 루프 실행에는 40 밀리 초가 걸립니다. elapsed이 20이되면 내부 루프가 실행되어 40 밀리 초가 걸립니다. 그런 다음 외부 루프가 이번에는 elapsed == 40으로 다시 실행됩니다. 그런 다음 내부 루프가 80 밀리 초가 걸리는 두 번 실행됩니다. elapsed은 이제 80입니다. 내부 루프는 160 밀리 초를 취하여 4 회 실행됩니다. elapsed은 160입니다. 내부 루프는 8 초에 320 밀리 초가 걸립니다.

물론 시뮬레이션 루프가 걸리는 시간은이 예제와 같이 일정하지 않지만 아이디어는 같습니다.루프를 실행할 시뮬레이션 단계보다 훨씬 더 많은 시간이 걸리지 않는다고 가정 할 수 있다면 좋습니다. 루프를 실행하는 데 1 초당 1/60 초 이상 걸리면 외부 루프가 완료되는 데 더 긴 시간이 소요되는 일종의 피드백 루프가 시작됩니다.

"framerate-dependent movement"문제를 해결하는 일반적인 방법은 내가 가지고있는 모든 update() 타입 함수에 델타 시간을 전달하는 것입니다. 그런 다음, 모든 움직임/공격/그 델타에 의존하는 모든 것. 예를 들어, 운동,이 같은이있을 것이다 :

const static pixelsPerSecond = 100 
update(float delta) { //delta is seconds 
    x += moveX * pixelsPerSecond * delta; 
    y += moveY * pixelsPerSecond * delta; 
} 

편집 : 그냥 내가 권장하는 변수 시간 단계를 필요로 단점을 언급 위의 게시 된 링크를 보았다. 일반적으로 정확한 물리 시뮬레이션이나 멀티 플레이를하지 않는다면 정상적으로 작동합니다. (재미있게도 링크에는 Glenn Fielder's article에 대한 링크가 포함되어 있는데 위의 "죽음의 소용돌이"에 대해서도 언급되어 있습니다.)