【问题标题】:Smooth movement of player SFML播放器 SFML 的平滑移动
【发布时间】:2020-11-09 13:49:15
【问题描述】:
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. 这个角度是否可以变得更平滑,以便运动本身不仅可以向左、向右、对角线等进行吗?我的几何知识在这里不够,所以我请求你的帮助。

【问题讨论】:

    标签: c++ sfml


    【解决方案1】:

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

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

    按照这种方法,用户输入用于计算每次调用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_;
    

    这将类似于阻力的影响。

    【讨论】:

    • 但是加速怎么办?它没有改变!于是精灵变得越来越快,不停歇
    • 你也没有说播放器的最大速度,但我自己实现了它:speed = sqrt(dx * dx + dy * dy); if (speed > maxSpeed) { dx *= maxSpeed / speed; dy *= maxSpeed / speed; }
    • ut 非常感谢你!我没有t thik of acceleration and delta acceleration! But I did it without Vector2f`!
    • @CodePenguin32 阻尼velocity_ = 0.99f * velocity_ 是为了让玩家最终停下来。在这种情况下,阻尼系数为0.99f,但您显然可以选择更强的,例如0.95f。这将使您的播放器提前停止移动。
    【解决方案2】:

    在那个人的帮助下,我做到了这一点,但更好)

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

    【讨论】:

    • 您可以同时创建 acceleartionXaccelerationY 局部变量,这样您就不需要在函数末尾将它们设置为零,因为它们的值不应该在不同的函数中可用来电。如果你想限制速度,我建议你改为计算最大速度的平方,即maxSpeedSquare,这样你就不需要每次调用update()时都调用sqrt(),因为它是一个相对的昂贵的电话。例如:speedSquare = dx * dx + dy * dy; 那么,if (speedSquare > maxSpeedSquare) ...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多