我的 pong 实现非常不稳定,我认为这可能是因为我计算程序睡眠时间的方式。 最大帧速率设置为 60,我的计算机应该能够以 60 帧运行它。
我遵循了本指南,但我不确定我做得是否正确。
这是我的main.cpp文件:
#include <SFML/Graphics.hpp>
#include <iostream>
#include "Paddle.hpp"
int framerateLimit = 60;
unsigned int width = 800;
unsigned int height = 600;
int main()
{
sf::RenderWindow window(sf::VideoMode({width, height}), "My window");
window.setFramerateLimit(framerateLimit);
sf::RectangleShape leftPaddle;
leftPaddle.setSize(sf::Vector2f(10,50));
leftPaddle.setPosition(sf::Vector2f(20, height / 2.0 - leftPaddle.getSize().y/2));
std::cout << leftPaddle.getPosition().x << "," << leftPaddle.getPosition().y << std::endl;
sf::RectangleShape rightPaddle;
rightPaddle.setSize(sf::Vector2f(10, 50));
rightPaddle.setPosition(sf::Vector2f(width - 20 - leftPaddle.getSize().x, height / 2.0 - leftPaddle.getSize().y / 2));
sf::Clock clock;
const float deltaTime = 0.01f;
float accumulator = 0.0f;
float currentTime = clock.getElapsedTime().asSeconds();
while (window.isOpen())
{
int64_t startTicks = clock.getElapsedTime().asMilliseconds();
float newTime = clock.getElapsedTime().asSeconds();
float frameTime = newTime - currentTime;
currentTime = newTime;
accumulator += frameTime;
while (accumulator >= deltaTime) {
while (const std::optional event = window.pollEvent())
{
// "close requested" event: we close the window
if (event->is<sf::Event::Closed>()) {
window.close();
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::W)) {
Paddle::moveUp(leftPaddle);
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::S)) {
Paddle::moveDown(leftPaddle);
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::Up)) {
Paddle::moveUp(rightPaddle);
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::Down)) {
Paddle::moveDown(rightPaddle);
}
}
accumulator -= deltaTime;
}
const float alpha = accumulator / deltaTime;
window.clear(sf::Color::Black);
window.draw(leftPaddle);
window.draw(rightPaddle);
window.display();
int frameTicks = clock.getElapsedTime().asMilliseconds() - startTicks;
if (frameTicks < 1000 / framerateLimit) {
int duration = 1000 / framerateLimit - frameTicks;
sf::sleep(sf::milliseconds(duration));
}
}
}
这是我的运动实现:
#include "Paddle.hpp"
void Paddle::moveUp(sf::RectangleShape& paddle) {
paddle.getPosition().y <= 10.f ? paddle.setPosition(sf::Vector2f(paddle.getPosition().x,0)) : paddle.move(sf::Vector2f(0, -10));
}
void Paddle::moveDown(sf::RectangleShape& paddle) {
paddle.getPosition().y >= height - paddle.getSize().y - 10 ? paddle.setPosition(sf::Vector2f(paddle.getPosition().x,height - paddle.getSize().y)) : paddle.move(sf::Vector2f(0, 10));
}
而不是使用 window.clear()、window.draw() 和 window.display() 然后睡觉。将这些调用放在 if() 语句中,该语句检查自上次重新绘制窗口以来是否已经过了 1/60 秒。
您还可以在绘制帧之前放置一些游戏计算逻辑,而不是您的 CPU 可以处理的数量
类似:
total += deltaTime;
if(total>=(1/framerate))
{
total=0;
additionalGameCalculationLogic();
window.clear();
window.draw();
window.display();
}