Код:
#include <assert.h>
#define NOMINMAX
#include <windows.h>
//#pragma comment(lib,"winmm.lib") //подключаем библиотеку
bool _running = false;
bool _active = false;
void init_window();
void term_window();
void init_timer();
void term_timer();
int main() {
init_window();
init_timer();
_running = true;
while (_running) {
MSG m;
GetMessage(&m, /*hWnd:*/NULL, /*wMsgFilterMin:*/0, /*wMsgFilterMax:*/0);
TranslateMessage(&m);
DispatchMessage(&m);
}
term_timer();
term_window();
return 0;
}
const char* const _window_class_name = "maze";
ATOM _window_class_id = 0;
HWND _window_han = NULL;
int _window_client_width = -1;
int _window_client_height = -1;
LRESULT CALLBACK window_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
void init_window() {
HINSTANCE exe_han = GetModuleHandle(NULL);
assert(_window_class_id == 0);
WNDCLASSEX wc_params;
wc_params.cbSize = sizeof(WNDCLASSEX);
wc_params.style = 0;
wc_params.lpfnWndProc = &window_proc;
wc_params.cbClsExtra = 0;
wc_params.cbWndExtra = 0;
wc_params.hInstance = exe_han;
wc_params.hIcon = NULL;
wc_params.hCursor = LoadCursor(NULL, IDC_ARROW);
wc_params.hbrBackground = NULL; // фон будем рисовать сами
wc_params.lpszMenuName = NULL;
wc_params.lpszClassName = _window_class_name;
wc_params.hIconSm = NULL;
_window_class_id = RegisterClassEx(&wc_params);
assert(_window_han == NULL);
_window_han = CreateWindowEx(
/*dwExStyle:*/0,
/*lpClassName:*/_window_class_name,
/*lpWindowName:*/"Maze", // название окна как я понял
/*dwStyle:*/WS_OVERLAPPEDWINDOW | WS_VISIBLE,
/*x:*/CW_USEDEFAULT,
/*y:*/CW_USEDEFAULT,
/*nWidth:*/CW_USEDEFAULT,
/*nHeight:*/CW_USEDEFAULT,
/*hWndParent:*/NULL,
/*hMenu:*/NULL,
/*hInstance:*/exe_han,
/*lpParam:*/NULL
);
}
void term_window() {
if (_window_han != NULL) {
DestroyWindow(_window_han);
_window_han = NULL;
}
if (_window_class_id != 0) {
HINSTANCE exe_han = GetModuleHandle(NULL);
UnregisterClass(_window_class_name, exe_han);
_window_class_id = 0;
}
}
void request_paint() {
assert(_window_han != NULL);
InvalidateRect(_window_han, /*lpRect:*/NULL, /*bErase:*/false);
}
bool _double_buffered = true;
HDC _gdi_context = NULL;
void update();
void paint_maze();
LRESULT CALLBACK window_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_CLOSE:
_running = false;
return 0;
case WM_SETFOCUS:
_active = true;
return 0;
case WM_KILLFOCUS:
_active = false;
return 0;
case WM_SIZE:
_window_client_width = LOWORD(lParam);
_window_client_height = HIWORD(lParam);
return 0;
case WM_USER:
update();
return 0;
case WM_ERASEBKGND:
return false;
case WM_PAINT: {
PAINTSTRUCT ps;
BeginPaint(hwnd, &ps);
if (_double_buffered) {
int x = ps.rcPaint.left;
int y = ps.rcPaint.top;
int w = ps.rcPaint.right - ps.rcPaint.left;
int h = ps.rcPaint.bottom - ps.rcPaint.top;
if ((w > 0) && (h > 0)) {
HBITMAP back_buf = CreateCompatibleBitmap(ps.hdc, w, h);
assert(_gdi_context == NULL);
_gdi_context = CreateCompatibleDC(ps.hdc);
SelectObject(_gdi_context, back_buf);
SetViewportOrgEx(_gdi_context, -x, -y, NULL);
paint_maze();
BitBlt(ps.hdc, x, y, w, h, _gdi_context, x, y, SRCCOPY);
DeleteDC(_gdi_context);
_gdi_context = NULL;
DeleteObject(back_buf);
}
} else {
assert(_gdi_context == NULL);
_gdi_context = ps.hdc;
paint_maze();
_gdi_context = NULL;
}
EndPaint(hwnd, &ps);
return 0;
}
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
const int _update_interval = 20; // это вроде задержка между одним шагом движения
UINT _timer_id = 0;
void CALLBACK tick(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2);
void init_timer() {
assert(_timer_id == 0);
_timer_id = timeSetEvent(/*uDelay:*/_update_interval, /*uResolution:*/0, &tick, /*dwUser:*/0, TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
}
void term_timer() {
UINT id = _timer_id;
if (id != 0) {
_timer_id = 0;
timeKillEvent(id);
}
}
void CALLBACK tick(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2) {
if (_timer_id == 0) return;
assert(uTimerID == _timer_id);
assert(_window_han != NULL);
SendMessage(_window_han, WM_USER, 0, 0);
}
bool key_is_down(int key) {
if (!_active) return false;
return static_cast<unsigned short>(GetKeyState(key)) >> 15;
}
struct Wall {
int x1, y1;
int x2, y2;
};
const Wall _walls[] = { //вот здесь ясно создаем массив в котором записываем координаты линий лабиринта
//{40, 40, 100, 40},
//{100, 40, 100, 70},
//{100, 70, 130, 70},
//{130, 70, 130, 100},
//{100, 100, 100, 160},
//{70, 70, 70, 130},
//{40, 130, 70, 130},
//{70, 160, 100, 160},
//{70, 160, 70, 220},
//{100, 190, 100, 220},
//{130, 160, 130, 340},
{70, 250, 130, 250},
{100, 130, 160, 130},
{160, 40, 160, 130},
{70, 280, 100, 280},
{70, 280, 70, 340},
{70, 310, 250, 310},
{40, 40, 40, 370},
{100, 340, 100, 370},
{130, 340, 160, 340},
{190, 310, 190, 370},
{40, 370, 190, 370},
{160, 130, 160, 210},
{130, 250, 190, 250},
{160, 100, 190, 100},
{190, 160, 190, 250},
{190, 160, 220, 160},
{190, 130, 280, 130},
{220, 70, 220, 130},
{190, 70, 220, 70},
{130, 40, 340, 40},
{250, 40, 250, 100},
{280, 70, 280, 130},
{280, 70, 310, 70},
{310, 70, 310, 160},
{340, 40, 340, 370},
{310, 190, 340, 190},
{220, 370, 340, 370},
{220, 190, 220, 280},
{160, 280, 280, 280},
{250, 130, 250, 250},
{250, 220, 340, 220},
{280, 160, 280, 220},
{250, 250, 310, 250},
{280, 280, 280, 340},
{220, 340, 280, 340},
{220, 340, 220, 370},
{280, 310, 310, 310},
{310, 280, 310, 340},
};
#define LEN(array) static_cast<int>(sizeof(array) / sizeof(array[0]))
int _obj_pos_x = 115;
int _obj_pos_y = 40;
const int _obj_radius = 14;
const int _obj_speed = 2;
bool obj_pos_is_valid(int obj_pos_x, int obj_pos_y);
void update() {
bool vis_change = false;
int dir_x = 0;
if (key_is_down(VK_LEFT)) dir_x--;
if (key_is_down(VK_RIGHT)) dir_x++;
int dir_y = 0;
if (key_is_down(VK_DOWN)) dir_y++;
if (key_is_down(VK_UP)) dir_y--;
if ((dir_x != 0) || (dir_y != 0)) {
for (int i = 0; i < _obj_speed; i++) {
int new_obj_pos_x = _obj_pos_x + dir_x;
int new_obj_pos_y = _obj_pos_y + dir_y;
if (obj_pos_is_valid(new_obj_pos_x, new_obj_pos_y)) {
_obj_pos_x = new_obj_pos_x;
_obj_pos_y = new_obj_pos_y;
vis_change = true;
} else {
break;
}
}
}
if (vis_change) {
request_paint();
}
}
inline int squ(int n) {
return n * n;
}
inline int clamp(int n, int min, int max) {
assert(min <= max);
if (n < min) return min;
if (n > max) return max;
return n;
}
bool obj_pos_is_valid(int obj_pos_x, int obj_pos_y) {
for (int i = 0; i < LEN(_walls); i++) {
const Wall* w = &_walls[i];
int x1 = w->x1;
int y1 = w->y1;
int x2 = w->x2;
int y2 = w->y2;
int closest_point_x, closest_point_y;
if (x1 == x2) {
assert(y1 < y2);
closest_point_x = x1;
closest_point_y = clamp(obj_pos_y, y1, y2);
} else {
assert(y1 == y2);
assert(x1 < x2);
closest_point_x = clamp(obj_pos_x, x1, x2);
closest_point_y = y1;
}
if (squ(obj_pos_x - closest_point_x) + squ(obj_pos_y - closest_point_y) < squ(_obj_radius)) return false;
}
return true;
}
void paint_maze() {
assert(_gdi_context != NULL);
RECT r = {0, 0, _window_client_width, _window_client_height};
FillRect(_gdi_context, &r, static_cast<HBRUSH>(GetStockObject(GRAY_BRUSH)));
SelectObject(_gdi_context, GetStockObject(WHITE_PEN));
for (int i = 0; i < LEN(_walls); i++) {
const Wall* w = &_walls[i];
MoveToEx(_gdi_context, w->x1, w->y1, NULL);
LineTo(_gdi_context, w->x2, w->y2);
}
SelectObject(_gdi_context, GetStockObject(WHITE_BRUSH));
SelectObject(_gdi_context, GetStockObject(NULL_PEN));
Ellipse(_gdi_context, _obj_pos_x - _obj_radius, _obj_pos_y - _obj_radius, _obj_pos_x + _obj_radius, _obj_pos_y + _obj_radius);
}
-- 27.03.2013, 08:19 --при запуке понятно появляется лабиринт и объект которым управляем помощью стрелок на клавиатуре