2014 dxdy logo

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

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




 
 Объясните программу
Сообщение27.03.2013, 06:18 
Код:
#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 
Чистый Win API, имеет смысл почитать что-то на эту тему, например msdn. Объяснять общие принципы долго.

 
 
 
 Re: Объясните программу
Сообщение27.03.2013, 10:12 
Да мне бы просто построчно а более детально сам разберу

 
 
 
 Re: Объясните программу
Сообщение27.03.2013, 20:32 
хоть ссылку киньте где можно про все это прочитать и разобрать самому

 
 
 
 Re: Объясните программу
Сообщение27.03.2013, 20:54 
Ловите: Google, MSDN (Microsoft Developer Network).

 
 
 [ Сообщений: 5 ] 


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group