Начальный коммит
This commit is contained in:
+441
@@ -0,0 +1,441 @@
|
||||
#define _USE_MATH_DEFINES
|
||||
#define NOMINMAX
|
||||
#include <windows.h>
|
||||
|
||||
// Решение проблемы с конфликтом min/max в GDI+
|
||||
#include <algorithm>
|
||||
using std::min;
|
||||
using std::max;
|
||||
|
||||
#include <gdiplus.h>
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <random>
|
||||
#include <chrono>
|
||||
|
||||
// Линковка библиотеки GDI+
|
||||
#pragma comment (lib, "Gdiplus.lib")
|
||||
|
||||
// Константы
|
||||
const int WIDTH = 800;
|
||||
const int HEIGHT = 600;
|
||||
const int HALF_HEIGHT = HEIGHT / 2;
|
||||
const int TILE_SIZE = 64;
|
||||
const float fov = static_cast<float>(M_PI) / 3.0f;
|
||||
const int NUM_RAYS = 160;
|
||||
const int SCALE = WIDTH / NUM_RAYS;
|
||||
const int MAP_SIZE = 32;
|
||||
|
||||
struct Color {
|
||||
unsigned char b, g, r, a;
|
||||
Color() : r(0), g(0), b(0), a(255) {}
|
||||
Color(unsigned char r, unsigned char g, unsigned char b) : r(r), g(g), b(b), a(255) {}
|
||||
};
|
||||
|
||||
std::vector<Color> frame_buffer(WIDTH* HEIGHT);
|
||||
|
||||
float player_x = 2.0f * TILE_SIZE + 32.0f;
|
||||
float player_y = 2.0f * TILE_SIZE + 32.0f;
|
||||
int cell_x = 2;
|
||||
int cell_y = 2;
|
||||
float player_angle = 0.0f;
|
||||
const float player_speed = 100.0f;
|
||||
const float rotation_speed = 2.0f;
|
||||
|
||||
bool demo_mode = true;
|
||||
bool day_mode = false;
|
||||
int current_dir_index = 0;
|
||||
const std::vector<float> DIRECTIONS = { 0.0f, static_cast<float>(M_PI) / 2.0f, static_cast<float>(M_PI), -static_cast<float>(M_PI) / 2.0f };
|
||||
|
||||
enum class AIState { MOVE, TURN };
|
||||
AIState ai_state = AIState::MOVE;
|
||||
float target_angle = 0.0f;
|
||||
|
||||
std::map<std::pair<int, int>, int> world_map;
|
||||
|
||||
std::mt19937 rng(std::random_device{}());
|
||||
float random_float() {
|
||||
std::uniform_real_distribution<float> dist(0.0f, 1.0f);
|
||||
return dist(rng);
|
||||
}
|
||||
|
||||
void generate_maze(int size) {
|
||||
for (int row = 0; row < size; ++row) {
|
||||
for (int col = 0; col < size; ++col) {
|
||||
if (col == 0 || col == size - 1 || row == 0 || row == size - 1) {
|
||||
world_map[{col, row}] = 1;
|
||||
}
|
||||
else if (col >= 1 && col <= 3 && row >= 1 && row <= 3) {
|
||||
world_map[{col, row}] = 0;
|
||||
}
|
||||
else {
|
||||
world_map[{col, row}] = (random_float() < 0.30f) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int get_wall_type(int col, int row) {
|
||||
auto it = world_map.find({ col, row });
|
||||
if (it != world_map.end()) return it->second;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::vector<Color> tex_wall(TILE_SIZE* TILE_SIZE);
|
||||
std::vector<Color> tex_ceil(TILE_SIZE* TILE_SIZE);
|
||||
std::vector<Color> tex_floor(TILE_SIZE* TILE_SIZE);
|
||||
|
||||
bool load_png_texture(const wchar_t* filename, std::vector<Color>& buffer) {
|
||||
Gdiplus::Bitmap bitmap(filename);
|
||||
if (bitmap.GetLastStatus() != Gdiplus::Ok) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Gdiplus::BitmapData bitmapData;
|
||||
Gdiplus::Rect rect(0, 0, bitmap.GetWidth(), bitmap.GetHeight());
|
||||
|
||||
if (bitmap.LockBits(&rect, Gdiplus::ImageLockModeRead, PixelFormat32bppARGB, &bitmapData) == Gdiplus::Ok) {
|
||||
UINT* pixels = (UINT*)bitmapData.Scan0;
|
||||
int stride = bitmapData.Stride / 4;
|
||||
|
||||
for (int y = 0; y < TILE_SIZE; ++y) {
|
||||
for (int x = 0; x < TILE_SIZE; ++x) {
|
||||
int src_x = (x * bitmap.GetWidth()) / TILE_SIZE;
|
||||
int src_y = (y * bitmap.GetHeight()) / TILE_SIZE;
|
||||
UINT p = pixels[src_y * stride + src_x];
|
||||
|
||||
Color c;
|
||||
c.a = (p >> 24) & 0xFF;
|
||||
c.r = (p >> 16) & 0xFF;
|
||||
c.g = (p >> 8) & 0xFF;
|
||||
c.b = p & 0xFF;
|
||||
buffer[y * TILE_SIZE + x] = c;
|
||||
}
|
||||
}
|
||||
bitmap.UnlockBits(&bitmapData);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void create_textures() {
|
||||
if (!load_png_texture(L"wall.png", tex_wall)) {
|
||||
std::fill(tex_wall.begin(), tex_wall.end(), Color(125, 45, 30));
|
||||
for (int y : {0, 16, 32, 48, 63})
|
||||
for (int x = 0; x < 64; ++x) tex_wall[y * TILE_SIZE + x] = Color(110, 105, 100);
|
||||
for (int x : {0, 32, 64}) {
|
||||
if (x < 64) {
|
||||
for (int y = 0; y < 16; ++y) tex_wall[y * TILE_SIZE + x] = Color(110, 105, 100);
|
||||
for (int y = 32; y < 48; ++y) tex_wall[y * TILE_SIZE + x] = Color(110, 105, 100);
|
||||
}
|
||||
}
|
||||
for (int x : {16, 48}) {
|
||||
for (int y = 16; y < 32; ++y) tex_wall[y * TILE_SIZE + x] = Color(110, 105, 100);
|
||||
for (int y = 48; y < 64; ++y) tex_wall[y * TILE_SIZE + x] = Color(110, 105, 100);
|
||||
}
|
||||
}
|
||||
|
||||
if (!load_png_texture(L"top.png", tex_ceil)) {
|
||||
std::fill(tex_ceil.begin(), tex_ceil.end(), Color(75, 75, 75));
|
||||
}
|
||||
|
||||
if (!load_png_texture(L"floor.png", tex_floor)) {
|
||||
std::fill(tex_floor.begin(), tex_floor.end(), Color(45, 45, 50));
|
||||
for (int i = 0; i < TILE_SIZE; i += 16) {
|
||||
for (int y = 0; y < TILE_SIZE; ++y) tex_floor[y * TILE_SIZE + i] = Color(25, 25, 28);
|
||||
for (int x = 0; x < TILE_SIZE; ++x) tex_floor[i * TILE_SIZE + x] = Color(25, 25, 28);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
|
||||
switch (uMsg) {
|
||||
case WM_DESTROY: PostQuitMessage(0); return 0;
|
||||
case WM_KEYDOWN:
|
||||
if (wParam == 'Y') { demo_mode = !demo_mode; ai_state = AIState::MOVE; }
|
||||
if (wParam == 'L') { day_mode = !day_mode; }
|
||||
if (wParam == VK_ESCAPE) PostQuitMessage(0);
|
||||
return 0;
|
||||
}
|
||||
return DefWindowProc(hwnd, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
|
||||
Gdiplus::GdiplusStartupInput gdiplusStartupInput;
|
||||
ULONG_PTR gdiplusToken;
|
||||
Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
|
||||
|
||||
const wchar_t CLASS_NAME[] = L"MazeWindowClass";
|
||||
WNDCLASS wc = {};
|
||||
wc.lpfnWndProc = WindowProc;
|
||||
wc.hInstance = hInstance;
|
||||
wc.lpszClassName = CLASS_NAME;
|
||||
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||
RegisterClass(&wc);
|
||||
|
||||
RECT rect = { 0, 0, WIDTH, HEIGHT };
|
||||
AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME & ~WS_MAXIMIZEBOX, FALSE);
|
||||
|
||||
HWND hwnd = CreateWindowEx(0, CLASS_NAME, L"3DMAZE",
|
||||
WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME & ~WS_MAXIMIZEBOX,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT, rect.right - rect.left, rect.bottom - rect.top,
|
||||
NULL, NULL, hInstance, NULL);
|
||||
|
||||
if (hwnd == NULL) {
|
||||
Gdiplus::GdiplusShutdown(gdiplusToken);
|
||||
return 0;
|
||||
}
|
||||
ShowWindow(hwnd, nCmdShow);
|
||||
|
||||
generate_maze(MAP_SIZE);
|
||||
create_textures();
|
||||
|
||||
BITMAPINFO bmi = {};
|
||||
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
bmi.bmiHeader.biWidth = WIDTH;
|
||||
bmi.bmiHeader.biHeight = -HEIGHT;
|
||||
bmi.bmiHeader.biPlanes = 1;
|
||||
bmi.bmiHeader.biBitCount = 32;
|
||||
bmi.bmiHeader.biCompression = BI_RGB;
|
||||
|
||||
auto last_time = std::chrono::high_resolution_clock::now();
|
||||
bool running = true;
|
||||
|
||||
while (running) {
|
||||
MSG msg;
|
||||
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
|
||||
if (msg.message == WM_QUIT) running = false;
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
|
||||
auto current_time = std::chrono::high_resolution_clock::now();
|
||||
float dt = std::chrono::duration<float>(current_time - last_time).count();
|
||||
last_time = current_time;
|
||||
|
||||
if (demo_mode) {
|
||||
if (ai_state == AIState::MOVE) {
|
||||
float target_x = static_cast<float>(cell_x * TILE_SIZE + 32);
|
||||
float target_y = static_cast<float>(cell_y * TILE_SIZE + 32);
|
||||
float move_cos = std::round(std::cos(DIRECTIONS[current_dir_index]));
|
||||
float move_sin = std::round(std::sin(DIRECTIONS[current_dir_index]));
|
||||
float dist = std::hypot(target_x - player_x, target_y - player_y);
|
||||
|
||||
if (dist > 1.0f) {
|
||||
float step = player_speed * dt;
|
||||
if (step > dist) step = dist;
|
||||
player_x += move_cos * step;
|
||||
player_y += move_sin * step;
|
||||
}
|
||||
else {
|
||||
player_x = target_x; player_y = target_y;
|
||||
std::vector<int> available_dirs;
|
||||
for (size_t i = 0; i < DIRECTIONS.size(); ++i) {
|
||||
int t_cos = static_cast<int>(std::round(std::cos(DIRECTIONS[i])));
|
||||
int t_sin = static_cast<int>(std::round(std::sin(DIRECTIONS[i])));
|
||||
if (get_wall_type(cell_x + t_cos, cell_y + t_sin) == 0) available_dirs.push_back(static_cast<int>(i));
|
||||
}
|
||||
|
||||
int backward_dir_index = (current_dir_index + 2) % 4;
|
||||
std::vector<int> forward_and_sides;
|
||||
for (int d : available_dirs) if (d != backward_dir_index) forward_and_sides.push_back(d);
|
||||
|
||||
int next_dir = current_dir_index;
|
||||
if (!forward_and_sides.empty()) {
|
||||
if (std::find(forward_and_sides.begin(), forward_and_sides.end(), current_dir_index) != forward_and_sides.end() && random_float() < 0.75f) {
|
||||
next_dir = current_dir_index;
|
||||
}
|
||||
else {
|
||||
std::uniform_int_distribution<int> dist_dir(0, static_cast<int>(forward_and_sides.size() - 1));
|
||||
next_dir = forward_and_sides[dist_dir(rng)];
|
||||
}
|
||||
}
|
||||
else if (std::find(available_dirs.begin(), available_dirs.end(), backward_dir_index) != available_dirs.end()) {
|
||||
next_dir = backward_dir_index;
|
||||
}
|
||||
|
||||
if (next_dir != current_dir_index) {
|
||||
current_dir_index = next_dir; target_angle = DIRECTIONS[current_dir_index]; ai_state = AIState::TURN;
|
||||
}
|
||||
else {
|
||||
cell_x += static_cast<int>(move_cos); cell_y += static_cast<int>(move_sin);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ai_state == AIState::TURN) {
|
||||
float angle_diff = std::fmod(target_angle - player_angle + static_cast<float>(M_PI), 2.0f * static_cast<float>(M_PI));
|
||||
if (angle_diff < 0) angle_diff += 2.0f * static_cast<float>(M_PI);
|
||||
angle_diff -= static_cast<float>(M_PI);
|
||||
|
||||
if (std::abs(angle_diff) > 0.01f) {
|
||||
float step = rotation_speed * dt;
|
||||
if (step > std::abs(angle_diff)) step = std::abs(angle_diff);
|
||||
player_angle += (angle_diff > 0 ? 1.0f : -1.0f) * step;
|
||||
}
|
||||
else {
|
||||
player_angle = target_angle;
|
||||
float move_cos = std::round(std::cos(DIRECTIONS[current_dir_index]));
|
||||
float move_sin = std::round(std::sin(DIRECTIONS[current_dir_index]));
|
||||
cell_x += static_cast<int>(move_cos); cell_y += static_cast<int>(move_sin); ai_state = AIState::MOVE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (GetAsyncKeyState('A') || GetAsyncKeyState(VK_LEFT)) player_angle -= 3.0f * dt;
|
||||
if (GetAsyncKeyState('D') || GetAsyncKeyState(VK_RIGHT)) player_angle += 3.0f * dt;
|
||||
|
||||
float cos_a = std::cos(player_angle), sin_a = std::sin(player_angle);
|
||||
float mx = 0, my = 0;
|
||||
if (GetAsyncKeyState('W') || GetAsyncKeyState(VK_UP)) { mx = player_speed * cos_a * dt; my = player_speed * sin_a * dt; }
|
||||
else if (GetAsyncKeyState('S') || GetAsyncKeyState(VK_DOWN)) { mx = -player_speed * cos_a * dt; my = -player_speed * sin_a * dt; }
|
||||
|
||||
float r = 12.0f;
|
||||
float sign_x = (mx > 0) ? r : (mx < 0 ? -r : 0);
|
||||
float sign_y = (my > 0) ? r : (my < 0 ? -r : 0);
|
||||
|
||||
if (get_wall_type(static_cast<int>((player_x + mx + sign_x) / TILE_SIZE), static_cast<int>(player_y / TILE_SIZE)) == 0) player_x += mx;
|
||||
if (get_wall_type(static_cast<int>(player_x / TILE_SIZE), static_cast<int>((player_y + my + sign_y) / TILE_SIZE)) == 0) player_y += my;
|
||||
|
||||
cell_x = static_cast<int>(player_x / TILE_SIZE); cell_y = static_cast<int>(player_y / TILE_SIZE);
|
||||
}
|
||||
|
||||
Color bg_color = day_mode ? Color(140, 140, 145) : Color(15, 15, 15);
|
||||
std::fill(frame_buffer.begin(), frame_buffer.end(), bg_color);
|
||||
|
||||
float start_angle = player_angle - fov / 2.0f;
|
||||
|
||||
for (int ray = 0; ray < NUM_RAYS; ++ray) {
|
||||
float angle = start_angle + ray * (fov / NUM_RAYS);
|
||||
float r_cos = (std::cos(angle) != 0) ? std::cos(angle) : 0.00001f;
|
||||
float r_sin = (std::sin(angle) != 0) ? std::sin(angle) : 0.00001f;
|
||||
|
||||
float x_depth = 9999.0f; int x_texture = 0;
|
||||
float x_step = TILE_SIZE / r_cos;
|
||||
float first_x = (r_cos > 0) ? static_cast<float>((static_cast<int>(player_x / TILE_SIZE) + 1) * TILE_SIZE) : static_cast<float>(static_cast<int>(player_x / TILE_SIZE) * TILE_SIZE);
|
||||
float current_depth_x = (first_x - player_x) / r_cos;
|
||||
|
||||
for (int i = 0; i < 30; ++i) {
|
||||
float tx = player_x + current_depth_x * r_cos;
|
||||
float ty = player_y + current_depth_x * r_sin;
|
||||
int col = static_cast<int>((tx + (r_cos > 0 ? 1.0f : -1.0f)) / TILE_SIZE);
|
||||
int row = static_cast<int>(ty / TILE_SIZE);
|
||||
if (get_wall_type(col, row) > 0) {
|
||||
x_depth = current_depth_x;
|
||||
x_texture = static_cast<int>(std::fmod(ty, static_cast<float>(TILE_SIZE)));
|
||||
if (x_texture < 0) x_texture += TILE_SIZE;
|
||||
break;
|
||||
}
|
||||
current_depth_x += std::abs(x_step);
|
||||
}
|
||||
|
||||
float y_depth = 9999.0f; int y_texture = 0;
|
||||
float y_step = TILE_SIZE / r_sin;
|
||||
float first_y = (r_sin > 0) ? static_cast<float>((static_cast<int>(player_y / TILE_SIZE) + 1) * TILE_SIZE) : static_cast<float>(static_cast<int>(player_y / TILE_SIZE) * TILE_SIZE);
|
||||
float current_depth_y = (first_y - player_y) / r_sin;
|
||||
|
||||
for (int i = 0; i < 30; ++i) {
|
||||
float tx = player_x + current_depth_y * r_cos;
|
||||
float ty = player_y + current_depth_y * r_sin;
|
||||
int col = static_cast<int>(tx / TILE_SIZE);
|
||||
int row = static_cast<int>((ty + (r_sin > 0 ? 1.0f : -1.0f)) / TILE_SIZE);
|
||||
if (get_wall_type(col, row) > 0) {
|
||||
y_depth = current_depth_y;
|
||||
y_texture = static_cast<int>(std::fmod(tx, static_cast<float>(TILE_SIZE)));
|
||||
if (y_texture < 0) y_texture += TILE_SIZE;
|
||||
break;
|
||||
}
|
||||
current_depth_y += std::abs(y_step);
|
||||
}
|
||||
|
||||
float depth = 0; int x_tex_coord = 0; bool is_vertical_wall = false;
|
||||
if (x_depth < y_depth) { depth = x_depth; x_tex_coord = x_texture; is_vertical_wall = true; }
|
||||
else { depth = y_depth; x_tex_coord = y_texture; is_vertical_wall = false; }
|
||||
|
||||
int wall_y_pos = HALF_HEIGHT;
|
||||
|
||||
if (depth < 9999.0f) {
|
||||
float fixed_depth = depth * std::cos(player_angle - angle);
|
||||
if (fixed_depth < 1.0f) fixed_depth = 1.0f;
|
||||
int proj_height = static_cast<int>((TILE_SIZE / fixed_depth) * 600.0f);
|
||||
if (proj_height > HEIGHT * 2) proj_height = HEIGHT * 2;
|
||||
|
||||
wall_y_pos = HALF_HEIGHT - proj_height / 2;
|
||||
|
||||
int shadow = 0;
|
||||
if (day_mode) {
|
||||
shadow = is_vertical_wall ? 15 : 0;
|
||||
}
|
||||
else {
|
||||
int base_shadow = static_cast<int>(fixed_depth * 0.75f);
|
||||
if (is_vertical_wall) base_shadow += 20;
|
||||
shadow = std::clamp(base_shadow, 0, 255);
|
||||
}
|
||||
|
||||
int start_screen_y = std::max(0, wall_y_pos);
|
||||
int end_screen_y = std::min(HEIGHT, wall_y_pos + proj_height);
|
||||
|
||||
for (int screen_y = start_screen_y; screen_y < end_screen_y; ++screen_y) {
|
||||
int tex_y = ((screen_y - wall_y_pos) * TILE_SIZE) / proj_height;
|
||||
tex_y = std::clamp(tex_y, 0, TILE_SIZE - 1);
|
||||
|
||||
Color pixel_color = tex_wall[tex_y * TILE_SIZE + std::clamp(x_tex_coord, 0, TILE_SIZE - 1)];
|
||||
pixel_color.r = static_cast<unsigned char>(std::max(0, pixel_color.r - shadow));
|
||||
pixel_color.g = static_cast<unsigned char>(std::max(0, pixel_color.g - shadow));
|
||||
pixel_color.b = static_cast<unsigned char>(std::max(0, pixel_color.b - shadow));
|
||||
|
||||
for (int s = 0; s < SCALE; ++s) {
|
||||
int pixel_x = ray * SCALE + s;
|
||||
if (pixel_x < WIDTH) frame_buffer[screen_y * WIDTH + pixel_x] = pixel_color;
|
||||
}
|
||||
}
|
||||
|
||||
float cos_tilt = std::cos(player_angle - angle);
|
||||
for (int screen_y = 0; screen_y < wall_y_pos; screen_y += 4) {
|
||||
if (screen_y >= HALF_HEIGHT) break;
|
||||
|
||||
float current_dist = (static_cast<float>(TILE_SIZE * HEIGHT)) / (2.0f * static_cast<float>(HALF_HEIGHT - screen_y) * cos_tilt);
|
||||
|
||||
int tex_x = static_cast<int>(player_x + r_cos * current_dist) % TILE_SIZE;
|
||||
int tex_y_floor = static_cast<int>(player_y + r_sin * current_dist) % TILE_SIZE;
|
||||
if (tex_x < 0) tex_x += TILE_SIZE;
|
||||
if (tex_y_floor < 0) tex_y_floor += TILE_SIZE;
|
||||
|
||||
int f_shadow = day_mode ? 0 : std::clamp(static_cast<int>(current_dist * 0.75f), 0, 255);
|
||||
|
||||
Color c_color = tex_ceil[tex_y_floor * TILE_SIZE + tex_x];
|
||||
c_color.r = static_cast<unsigned char>(std::max(0, c_color.r - f_shadow));
|
||||
c_color.g = static_cast<unsigned char>(std::max(0, c_color.g - f_shadow));
|
||||
c_color.b = static_cast<unsigned char>(std::max(0, c_color.b - f_shadow));
|
||||
|
||||
Color fl_color = tex_floor[tex_y_floor * TILE_SIZE + tex_x];
|
||||
fl_color.r = static_cast<unsigned char>(std::max(0, fl_color.r - f_shadow));
|
||||
fl_color.g = static_cast<unsigned char>(std::max(0, fl_color.g - f_shadow));
|
||||
fl_color.b = static_cast<unsigned char>(std::max(0, fl_color.b - f_shadow));
|
||||
|
||||
for (int h = 0; h < 4; ++h) {
|
||||
int curr_y = screen_y + h;
|
||||
int floor_y = HEIGHT - curr_y - 1;
|
||||
|
||||
if (curr_y < wall_y_pos) {
|
||||
for (int s = 0; s < SCALE; ++s) {
|
||||
int pixel_x = ray * SCALE + s;
|
||||
if (pixel_x < WIDTH) {
|
||||
frame_buffer[curr_y * WIDTH + pixel_x] = c_color;
|
||||
frame_buffer[floor_y * WIDTH + pixel_x] = fl_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HDC hdc = GetDC(hwnd);
|
||||
StretchDIBits(hdc, 0, 0, WIDTH, HEIGHT, 0, 0, WIDTH, HEIGHT, frame_buffer.data(), &bmi, DIB_RGB_COLORS, SRCCOPY);
|
||||
ReleaseDC(hwnd, hdc);
|
||||
}
|
||||
|
||||
Gdiplus::GdiplusShutdown(gdiplusToken);
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user