Я пытаюсь написать простую игру об астероидах на C ++, используя SFML. Хотя я могу довольно легко перемещать свой треугольник (игрока), способ его перемещения меня не совсем устраивает.
В настоящее время движение не относительно направления, к которому он смотрит. Например, если я нажму «w», чтобы двигаться вперед, треугольник просто переместится вверх по экрану независимо от его направления.
То, что я хотел бы сделать для треугольника, это двигаться вперед, когда нажата клавиша «w», но сделать фактическое направление его перемещения (относительно размеров экрана) относительно фактического направления его ориентации.
Таким образом, если передний конец треугольника направлен вправо, при нажатии «W» он будет двигаться вправо. Если в этом случае нажать «S», он будет двигаться влево. «А» заставит его двигаться вверх, и, конечно, «Д» заставит его двигаться вниз.
Мой текущий код не выполняет этот бит — я думаю, что есть действительно хакерское решение, но я бы предпочел подойти к этому с более математической и элегантной точки зрения, если это возможно.
Итак, что было бы лучшим способом сделать это?
У меня есть три релевантных метода: один для обработки ввода с клавиатуры, другой для обработки движения мыши и метод обновления.
Код
void Game::OnKeyPress( void )
{
int count = 0;
const float playerCenterMag = Magnitude( mPlayer.GetShape().GetCenter() );
//Shoddy attempt resulting in absolutely nothing of note
const float moveRateX = ( cosf( mMouseAoR ) * playerCenterMag ) + mPlayer.MoveSpeed;
const float moveRateY = ( sinf( mMouseAoR ) * playerCenterMag ) + mPlayer.MoveSpeed;
if ( mInput.IsKeyDown( sf::Key::W ) ) // Up
{
mPlayer.Position.y -= moveRateY;
++count;
}
if ( mInput.IsKeyDown( sf::Key::S ) ) // Down
{
mPlayer.Position.y += moveRateY;
++count;
}
if ( mInput.IsKeyDown( sf::Key::A ) ) // Left
{
mPlayer.Position.x -= moveRateX;
++count;
}
if ( mInput.IsKeyDown( sf::Key::D ) ) // Right
{
mPlayer.Position.x += moveRateX;
++count;
}
std::cout << "Key Press Rate => " << count << " seconds" << std::endl;
}
void Game::OnMouseEvent( void )
{
mPlayer.GetShape().Rotate( mMouseAoR + 5 );
}
void Game::Update( void )
{
const int x = mInput.GetMouseX();
const int y = mInput.GetMouseY();
mMouseAoR = ( y == 0 ) ? 0
: tanf( x / y );
PrintInfo();
}
Есть две версии этой игры. Если вы хотите, скажем, «W» для «продвижения» вперед, то вам нужно добавлять moveRate в каждом цикле и использовать W для изменения скорости.
Здесь, по-видимому, вы перемещаетесь только при нажатии кнопки, поэтому вам нужно всегда обновлять X и Y:
if ( mInput.IsKeyDown( sf::Key::W ) ) // Up
{
mPlayer.Position.x += moveRateX;
mPlayer.Position.y += moveRateY;
++count;
}
MoveRate изменяется в зависимости от ориентации. При движении в боковом направлении, вы бы сделали
mPlayer.Position.x += moveRateY;
mPlayer.Position.y += moveRateX;
при движении влево (или вправо) и -=
в другом направлении.
Других решений пока нет …