То, с чего вам нужно начать, это, если быть точным, координаты ваших пушек в системе координат корабля (или «системе отсчета»). Это похоже на то, что у вас есть сейчас, но начинается с 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).