2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему
 
 Объясните программу
Сообщение27.03.2013, 06:18 


12/01/13
58
Код:
#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 --

при запуке понятно появляется лабиринт и объект которым управляем помощью стрелок на клавиатуре

 Профиль  
                  
 
 Re: Объясните программу
Сообщение27.03.2013, 09:52 


10/04/12
705
Чистый Win API, имеет смысл почитать что-то на эту тему, например msdn. Объяснять общие принципы долго.

 Профиль  
                  
 
 Re: Объясните программу
Сообщение27.03.2013, 10:12 


12/01/13
58
Да мне бы просто построчно а более детально сам разберу

 Профиль  
                  
 
 Re: Объясните программу
Сообщение27.03.2013, 20:32 


12/01/13
58
хоть ссылку киньте где можно про все это прочитать и разобрать самому

 Профиль  
                  
 
 Re: Объясните программу
Сообщение27.03.2013, 20:54 
Заслуженный участник


28/04/09
1933
Ловите: Google, MSDN (Microsoft Developer Network).

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 5 ] 

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group