播放器 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);
}
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);
}