В программировании очень популярна техника создания программных интерфейсов — API. Этот прием очень полезен, чтобы скрыть все тонкости реализации и не обременять ими обывателя.
Но бывают случаи, когда вам нужно поддерживать в своем коде несколько API, выполняющих одну и ту же задачу, с минимальным переписыванием кода.
Например: поддержка работы игры (движка) на различных графических API: DirectX, OpenGL, Vulkan. В этой статье представлены мысли о том, как это сделать.
Описание проблемы
Давайте рассмотрим пример: вы хотите написать кроссплатформенный игровой движок.Допустим, вы знаете C/C++, OpenGL, DirectX, Vulkan. Поскольку движок кроссплатформенный, вы сначала думаете «а как насчет того, чтобы сделать его на OpenGL», и у вас все получается хорошо, пока вам не закрадывается мысль, что, может быть, OpenGL не идеален для Windows? Почему крупные компании поддерживают сразу все API, а UnrealEngine для Windows компилируется с использованием DirectX (по умолчанию), а не OpenGL/Vulkan. И теперь перед вами стоит задача как-то обобщить все API. Вы пытаетесь написать интерфейс — IRenderer и классы-потомки, которые бы сами инициализировали необходимый API и отвечали за отрисовку.
Но проблема не в этом, OpenGL не может работать без созданного окна (скрытое окно тоже окно), а DirectX и vulkan могут. И тут два решения: либо сделать IRenderer так, чтобы он отвечал еще и за создание окна (классы несут дополнительную ответственность), либо привязать IRenderer к какому-то уже созданному окну (но можно рендерить и без окон!!! Не универсально!!).
В общем, об IRenderer можно и не думать сразу, API слишком отличаются друг от друга, хотя казалось бы, они решают одну и ту же задачу — доступ к видеокарте и обеспечение отрисовки.
Но я все равно хочу написать игру и хочу, чтобы она работала под разными платформами, с разными несовместимыми API, а еще я хочу, чтобы код был читаемым, минимальным и не переписывался по 10 раз.
Я постараюсь ответить на этот вопрос.
Таким образом, несовместимые API — это API, которые решают одну и ту же задачу, но имеют совершенно разные подходы к решению и, следовательно, разный набор функций.
Подходы настолько разные, что обобщить работу под один интерфейс невозможно.
А совместимые API — это API, состоящие из похожих функций (сигнатуры похожи).
Примеры совместимых API: сокеты, потоки, кучи, файлы.
Их работу легко свести в один интерфейс, поэтому для работы с ними написано так много библиотек.
Предлагаемое решение
А решение простое: обобщать не API, а приложение.Код прикладного приложения (игровая логика, физика, AI, GUI и т.д.) оформлен в виде отдельной библиотеки со специфическим интерфейсом.
Пример объявления библиотеки:
Теги: #Разработка игр #vulkan #api #Системный анализ и проектирование #дизайн #дизайн и рефакторинг #DirectX #gamedev #opengltemplate<typename InputData, typename OutputData> class IGame { public:
-
Получите Сертификацию Ccna За Несколько Дней
19 Oct, 24 -
Литейная Ядерная Бомба. Введение
19 Oct, 24 -
Удобство И Дизайн Электронных Журналов
19 Oct, 24 -
Буддизм Сегодня
19 Oct, 24