2010-09-03 4 views
4

Я пытаюсь сделать игру Астероиды. Моя проблема, которую я имею прямо сейчас, это если вы нажмете клавишу со стрелкой ВВЕРХ, она переместит «корабль» на 10 пикселей вверх. И если вы нажмете клавишу «ВЛЕВО», она повернет «корабль» на 5 градусов влево, вопрос, который я ввожу в игру, когда вы поворачиваете налево или вправо. И затем попытайтесь подняться. Он не будет двигаться в обратном направлении. Он просто переместит повернутый «корабль» на 10 градусов в направлении Y.Астероиды Игра Движение В C#

То, что я собираюсь сделать, - это переменная, называемая направлением, подумайте об этой переменной как о круге с 360 градусами. То, что я пытаюсь сделать, - это каждый раз, когда я нажимаю на стрелку влево, он вычитает 5 из направления, которое начинается с 0 и идет назад от 360 и, таким образом, устанавливает его на 355. Затем я разделил бы 355 на 10 и получал бы 35.5. Затем я разделил бы 10 на 35,5 и получил 0,355. Затем я вычитал 0,355 из 10 (двигаясь вверх по Y). И вычтите его из 0 (перемещение влево в X). Таким образом, я бы двигал 9.645 вверх по Y и перемещал 0,355 влево в X.

Проблема, с которой я столкнулся, - это «корабль» в астероидах. У меня есть Graphics.FillPie, в котором нужны инты для использования в качестве Угол запуска и угол развертки, однако, как вы можете видеть, мне придется работать с удвоениями или плаваниями. Я почти уверен, что это слишком сложно, и я уверен, что есть что-то в 100 раз проще, я что-то думаю по линии линейного алгоритма Брешенема. Если бы кто-нибудь мог помочь, предложив что-то проще или исправить мою проблему, это было бы очень признательно. Заранее спасибо.

+0

tigonometry поможет здесь. Я понятия не имею, как вы придумали свой алгоритм, и его вероятность, что даже если он будет работать в некоторых случаях, он вернет причудливые результаты в общем случае. – ldog

ответ

13

Похоже, вам нужно рассчитать ориентиры для корабля на основе его текущей ориентации в радианах. Например:

double xVector = Math.Sin(orientationInRadians); 
double yVector = Math.Cos(orientationInRadians); 

Затем используйте левую и правую стрелки для управления текущей ориентацией судна. Когда у вас есть вектор, вы можете рассчитать местоположение корабля, которое находится на расстоянии 10 единиц от его текущего положения вдоль вектора курса. Сначала вам нужно масштабировать вектор до единицы (длины 1) вектора.

double magnitude = sqrt(xVector*xVector + yVector*yVector); 
double unitVectorX = xVector/magnitude; 
double unitVectorY = yVector/magnitude; 

Теперь у вас есть вектор длиной 1 единица, но все же указывает на текущую ориентацию судна. Затем переместите корабль с позициейX и positionY как текущие его координаты.

double distanceToTravel = 10; 
double newPositionX = positionX + unitVectorX*distanceToTravel; 
double newPositionY = positionY + unitVectorY*distanceToTravel; 

Вы хотите, чтобы отслеживать положение судна и ориентацию с двойниками или плаваете, даже если вы в конечном итоге рендеринг с системой, которая позволяет только Интсу. Вы не должны сохранять текущую позицию и ориентацию с помощью точности движка рендеринга, или вы начнете видеть странные прыжки и паузы при перемещении и повороте. Кроме того, используя вышеизложенное, вы можете сделать distanceToTravel непостоянным (представьте ускорение, пока клавиша нажата, вместо того, чтобы перемещать фиксированное расстояние от нажатия клавиши).

+0

+1 для обозначения тригонометрии как способа расчета ориентации. – Brian

+0

Beat me to :) :) +1 Для простоты и yay для векторов. –

+0

Я пропустил что-то или «величина» всегда будет 1? Math.Sin и Math.Cos, безусловно, возвращают значения на единицу круга, не так ли? –

1

Я не хочу отвлекаться, но вы всегда можете скачать чужой код и посмотреть на него, чтобы выяснить, как это сделать самостоятельно. Вы можете получить одну реализацию здесь: http://www.c-sharpcorner.com/UploadFile/dannaboneheart/Asteroids11292005064500AM/Asteroids.aspx

анс здесь: http://www.codeproject.com/KB/game/hucsharpasteroids.aspx

1

Там нет никаких проблем с использованием поплавков внутри и преобразования их в Интс, когда вам нужно использовать их таким образом:

double angle = ...; 
int angleAsInt = (int)Math.Round(angle); 

я предлагаю вы изучаете использование тригонометрических функций, таких как sin и cos для определения компонент X и Y скоростей и ускорений.

2

Вы закончили думать об этом. ;> Просто используйте матричные преобразования, чтобы вращать и перемещать корабль. Когда судно указывается «на северо-запад», и пользователь нажимает клавишу ВВЕРХ, вы корректируете матрицу перевода корабля на 10 единиц по оси Y судна. Вы применяете матрицы вращения и перевода, чтобы преобразовать систему координат корабля в систему координат экрана. Порядок операций имеет решающее значение - если вы применяете перевод перед ротацией, корабль будет размахивать вокруг центральной точки, а не вращаться вокруг источника корабля, а затем переходить в новое «прямое» направление.

Поскольку вы можете использовать те же матричные преобразования для рисования, вы можете просто нарисовать корабль в той же фиксированной ориентации (нос, указывающий «вверх» положительную ось Y) относительно своей локальной системы координат. Вращение изображения будет зависеть от матричного преобразования.

+1

+1 хотя это решение более сложное, это сделает переход на 3D-игры намного проще. Обратите внимание, что в матрицах будет много нулей, и преобразования будут так или иначе привести к тем же простым уравнениям, что и в принятом решении. – karlipoppins

+1

Ну, этот подход требует/предполагает, что у вас есть хороший механизм преобразования, доступный в любой среде или среде, в которой вы работаете. Если вам нужно реализовать все с нуля, было бы быстрее непосредственно самостоятельно вычислять вращения (как в других ответы), чем реализовать свой собственный мир. Но если у вас уже есть хороший стек преобразования (как в WinGDI, DirectX, OpenGL), то дело с (перемещением, рисованием) корабля относительно его собственных веревок намного проще, ИМО. Все относительно чего-то. Правило ориентации Эндера Виггина: «Вражеские ворота опущены». – dthorpe

0

Одна вещь, о которой вы еще не упоминали, заключается в том, что в игровых автоматах и ​​видеоиграх Asteroids (R), полученных оттуда, у корабля игрока есть инерция. Следовательно, вам нужно следить за скоростью судна. Каждый кадр вы должны сделать что-то вроде:

if (thrusting) 
{ 
    XVelocity += (XVelocity - Math.Cos(Heading)*MAX_SPEED) * (1/INERTIA_CONSTANT); 
    YVelocity += (YVelocity - Math.Sin(Heading)*MAX_SPEED) * (1/INERTIA_CONSTANT); 
} 
else 
{ 
    XVelocity -= XVelocity * (1/FRICTION_CONSTANT); 
    YVelocity -= YVelocity * (1/FRICTION_CONSTANT); 
} 

XPosition += XVelocity; // Do twice--once before and once after speed adjust 
YPosition += YVelocity; 

Обратите внимание, что некоторые игры просто добавить к скорости некоторые постоянные раз косинус/синус. У этого будет неудачное последствие: если игрок указывает на свое судно в каком-то направлении и начинает толкаться непрерывно, расстояние, пройденное кораблем, каждый кадр может вырасти до абсурдных пределов. Код, как показано, приведет к уменьшению ускорения, поскольку скорость судна асимптотически приближается к максимуму.

Смежные вопросы