2016-12-12 9 views
0

Ich suchte nach diesem Thema und festgestellt, dass die Verwendung von sf::Clock Frame unabhängige Update (mit deltaTime) zu implementieren kann dazu beitragen, es zu lösen. Aber auch nach dem Hinzufügen stottert die Paddelbewegung ein wenig. Auf der anderen Seite, wenn ich den gesamten Playing Fall auf event polling loop ohne Verwendung von deltatime verschiebe, scheint das Spiel reibungslos zu laufen.Kann nicht reibungslose Bewegung in SFML

Wie gehe ich über sf::Clock richtig in meinem Code verwenden und warum ist mein Spiel scheint glatt zu laufen, wenn ich den Playing Fall in Ereignispool Schleife verschieben, ohne auch nur deltatime zu verwenden?

Spiel Initialisierung:

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(); 
} 

Spiel Loop:

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(); 
    } 
} 

Paddle-Update-Logik:

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

Wenn die verstrichene Zeit nicht verwenden, dann Welchen Wert übergeben Sie an die Update-Funktion? –

+0

@DenisErmolin 1 –

+0

@KaranJoisher Wie oft wird FirstPass wahr? Kannst du Codes anzeigen? –

Antwort

0

Ich habe nicht genug Reputation, um einen Kommentar zu posten, also muss ich das eine Antwort geben ...

Sie aktualisieren (und zeichnen) jeden Frame. Ihre Spielschleife macht keinen Sinn, wenn Sie einen festen Aktualisierungszeitschritt implementieren möchten.

So sollte Ihre Spielschleife aussehen. Ich benutze Ihre Variablennamen für Ihre Bequemlichkeit:

// ... 

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(); 
    } 
} 

// ... 

Das aktualisiert Ihr Spiel mit einer festen Rate (1/60s) und macht es, wenn möglich (Sie können setFramerateLimit() verwenden, um die FPS zu begrenzen, dies wird keine Auswirkungen auf die Update-Intervall behoben, also kein Problem da).

Sie jetzt sf::Time auf Ihre manager.updateAllLayers geben, die wie Ihre verwendet wird elapsedTime (es hat funktioniert wie .asSeconds() so im wesentlichen nichts ändert, aber Sie werden müssen offensichtlich die Werte für speed einstellen)

+0

Ur Antwort ist korrekt für den festen Update-Ansatz, während ich versuche, eine Lösung zu erreichen, die unabhängig von der Anzahl der Updates pro Sekunde ist. Ich weiß, dass es für Spiele wie Pong keine Rolle spielt, aber ich tue es, um neue Konzepte zu lernen. –