播放器 SFML 的流畅移动

Smooth movement of player SFML

void update(RenderWindow& window)
{
    if (Keyboard::isKeyPressed(Keyboard::W))
    {
        dy = -0.3;
    }
    if (Keyboard::isKeyPressed(Keyboard::A))
    {
        dx = -0.3;
    }
    if (Keyboard::isKeyPressed(Keyboard::S))
    {
        dy = 0.3;
    }
    if (Keyboard::isKeyPressed(Keyboard::D))
    {
        dx = 0.3;
    }
    
    x += dx;
    y += dy;

    dx = dy = 0;

    EntitySprite.setPosition(x, y);

    window.draw(EntitySprite);         
}

当在这样的代码中描述移动时,玩家会按角度移动:向左或向上,或向右或向下,或通过同时按下两个按钮以 45 度角对角线移动,例如 S 和 D。这个角度是否可以变得更平滑,以便运动本身不仅可以向左、向右、对角线等方向进行?我的几何学知识还不够,所以我请求你的帮助)。

在您的代码中,用户输入直接修改玩家位置。这可能是玩家移动看起来如此突然的原因。从技术上讲,在您的代码中,用户输入决定了玩家在任何给定时刻的速度。

更现实的方法是让玩家拥有 速度 属性 – 表示玩家位置的变化率——然后玩家位置只通过这个速度更新,而不是直接从用户输入。相反,速度将直接由输入修改,但不完全由当前输入决定,因为它还取决于其先前的值。

按照这种方法,用户输入用于在每次调用 update() 时计算玩家 加速度。该加速度(速度的变化率)用于直接更新玩家速度。最后,玩家速度反过来用于更新玩家位置。

以下代码通过引入 velocity_ 数据成员和 acceleration 局部变量来实现此方法:

void update(RenderWindow& window) {
    sf::Vector2f acceleration;

    // adjust this at will
    const float dAcc = 0.3f;

    // set acceleration
    if (Keyboard::isKeyPressed(Keyboard::W))
      acceleration.y -= dAcc;
    if (Keyboard::isKeyPressed(Keyboard::A))
      acceleration.x -= dAcc;
    if (Keyboard::isKeyPressed(Keyboard::S))
      acceleration.y += dAcc;
    if (Keyboard::isKeyPressed(Keyboard::D))
      acceleration.x += dAcc;

    // update velocity through acceleration
    velocity_ += acceleration;
    
    // update position through velocity
    x += velocity_.x;
    y += velocity_.y;

    // apply damping to the velocity
    velocity_ = 0.99f * velocity_;

    EntitySprite.setPosition(x, y);

    window.draw(EntitySprite);
};

这样一来,玩家就有了某种惯性,动作看起来更流畅了。

请注意,您可能希望对速度进行一些阻尼,如:

velocity_ = 0.99f * velocity_;

这将类似于阻力的效果。

在那个人的帮助下我这样做了,但有些更好)

 void update(RenderWindow& window) 
        {
            float decceleration = 0.3;
    
            if (Keyboard::isKeyPressed(Keyboard::W))
            {
                accelerationY -= decceleration;
            }
            if (Keyboard::isKeyPressed(Keyboard::S))
            {
                accelerationY += decceleration;
            }
            if (Keyboard::isKeyPressed(Keyboard::A))
            {
                accelerationX -= decceleration;
            }
            if (Keyboard::isKeyPressed(Keyboard::D))
            {
                accelerationX += decceleration;
            }
    
            dx += accelerationX;
            dy += accelerationY;
    
            speed = sqrt(dx * dx + dy * dy);
            if (speed > maxSpeed)
            {
                dx *= maxSpeed / speed;
                dy *= maxSpeed / speed;
            }
    
            x += dx;
            y += dy;
    
            dx *= 0.9;
            dy *= 0.9;
    
            accelerationX = 0;
            accelerationY = 0;
    
            EntitySprite.setPosition(x, y);
            window.draw(EntitySprite);
    
        }