Всем привет!
Вы давно хотели создать свой собственный движок, но не знаете как?
Я скажу тебе!
Итак, нам нужно установить Visual Studio 2022 с Windows SDK.
Вот что нам нужно установить, а также языковой пакет «Английский».

Все установлено? Теперь о коде!
Создайте пустой проект C++

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

Для начала нужно зайти в настройки и сделать так:

И создайте файл Main.cpp
Для тех, кто не умеет создавать

Щелкните правой кнопкой мыши папку и «Создать новый элемент».
И давайте перейдем к коду!
Я буду обозначать концы функций как
//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);
после показа окна я пишу:
d3dinit(hWnd)
примерно так:

а также перед «возвратом 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();
}
теперь запустите:
Как и в прошлый раз
Всем пока! В следующей части мы будем рисовать рамки.