2016-12-12 65 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这样的游戏并不重要,但我正在学习新的概念。 –