Я делаю игру «астероиды» на C ++ и SFML, и меня интересует плавное замедление и ускорение. В оригинальной игре, когда вы двигались в каком-то направлении, вы набирали «импульс», который увеличивался, пока кнопка удерживалась, и уменьшался при отпускании. Я начал свою собственную версию этого. В настоящее время у меня есть sf::Vector2f
содержащий импульс корабля. Это может быть отрицательным или положительным. Проблема в том, что я не могу правильно реализовать замедление (я даже не пытался ускорить его). Я пробовал следующее;
if (plr.momentum.x < 0) {
plr.momentum.x++;
}
if (plr.momentum.x > 0) {
plr.momentum.x--;
}
if (plr.momentum.y < 0) {
plr.momentum.y++;
}
if (plr.momentum.y > 0) {
plr.momentum.y--;
}
При этом после перемещения игрок медленно перетаскивается в верхний левый угол окна (координаты 0,0). Я предполагаю, что это потому, что число с плавающей запятой, например, 0,05, соответствует выражению «больше 0» if. От этого требуется один, что делает его минус. Следующий оператор if добавляет один к нему, и это непрерывно зацикливается. отрицательный x
импульс движется влево, а отрицательный y
импульс движет вас вверх, и наоборот. Я хотел бы знать методологию плавного замедления и ускорения.
Если вам интересно / интересно, я использую следующий код для перемещения игрока в соответствии с его динамикой;
playerSprite.move(plr.momentum);
Если вы не знакомы с SFML, sf::Vector2f
имеет .x
а также .y
, которые используются в .move
из sf::Sprite playerSprite
, .move
перемещает игрока относительно его текущей позиции; так что если игрок в (5,0), и вы делаете player.move(sf::Vector2f(-1,0))
их координаты будут (4,0).
РЕДАКТИРОВАТЬ:
Теперь у меня есть следующий код для замедлений в качестве предложения от друга. Замедление работает отлично, но после замедления оно снова начинает двигаться в верхний левый угол. Чем это вызвано?
if (plr.xSlowdown < 0.f) {
plr.xSlowdown += 0.1f;
}
if (plr.xSlowdown > 0.f) {
plr.xSlowdown -= 0.1f;
}
if (plr.ySlowdown < 0.f) {
plr.ySlowdown += 0.1f;
}
if (plr.ySlowdown > 0.f) {
plr.ySlowdown -= 0.1f;
}
plr.xMomentum = floor(plr.xSlowdown);
plr.yMomentum = floor(plr.ySlowdown);
Если вы хотите, чтобы ваш космический корабль замедлялся, когда двигатели выключены, вы должны добавить сопротивление.
Перетащите силу, основанную на скорости: самый простой способ сделать F = -K v
для коэффициента сопротивления K
, Итак, если импульс вашего корабля хранится в plr.xMomentum
а также plr.yMomentum
Ваша программа будет:
// note: "dt" is your timestep;
// if you don't have one, just choose some small value for "fraction", like 0.005
float fraction = drag_coefficient_K * dt;
plr.xMomentum -= fraction * plr.xMomentum;
plr.yMomentum -= fraction * plr.yMomentum;
Ускорение будет зависеть от ориентации вашего космического корабля:
// note: "orientation" is the angle of your spaceship;
// the units of orientation are determined by "angle_scale",
// which should be chosen such that "angle_in_radians" is in radians...
float angle_in_radians = angle_scale * orientation;
float thrust_per_timestep = thrust_value * dt;
plr.xMomentum += thrust_per_timestep * cos(angle_in_radians);
plr.yMomentum += thrust_per_timestep * sin(angle_in_radians);
Комбинация сопротивления и тяги фактически устанавливает верхний предел скорости, которую вы можете достичь (по крайней мере, без помощи гравитации или чего-то еще …).
То, что вы хотите, это физика. Очень простая физика: F = ма.
Вам нужно иметь некоторое представление об ускорении, скорости и положении. Пользовательский ввод диктует ускорение. Ускорение меняет скорость, а скорость меняет положение.
В сторону: нет разницы между замедлением и ускорением. Они оба ускорение.