Я пытаюсь сделать клон астероидов, и пока я получил свой корабль, чтобы летать. Однако его скорость также зависит от FPS. Итак, чтобы смягчить то, что я прочитал, мне нужно умножить мои управляющие переменные на deltaTime (время между кадрами, если я собрал правильно). Однако когда я попытался осуществить это, корабль отказался двигаться. Я думал, что это связано с возможным неявным округлением до 0 (преобразование в int?), Но предупреждений не выдается. Что я делаю неправильно?
Вот как выглядит код:
sf::Vector2f newPosition(0,0);
sf::Vector2f velocity(0,0);
float acceleration = 3.0f;
float angle = 0;
float angularVelocity = 5;
float velDecay = 0.99f;sf::Clock deltaClock;
window.setFramerateLimit(60);
while (window.isOpen())
{
sf::Time deltaTime = deltaClock.restart();
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed || ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape)))
window.close();
}
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
{
if(velocity.x < 10)velocity.x += acceleration * deltaTime.asSeconds();
if(velocity.y < 10)velocity.y += acceleration * deltaTime.asSeconds();
angle = player.getRotation() - 90;
}
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
{
if(velocity.x > 0)velocity.x -= acceleration * deltaTime.asSeconds();
else velocity.x = 0;
if(velocity.y > 0)velocity.y -= acceleration * deltaTime.asSeconds();
else velocity.y = 0;
}
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
{
player.rotate(-angularVelocity);
}
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
{
player.rotate(angularVelocity);
}
newPosition.x = player.getPosition().x + (velocity.x * cos(angle * (M_PI / 180.0))) * deltaTime.asSeconds();
newPosition.y = player.getPosition().y + (velocity.y * sin(angle * (M_PI / 180.0))) * deltaTime.asSeconds();
player.setPosition(newPosition);
velocity.x *= velDecay;
velocity.y *= velDecay;
window.clear();
window.draw(background);
window.draw(player);
window.draw(debugText);
window.display();
}
Я не могу запустить ваш код, поэтому я не могу быть уверен на 100%, но следующее выглядит некорректно:
velocity.x = (player.getPosition().x + (acceleration * cos(angle * (M_PI / 180.0)) * deltaTime.asSeconds()));
velocity.y = (player.getPosition().y + (acceleration * sin(angle * (M_PI / 180.0)) * deltaTime.asSeconds()));
Попробуйте изменить это на что-то вроде этого:
velocity.x = (player.getVelocity().x + (acceleration * cos(angle * (M_PI / 180.0)) * deltaTime.asSeconds()));
velocity.y = (player.getVelocity().y + (acceleration * sin(angle * (M_PI / 180.0)) * deltaTime.asSeconds()));
Для этого используется простое физическое уравнение vf = vi + a * t, но в виде компонента x, y. Я считаю, что использование Position.x и Position.y полностью отбросит это уравнение.
Примечание: с точки зрения синтаксиса приведенный мною код может не работать. Поместите любой код в player.getVelocity().x
это даст вам текущую скорость игрока в направлении X. Сделайте то же самое для направления Y.
Я не могу быть уверен, если player.setPosition(velocity);
это правильно или нет. Если функция setPosition позаботится о следующем:
newPosition.x = oldPosition.x + (velocity.x/dt)
и в направлении х и у, то это должно работать.
Но если он просто делает:
newPosition.x = velocity.x
Тогда я считаю, что это будет неправильно и приведет к неправильной симуляции.
В вашем коде могут быть другие математические ошибки. Особенно с тем, как вы рассчитываете ускорение. Я не проверял это дважды, и на данный момент у меня нет времени. Если вы внесете коррективы, о которых я упоминал, и они все еще не работают, оставьте мне комментарий, и я смогу попытаться посмотреть больше, когда у меня будет время. У меня есть своя собственная игра, чтобы начать работу прямо сейчас.
Ваш код выглядит намного лучше. Отсюда я бы добавил код, который меняет ваше ускорение. Скажем, нажатие клавиши w включит «подруливающие устройства», что даст вам ускорение 2. Ускорение будет уменьшаться (возвращаться к нулю) в течение ВРЕМЕНИ, когда ни одна клавиша не будет нажата. Не за кадр. До того, как вы умножили на 0,99 за кадр. Это означает, что ускорение может быть нулевым за полсекунды, если вы получаете 120 кадров в секунду (это вполне возможно в простой игре, подобной этой). Вы должны уменьшить его в зависимости от вашей переменной dt. Однако, как только он достигнет нуля, у вас все равно будет положительная скорость. Обычно эта скорость со временем уменьшается из-за силы тяжести, но гравитация в космосе будет очень мала по сравнению с тем, что вы найдете на Земле (-9,8 м / с или -32 фут / с). Так что, возможно, вы могли бы реализовать гравитационный спад на вашей скорости, который также рассчитывается во времени
ИЛИ ЖЕ
Вы можете игнорировать гравитацию и позволить им нажать клавишу S и применить отрицательное ускорение (-2), а затем применить это к своей скорости, как вы это сделали. Это позволит отрицательным значениям ухудшить вашу скорость и может рассматриваться как то, что ваши корабли поворачивают двигатели в противоположном направлении.
Конечно, вы можете обманывать разработчика игры и не допускать, чтобы ваша скорость опускалась ниже нуля (если вы хотите, чтобы игрок двигался только вперед). И когда вы обнаружите отрицательную скорость, установите Velocity на 0 и ускорение на 0.
Примечание: ускорение «ухудшается» будет как для положительного, так и для отрицательного, и оно будет «ухудшаться» до нуля. Вам нужно будет поработать с этими значениями и сыграть в тест, чтобы увидеть, что кажется правильным. Должно ли ускорение ухудшаться до 1 в секунду? Следует ли вам использовать значения 2 и -2 в качестве значений ускорения, о которых я упоминал ранее? 2 и -2 могут работать, но, возможно, 3 и -3 лучше? Это все вопросы, на которые вы можете сами ответить, протестировав их.
Я надеюсь, что это даст вам больше идей и поможет полностью решить ваш вопрос! Дайте мне знать, как это происходит.
Других решений пока нет …