You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SFML代码中打印速度值为何会影响矩形的加减速行为?

SFML加速度模拟程序异常:移除打印语句后速度失控

我编写了一个SFML加速度模拟程序:按下按键时矩形加速,松开按键时矩形减速直至停止。但出现了奇怪的问题——只要保留打印速度值(x_change或y_change)的std::cout语句,程序运行完全正常;一旦删除这些打印语句,矩形就会失控,移动速度远超设定的max_speed。我使用VSCode搭配g++编译器,尝试将max_speed从5降至1也无效果,只有保留打印时程序才正常。

原代码

#include <SFML/Graphics.hpp>
#include <iostream>

int main()
{
    int width = 600, height = 800;

    sf::RenderWindow window(sf::VideoMode(width, height), "Testing things");


    sf::RectangleShape r1(sf::Vector2f(50, 50));
    r1.setFillColor(sf::Color::Blue);

    float acc_x = 0, acc_y = 0;
    float x_change = 0, y_change = 0;
    float x = 300, y = 300;
    float max_speed = 2;

    sf::Vector2f rect_pos = sf::Vector2f(x, y);


    bool run = true;
    while (run)
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                run = false;
        }

        acc_x = 0; acc_y = 0;

        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
            acc_x = -0.2;
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
            acc_x = 0.2;
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
            acc_y = -0.2;
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
            acc_y = 0.2;


        //X axis acceleration
        x_change += acc_x;

        //Normalizing the speed.
        if (abs(x_change) >= max_speed)
            x_change = x_change / abs(x_change) * max_speed;

        //Decelerating.
        if (acc_x == 0)
            x_change *= 0.99;


        //The printing lines (necessary for the code to work ??)
        std::cout << x_change << std::endl;
        std::cout << y_change << std::endl;

        rect_pos.x += x_change;

        //Y axis acceleration
        y_change += acc_y;

        if (abs(y_change) >= max_speed)
            y_change = y_change / abs(y_change) * max_speed;

        if (acc_y == 0)
            y_change *= 0.99;

        rect_pos.y += y_change;

        r1.setPosition(rect_pos);


        window.clear();
        window.draw(r1);
        window.display();
    }

    return 0;
}

问题根源

你的程序没有**固定帧率或使用时间差(delta time)**计算运动。打印语句会大幅减慢循环执行速度,间接限制了每秒循环次数(帧率);一旦去掉打印,CPU会全力运行循环,每秒循环次数暴增,导致加速度acc_x/acc_y被叠加的次数异常多,速度自然突破max_speed限制。

解决方案

有两种简单的修复方式:

方式1:固定帧率

在创建窗口后,添加一行代码固定帧率(比如60帧/秒),让循环每秒执行固定次数:

window.setFramerateLimit(60);

方式2:使用时间差(delta time)

用SFML的sf::Clock计算每帧的时间间隔,将加速度和速度变化乘以这个时间差,让运动完全独立于帧率,这是更专业的游戏运动处理方式:

修改后的代码示例:

#include <SFML/Graphics.hpp>
#include <iostream>
#include <cmath>

int main()
{
    int width = 600, height = 800;

    sf::RenderWindow window(sf::VideoMode(width, height), "Testing things");
    sf::Clock clock; // 添加时钟对象

    sf::RectangleShape r1(sf::Vector2f(50, 50));
    r1.setFillColor(sf::Color::Blue);

    float acc_x = 0, acc_y = 0;
    float x_change = 0, y_change = 0;
    float x = 300, y = 300;
    float max_speed = 200; // 因乘以时间差,速度值可适当调大
    sf::Vector2f rect_pos = sf::Vector2f(x, y);

    bool run = true;
    while (run)
    {
        sf::Time deltaTime = clock.restart(); // 获取从上一帧到当前的时间差
        float dt = deltaTime.asSeconds(); // 转换为秒数

        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                run = false;
        }

        acc_x = 0; acc_y = 0;

        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
            acc_x = -100; // 加速度值适配时间差调大
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
            acc_x = 100;
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
            acc_y = -100;
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
            acc_y = 100;

        //X axis acceleration
        x_change += acc_x * dt; // 加速度叠加乘以时间差

        //速度限制
        if (abs(x_change) >= max_speed)
            x_change = x_change / abs(x_change) * max_speed;

        //减速适配时间差
        if (acc_x == 0)
            x_change *= pow(0.99, 1/dt);

        rect_pos.x += x_change * dt; // 位置更新乘以时间差

        //Y axis acceleration
        y_change += acc_y * dt;

        if (abs(y_change) >= max_speed)
            y_change = y_change / abs(y_change) * max_speed;

        if (acc_y == 0)
            y_change *= pow(0.99, 1/dt);

        rect_pos.y += y_change * dt;

        r1.setPosition(rect_pos);

        window.clear();
        window.draw(r1);
        window.display();
    }

    return 0;
}

内容的提问来源于stack exchange,提问作者kripi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 09:47:04