Астероиды игры движение в C # - PullRequest
4 голосов
/ 03 сентября 2010

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

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

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

Ответы [ 5 ]

13 голосов
/ 03 сентября 2010

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

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 непостоянным (представьте, что ускорение при нажатии клавиши вместо перемещения на фиксированное расстояние от нажатия клавиши).

2 голосов
/ 03 сентября 2010

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

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

1 голос
/ 03 сентября 2010

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

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

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

1 голос
/ 03 сентября 2010

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

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

0 голосов
/ 14 марта 2013

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

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;

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

...