Рассмотрим игру с разрешением по умолчанию 800x600. Объекты с масками столкновений размещаются в игровом мире размером 800х600. Маски столкновения могут определять, когда мышь сталкивается с ними.
Теперь предположим, что мы масштабируем игру до 1024x768 (предположим, что мы масштабируем графику, просто визуализируя все в слой, а затем масштабируя весь слой сразу). У нас есть два варианта правильной работы коллизий с мышью в этом новом разрешении:
A.) Масштабируйте мир до 1024x768 и соответственно масштабируйте маску столкновения каждого объекта.
B.) «Нанесите на карту» положение мыши в исходном мире (800x600).
Под «картой» я подразумеваю просто масштабирование положения мыши в исходном мире 800x600. Так, например, если положение мыши на экране (1024, 768), то положение мыши в мире (800, 600).
Теперь , очевидно, вариант Б требует способа меньше вычислений и, вероятно , менее склонен к геометрическим ошибкам, но он также чувствует себя своим рода «хак» для меня, как есть непредвиденные последствия происходят с помощью этого метода , который будет ад , чтобы исправить позже.
Какой метод я должен использовать: A, B или что-то еще?
источник
Ответы:
Как правило (даже для 2d игр) для игры существует отдельная система координат, которая не зависит от разрешения, обычно ее называют мировым пространством. Это позволяет масштабировать до произвольного разрешения.
Самый простой способ добиться этого - использовать 2D-камеру, которая, по сути, представляет собой матрицу, которая определяет переход от мирового пространства (ваши произвольные единицы) к экранному пространству (пиксели на экране). Это делает работу с математикой тривиальной.
Посмотрите на приведенный ниже раздел XNA 2d Camera Scrolling - зачем использовать матричное преобразование?
Это позволяет легко конвертировать определения системы координат
Для перехода от экрана к мировому пространству просто используйте Vector2.Transform. Это обычно используется для определения местоположения мыши в мире для выбора объектов.
Чтобы перейти от мира к экранному пространству, просто сделайте обратное.
Нет недостатков в использовании матрицы, за исключением небольшого обучения.
источник
Другой вариант: при каждом входном событии перемещения мыши перемещайте внутриигровой курсор мыши на количество игровых пикселей, соответствующее количеству пикселей в событии мыши. Это естественно для 3D-игр, которые фиксируют реальный указатель мыши на центре и поворачивают направление прицеливания на величину, соответствующую движению мыши при вводе, но вы можете сделать то же самое, переместив спрайт, представляющий внутриигровой курсор мыши.
Вы, очевидно, должны игнорировать любые события перемещения мыши, вызванные деформацией ее к центру, и если ваша игра имеет какую-либо задержку ввода, то неотзывчивость курсора будет самым неприятным и заметным аспектом.
Частично, какое решение вы используете, зависит от того, насколько важно положение мыши для игрового процесса. Если это RTS и игрок просто щелкает, чтобы выбрать юниты, вы, вероятно, можете просто выбрать любую из ваших A или B. Если это стрелок сверху вниз и мышь непосредственно контролирует движения персонажа, то вам, вероятно, понадобится более глубокое решение, которое ограничивает степень изменчивости в том, как персонаж может двигаться, основываясь не только на разрешении, но и на таких вещах, как движение мыши. скорость. Если вместо этого мышь контролирует направление прицеливания, вам понадобится другое решение и т. Д.
источник
Ответ ClassicThunder правильный, но я бы хотел привести пример альтернативного / более простого способа достижения желаемого эффекта. Это более простое решение для быстрого создания прототипов, в случаях, когда у вас нет доступа к полнофункциональной библиотеке, или в случаях, когда у вас нет доступа к графическому процессору (например, во встроенных системах).
Для выполнения указанного отображения вы можете использовать следующую функцию (предположим, что она определена в статическом классе
Helper
):(Вы не указали язык, но я вижу, что вы немного знаете C #, поэтому мой пример на C #.)
Затем вы можете использовать эту функцию следующим образом:
Где
camera.Bounds
прямоугольник, представляющий область мира, которую может видеть камера (то есть область, проецируемая на экран).Если у вас есть класс
Vector
илиPoint
, вы можете еще больше упростить этот процесс, создав 2D-эквивалент функции карты, например:Что сделало бы ваш код отображения простым однострочником:
источник
Опция (C): изменить разрешение экрана обратно на 800x600.
Даже если вы этого не сделаете, считайте это мысленным экспериментом. В этом случае ответственность дисплея заключается в том, чтобы изменить размер графики, чтобы он соответствовал ее физическим размерам, а затем операционная система должна предоставить вам события указателя с разрешением 800x600.
Я думаю, что все зависит от того, является ли ваша графика растровой или векторной. Если они растровые, и вы выполняете рендеринг в буфер 800x600, то да, гораздо проще переназначить мышь в пространство экрана и игнорировать реальное разрешение экрана. Однако большой недостаток этого заключается в том, что масштабирование может выглядеть ужасно, особенно если вы работаете с блочной графикой в стиле «8 бит».
источник