Пишем свой игровой движок.Часть 1 — WinApi и Directx

от автора

Всем привет!

Давно хотели создать свой движок но не знаете как?

Я вам расскажу!

Итак, нам надо установить Visual studio 2022 с Windows SDK.

компоненты

компоненты

Вот следущее нам надо установить и дополнительно языковой пакет ‘Английский’

Все установили? Теперь погнали к коду!

Создаем на С++ пустой проект

И называем Beta-Engine

Сначала надо зайти в настройки и делаем так:

И создаем файл Main.cpp

Для тех кто не знает как создать

Нажимаем на папку пкм и ‘Create new item’

И приступаем к коду!

Я буду обозначать концы функций как

//winapi functon

И Т.Д.

Нам надо сначала включить в проект файлы WinApi

#include <Windows.h

Отлично написали.

теперь нам надо Создать точку входа и сразу делаем дескриптор окна

int WINAPI WinMain(HINSTANCE hInstance,                    HINSTANCE hPrevInstance,                    LPSTR lpCmdLine,                    int nCmdShow) {   //win api start   //дескриптор окна   HWND hWnd;      //этот калсс содержит информацию о нашем окне   WNDCLASSEX wc;        //win api end }

Теперь нам надо же заполнить информацию об окне?

Ну так поехали:

//очищаем память для окна ZeroMemory(&wc, sizeof(WNDCLASSEX));  //заполняем информацию wc.cbSize = sizeof(WNDCLASSEX);     wc.style = CS_HREDRAW | CS_VREDRAW; //стиль окна     wc.lpfnWndProc = WindowProc; //функция обработки сообщений     wc.hInstance = hInstance; // у меня нет коментариев     wc.hCursor = LoadCursor(NULL, IDC_ARROW); //стандартный курсор     wc.hbrBackground = (HBRUSH)COLOR_WINDOW; //задний фон     wc.lpszClassName = L"WindowClass1"; //название класса  //win api end

Пока вы пишете это я расскажу прикол:

Я сижу на ПК пишу этот пост и на телефоне вылезает реклама, я мышкой попытался ‘закрыть рекламу на телефоне’

Пишем дальше:

Чтобы создать окно надо же его зарегистрировать?Конечно!

//регистрируем окно RegisterClassEx(&wc);

И создаем окно наконец-то

//создаем окно hWnd = CreateWindowEx(NULL,                           L"WindowClass1",    //имя класса                           L"Our First Windowed Program",   // название окна                           WS_OVERLAPPEDWINDOW,    //стиль окна                           300,    // x-позиция                           300,    // y-позиция                           500,    // ширина окна                           400,    // высота окна                           NULL,    // у нас нет родительских окон,значит Null                           NULL,    // мы не используем меню, NULL                           hInstance,    // Дескриптор приложения                           NULL);    // используем только когда мульти-оконость, NULL   //win api end

Теперь показываем окно(кстати во всем коде много раз используется наш hwnd и wc):

ShowWindow(hWnd, nCmdShow);

Создаем обработку сообщений

 MSG msg;   while(GetMessage(&msg, NULL, 0, 0)) {   //переводим сообщение в правильный формат   TranslateMessage(&msg);    //отправляем сообщения в windproc   DispatchMessage(&msg); }  return msg.wParam;  //win api закончился
СПОЙЛЕР: весь код для тех кто запутался
#include <Windows.h>  int WINAPI WinMain(HINSTANCE hInstance,     HINSTANCE hPrevInstance,     LPSTR lpCmdLine,     int nCmdShow) {     //win api start     //дескриптор окна     HWND hWnd;      //этот калсс содержит информацию о нашем окне     WNDCLASSEX wc;           //очищаем память для окна     ZeroMemory(&wc, sizeof(WNDCLASSEX));      //заполняем информацию     wc.cbSize = sizeof(WNDCLASSEX);     wc.style = CS_HREDRAW | CS_VREDRAW; //стиль окна     wc.lpfnWndProc = WindowProc; //функция обработки сообщений     wc.hInstance = hInstance; // у меня нет коментариев     wc.hCursor = LoadCursor(NULL, IDC_ARROW); //стандартный курсор     wc.hbrBackground = (HBRUSH)COLOR_WINDOW; //задний фон     wc.lpszClassName = L"WindowClass1"; //название класса               //регистрируем окно     RegisterClassEx(&wc);      //создаем окно     hWnd = CreateWindowEx(NULL,         L"WindowClass1",    //имя класса         L"Our First Windowed Program",   // название окна         WS_OVERLAPPEDWINDOW,    //стиль окна         300,    // x-позиция         300,    // y-позиция         500,    // ширина окна         400,    // высота окна         NULL,    // у нас нет родительских окон,значит Null         NULL,    // мы не используем меню, NULL         hInstance,    // Дескриптор приложения         NULL);    // используем только когда мульти-оконость, NULL      ShowWindow(hWnd, nCmdShow);     MSG msg;       while (GetMessage(&msg, NULL, 0, 0))     {         //переводим сообщение в правильный формат         TranslateMessage(&msg);          //отправляем сообщения в windproc         DispatchMessage(&msg);     }     return msg.wParam;     //win api закончился }

Чтобы закончить обработку сообщений нам надо написать windowproc

LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {     // сортируем сообщения     switch(message)     {         // сообщения когда закрывают окно         case WM_DESTROY:             {                 // закрываем окно                 PostQuitMessage(0);                 return 0;             } break;     }      // Обработка всех сообщений, не полученных инструкцией switch     return DefWindowProc (hWnd, message, wParam, lParam); }

Теперь в начало кода надо сделать прототип windowproc

LRESULT CALLBACK WindowProc(HWND hWnd,     UINT message,     WPARAM wParam,     LPARAM lParam);

Вот куда ставить:

вот весь код:

Весь код
#include <Windows.h>  LRESULT CALLBACK WindowProc(HWND hWnd,     UINT message,     WPARAM wParam,     LPARAM lParam);  int WINAPI WinMain(HINSTANCE hInstance,     HINSTANCE hPrevInstance,     LPSTR lpCmdLine,     int nCmdShow) {     //win api start     //дескриптор окна     HWND hWnd;      //этот калсс содержит информацию о нашем окне     WNDCLASSEX wc;       //очищаем память для окна     ZeroMemory(&wc, sizeof(WNDCLASSEX));      //заполняем информацию     wc.cbSize = sizeof(WNDCLASSEX);     wc.style = CS_HREDRAW | CS_VREDRAW; //стиль окна     wc.lpfnWndProc = WindowProc; //функция обработки сообщений     wc.hInstance = hInstance; // у меня нет коментариев     wc.hCursor = LoadCursor(NULL, IDC_ARROW); //стандартный курсор     wc.hbrBackground = (HBRUSH)COLOR_WINDOW; //задний фон     wc.lpszClassName = L"WindowClass1"; //название класса       //регистрируем окно     RegisterClassEx(&wc);      //создаем окно     hWnd = CreateWindowEx(NULL,         L"WindowClass1",    //имя класса         L"Our First Windowed Program",   // название окна         WS_OVERLAPPEDWINDOW,    //стиль окна         300,    // x-позиция         300,    // y-позиция         500,    // ширина окна         400,    // высота окна         NULL,    // у нас нет родительских окон,значит Null         NULL,    // мы не используем меню, NULL         hInstance,    // Дескриптор приложения         NULL);    // используем только когда мульти-оконость, NULL      ShowWindow(hWnd, nCmdShow);     MSG msg;       while (GetMessage(&msg, NULL, 0, 0))     {         //переводим сообщение в правильный формат         TranslateMessage(&msg);          //отправляем сообщения в windproc         DispatchMessage(&msg);     }     return msg.wParam;     //win api закончился } LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {     // сортируем сообщения     switch (message)     {         // сообщения когда закрывают окно     case WM_DESTROY:     {         // закрываем окно         PostQuitMessage(0);         return 0;     } break;     }      // Обработка всех сообщений, не полученных инструкцией switch     return DefWindowProc(hWnd, message, wParam, lParam); }

Запускаем и видим:

Пока что нам надо добавить сам d3d

#include <d3d11.h> //добавляем в начало   #pragma comment (lib, "d3d11.lib")

теперь объявляем:

IDXGISwapChain *swapchain;             // Указатель на интерфейс цепочки буферов ID3D11Device *dev;                     // указатель на интерфейс устройства Direct3D ID3D11DeviceContext *devcon;           // указатель на контекст устройства Direct3D 

объявляем функции(позже мы их напишем)

void d3dinit(HWND hWnd); void d3dcl(void);

после show window пишем:

  d3dinit(hWnd)

вот так примерно:

и также перед ‘return msg.wparam’

уже создаем функцию d3dinit в самом конце

void d3dinit(HWND hWnd) {   //создаем структуру которая держит информацию о  буффере   DXGI_SWAP_CHAIN_DESC scd;   //очищаем память для использования   ZeroMemory(&scd, sizeof(DXGI_SWAP_CHAIN_DESC));    scd.BufferCount = 1;  //Один задний буфер   scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; // используем 32 битный цвет   scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; //Как следует использовать цепочку буферов   scd.OutputWindow = hWnd;                                // Окно, которое будет использоваться   scd.SampleDesc.Count = 4;                               // кол-во уровней сглаживания   scd.Windowed = TRUE;                                    // оконный/полноэкранный режим     //создаем девайс d3d     D3D11CreateDeviceAndSwapChain(NULL,                                   D3D_DRIVER_TYPE_HARDWARE,                                   NULL,                                   NULL,                                   NULL,                                   NULL,                                   D3D11_SDK_VERSION,                                   &scd,                                   &swapchain,                                   &dev,                                   NULL,                                   &devcon); }

Написали? Молодцы

Теперь следущую функцию d3dcl

void d3dcl(void) {     // закройте и освободите все существующие COM-объекты     swapchain->Release();     dev->Release();     devcon->Release(); }

теперь запускаем:

Как и в прошлый раз

Всем пока! В следущей части сделаем отрисовку кадров.


ссылка на оригинал статьи https://habr.com/ru/articles/740770/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *