From 3ca20dd8b80674e310be49b5e7a484571917a2e4 Mon Sep 17 00:00:00 2001 From: serenitatis <30504381+serenitatis@users.noreply.github.com> Date: Fri, 19 Jun 2026 21:51:51 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9D=D0=B0=D1=87=D0=B0=D0=BB=D1=8C=D0=BD?= =?UTF-8?q?=D1=8B=D0=B9=20=D0=BA=D0=BE=D0=BC=D0=BC=D0=B8=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitattributes | 63 ++++++ .gitignore | 5 + 3dmaze.cpp | 441 +++++++++++++++++++++++++++++++++++++++++ 3dmaze.h | 3 + 3dmaze.ico | Bin 0 -> 46227 bytes 3dmaze.rc | Bin 0 -> 6924 bytes 3dmaze.sln | 31 +++ 3dmaze.vcxproj | 162 +++++++++++++++ 3dmaze.vcxproj.filters | 49 +++++ Resource.h | 30 +++ framework.h | 15 ++ small.ico | Bin 0 -> 46227 bytes targetver.h | 6 + 13 files changed, 805 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 3dmaze.cpp create mode 100644 3dmaze.h create mode 100644 3dmaze.ico create mode 100644 3dmaze.rc create mode 100644 3dmaze.sln create mode 100644 3dmaze.vcxproj create mode 100644 3dmaze.vcxproj.filters create mode 100644 Resource.h create mode 100644 framework.h create mode 100644 small.ico create mode 100644 targetver.h diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2a18136 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +Debug/ +Release/ +*.user +*.suo +.vs/ \ No newline at end of file diff --git a/3dmaze.cpp b/3dmaze.cpp new file mode 100644 index 0000000..b2bdaf4 --- /dev/null +++ b/3dmaze.cpp @@ -0,0 +1,441 @@ +#define _USE_MATH_DEFINES +#define NOMINMAX +#include + +// Решение проблемы с конфликтом min/max в GDI+ +#include +using std::min; +using std::max; + +#include +#include +#include +#include +#include +#include + +// Линковка библиотеки 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(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 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 DIRECTIONS = { 0.0f, static_cast(M_PI) / 2.0f, static_cast(M_PI), -static_cast(M_PI) / 2.0f }; + +enum class AIState { MOVE, TURN }; +AIState ai_state = AIState::MOVE; +float target_angle = 0.0f; + +std::map, int> world_map; + +std::mt19937 rng(std::random_device{}()); +float random_float() { + std::uniform_real_distribution 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 tex_wall(TILE_SIZE* TILE_SIZE); +std::vector tex_ceil(TILE_SIZE* TILE_SIZE); +std::vector tex_floor(TILE_SIZE* TILE_SIZE); + +bool load_png_texture(const wchar_t* filename, std::vector& 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(current_time - last_time).count(); + last_time = current_time; + + if (demo_mode) { + if (ai_state == AIState::MOVE) { + float target_x = static_cast(cell_x * TILE_SIZE + 32); + float target_y = static_cast(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 available_dirs; + for (size_t i = 0; i < DIRECTIONS.size(); ++i) { + int t_cos = static_cast(std::round(std::cos(DIRECTIONS[i]))); + int t_sin = static_cast(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(i)); + } + + int backward_dir_index = (current_dir_index + 2) % 4; + std::vector 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 dist_dir(0, static_cast(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(move_cos); cell_y += static_cast(move_sin); + } + } + } + else if (ai_state == AIState::TURN) { + float angle_diff = std::fmod(target_angle - player_angle + static_cast(M_PI), 2.0f * static_cast(M_PI)); + if (angle_diff < 0) angle_diff += 2.0f * static_cast(M_PI); + angle_diff -= static_cast(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(move_cos); cell_y += static_cast(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((player_x + mx + sign_x) / TILE_SIZE), static_cast(player_y / TILE_SIZE)) == 0) player_x += mx; + if (get_wall_type(static_cast(player_x / TILE_SIZE), static_cast((player_y + my + sign_y) / TILE_SIZE)) == 0) player_y += my; + + cell_x = static_cast(player_x / TILE_SIZE); cell_y = static_cast(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((static_cast(player_x / TILE_SIZE) + 1) * TILE_SIZE) : static_cast(static_cast(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((tx + (r_cos > 0 ? 1.0f : -1.0f)) / TILE_SIZE); + int row = static_cast(ty / TILE_SIZE); + if (get_wall_type(col, row) > 0) { + x_depth = current_depth_x; + x_texture = static_cast(std::fmod(ty, static_cast(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((static_cast(player_y / TILE_SIZE) + 1) * TILE_SIZE) : static_cast(static_cast(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(tx / TILE_SIZE); + int row = static_cast((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(std::fmod(tx, static_cast(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((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(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(std::max(0, pixel_color.r - shadow)); + pixel_color.g = static_cast(std::max(0, pixel_color.g - shadow)); + pixel_color.b = static_cast(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(TILE_SIZE * HEIGHT)) / (2.0f * static_cast(HALF_HEIGHT - screen_y) * cos_tilt); + + int tex_x = static_cast(player_x + r_cos * current_dist) % TILE_SIZE; + int tex_y_floor = static_cast(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(current_dist * 0.75f), 0, 255); + + Color c_color = tex_ceil[tex_y_floor * TILE_SIZE + tex_x]; + c_color.r = static_cast(std::max(0, c_color.r - f_shadow)); + c_color.g = static_cast(std::max(0, c_color.g - f_shadow)); + c_color.b = static_cast(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(std::max(0, fl_color.r - f_shadow)); + fl_color.g = static_cast(std::max(0, fl_color.g - f_shadow)); + fl_color.b = static_cast(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; +} \ No newline at end of file diff --git a/3dmaze.h b/3dmaze.h new file mode 100644 index 0000000..d00d47e --- /dev/null +++ b/3dmaze.h @@ -0,0 +1,3 @@ +#pragma once + +#include "resource.h" diff --git a/3dmaze.ico b/3dmaze.ico new file mode 100644 index 0000000000000000000000000000000000000000..b3ec03bd617f32e58128fa977fd6ac9605124f4b GIT binary patch literal 46227 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 + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {49a20b97-6b53-4055-bfb4-7e27e8bfc5c5} + My3dmaze + 10.0 + + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + false + + + true + + + false + + + + Level3 + true + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + true + stdcpp17 + + + Windows + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + true + stdcpp17 + + + Windows + true + true + true + + + + + Level3 + true + _DEBUG;_WINDOWS;%(PreprocessorDefinitions) + true + + + Windows + true + + + + + Level3 + true + true + true + NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + true + + + Windows + true + true + true + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/3dmaze.vcxproj.filters b/3dmaze.vcxproj.filters new file mode 100644 index 0000000..672daae --- /dev/null +++ b/3dmaze.vcxproj.filters @@ -0,0 +1,49 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Файлы заголовков + + + Файлы заголовков + + + Файлы заголовков + + + Файлы заголовков + + + + + Исходные файлы + + + + + Файлы ресурсов + + + + + Файлы ресурсов + + + Файлы ресурсов + + + \ No newline at end of file diff --git a/Resource.h b/Resource.h new file mode 100644 index 0000000..5a1e4fe --- /dev/null +++ b/Resource.h @@ -0,0 +1,30 @@ +//{{NO_DEPENDENCIES}} +// Включаемый файл, созданный в Microsoft Visual C++. +// Используется 3dmaze.rc + +#define IDS_APP_TITLE 103 + +#define IDR_MAINFRAME 128 +#define IDD_MY3DMAZE_DIALOG 102 +#define IDD_ABOUTBOX 103 +#define IDM_ABOUT 104 +#define IDM_EXIT 105 +#define IDI_MY3DMAZE 107 +#define IDI_SMALL 108 +#define IDC_MY3DMAZE 109 +#define IDC_MYICON 2 +#ifndef IDC_STATIC +#define IDC_STATIC -1 +#endif +// Следующие стандартные значения для новых объектов +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS + +#define _APS_NO_MFC 130 +#define _APS_NEXT_RESOURCE_VALUE 129 +#define _APS_NEXT_COMMAND_VALUE 32771 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 110 +#endif +#endif diff --git a/framework.h b/framework.h new file mode 100644 index 0000000..a8f6dc8 --- /dev/null +++ b/framework.h @@ -0,0 +1,15 @@ +// header.h: включаемый файл для стандартных системных включаемых файлов +// или включаемые файлы для конкретного проекта +// + +#pragma once + +#include "targetver.h" +#define WIN32_LEAN_AND_MEAN // Исключите редко используемые компоненты из заголовков Windows +// Файлы заголовков Windows +#include +// Файлы заголовков среды выполнения C +#include +#include +#include +#include diff --git a/small.ico b/small.ico new file mode 100644 index 0000000000000000000000000000000000000000..b3ec03bd617f32e58128fa977fd6ac9605124f4b GIT binary patch literal 46227 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