Форум программистов, компьютерный форум, киберфорум
C++: WinAPI
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.57/7: Рейтинг темы: голосов - 7, средняя оценка - 4.57
0 / 0 / 0
Регистрация: 04.05.2016
Сообщений: 6
1

Лабиринт для мыши. C++ и WinAPI

01.07.2016, 12:43. Показов 1425. Ответов 7
Метки нет (Все метки)

Доброго времени суток! Нужна помощь в написании небольшой игры "Лабиринт для мыши" с использованием WinAPI. Как ограничить курсор стенками лабиринта? И как если курсор коснулся стены лабиринта вернуть его в начало?

Заранее спасибо!
0

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
01.07.2016, 12:43
Ответы с готовыми решениями:

Функция WinAPI для получения данных о вращении колёсика мыши
Народ, кто-нибудь знает функцию виндовского апи, которая позволяла бы получить данные о вращении...

Координаты мыши, WinAPI
Как получит координаты мыши в окне программы?

Крутится курсор мыши в WinAPI
Если при запуске приложения курсор мыши находится в окне(в клиентской области, не на кнопке) то он...

WinApi и обработка сообщений мыши
Добрый вечер! Извините, если где-то уже есть такой вопрос - я не нашла. Я пишу программку типа...

7
900 / 420 / 159
Регистрация: 02.04.2014
Сообщений: 1,206
01.07.2016, 13:35 2
Если ограничить только габаритами всего лабиринта, то можно функцией ClipCursor.

А если, что бы мышка "натыкалась" и на перегородки, то наверное придется получать сообщение WM_MOUSEMOVE, анализировать координаты и решать что делать с курсором (пускать ли его за стенку лили нет).

Или, что бы облегчить эту задачу, еще наверное можно создать дочернее окно в форме стенок-перегородок. (функцией SetWindowRgn), тогда это окно будет само знать, когда курсор залез на его территорию (ему будут приходить сообщения WM_SETCURSOR).
0
0 / 0 / 0
Регистрация: 04.05.2016
Сообщений: 6
01.07.2016, 13:48  [ТС] 3
rao, Да, без перегородок, только границы лабиринта. Про ClipCursor знаю, но не могу реализовать, с WinAPI совсем не давно познакомился.
0
900 / 420 / 159
Регистрация: 02.04.2014
Сообщений: 1,206
01.07.2016, 16:27 4
Например ограничение курсора окном программы:
C++
1
2
3
    RECT rtClientArea = {0, 0, 300, 300}; // инициализировать не обязательно
    ::GetWindowRect(m_hWnd, &rtClientArea);
    ClipCursor(&rtClientArea);
1
0 / 0 / 0
Регистрация: 04.05.2016
Сообщений: 6
01.07.2016, 17:06  [ТС] 5
rao, Спасибо, А как ограничить стенками лабиринта?
0
900 / 420 / 159
Регистрация: 02.04.2014
Сообщений: 1,206
01.07.2016, 17:42 6
truekot, запиши в структуру rtClientArea координаты своего лабиринта. В строке 1, вместо {0, 0, 300, 300}.
Должно быть:
C++
1
RECT rtClientArea = {X_ЛевогоВерхнегоУгла, У_ЛевогоВерхнегоУгла, X_ПравогоНижнегоУгла, Y_ПравогоНижнегоУгла};
а строку 2 закомментируй, а то значения перезапишутся.
0
0 / 0 / 0
Регистрация: 04.05.2016
Сообщений: 6
02.07.2016, 10:27  [ТС] 7
rao, У меня не получилось. Как ограничить белым лабиринтом, и при касании стенки курсор уходил назад?
Вот код:

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
#include <Windows.h>
#include <gdiplus.h>
#include <iostream>
#pragma comment(lib, "gdiplus.lib")
 
using namespace Gdiplus;
using namespace std;
 
#define widht 800 //по иксу
#define height 600 //по игреку
 
VOID OnPaint(HDC hdc) //функциия для вывода текста
{
    Graphics    graphics(hdc);
    SolidBrush  brush(Color::White);
    FontFamily  fontFamily(L"Times New Roman");
    Font        font(&fontFamily, 24, FontStyleRegular, UnitPixel);
    PointF      pointF(300.0f, 0.0f);
 
    graphics.DrawString(L"Maze Mouse", -1, &font, pointF, &brush);
}
 
VOID DrawRectangle(HDC hdc) // функция прорисовки лабиринта
{
    Graphics     graphics(hdc);
    GraphicsPath path;
    Pen          pen(Color::Black, 2);
    SolidBrush   brush(Color::White);
    
    path.AddRectangle(Rect(0, 50, 150, 200));
    path.AddRectangle(Rect(150, 70, 500, 60));
    path.AddRectangle(Rect(650, 70, 30, 400));
    path.AddRectangle(Rect(350, 400, 300, 70));
    path.AddRectangle(Rect(310, 180, 40, 290));
    path.AddRectangle(Rect(310, 150, 250, 30));
    path.AddRectangle(Rect(560, 150, 50, 220));
    path.AddRectangle(Rect(410, 340, 150, 30));
    path.AddEllipse(420,345,20,20);
 
    graphics.DrawPath(&pen, &path);
    graphics.FillPath(&brush, &path);
    
}
 
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); //
int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) // главная функция, аналог main
{
    WNDCLASSEX windowClass; //название структуры
    HWND hWnd;
    MSG uMsg;
 
    GdiplusStartupInput gdiplusStartupInput;
    ULONG_PTR gdiplusToken;
 
    memset(&windowClass, 0, sizeof(WNDCLASSEX));
    windowClass.cbSize = sizeof(WNDCLASSEX);    //размер окна
    windowClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); //цвет фона
    windowClass.hCursor = LoadCursor(NULL, IDC_ARROW); // вид курсора
    windowClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); //иконка окна
    windowClass.hInstance = hInstance;
    windowClass.lpfnWndProc = WindowProc;
    windowClass.lpszClassName = "Maze Mouse";
 
    RegisterClassEx(&windowClass);
 
    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
    SetCursorPos(800,600);
    
 
    hWnd = CreateWindow(windowClass.lpszClassName, "Maze Mouse", WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
        (GetSystemMetrics(SM_CXSCREEN) - widht) / 2, (GetSystemMetrics(SM_CYSCREEN) - height) / 2, widht, height, NULL, NULL, NULL, NULL);
    
    ShowWindow(hWnd, nCmdShow);
    
    while (GetMessage(&uMsg, hWnd,NULL,NULL))
    {
        TranslateMessage(&uMsg);
        DispatchMessage(&uMsg);
        
    }
 
    GdiplusShutdown(gdiplusToken);
    
    return uMsg.wParam;
}
 
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    HDC hDC;
    PAINTSTRUCT ps;
    RECT rtClientArea = { 0, 50, 150, 200 };
    RECT rtClientArea1 = { 150, 70, 500, 60 };
    RECT rtClientArea2 = { 650, 70, 30, 400 };
    
    switch (uMsg)
    {
    case WM_CLOSE:
        ExitProcess(0);
        break;
 
    case WM_PAINT:
        hDC = BeginPaint(hWnd, &ps);
        OnPaint(hDC);
        DrawRectangle(hDC);
        EndPaint(hWnd, &ps);
        break;
 
 
 
    case WM_KEYDOWN:            //закрытие программы Esc
        switch (wParam)
        {
        case VK_ESCAPE:
            exit(0);
            break;
        }
    return 0;
    
    case WM_SIZE:
    case WM_EXITSIZEMOVE:
        //GetWindowRect(hWnd, &rtClientArea);
        ClipCursor(&rtClientArea);
        return 0;
 
    default:
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
        
    }
    
}
0
900 / 420 / 159
Регистрация: 02.04.2014
Сообщений: 1,206
05.07.2016, 21:07 8
truekot, вот я твой код немножко подредактировал. Принцип действия надеюсь поймешь:
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
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
#include <windows.h>
#include <windowsx.h>
 
#include <gdiplus.h>
using namespace Gdiplus;
#pragma comment(lib, "gdiplus.lib")
 
#define widht 800 //по иксу
#define height 600 //по игреку
 
VOID OnPaint(HDC hdc) //функциия для вывода текста
{
    Graphics    graphics(hdc);
    SolidBrush  brush(Color::White);
    FontFamily  fontFamily(L"Times New Roman");
    Font        font(&fontFamily, 24, FontStyleRegular, UnitPixel);
    PointF      pointF(300.0f, 0.0f);
 
    graphics.DrawString(L"Maze Mouse", -1, &font, pointF, &brush);
}
 
VOID DrawRectangle(HDC hdc) // функция прорисовки лабиринта
{
    Graphics     graphics(hdc);
    GraphicsPath path;
    Pen          pen(Color::Black, 2);
    SolidBrush   brush(Color::White);
 
    path.AddRectangle(Rect(0, 50, 150, 200));
    path.AddRectangle(Rect(150, 70, 500, 60));
    path.AddRectangle(Rect(650, 70, 30, 400));
    path.AddRectangle(Rect(350, 400, 300, 70));
    path.AddRectangle(Rect(310, 180, 40, 290));
    path.AddRectangle(Rect(310, 150, 250, 30));
    path.AddRectangle(Rect(560, 150, 50, 220));
    path.AddRectangle(Rect(410, 340, 150, 30));
    path.AddEllipse(420,345,20,20);
 
    graphics.DrawPath(&pen, &path);
    graphics.FillPath(&brush, &path);
 
}
LRESULT CALLBACK WndMaskProc(HWND hwnd, UINT Message, WPARAM wparam,LPARAM lparam);
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); //
 
HWND g_hMaskWindow;
POINT g_ptPrevMousePos;
 
DWORD WINAPI fnRunMaskWindowProc( _In_ LPVOID lpParameter)
{
    WNDCLASSEX windowClass; 
    // -------------------------------------------------------------------
    // Класс окна маски:
    // -------------------------------------------------------------------
    memset(&windowClass, 0, sizeof(WNDCLASSEX));
    windowClass.cbSize = sizeof(WNDCLASSEX);
    windowClass.lpfnWndProc = WndMaskProc;
    windowClass.hInstance = (HINSTANCE)GetModuleHandle(NULL);
    windowClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //  GRAY_BRUSH);
    windowClass.lpszClassName = L"MaskWClass";
    windowClass.hCursor=LoadCursor(NULL,IDC_ARROW); 
    RegisterClassEx(&windowClass);
    int iErr = GetLastError();
 
    RECT rtWindow;
    GetWindowRect( (HWND)lpParameter, &rtWindow);
    int iWidth = rtWindow.right - rtWindow.left;
    int iHeight = rtWindow.bottom - rtWindow.top;
    g_hMaskWindow = CreateWindowEx(WS_EX_TOOLWINDOW | WS_EX_TOPMOST, 
        _T("MaskWClass"), L"eee",
        WS_VISIBLE | WS_POPUP,
        rtWindow.left, rtWindow.top, 
        iWidth, iHeight,
        NULL, (HMENU)0, NULL, NULL );
 
    int iPointCount = 20;
    POINT aPolygonContour[] = { 
        {30, 70}, {150, 70}, {150, 90}, {680, 90}, {680, 490}, 
        {310, 490}, {310, 170}, {610, 170}, {610, 390}, {410, 390},
        { 410, 360 }, {560, 360}, {560, 200}, {350, 200}, {350, 420}, 
        {650, 420}, {650, 150}, {150, 150}, {150, 270}, {30, 270} };
 
    HRGN hMaskRgn = CreatePolygonRgn(aPolygonContour, iPointCount, WINDING);
    SetWindowRgn(g_hMaskWindow, hMaskRgn, TRUE);
 
    ShowWindow(g_hMaskWindow, SW_SHOW);
    UpdateWindow(g_hMaskWindow);
 
    MSG uMsg;
    while (GetMessage(&uMsg, g_hMaskWindow, NULL,NULL))
    {
        TranslateMessage(&uMsg);
        DispatchMessage(&uMsg);
    }
    return 0;
}
 
int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) // главная функция, аналог main
{
    WNDCLASSEX windowClass; //название структуры
    HWND hWnd;
    MSG uMsg;
 
    GdiplusStartupInput gdiplusStartupInput;
    ULONG_PTR gdiplusToken;
 
    memset(&windowClass, 0, sizeof(WNDCLASSEX));
    windowClass.cbSize = sizeof(WNDCLASSEX);    //размер окна
    windowClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); //цвет фона
    windowClass.hCursor = LoadCursor(NULL, IDC_ARROW); // вид курсора
    windowClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); //иконка окна
    windowClass.hInstance = hInstance;
    windowClass.lpfnWndProc = WindowProc;
    windowClass.lpszClassName = L"Maze Mouse";
 
    RegisterClassEx(&windowClass);
 
    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
    SetCursorPos(0,0);
 
    hWnd = CreateWindow(L"Maze Mouse", L"Maze Mouse", 
        WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
        (GetSystemMetrics(SM_CXSCREEN) - widht) / 2, (GetSystemMetrics(SM_CYSCREEN) - height) / 2, 
        widht, height, NULL, NULL, NULL, NULL);
 
    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);
 
    CreateThread(NULL, 0, fnRunMaskWindowProc, (LPVOID)hWnd, 0, NULL);
 
 
    while (GetMessage(&uMsg, hWnd,NULL,NULL))
    {
        TranslateMessage(&uMsg);
        DispatchMessage(&uMsg);
    }
 
    GdiplusShutdown(gdiplusToken);
 
    return uMsg.wParam;
}
 
LRESULT CALLBACK WndMaskProc(HWND hwnd, UINT Message, WPARAM wparam,LPARAM lparam)
{
    HDC hDC;
    PAINTSTRUCT psMask;
    RECT rtWindow;
    HRGN hMaskRgn;
 
    switch (Message)
    {
        case WM_MOUSEMOVE:
            SetCursorPos(g_ptPrevMousePos.x, g_ptPrevMousePos.y);
            break;
        case WM_DESTROY:
            return 0;
 
        default:
            return DefWindowProc(hwnd, Message, wparam, lparam);
    }
}
 
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    HDC hDC;
    PAINTSTRUCT ps;
    RECT rtClientArea = { 0, 50, 150, 200 };
    // RECT rtClientArea1 = { 150, 70, 500, 60 };
    // RECT rtClientArea2 = { 650, 70, 30, 400 };
 
    HWND hWndMask;
    int iError = 0;
    int iWidth, iHeight = 0;
    POINT ptLeftTop;
 
    WNDCLASSEX windowClass;
 
    switch (uMsg)
    {
    case WM_MOUSEMOVE:
        g_ptPrevMousePos.x = GET_X_LPARAM(lParam);
        g_ptPrevMousePos.y = GET_Y_LPARAM(lParam);
        ClientToScreen(hWnd, &g_ptPrevMousePos);
        break;
 
    case WM_CLOSE:
        ExitProcess(0);
        break;
 
    case WM_PAINT:
        hDC = BeginPaint(hWnd, &ps);
        OnPaint(hDC);
        // DrawRectangle(hDC);
        EndPaint(hWnd, &ps);
        break;
 
    case WM_WINDOWPOSCHANGED:
        GetWindowRect(hWnd, &rtClientArea);
        ptLeftTop.x = 0;
        ptLeftTop.y = 0;
        ClientToScreen(hWnd, &ptLeftTop);
        iWidth = rtClientArea.right - rtClientArea.left;
        iHeight = rtClientArea.bottom - rtClientArea.top;
        MoveWindow(g_hMaskWindow, ptLeftTop.x, ptLeftTop.y, iWidth, iHeight, TRUE);
        break;
    case WM_KEYDOWN:            //закрытие программы Esc
        switch (wParam)
        {
        case VK_ESCAPE:
            exit(0);
            break;
        }
        return 0;
 
    //case WM_SIZE:
    //case WM_EXITSIZEMOVE:
        // GetWindowRect(hWnd, &rtClientArea);
        // ClipCursor(&rtClientArea);
    //  return 0;
 
    default:
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
 
    }
 
}
1
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
05.07.2016, 21:07

Имитация мыши. Полное управление курсором. WinAPI
Требуется найти функции, которые используем мыщьх. Движение курсора, нажатие LB\RB, прокрутка...

Игра лабиринт. ИИ в лабиринте. Как задать лабиринт
У меня есть следующее задание: Дано: - робот - лабиринт Задание: - Нужно реализовать...

Как сделать клик левой кнопкой мыши без WinApi
Я не нашел, везде WinApi

Лабиринт для матрицы соединений
Дана матрица соединений для лабиринта из n комнат и номера комнат i,j (1&lt;=i&lt;=n,1&lt;=j&lt;=n) Построить...


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

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.