Одна из периодически встречающихся проблем в разработке компьютерных игр это выбор 3D моделей мышкой. В некоторых 3D
движках это реализовано в готовом виде но не во всех. В некоторых это приходится добавлять
самостоятельно прописывая свой код в тех случаях когда в движке где все это уже есть нет
чего-то что нужно или он заглючивает и находится стабильный движек но в нем нет нужных
опций в готовом виде.
В Windows координаты мышки X,Y движки обычно извлекают обращаясь к DLL библиотеки OS прямо в ее папки - там лежит DLL такая как Kernel32 или User32 или подобные. Внутри них прописано много функиций, одна из которых выдает коордианты мышки на экране - при полноэкранном режиме приложния, не оконном, они совпадают с указателем мышки в условной игре. Вызывая эту библиотеку движек выдает координаты мышки обращаясь к OS. Это наиболее частая реализация, могут быть и другие - то так же определяет будет ли работать игра в следующей версии OS если разработчик изменит имя вызываемой функции которая дает XY мышки в программу - то игра небудет работать вылетев с ошибкой таким образом EXE файлы если использует мышку привязывается к определенной линейки операционных систем. Хотя есть варианты сделать все более адаптивно но они и более сложные - просще просто обращатся к этим DLL в OS просто прописав что файл работает только вот в этом списке OS и ни в каких других - для начала так точно будет просще.
Получив командой координаты XY мышки на экране необходимо превратить их в 3D точку указателя мышки в 3D пространстве. Для этого к этим коордиантам добавляется точка местонахождения камеры в пространстве чрез которую картинка выводится на экран. Далее необходимо установить вторую точку - ту куда указывает мышка - а не ту в которой она находится - создать виртуальный луч в даль на основе 2х точек в пространстве, в даль от плоскости прямугольника камеры (при этом камера может быть развернута в самых разных направлениях в пространстве), для этого нужно либо обратится к готовой команде движка которая выдаст этот ответ, либо написать свою формулу для проведения линии под прямым углом к плоскости камеры - это не так просто потому что сначала требуется установить позицию камеры и ее углов в 3Д мире. По этой причине движки где все это уже готово и вызывается буквально одной командой без лишнего кода лучше, минусы в том что иногда способ которые встроен в движек разработчикам очень "ресурсозатратный" т.е. не оптимальный по расходу мощностей компьютера при большом числе 3Д моделей на экране.
Дальше необходимо создать 3D-Объект конусообразной формы - конус, который будет минимального диаметра возле указателя 3D мышки. И более крупного диаметра в далеке от мышки - проецируясь в даль от экрана в ранее установленную точку куда смотри проекция от мышки в даль относительно прямоугольника камеры. Когда Мышка двигается по экрану, исходящая точка начала 3Д конуса будет слега перемещаться в след за мышкой, в пространстве но при этом должна двигатся и дальшая часть Конуса (и вот это нужно запрограммировать - перемещая точку впереди камеры куда будет смотреть широкая часть КОНУСА, что бы это было просще можно установить еще одну 3Д модель - невидиый PIVOT в далеке от начала линии мышки и привязав этот PIVOT к ротации камеры - тогда не придется писать код определения дальней точки куда смотрит мышка в даль, и достаточно будет немного смещать невидимую точку впереди в зависимости от движения мышки возле плоскости камеры. Для начала 3д конус которым проверяется какие модели пересеклись с ним можно сделать частично прозрачным, что бы смотреть как это работает, затем когда технология будет отточена - сделать его невидимым) - трехмерная модель конусообразной формы пересекаясь с другими моделями в игре будет сталкиватся с ними, со всеми моделями которые окажутся внутри конуса исходящего из координат мышки (можно сделать просто ЛУЧ - но чем он будет дальше идти тем чаще он будет Промахиваться мимо моделей в далеке). Это можно сделать чуть ли не 3-мя способами - опцией внутри движков есть такая команда позволяющая извлечь названия 3Д моделей пересекающихся друг с другом. Далее эти модели нужно внести в СПИСОК - после чего определить растояние каждой до камеры игрока, и выбрать самую ближайшую - имя ближайшей модели можно например вывести на экран - она и будет считать той на которую указывает мышка. Другие способы заключаются в том что бы сделать это собственым кодом - без задействования опции 3Д движка - написав свою программу проверки пересечения координат каждых 2-х 3Д моделей в пространстве - каждая модель представлена списком точек и плоскостей и при помощи формул можно проводить проверку пересекаются ли эти поверхности или нет.
Прежде чем активно наполнять игровое пространство при разработки компьютерной игры графикой, потребуется реализовать ряд 3D механизмов, если выбор моделей в пространстве в движке есть в комплекте то отлично, если нет то его нужно реализовать, это 1 шаг из множества которые нужно сделать что бы двигаться дальше. Обычно чем более "древний" движек тем больше в нем всего уже есть в готовом виде за многие годы его доработки разработчиками - иногда это вызывает желание вернутся к ним, но они к сожалению часто либо медленные либо не факт что будут без сбоев работать в новых версиях Windows т.к. создавались еще под Windows 7 или даже незадолго до того, во времена Vista и имея возраст разработки или поддержки до ее заврешения в 9-12 лет конечно же оснащены различными встроенными улучшениями добавляемыми и обновляемыми разработчиками за это время.
Полная ротация камеры - часто движки оснащаются разработчиками обычной камерой которая упирается в стопы-блоки вверху и внизу ротации, это подходит для большинства видов игр - однако есть решения полной камеры, без готового кода адаптация рекомендаций из интернета как это сделать может занять недели времени, при играх в форме ходьбы по улицам городов это не так важно, а для разработки компьютерной игры в стиле космических сражений никакие стопы камеры при ротации вверх-вниз ненужны.
Тени - слабые по качеству картинки теней, либо со сбоями, в некоторых случаях могут быть отключены и заменены самописными через пиксель-шейдеры, имея готовый код это на самом деле не сложно, но опыт показал что это крайне нежелательное решение которое только изначально казалось приемлемым, потому что видеокарта в этом случае перегружена вычислениями и работает на максимуме - что может привести к более быстрому ее выгоранию - в первую очередь по элементами питания микросхемы GPU, особенно на картах которые уже проработали много лет. В нормальной ситуации внутри движков реализованы либо безшейдерные тени либо шейдерные - в DX11 но они реализованы так что не создают слишком большую нагрузку на видео-карту что как раз чаще всего и может произойти при самописной реализации теней через шейдеры, по началу казалось что можно применять движки где есть проблемы с тенями в случае если других проблем у них нет, разобравшись как это сделать и в итоге дописав тени - но все же лучше этого не делать, и подобрать такой движек для разработки компьютерных игр, где все работает как нужно с самого начала. (рассматривая коды теней в бесплатных движках иногда они представлены 2D матрицами которые создаются в памяти по одной для каждой 3D модели в пространстве - матрицы с числами в ячейках, где каждое число это затенение элемента (треугольника) поверхности модели, иногда эти реализации содержат ошибки и недочеты, попытки рекомендуемыми способами (поменять расстояния допустимого рендеринга и т.д.) исправить эти недочеты приводили к полной неудаче и неработоспособности движков.)
Многопоточность - что бы работать с 3D графикой например в 4 ядра, на каждом запускается код программы, в который передается ссылка на элемент 3D движка в который каждое ядро передает данные о изменении параметров на экране, тут часто могут происходить непредсказуемые случайные краши и вылеты - потому что ненужно в функцию подпрограммы передаваемую на много ядер, разом передавать массу параметров (через запятую) - лучше передавать в поток только 1 параметр - это ссылку на 3D движек и все, ненужно передавать в потоки/ядра для вычислений длинный список переменных из 5-6 или же 30 штук, вместе со ссылкой на движек одним разом - когда ссылка на программный объект 3Д движка передается в одном списке переменных в функцию в разные потоки-ядра, движек при парралелизации может заглючить и вступить к конфликт с другими переменными передаваемыми в эту же функцию в поток, если это происходит в форме одной строки передаваемых параметров - лучше передавать в функции при запуске нескольких потоков только 1 параметр - ссылку на движек для доступа к нему, все остальные переменные передавать как глобально объявленный класс или структуру данных обеспечив потоко-безопасность (при создании первых x86 процессоров многоядерность не предполагалась, в результате когда она появилась, кэш память в процессоре осталась прежней такой же как для 1 ядра по своей релизации, в итоге храняющиеся в кэше данные могут быть перепутаны разными ядрами т.к. разные ядра могут обращаятся к одной и той же кэш памяти к одним и тем же названиям переменных внутри нее и нужно заранее предусматривать менеджмент этих процессов в процессе разработки компьютерных игр кроме этого среда разработки может осуществлять проверку на ошибки кода перед компиляцией и выдавать сбой если обнаружит конфликт при попытке передать в параметрах функции ссылку на движек совместно с множеством других переменных в одну строку - это решается минимизацией передаваемых параметров и вывод части параметров в глобальные переменные для вызова их прямо из потоков-ядер), в целом, н енужно передавать много переменных в одну строку в поток через запятую - это небезопасно и тут скорее проблема в не идеальности средств разработки и самой технологии многоядерности - это решается использованием глобально объявленных структур и классов с параметрами внутри, все параметры передаются структуры и классы, и только ссылка на 3D движек передается в функцию напрямую - тогда многопоточность работает с 3D без случайных ошибок в неизвестные моменты времени и работает безопасно и надежно - без непредсказуемых сбоев.