Форум программистов, компьютерный форум, киберфорум
C/C++: WinAPI
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.60/15: Рейтинг темы: голосов - 15, средняя оценка - 4.60
3 / 3 / 0
Регистрация: 05.04.2020
Сообщений: 69

Попытка реализовать простенькую игру на WinAPI и GDI+ (Проблема низкий FPS)

09.09.2021, 19:14. Показов 3133. Ответов 1

Студворк — интернет-сервис помощи студентам
Всем доброго времени суток.
Я новичок и пытаюсь постичь основы Win Api. Я новичок в принципе. ООП на C++ почти не юзал и большинство моих проектов - это один файл. Короче я очередной говнокодер и сейчас я это продемонстрирую.

Идея следующая: написать простенькую игру (типа увернись как бои в undertele), но чтобы действие как бы происходило непосредственно на рабочей столе(не в окне).

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, PSTR, INT iCmdShow) //для проекта под Windows
//INT APIENTRY main(HINSTANCE hInstance, HINSTANCE, PSTR, INT iCmdShow) //для консольного проекта
{
    HWND                hWnd;
    MSG                 msg = {0};
    WNDCLASS            wndClass;
 
    // Определяем разрешение экрана
    scrWidth = GetSystemMetrics(SM_CXSCREEN);
    scrHeight = GetSystemMetrics(SM_CYSCREEN);
 
    GdiplusStartupInput gdiplusStartupInput;
    ULONG_PTR           gdiplusToken;
 
    // Initialize GDI+.
    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
 
    wndClass.style = 0;// CS_HREDRAW | CS_VREDRAW;
    wndClass.lpfnWndProc = WndProc;
    wndClass.cbClsExtra = 0;
    wndClass.cbWndExtra = 0;
    wndClass.hInstance = hInstance;
    wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndClass.hbrBackground = 0;// (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndClass.lpszMenuName = NULL;
    wndClass.lpszClassName = TEXT("GettingStarted");
  
    globalhInstance = hInstance;
 
    RegisterClass(&wndClass);
 
    hWnd = CreateWindowEx(
        WS_EX_TOPMOST,
        TEXT("GettingStarted"),     // window class name
        TEXT("Getting Started"),    // window caption
        WS_POPUP,                   // window style
        0,                          // initial x position
        0,                          // initial y position
        scrWidth,                   // initial x size
        scrHeight,                  // initial y size
        NULL,                       // parent window handle
        NULL,                       // window menu handle
        hInstance,                  // program instance handle
        NULL);                      // creation parameters
 
    
    while (msg.message != WM_QUIT)
    {
        if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        
    }
    
 
    GdiplusShutdown(gdiplusToken);
    return msg.wParam;
}
Тут всё вроде ок. Окно создаётся пустое и прозрачное.
Далее я рванул отрисовывать гифку. Это оказалась ещё та задача. Пока я не стал особо заморачиваться: не вытаскиваю ни количество кадров, ни длительности между ними. Я заранее определил что именно в той гифке, что я использую, 60 кадров и я их меняю каждый кадр.

Добавляем отрисовку кадра в главный цикл:
C++
1
2
3
4
5
6
7
8
9
10
11
12
 while (msg.message != WM_QUIT)
    {
        if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else  update_screen(hWnd);
        
    }
        
    }
И функция отрисовки:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
VOID update_screen(HWND hWnd) {
 
    HDC wndw = GetDC(hWnd);
    HDC memDC = CreateCompatibleDC(wndw);
    HBITMAP  memBM = CreateCompatibleBitmap(wndw, scrWidth, scrHeight);
    SelectObject(memDC, memBM);
 
    Graphics graphics(memDC);
    
       //GIF------------------
        Image image(L"gif1.gif");
        frame++;
        if (frame > 59) frame = 0;
        
        GUID pageGuid = FrameDimensionTime;
        image.SelectActiveFrame(&pageGuid, frame);
       
        graphics.DrawImage(&image, 0, 0);
        //GIF------------
 
 
        //FPS-----------------   
        FontFamily  fontFamily(L"Times New Roman");
        Font        font(&fontFamily, 24, FontStyleRegular, UnitPixel);
        PointF      pointF(30.0f, 10.0f);
        SolidBrush  solidBrush(Color(255, 0, 0, 255));
        
        std::wstring str = std::to_wstring(FPS);
        const wchar_t* wstrFPS = str.c_str();
        size_t newLen = 6 + wcslen(wstrFPS) + 1;
        wchar_t* cmd = (wchar_t*)malloc(newLen * sizeof(wchar_t));
        wcscpy_s(cmd, newLen, L"FPS = ");
        wcscat_s(cmd, newLen, wstrFPS);
       
        graphics.DrawString(cmd, -1, &font, pointF, &solidBrush);
        //FPS-----------------
 
       
    BitBlt(wndw, 0, 0, scrWidth, scrHeight, memDC, 0, 0, SRCCOPY);
    DeleteDC(memDC);
    DeleteObject(memBM);
    mtime = GetTickCount();
    FPS = 1000 / (mtime - last_screeen_tick);
    last_screeen_tick = GetTickCount();
    
 
}
В принципе гика замаячила, но как вы наверняка уже догадались, кадры накладываются друг на друга. И вот первая проблема. Если я хочу, чтобы игра как бы происходила не в окне, заливка не подходит. Значит в начале нам нужно делать скриншот и использовать его как фон. Но я так и не понял как вытащить статичную картинку из контекста (DC). В итоге нашёл на форуме код, который сохраняет скриншот в файл. Я закинул его в обработчик сообщений на WM_CREATE. Но к моему стыду так и не смок переменную bitmap вытащить из локальных. В итоге решил временно забить

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_CREATE: 
    {
        HDC scrdc, memdc;
        HBITMAP membit;
        // Получаем HDC рабочего стола
        // Параметр HWND для рабочего стола всегда равен нулю.
        scrdc = GetDC(0);
 
       
        // Создаем новый DC, идентичный десктоповскому и битмап размером с экран.
        memdc = CreateCompatibleDC(scrdc);
        membit = CreateCompatibleBitmap(scrdc, scrWidth, scrHeight);
        SelectObject(memdc, membit);
 
        // Улыбаемся... Снято!
        BitBlt(memdc, 0, 0, scrWidth, scrHeight, scrdc, 0, 0, SRCCOPY);
        HBITMAP hBitmap;
        hBitmap = (HBITMAP)SelectObject(memdc, membit);
        Gdiplus::Bitmap bitmap(hBitmap, NULL);
        bitmap.Save(L"screen.png", &png);
        DeleteDC(scrdc);
        DeleteDC(memdc);
 
        ShowWindow(hWnd, SW_SHOW);
        UpdateWindow(hWnd);
 
    }
        return 0;
 
    case WM_DESTROY:
 
        PostQuitMessage(0);
        return 0;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
} // WndProc
Отсюда первый вопрос, как получить скриншот в виде экземпляра класса Image, или в другом виде, но с возможностью отрисовать иным способом?

В функции отрисовки добавился вывод скрина в начале и ещё меня чёрт дёрнул сделать что-то типа ограничения maxFPS, которое я приравнял к 120.
C++
1
2
3
4
5
6
7
8
9
10
 while (msg.message != WM_QUIT)
    {
        if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else if (GetTickCount() - last_screeen_tick >= 1000 / maxFPS) update_screen(hWnd);
        
    }
Но даже без него FPS не поднимается выше 30 и это при условии, что я обрисовываю только фон, одну GIF-ку (считай спрайт анимированный) и сам FPS. А что будет если я буду просчитывать персонажа и врагов, атаки, коллизию и тд.? 2 FPS?
Я хотел отказаться от погрузки картинок из памяти каждый кадр, и остановиться на подгрузке лишь раз(при старте) однако компилятор не позволил мне обьявить экземпляры не в глобалке, ни в WinMain, ни в WM_CREATE.

Вопрос номер два и самый важный: как повысить FPS?

Еще я хотел подгружать данные из ресурсов. Но Image не берёт их просто так. Форум и я нашёл вот такую замечательную функцию:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Bitmap* BitmapFromResource(HINSTANCE hInstance, LPCTSTR szResName, LPCTSTR szResType)
{
    HRSRC hrsrc = FindResource(hInstance, szResName, szResType);
    if (!hrsrc) return 0;
    // "ненастоящий" HGLOBAL - см. описание LoadResource
    HGLOBAL hgTemp = LoadResource(hInstance, hrsrc);
    DWORD sz = SizeofResource(hInstance, hrsrc);
    void* ptrRes = LockResource(hgTemp);
    HGLOBAL hgRes = GlobalAlloc(GMEM_MOVEABLE, sz);
    if (!hgRes) return 0;
    void* ptrMem = GlobalLock(hgRes);
    // Копируем растровые данные
    CopyMemory(ptrMem, ptrRes, sz);
    GlobalUnlock(hgRes);
    IStream* pStream;
    // TRUE означает освободить память при последнем Release
    HRESULT hr = CreateStreamOnHGlobal(hgRes, TRUE, &pStream);
    if (FAILED(hr))
    {
        GlobalFree(hgRes);
        return 0;
    }
    // Используем загрузку из IStream
    Bitmap* image = Bitmap::FromStream(pStream);
    pStream->Release();
    return image;
}
А Bitmap уже можно передать в Image, но это естественно не подходит анимированным GIF.
Вопрос 3: Как вытащить GIF-ку из ресурсов и передать её в Image?(Наименьший приоритет)

Также я тестил прогу на своем ПК и соседа. Думал, может просто что-то изменится к лучшему. Чудес не бывает. Стало хуже. Если у меня скрин делается всего экрана как и задумано, то на ПК соседа скрин получается урезанным, словно не верно определяются scrWidth и scrHeight.

Код целиком:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
#include <iostream>
#include <windows.h>
#include <gdiplus.h>
#include <string>
#include "resource.h"
 
using namespace Gdiplus;
#pragma comment (lib,"Gdiplus.lib")
 
int scrWidth;
int scrHeight;
int maxFPS = 120;
float FPS;
DWORD last_screeen_tick, mtime;
int frame = 0;
HINSTANCE globalhInstance;
 
static const GUID png =
{ 0x557cf406, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e } };
 
 
Bitmap* BitmapFromResource(HINSTANCE hInstance, LPCTSTR szResName, LPCTSTR szResType)
{
    HRSRC hrsrc = FindResource(hInstance, szResName, szResType);
    if (!hrsrc) return 0;
    // "ненастоящий" HGLOBAL - см. описание LoadResource
    HGLOBAL hgTemp = LoadResource(hInstance, hrsrc);
    DWORD sz = SizeofResource(hInstance, hrsrc);
    void* ptrRes = LockResource(hgTemp);
    HGLOBAL hgRes = GlobalAlloc(GMEM_MOVEABLE, sz);
    if (!hgRes) return 0;
    void* ptrMem = GlobalLock(hgRes);
    // Копируем растровые данные
    CopyMemory(ptrMem, ptrRes, sz);
    GlobalUnlock(hgRes);
    IStream* pStream;
    // TRUE означает освободить память при последнем Release
    HRESULT hr = CreateStreamOnHGlobal(hgRes, TRUE, &pStream);
    if (FAILED(hr))
    {
        GlobalFree(hgRes);
        return 0;
    }
    // Используем загрузку из IStream
    Bitmap* image = Bitmap::FromStream(pStream);
    pStream->Release();
    return image;
}
 
VOID update_screen(HWND hWnd) {
 
    HDC wndw = GetDC(hWnd);
    HDC memDC = CreateCompatibleDC(wndw);
    HBITMAP  memBM = CreateCompatibleBitmap(wndw, scrWidth, scrHeight);
    SelectObject(memDC, memBM);
 
    Graphics graphics(memDC);
 
        //background----------
        Image bimage(L"screen.png");
        graphics.DrawImage(&bimage, 0, 0);
        //background----------
 
        //GIF----------
        Image image(L"gif1.gif");
        frame++;
        if (frame > 59) frame = 0;
        GUID pageGuid = FrameDimensionTime;
        image.SelectActiveFrame(&pageGuid, frame);
        //graphics.Clear(Color(0, 0, 0, 0));
        graphics.DrawImage(&image, 0, 0);//, image.GetWidth(), image.GetHeight());
        //GIF----------
 
        //FPS-----------------
        FontFamily  fontFamily(L"Times New Roman");
        Font        font(&fontFamily, 24, FontStyleRegular, UnitPixel);
        PointF      pointF(30.0f, 10.0f);
        SolidBrush  solidBrush(Color(255, 0, 0, 255));
        
        std::wstring str = std::to_wstring(FPS);
        const wchar_t* wstrFPS = str.c_str();
        size_t newLen = 6 + wcslen(wstrFPS) + 1;
        wchar_t* cmd = (wchar_t*)malloc(newLen * sizeof(wchar_t));
        wcscpy_s(cmd, newLen, L"FPS = ");
        wcscat_s(cmd, newLen, wstrFPS);
 
        graphics.DrawString(cmd, -1, &font, pointF, &solidBrush);
        //FPS-----------------
 
    BitBlt(wndw, 0, 0, scrWidth, scrHeight, memDC, 0, 0, SRCCOPY);
    DeleteDC(memDC);
    DeleteObject(memBM);
    mtime = GetTickCount();
    FPS = 1000 / (mtime - last_screeen_tick);
    last_screeen_tick = GetTickCount();
}
 
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
 
INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, PSTR, INT iCmdShow)
//INT APIENTRY main(HINSTANCE hInstance, HINSTANCE, PSTR, INT iCmdShow)
{
    HWND                hWnd;
    MSG                 msg = {0};
    WNDCLASS            wndClass;
 
    // Определяем разрешение экрана
    scrWidth = GetSystemMetrics(SM_CXSCREEN);
    scrHeight = GetSystemMetrics(SM_CYSCREEN);
 
    GdiplusStartupInput gdiplusStartupInput;
    ULONG_PTR           gdiplusToken;
 
    // Initialize GDI+.
    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
 
    wndClass.style = 0;// CS_HREDRAW | CS_VREDRAW;
    wndClass.lpfnWndProc = WndProc;
    wndClass.cbClsExtra = 0;
    wndClass.cbWndExtra = 0;
    wndClass.hInstance = hInstance;
    wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndClass.hbrBackground = 0;// (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndClass.lpszMenuName = NULL;
    wndClass.lpszClassName = TEXT("GettingStarted");
  
    globalhInstance = hInstance;
 
    RegisterClass(&wndClass);
 
    hWnd = CreateWindowEx(
        WS_EX_TOPMOST,
        TEXT("GettingStarted"),     // window class name
        TEXT("Getting Started"),    // window caption
        WS_POPUP,                   // window style
        0,                          // initial x position
        0,                          // initial y position
        scrWidth,                   // initial x size
        scrHeight,                  // initial y size
        NULL,                       // parent window handle
        NULL,                       // window menu handle
        hInstance,                  // program instance handle
        NULL);                      // creation parameters
 
    
    while (msg.message != WM_QUIT)
    {
        if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else if (GetTickCount() - last_screeen_tick >= 1000 / maxFPS) update_screen(hWnd);
        
    }
    
 
    GdiplusShutdown(gdiplusToken);
    return msg.wParam;
}  // WinMain
 
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_CREATE: 
    {
        HDC scrdc, memdc;
        HBITMAP membit;
        // Получаем HDC рабочего стола
        // Параметр HWND для рабочего стола всегда равен нулю.
        scrdc = GetDC(0);
       
        // Создаем новый DC, идентичный десктоповскому и битмап размером с экран.
        memdc = CreateCompatibleDC(scrdc);
        membit = CreateCompatibleBitmap(scrdc, scrWidth, scrHeight);
        SelectObject(memdc, membit);
 
        // Улыбаемся... Снято!
        BitBlt(memdc, 0, 0, scrWidth, scrHeight, scrdc, 0, 0, SRCCOPY);
        HBITMAP hBitmap;
        hBitmap = (HBITMAP)SelectObject(memdc, membit);
        Gdiplus::Bitmap bitmap(hBitmap, NULL);
        bitmap.Save(L"screen.png", &png);
        DeleteDC(scrdc);
        DeleteDC(memdc);
 
        ShowWindow(hWnd, SW_SHOW);
        UpdateWindow(hWnd);
    }
        return 0;
 
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
} // WndProc
И вопросы по приоритету:
1. Как можно повысить FPS?
2. Как получить скриншот в виде экземпляра класса Image, или в другом виде, но с возможностью отрисовать иным способом?
3. С чем может быть связана проблема с урезанным скрином и как это можно решить?
4. Есть ли более простой и грамотный способ проиграть анимированную GIF-ку?
5. Как вытащить GIF-ку из ресурсов и передать её в Image?


Буду очень благодарен за помощь))
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
09.09.2021, 19:14
Ответы с готовыми решениями:

Как возможно реализовать простенькую 2д игру?
Здравствуйте, подскажите пожалуйста, как при помощи js и его фреймворков можно написать простенькую игру. Просто перетащить объект с одного...

Микрофризы , падения фпс , низкий 1% FPS и 0.1% fps
MSI Z370 A-PRO Intel i5-8600K ( Thermalright Macho Rev.A (BW) ) DDR4 2666 apecer 2 плашки по 8gb / разогнан до 3000 MSI rtx 2080...

Попытка написать простенькую БД
Хочу попробовать написать простенькую БД, но есть некоторые вопросы по реализации. Немогу придумать как реализовать: У каждой ячейки...

1
2738 / 1664 / 267
Регистрация: 19.02.2010
Сообщений: 4,396
09.09.2021, 20:40
Цитата Сообщение от Muramur2000 Посмотреть сообщение
Как можно повысить FPS?
Не делать при обработке каждого сообщения (или на каждой итерации цикла, если брать другой пример) то, что не зависит от этого сообщения (или от переменной цикла).
Ну нафига, например, каждый раз внутри update_screen() делать вот это?
Цитата Сообщение от Muramur2000 Посмотреть сообщение
C++
1
2
3
4
    HDC wndw = GetDC(hWnd);
    HDC memDC = CreateCompatibleDC(wndw);
    HBITMAP  memBM = CreateCompatibleBitmap(wndw, scrWidth, scrHeight);
    SelectObject(memDC, memBM);
и в конце функции затем удалять пару этих объектов?
Что, hWnd, пришедший аргументом в функцию, будет меняться от вызова к вызову? Нет, не будет он меняться, как и запрашиваемый для него контекст устройства, и т.д.
Сделай это глобальными переменными, однократно инициализируемыми при WM_CREATE, и удаляемыми при WM_DESTROY.

Причём я указал далеко не все локальные переменные, не изменяющиеся (по своему значению или своему "смыслу") при внутри update_screen(). Вот нафига, например, фонт и кисть снова создавать на каждом вызове? Разбирайся, в смысле, тренируйся видеть то, что можно вынести "за скобки".

Ну и память течёт внутри update_screen() - для malloc() нет парного ему free().
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
09.09.2021, 20:40
Помогаю со студенческими работами здесь

Низкий FPS
Здравствуйте. Проблема с fps в играх, проседает до 30. Конфигурация ПК: i7 6700, 1070ti, 16ram, ssd 120, hdd 1tbx3. Загрузка на 100%...

Низкий fps
Недавно столкнулся с проблемой, практически во всех играх fps держится на отметке 18-25 фпс, проблема пропадает если например посмотреть в...

Низкий FPS в GTA 5
в GTA 5 видеопамять не загружена даже на половину, но больше 40 фпс не выдает, также периодически когда захожу в меню, ощущение будто фпс...

Низкий FPS у программы.
При написании скринсайвера возникла проблема с низким FPS. Что можно в коде &quot;подкрутить&quot; чтобы повысить FPS? Color...

Низкий low 1%, 0.1% fps
Здравствуйте. Столкнулся с проблемой после покупки и замены материнской платы Huananzhi X79-ZD3, а также процессора Xeon E5-2689. Проблема...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
2
Ответ Создать тему
Новые блоги и статьи
Оттенки серого
Argus19 18.03.2026
Оттенки серого Нашёл в интернете 3 прекрасных модуля: Модуль класса открытия диалога открытия/ сохранения файла на Win32 API; Модуль класса быстрого перекодирования цветного изображения в оттенки. . .
SDL3 для Desktop (MinGW): Рисуем цветные прямоугольники с помощью рисовальщика SDL3 на Си и C++
8Observer8 17.03.2026
Содержание блога Финальные проекты на Си и на C++: finish-rectangles-sdl3-c. zip finish-rectangles-sdl3-cpp. zip
Символические и жёсткие ссылки в Linux.
algri14 15.03.2026
Существует два типа ссылок — символические и жёсткие. Ссылка в Linux — это запись в каталоге, которая может указывать либо на inode «файла-ИСТОЧНИКА», тогда это будет «жёсткая ссылка» (hard link),. . .
[Owen Logic] Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора
ФедосеевПавел 14.03.2026
Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора ВВЕДЕНИЕ Выполняя задание на управление насосной группой заполнения резервуара,. . .
делаю науч статью по влиянию грибов на сукцессию
anaschu 13.03.2026
прикрепляю статью
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru