2016-12-12 68 views
0

我搜索了這個主題,發現使用sf::Clock來實現幀獨立更新(使用deltaTime)可以幫助解決它。然而,即使在添加槳後,槳運動也會有一些停頓。另一方面,當我將整個Playing的情況轉移到event polling loop而不使用deltatime時,遊戲似乎運行順利。無法順利移動SFML

如何去使用sf::Clock正常在我的代碼?爲什麼我的遊戲,似乎當我甚至不用deltatimePlaying情況下,事件池循環轉移到平穩運行?

遊戲初始化:

void Game::start() { 
    if (_gameState != Uninitialized) { 
     return; 
    } 
    //Creating window 
    _mainWindow.create(sf::VideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, 32), "Pong"); 
    _gameState = ShowingMenu; 

    //Adding game entities to the manager  
    VisibleGameObject *paddle1 = new PlayerPaddle("Player1", 1.0f, sf::Keyboard::Key::Up, sf::Keyboard::Key::Down); 
    VisibleGameObject *paddle2 = new PlayerPaddle("Player2", 1.0f, sf::Keyboard::Key::W, sf::Keyboard::Key::S); 
    VisibleGameObject *background = new Background("Background", 0.0f); 
    paddle1 -> setPosition(SCREEN_WIDTH - (paddle1 -> getWidth()), 0); 
    paddle2->setPosition(0, 0); 
    manager.addObject(paddle1); 
    manager.addObject(paddle2); 
    manager.addObject(background); 

    //Starting Clock 
    deltaTime = 0.0f; 
    frameClock.restart(); 


    while (!isExiting()) {  
     gameLoop(); 
    } 
    _mainWindow.close(); 
} 

遊戲循環:

void Game::gameLoop() 
{ 
    static bool firstPass = true; 
    sf::Event currentEvent; 

    //Event loop 
    while(_mainWindow.pollEvent(currentEvent) || firstPass) 
    { 

     if (firstPass) { 
      currentEvent = sf::Event(); 
      currentEvent.type = sf::Event::GainedFocus; 
      firstPass = false; 
     } 

     if (currentEvent.type == sf::Event::Closed) 
     { 
      _gameState = Exiting; 
     } 

     switch (_gameState) 
     { 
      case ShowingMenu: 
      { 
       showingMenu(); 
       break; 
      } 
      case Paused: 
      { 
       break; 
      } 


      default: 
       break; 
     } 

    } 

    //Extracting deltaTime to update game logic 

    deltaTime = frameClock.restart().asSeconds(); 
    if(_gameState == Playing) 
    { 
     manager.updateAllLayers(deltaTime); 
     manager.drawAllLayers(_mainWindow); 
     _mainWindow.display(); 
    } 
} 

槳更新邏輯:

void PlayerPaddle::update(const float & elapsedTime) 
{ 
    sf::Vector2f currentPos = getPosition(); 
    float displacement = 0.0f; 

    if (sf::Keyboard::isKeyPressed(controls.up)) 
    { 
     displacement = -speed * elapsedTime;  
    } 
    else if (sf::Keyboard::isKeyPressed(controls.down)) 
    { 
     displacement = speed * elapsedTime; 
    } 

    if (displacement + currentPos.y < 0.0f) 
    { 
     setPosition(currentPos.x, 0.0f); 
     return; 
    } 
    else if (displacement + currentPos.y + getHeight() > Game::SCREEN_HEIGHT) 
    { 
     setPosition(currentPos.x, Game::SCREEN_HEIGHT - getHeight()); 
     return; 
    } 

    setPosition(currentPos.x, currentPos.y + displacement); 
} 
+0

,然後你傳遞給Update函數的值是多少? –

+0

@DenisErmolin 1 –

+0

@KaranJoisher firstPass多久出現一次?你能顯示代碼嗎? –

回答

0

我沒有足夠的聲望發表評論,所以我不得不作出回答...

您更新(並繪製)每一幀。如果你想實現一個固定的更新時間步驟,你的遊戲循環沒有意義。

這就是你的遊戲循環應該如何。我用你的變量名爲了您的方便:

// ... 

sf::Clock frameClock; 
const sf::Time timePerFrame = sf::seconds(1.0f/60.0f); 
sf::Time timeSinceLastUpdate = sf::Time::Zero; 

while (_mainWindow.isOpen()) { 
    timeSinceLastUpdate += frameClock.restart(); 

    // events 
    { 
    sf::Event evt; 
    while (_mainWindow.pollEvent(evt)) { 
     //... 
    } 
    } 

    // update 
    { 
    while (timeSinceLastUpdate > timePerFrame) { 
     timeSinceLastUpdate -= timePerFrame; 
     manager.updateAllLayers(timePerFrame); 
    } 
    } 

    // render 
    { 
    _mainWindow.clear(); 
    // ... 
    _mainWindow.display(); 
    } 
} 

// ... 

這將更新您的遊戲在一個固定的速度(1/60),並使得它儘可能(可以使用setFramerateLimit()限制FPS,這會不會影響固定更新間隔,所以沒有問題)。

現在通過sf::Timemanager.updateAllLayers這是用來喜歡你elapsedTime(它有一個像.asSeconds()所以基本上就沒什麼變化的功能,但你顯然需要調整值speed)如果不使用經過時間

+0

烏爾答案是正確的固定更新方法,而我試圖實現一個獨立的更新每秒數的解決方案。我知道,像pong這樣的遊戲並不重要,但我正在學習新的概念。 –