Ich arbeite derzeit an einem Jump'n'Run und versuche, einen Zeitschritt zu implementieren, aber für Framerate Grenzen mehr als 60 die CPU-Auslastung steigt von 1% bis 25% und mehr.Einfaches C++ SFML Programm hohe CPU-Auslastung
Ich habe dieses Minimalprogramm, das Problem zu demonstrieren. Es gibt zwei Kommentare (Zeilen 10-13, Zeilen 26-30) im Code, die das Problem beschreiben und was ich getestet habe.
Beachten Sie, dass die FPS Sachen nicht relevant für das Problem ist (glaube ich).
Ich habe versucht, den Code kurz und einfach zu halten:
#include <memory>
#include <sstream>
#include <iomanip>
#include <SFML\Graphics.hpp>
int main() {
// Window
std::shared_ptr<sf::RenderWindow> window;
window = std::make_shared<sf::RenderWindow>(sf::VideoMode(640, 480, 32), "Test", sf::Style::Close);
/*
When I use the setFramerateLimit() function below, the CPU usage is only 1% instead of 25%+
(And only if I set the limit to 60 or less. For example 120 increases CPU usage to 25%+ again.)
*/
//window->setFramerateLimit(60);
// FPS text
sf::Font font;
font.loadFromFile("font.ttf");
sf::Text fpsText("", font, 30);
fpsText.setColor(sf::Color(0, 0, 0));
// FPS
float fps;
sf::Clock fpsTimer;
sf::Time fpsElapsedTime;
/*
When I set framerateLimit to 60 (or anything less than 60)
instead of 120, CPU usage goes down to 1%.
When the limit is greater, in this case 120, CPU usage is 25%+
*/
unsigned int framerateLimit = 120;
sf::Time fpsStep = sf::milliseconds(1000/framerateLimit);
sf::Time fpsSleep;
fpsTimer.restart();
while (window->isOpen()) {
// Update timer
fpsElapsedTime = fpsTimer.restart();
fps = 1000.0f/fpsElapsedTime.asMilliseconds();
// Update FPS text
std::stringstream ss;
ss << "FPS: " << std::fixed << std::setprecision(0) << fps;
fpsText.setString(ss.str());
// Get events
sf::Event evt;
while (window->pollEvent(evt)) {
switch (evt.type) {
case sf::Event::Closed:
window->close();
break;
default:
break;
}
}
// Draw
window->clear(sf::Color(255, 255, 255));
window->draw(fpsText);
window->display();
// Sleep
fpsSleep = fpsStep - fpsTimer.getElapsedTime();
if (fpsSleep.asMilliseconds() > 0) {
sf::sleep(fpsSleep);
}
}
return 0;
}
Ich will nicht SFML der setFramerateLimit(), aber meine eigene Implementierung mit dem Schlaf verwenden, weil ich die fps Daten verwenden, wird mein zu aktualisieren Physik und so.
Gibt es einen logischen Fehler in meinem Code? Ich sehe es nicht, da es mit einer Framerate-Grenze von beispielsweise 60 (oder weniger) arbeitet. Liegt es daran, dass ich einen 60 Hz Monitor habe?
PS: Mit SFML des Window-> setVerticalSync() ändert sich nicht die Ergebnisse
Vielen Dank dafür!(Entschuldigung für die späte Antwort). Eine Frage zu deinem Code: Verstehe ich richtig, dass die Update-Funktion jetzt einen festen Zeitschritt verwendet, aber es gibt kein Framerate-Limit für das Rendering? Wenn ja, genau das will ich. –
Genau das macht es. –