Проблемы с точками входа пули для «навесных» пистолетов - PullRequest
1 голос
/ 19 марта 2012

Я делаю игру SHMUP с космическим кораблем. Этот космический корабль в настоящее время выпускает главную пушку из своей центральной точки. Спрайт, представляющий корабль, имеет центральную точку регистрации. 0,0 - центр корабля.

Когда я запускаю основную пушку, я делаю пулю и назначаю ее координаты x & y, совпадающие с аватаром, и добавляю ее в список отображения. Это отлично работает.

Затем я создал две новые функции: fireLeftCannon, fireRightCannon. Они создают маркер и добавляют его в список отображения, но значения x, y: this.y + 15 и this.y + (-) 10. Это создает своего рода треугольник точек входа маркера.

Аналогично этому:

▲ ▲

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

Мой вопрос заключается в том, как использовать текущую центральную позицию (this.x, this.y) и отрегулировать их в соответствии с моим текущим вращением, чтобы разместить новую пулю так, чтобы она имела правильный угол.

Большое спасибо заранее. Тайлер

EDIT Хорошо, я попробовал ваше решение, но оно не сработало. Вот мой код перемещения пули:

var pi:Number = Math.PI
var _xSpeed:Number = Math.cos((_rotation - 90) * (pi/180)  );
var _ySpeed:Number = Math.sin((_rotation - 90) * (pi / 180) );
this.x += (_xSpeed * _bulletSpeed  );
this.y += (_ySpeed * _bulletSpeed  );

И я попытался добавить ваш код к пушке левого плеча:

_bullet.x = this.x + Math.cos( StaticMath.ToRad(this.rotation) ) * ( this.x - 10 ) - Math.sin( StaticMath.ToRad(this.rotation)) * ( this.x - 10 );
_bullet.y = this.y + Math.sin( StaticMath.ToRad(this.rotation)) * ( this.y + 15 ) + Math.cos( StaticMath.ToRad(this.rotation)) * ( this.y + 15 );

Это размещение снимков на большом расстоянии от корабля, а иногда и за кадром.

Как мне испортить код перевода?

1 Ответ

1 голос
/ 19 марта 2012

То, с чего вам нужно начать, это, если быть точным, координаты ваших пушек в системе координат корабля (или «системе отсчета»). Это похоже на то, что у вас есть сейчас, но начинается с 0, а не с позиции корабля, поэтому они будут выглядеть примерно так:

(0, 0)     -- center
(10, 15)   -- left shoulder
(-10, 15)  -- right shoulder

Тогда вам нужно преобразовать эти координаты в систему координат мира / сцены ; это то же самое, что ваша графическая библиотека делает для рисования спрайта.

В вашем конкретном случае промежуточные преобразования

мир ← перевод → положение корабля ← вращение → корабль расположен и повернут

Итак, учитывая, что у вас есть координаты в третьем кадре (как нарисован спрайт корабля), вам нужно применить вращение, а затем применить перевод, и в этот момент вы находитесь в первом кадре. Есть два подхода к этому: один матричный арифметический, а другой выполняет преобразования по отдельности.

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


Теперь я объясню, как это сделать напрямую.

Общий метод применения поворота к координатам (в двух измерениях) заключается в следующем (где (x1,y1) - исходная точка, а (x2,y2) - новая точка):

x2 = cos(angle)*x1 - sin(angle)*y1
y2 = sin(angle)*x1 + cos(angle)*y1

Будет ли это вращение по часовой стрелке или против часовой стрелки, будет зависеть от «руки» вашей системы координат; просто попробуйте оба способа (+angle и -angle), пока не получите правильный результат. Не забудьте использовать соответствующие единицы измерения (радианы или градусы, но, скорее всего, радианы) для ваших углов с учетом имеющихся у вас функций триггера.

Теперь вам нужно применить перевод. Я продолжу использовать те же имена, поэтому (x3,y3) - это точка поворота и перевода. (dx,dy) это то, что мы переводим.

x3 = dx + x2
y3 = dy + x2

Как видите, это очень просто; Вы можете легко комбинировать его с формулами вращения.


Я описал преобразования в целом. В конкретном случае с корабельными пулями это работает, в частности:

bulletX = shipPosX + cos(shipAngle)*gunX - sin(shipAngle)*gunY
bulletY = shipPosY + sin(shipAngle)*gunX + cos(shipAngle)*gunY

Если ваши пули поворачивают в неправильном направлении, отрицайте угол.

Если вы хотите установить начальную скорость, зависящую от направления, для ваших пуль (например, ружей с постоянным прицелом), то вы просто применяете вращение, но не перевод к скорости (gunVelX, gunVelY).

bulletVelX = cos(shipAngle)*gunVelX - sin(shipAngle)*gunVelY
bulletVelY = sin(shipAngle)*gunVelX + cos(shipAngle)*gunVelY

Если бы вы использовали векторную и матричную математику, вы бы делали все те же вычисления, что и здесь, но они были бы связаны в отдельные объекты, а не в пары х и у и четыре тригонометрические функции. Это может значительно упростить ваш код:

shipTransform = translate(shipX, shipY)*rotate(shipAngle)
bulletPos = shipTransform*gunPos

Я дал явные формулы, потому что знание, как работает голая арифметика, полезно для концептуального понимания.


Ответ на редактирование:

В коде, который вы отредактировали в своем вопросе, вы добавляете то, что я предполагаю, является позицией корабля в координаты, которые вы умножаете на sin / cos. Не делайте этого - просто умножьте смещение орудия от центра корабля на sin / cos и только затем добавьте это к положению корабля. Кроме того, вы используете x x; y y в двух строках, где вы должны использовать x y; x y. Вот ваш код, отредактированный для исправления этих двух вещей:

_bullet.x = this.x + Math.cos( StaticMath.ToRad(this.rotation)) * (-10) - Math.sin( StaticMath.ToRad(this.rotation)) * (+15);
_bullet.y = this.y + Math.sin( StaticMath.ToRad(this.rotation)) * (-10) + Math.cos( StaticMath.ToRad(this.rotation)) * (+15);

Это код пистолета со смещением (-10, 15).

...