Как бороться с различиями между 2D экранными координатами и декартовыми координатами

23
  • Большинство систем координат 2D-экрана / растрового изображения имеют положительную ось Y, направленную вниз (с началом координат в верхнем левом углу).
  • Это противоречит тому, как большинство людей думают геометрически с положительной осью Y, направленной вверх (с началом координат в центре).

Как большинство игр управляют двумя разными 2D системами координат? Существует два основных типа координат (экран против декартовых), но может быть много разных координатных пространств: пространство спрайтов, пространство мира, пространство просмотра, пространство экрана и т. Д.

Задний план:

Изначально я установил, что мировые координаты в моей игре соответствуют соглашению о координатах 2D-экрана. Это сделало очень естественным использование процедур рисования графики, но при использовании тригонометрических функций, таких как atan2 (), возникли тонкие проблемы. Результаты ввода координат экрана 2D atan2 () очень запутаны, потому что atan2 () предполагает, что положительная ось y направлена ​​вверх.

Поэтому я изменил свои мировые координаты в соответствии с классической декартовой системой координат (с источником в левом нижнем углу экрана). Рассуждать с atan2 () гораздо проще, но теперь сложнее делать другие рассуждения:

  • Если я нажму на экран здесь, какой спрайт внизу?
  • Где я нажал на этот спрайт?
  • Если спрайт нарисован не в том месте, что было вычислено неправильно? Координаты экрана или мировые координаты?

Я понимаю, что преобразование из экранных в декартовые координаты включает в себя просто масштабирование значения y на -1 с необязательным переводом обоих значений (x, y). Меня больше интересуют лучшие практики для игрового дизайна:

  • Разве большинство игр просто придерживаются соглашения о координатах экрана и изменяют свое мнение о том, как должны работать такие вещи, как atan2 ()?
  • Когда и как выполняются преобразования системы координат? (С использованием матриц, абстракций ООП и т. Д.)
  • Сохраняются ли местоположения спрайтов как центр спрайта или один из углов? Высота / ширина спрайта в «неправильном» направлении, кажется, является общей проблемой, когда я рисую их.

Хотя мой вопрос в основном касается 2D-игр, кажется, что OpenGL использует систему координат, где ось Y направлена ​​вверх. OpenGL должен в конечном итоге проецировать эти трехмерные координаты в 2D-систему координат экрана. Возможно, какое-то руководство можно найти в методе OpenGL ...

Leftium
источник

Ответы:

8

Перепробовав все мыслимые способы сделать это, я обнаружил, что если это чисто 2D-игра, просто используйте систему рисования экрана, это сделает вашу жизнь намного проще. Sin, Cos и atan2 должны использоваться немного по-разному, но это неудобство легко компенсируется простотой определения того, какой путь вверх, вниз, по часовой стрелке и против часовой стрелки. Я бы также порекомендовал работать в пикселях, а не в метрах для 2D-игр - гораздо проще думать о расстояниях на экране, и вероятность того, что вы захотите изменить весь масштаб вашей игры, близка к нулю.

«Как большинство игр управляют двумя разными 2D системами координат?»

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

«Сохраняются ли местоположения спрайтов как центр спрайта или один из углов?»

  • Если вы работаете из центра, вращение становится более прямым, хотя вам также нужно знать углы.

«Возможно, какое-то руководство можно найти в методе OpenGL ...»

  • 3D движки - это совершенно другой случай. Поскольку у них есть настоящие камеры, положение экрана может сильно отличаться от положения в мире. В нисходящей игре вы будете работать по осям X и Z, а не по X и Y с одной стороны.
Iain
источник
1

Возможно, я здесь слишком упрощаю, но я бы хотел, чтобы любая подсистема 2D / UI действовала строго в соответствии с тем, что вы назвали «экранными» координатами. У вас будет две матрицы: ScreenToCartesianTransform и CartesianToScreenTransform. Когда события ввода мыши получены, координаты мыши будут преобразованы с использованием CartesianToScreenTransform перед передачей в менеджер ввода системы 2D / UI. Оттуда система пользовательского интерфейса будет выполнять тестирование попаданий с использованием системы координат экрана и обрабатывать (или не обрабатывать) событие соответствующим образом. Если событие ввода мыши не обрабатывается 2D / UI, его можно передать в 3D-систему (если она существует) с использованием исходных, не преобразованных координат.

Поскольку система 2D / UI будет работать только в «экранных» координатах, ее геометрию необходимо будет преобразовать с помощью ScreenToCartesianTransform, прежде чем она будет обработана механизмом рендеринга.

Майк Штробель
источник
На самом деле, в зависимости от того, какой инструментарий вы используете, события ввода мыши уже могут быть в экранных координатах. В этом случае вы бы не трансформировали их для системы 2D / UI, а для системы 3D (если она существует).
Майк Штробель
0

Я предпочитаю использовать дерево отображения, как во Flash. У меня будет корневой узел (вид игры), который содержит дочерний элемент для мира (мировой узел) и один сверху для HUD. Внутри мира будут узлы для объектов в игровом мире.

Затем я просто трансформирую мировой узел. Наряду с переводом (панорамирование камеры) и пропорциональным масштабированием (масштабирование камеры) я также применяю два других преобразования:

  • -1 y-шкала, чтобы перевернуть систему координат.
  • Масштабирование, чтобы преобразовать мировые единицы (метры) в единицы экрана (пиксели)

Затем я использую координаты y-вверх / мир в коде рисования игрового объекта и координаты y-вниз / экран в коде рисования HUD, которые кажутся очень естественными.

Чтобы ответить на такие вопросы, как «на каком объекте я щелкаю», я использую методы отображения узла для преобразования координат между системами координат (например, globalToLocalи его обратное во Flash).

Кстати, на atanсамом деле не работает по-другому, когда у вниз, вам просто нужно думать о всех углах как по часовой стрелке, а не против часовой стрелки.

Барт ван Хейкелом
источник
0

OpenGL, как и DirectX, имеет оси X и Z вдоль горизонтальной плоскости, а Y - вверх.
У меня никогда не было проблем с экранными координатами, и я думаю, что проще всего было бы просто отнестись к нему так, как оно есть: если что-то, например, atan2, не нравится, то измените параметры подачи.

Если вы используете относительные или локальные координаты, такие как граф сцены, тогда подойдет простая функция, такая как ToGlobalCoords (). На самом деле, если вы хотите узнать больше о пространственном позиционировании, графах сцен и localToGlobal, бесплатный отрывок из Game Engine Architecture об этом.

Спрайты нарисованы из верхнего левого угла или (0,0) начала координат. Причины почему из-за верхнего левого происхождения окна.

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

Коммунистическая утка
источник