Настройка проекта игры

Примечание

Этот раздел является частью серии учебников Создание простой игры универсальная платформа Windows (UWP) с помощью DirectX. Раздел по этой ссылке задает контекст для ряда.

Первым шагом в разработке игры является создание проекта в Microsoft Visual Studio. Настроив проект специально для разработки игр, вы можете повторно использовать его в качестве своего рода шаблона.

Задачи

  • Создайте проект в Visual Studio с помощью шаблона проекта.
  • Изучите точку входа и инициализацию игры, изучив исходный файл для класса App .
  • Посмотрите на игровой цикл.
  • Просмотрите файл проекта package.appxmanifest .

Создание проекта в Visual Studio

Примечание

Сведения об установке Visual Studio для разработки с использованием C++/WinRT, включая установку и использование расширения C++/WinRT для Visual Studio (VSIX) и пакета NuGet (которые вместе обеспечивают поддержку шаблона проекта и сборки), приведены в разделе Поддержка Visual Studio для C++/WinRT.

Сначала установите (или обновите до) последнюю версию расширения C++/WinRT Visual Studio (VSIX); см. примечание выше. Затем в Visual Studio создайте проект на основе шаблона проекта Основное приложение (C++/WinRT). В качестве цели выберите последнюю общедоступную (то есть не предварительную) версию Windows SDK.

Просмотрите класс App , чтобы понять IFrameworkViewSource и IFrameworkView.

В проекте основного приложения откройте файл App.cppисходного кода . В есть реализация класса App , который представляет приложение и его жизненный цикл. В этом случае, конечно, мы знаем, что приложение является игрой. Но мы будем называть его приложением, чтобы более широко говорить о том, как приложение универсальная платформа Windows (UWP) инициализируется.

Функция wWinMain

Функция wWinMain является точкой входа для приложения. Вот как выглядит wWinMain (из App.cpp).

int __stdcall wWinMain(HINSTANCE, HINSTANCE, PWSTR, int)
{
    CoreApplication::Run(winrt::make<App>());
}

Мы создаем экземпляр класса App (это единственный экземпляр созданного приложения ) и передадим его в статический метод CoreApplication.Run . Обратите внимание, что CoreApplication.Run ожидает интерфейс IFrameworkViewSource . Поэтому класс App должен реализовать этот интерфейс.

В следующих двух разделах этого раздела описываются интерфейсы IFrameworkViewSource и IFrameworkView . Эти интерфейсы (а также CoreApplication.Run) представляют собой способ предоставления Windows поставщиком представления. Windows использует этот поставщик представлений для подключения приложения к оболочке Windows, чтобы можно было обрабатывать события жизненного цикла приложения.

Интерфейс IFrameworkViewSource

Класс App действительно реализует IFrameworkViewSource, как показано в описании ниже.

struct App : winrt::implements<App, IFrameworkViewSource, IFrameworkView>
{
    ...
    IFrameworkView CreateView()
    {
        return *this;
    }
    ...
}

Объект, реализующий IFrameworkViewSource , является объектом фабрики поставщика представления . Задача этого объекта состоит в том, чтобы создать и вернуть объект поставщика представления .

IFrameworkViewSource имеет один метод IFrameworkViewSource::CreateView. Windows вызывает эту функцию для объекта, передаваемого в CoreApplication.Run. Как видно выше, реализация App::CreateView этого метода возвращает *this. Иными словами, объект App возвращает себя. Так как IFrameworkViewSource::CreateView имеет тип возвращаемого значения IFrameworkView, из этого следует, что класс App также должен реализовать этот интерфейс. И это можно увидеть в приведенном выше списке.

Интерфейс IFrameworkView

Объект, реализующий IFrameworkView , является объектом поставщика представления . Теперь мы предоставили Windows с этим поставщиком представлений. Это тот же объект App , который мы создали в wWinMain. Таким образом, класс App служит как фабрикой поставщика представлений , так и поставщиком представлений.

Теперь Windows может вызывать реализации методов IFrameworkView в классе App. В реализациях этих методов ваше приложение может выполнять такие задачи, как инициализация, начать загрузку необходимых ресурсов, подключить соответствующие обработчики событий и получить CoreWindow , который приложение будет использовать для отображения выходных данных.

Реализации методов IFrameworkView вызываются в порядке, показанном ниже.

Ниже приведена структура класса AppApp.cpp), в которой показаны сигнатуры этих методов.

struct App : winrt::implements<App, IFrameworkViewSource, IFrameworkView>
{
    ...
    void Initialize(Windows::ApplicationModel::Core::CoreApplicationView const& applicationView) { ... }
    void SetWindow(Windows::UI::Core::CoreWindow const& window) { ... }
    void Load(winrt::hstring const& entryPoint) { ... }
    void OnActivated(
        Windows::ApplicationModel::Core::CoreApplicationView const& applicationView,
        Windows::ApplicationModel::Activation::IActivatedEventArgs const& args) { ... }
    void Run() { ... }
    void Uninitialize() { ... }
    ...
}

Это было просто введение в IFrameworkView. Мы подробно рассмотрим эти методы и способы их реализации в разделе Определение платформы приложений UWP в игре.

Приведите в порядок проект

Проект "Основное приложение", созданный на основе шаблона проекта, содержит функциональные возможности, которые мы должны привести в порядок на этом этапе. После этого мы можем использовать проект для повторного создания игры из тире (Simple3DGameDX). Внесите следующие изменения в класс App в App.cpp.

  • Удалите его элементы данных.
  • Удаление OnPointerPressed, OnPointerMoved и AddVisual
  • Удалите код из SetWindow.

Проект будет построен и запущен, но в клиентской области будет отображаться только сплошной цвет.

Игровой цикл

Чтобы получить представление о том, как выглядит игровой цикл, просмотрите в исходном коде скачанный пример игры Simple3DGameDX .

Класс App имеет элемент данных с именем m_main типа GameMain. И этот элемент используется в App::Run следующим образом.

void Run()
{
    m_main->Run();
}

GameMain::Run можно найти в GameMain.cpp. Это main цикл игры, и вот очень грубый контур, показывающий наиболее важные функции.

void GameMain::Run()
{
    while (!m_windowClosed)
    {
        if (m_visible)
        {
            CoreWindow::GetForCurrentThread().Dispatcher().ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);
            Update();
            m_renderer->Render();
            m_deviceResources->Present();
        }
        else
        {
            CoreWindow::GetForCurrentThread().Dispatcher().ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending);
        }
    }
}

А вот краткое описание того, что делает этот main игровой цикл.

Если окно игры не закрыто, разослайте все события, обновите таймер, а затем отрисовку и представление результатов графического конвейера. Существует многое другое, чтобы сказать об этих проблемах, и мы сделаем это в разделах Определение платформы приложений UWP в игре, Инфраструктура отрисовки I: Введение в отрисовку и Инфраструктура отрисовки II: рендеринг игры. Но это базовая структура кода игры UWP DirectX.

Изучение и обновление файла package.appxmanifest

Файл Package.appxmanifest содержит метаданные о проекте UWP. Эти метаданные используются для упаковки и запуска игры, а также для отправки в Microsoft Store. Файл также содержит важную информацию, которую система игрока использует для предоставления доступа к системным ресурсам, необходимым для запуска игры.

Запустите конструктор манифестов, дважды щелкнув файл Package.appxmanifest в Обозреватель решений.

Снимок экрана редактора манифеста package.appx.

Подробнее о файле package.appxmanifest и упаковке см. в статье Конструктор манифестов. Сейчас взгляните на вкладку Возможности и просмотрите предоставленные параметры.

Снимок экрана с возможностями по умолчанию для приложения Direct3D.

Если вы не выберете возможности, используемые в вашей игре, например доступ к Интернету для глобальной доски высокой оценки, вы не сможете получить доступ к соответствующим ресурсам или функциям. При создании новой игры убедитесь, что вы выбрали все возможности, необходимые api- интерфейсам, вызываемым вашей игрой.

Теперь рассмотрим остальные файлы, которые поставляются с примером игры Simple3DGameDX .

Просмотр других важных библиотек и файлов исходного кода

Если вы планируете создать шаблон игрового проекта для себя, чтобы повторно использовать его в качестве отправной точки для будущих проектов, вам потребуется скопировать GameMain.h скачанный проект Simple3DGameDX и GameMain.cpp добавить их в новый проект Core App. Изучите эти файлы, узнайте, что они делают, и удалите все, что связано с Simple3DGameDX. Кроме того, закомментируйте все, что зависит от кода, который вы еще не скопировали. В качестве примера GameMain.h зависит от GameRenderer.h. Вы сможете раскомментировать при копировании дополнительных файлов из Simple3DGameDX.

Ниже приведен краткий обзор некоторых файлов в Simple3DGameDX , которые вы найдете полезными для включения в шаблон, если вы делаете его. В любом случае это не менее важно для понимания того, как работает сам Simple3DGameDX .

Исходный файл Папка с файлами Описание
DeviceResources.h/.cpp Служебные программы Определяет класс DeviceResources , который управляет всеми ресурсами устройств DirectX. Также определяет интерфейс IDeviceNotify, используемый для уведомления приложения о потере или повторном создании графического адаптера.
DirectXSample.h Служебные программы Реализует вспомогательные функции, такие как ConvertDipsToPixels. ConvertDipsToPixels преобразовывает длину в аппаратно независимых пикселях (DIP) в длину в физических пикселях.
GameTimer.h/.cpp Служебные программы Определяет высокоточный таймер для игр или интерактивных приложений с отрисовкой.
GameRenderer.h/.cpp Отрисовка Определяет класс GameRenderer , который реализует базовый конвейер отрисовки.
GameHud.h/.cpp Отрисовка Определяет класс для отрисовки дисплея (HUD) для игры с помощью Direct2D и DirectWrite.
VertexShader.hlsl и VertexShaderFlat.hlsl Шейдеры Содержит код HLSL для базовых вершинных шейдеров.
PixelShader.hlsl и PixelShaderFlat.hlsl Шейдеры Содержит код HLSL для базовых пиксельных шейдеров.
ConstantBuffers.hlsli Шейдеры Содержит определения структуры данных для буферов констант и структур шейдеров, используемых для передачи матриц модели, представления и проекции (MVP) и данных для каждой вершины в шейдер вершин.
pch.h/.cpp Н/Д Содержит общие компоненты C++/WinRT, Windows и DirectX.

Дальнейшие действия

На этом этапе мы показали, как создать новый проект UWP для игры DirectX, рассмотрели некоторые элементы в ней и начали думать о том, как превратить этот проект в своего рода шаблон для повторного использования для игр. Мы также рассмотрели некоторые важные элементы примера игры Simple3DGameDX .

Следующий раздел — Определение платформы приложений UWP для игры. Здесь мы более подробно рассмотрим, как работает Simple3DGameDX .