블로그 이미지
하루, 글. 그림. 영상매체. 표현을 도와주는 기기들. 도전 중. 동화다아아
    동화다아아

    카테고리

    분류 전체보기 (176)
    잡담 (1)
    IT 기기-리뷰&뉴스 (7)
    리뷰 - 도서 (1)
    리뷰 - 영상 (0)
    리뷰 - 그림/음악 (1)
    내장형 하드웨어 (163)
    Total
    Today
    Yesterday
    - 소코반은 여기저기 흩어져 있는 짐을 밀어서 창고에 순서대로 쌓는 게임이다.
    - 소스 작성(제작 중)
    #include<windows.h>
    #include
     "resource.h"

    #define BLOCK 30

    void DrawBitmap(HDC hdc, int x, int y, HBITMAP hBit);
    /* 고정 형식 */
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // 메세지 처리 함수
    HINSTANCE g_hInst; // instance 전역 변수 선언
    LPCTSTR lpszClass = TEXT("First"); // 윈도 클래스 이름 정의


    int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow)
    {
      HWND hWnd;
      MSG Message; // MSG 구조체 사용
      WNDCLASS WndClass; // WndClass 구조체 사용
      g_hInst = hInstance; // 윈도우 클래스를 등록하는 프로그램의 번호이며 WinMain의 인수로 전달된 hInstance값을 그대로 대입

      /* 윈도우 클래스 정의 */
      WndClass.cbClsExtra = 0// 예약 영역, 사용하지 않을 경우는 0
      WndClass.cbWndExtra = 0;
      WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); // HBRUSH 타입으로 형변환
      WndClass.hCursor = LoadCursor(NULL, IDC_ARROW); // 윈도우가 사용할 마우스 커서지정
      WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); // 윈도우가 사용할 아이콘 지정
      WndClass.hInstance = hInstance;
      WndClass.lpfnWndProc = WndProc; // 윈도우의 메시지 처리 함수를 지정
      WndClass.lpszClassName = lpszClass; // 윈도우 클래스의 이름을 문자열로 정의 - 여기서는 First라는 문자열을 보내준다.
      WndClass.lpszMenuName = NULL; // 프로그램이 사용할 메뉴를 지정
      WndClass.style = CS_HREDRAW|CS_VREDRAW; // 윈도우가 어떤 형태를 가질 것인가-윈도우의크기가 변할 경우 윈도우를 다시 그린다.
      
      /* 윈도우 클래스 등록 */
      RegisterClass(&WndClass);  // WndClass 구조체의 번지를 전달

      // 메모리 상에 윈도우 생성
      hWnd=CreateWindow(lpszClass, TEXT("Sokoban!!!"), WS_CAPTION|WS_SYSMENU|WS_MAXIMIZEBOX|WS_MINIMIZEBOX, 3030, (BLOCK*25)+6, (BLOCK*15)+33, NULL, (HMENU)NULL, hInstance, NULL);
      
    /* 인자의 의미 -> (윈도우 클래스 이름, 타이틀바에 나타날 문자열-윈도우 네임(클래스 이름과 같게 하려면 lpszClass), 
                윈도우의 형태 지정, 윈도우의 크기와 위치(픽셀단위)-x, y, nWidth, nHeight, 
                부모 윈도우가 있을 경우 부모윈도우의 핸들-hWndParent, 윈도우에서 사용할 메뉴의 핸들-hmenu, 
                프로그램의 핸들 지정-hinst(프로그램이 종료될 때 파괴되지 않은 윈도우를 자동으로 파괴),
                여러개의 윈도우를 만들때 각 윈도우에 고유의 파라미터를 전달하는 특수 목적에 사용-lpvParam)
                */


      /* 화면에 윈도우 표시 */
      ShowWindow(hWnd, nCmdShow); //  CreateWindow 함수가 리턴한 핸들을 이용하여 출력

      /* 사용자로부터의 메시지 처리*/
      while(GetMessage(&Message, NULL, 00)) // 메시지 큐에서 메시지 읽어옴, 
                          // WN_QUIT이면 False 리턴 후 while문을 빠져나간다.
      {
        TranslateMessage(&Message); // 키보드 입력 처리 
                      // 만약 A키를 누르면 A문자가 입력되었다는 메시지를 만들어 낸다.
        DispatchMessage(&Message); // 큐에서 꺼낸 메시지를 WndProc 함수의 iMAssage로 전달
      }
      return (int)Message.wParam; // 메시지 루프 종료 후 이 프로그램을 실행시킨 OS로 리턴
    }

    // 비트맵을 간단하게 출력할 수 있는 레퍼 함수
    void DrawBitmap(HDC hdc, int x, int y, HBITMAP hBit)
    {
      HDC MemDC;
      HBITMAP OldBitmap;
      int bx, by;
      BITMAP bit;

      MemDC = CreateCompatibleDC(hdc);
      OldBitmap = (HBITMAP)SelectObject(MemDC, hBit);

      GetObject(hBit, sizeof(BITMAP), &bit); // 비트맵의 크기 조사
      bx = bit.bmWidth;
      by = bit.bmHeight;

      BitBlt(hdc, x, y, bx, by, MemDC, 00, SRCCOPY);

      SelectObject(MemDC, OldBitmap);
      DeleteDC(MemDC);
    }


    // 사용자와 시스템이 보내오는 메시지를 처리
    // 운영체제가 호출하는 함수는 CALLBACK 표시, LRESULT = 4byte long
    LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
    {
      // +1은 "를 포함하며 이것은 NULL을 집어넣는다.
      // 화면에 1대 1 대응시키기 위한 것
      static unsigned char ucStage[][15][25+1]=
      {
        { "#########################"
        , "#########################"
        , "#########################"
        , "#######   ###############"
        , "#######$  ###############"
        , "#######  $###############"
        , "#####  $ $ ##############"
        , "##### # ## ##############"
        , "###   # ## ########    ##"
        , "### $  $               ##"
        , "####### ###### #@##    ##"
        , "#######        ##########"
        , "#########################"
        , "#########################"
        , "#########################"
        }
      }; // 가로, 세로
      HDC hdc;
      PAINTSTRUCT ps;
      static HBITMAP MyBitmap1; // 배경 블록을 불러오기 위한 변수
      static HBITMAP MyBitmap2; // 캐릭터 불러오기 위한 변수
      static HBITMAP MyBitmap3; // 움직이는 블록을 불러오기 위한 변수
      int iCount_x;
      int iCount_y;
      static int hero_x=BLOCK*16// 캐릭터 좌표, 좌표값을 기억해야 하므로 static변수로 선언
      static int hero_y=BLOCK*10;
      int mBlock; // 움직이는 블록

      switch(iMessage) // 운영체제로부터 들어온 메시지에 대한 처리
      {
        /* 고정 형식 */
        case WM_CREATE:
          MyBitmap1 = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_BITMAP1)); // 비트맵을 읽는다.(배경 블록)
          MyBitmap2 = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_BITMAP3)); // 비트맵을 읽는다.(캐릭터)
          MyBitmap3 = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_BITMAP2)); // 움직이는 블록
        case WM_KEYDOWN:
          switch(wParam)
          {
            // 키 입력에 따른 히어로의 좌표 변화
            case VK_LEFT: 
              hero_x = hero_x-BLOCK;
              break;
            case VK_RIGHT:
              hero_x = hero_x+BLOCK;
              break;
            case VK_UP:
              hero_y = hero_y-BLOCK;
              break;
            case VK_DOWN:
              hero_y = hero_y+BLOCK;
              break;
          }
          // 조정된 좌표가 화면에 반영되도록 InvalidateRect(hWnd, NULL, TRUE); 사용.
          // hWnd->무효화 대상 윈도우(다시그려져야 되는),NULL->윈도우 전영역 다시 그린다,TRUE->배경을 지우고 다시 그린다.
          InvalidateRect(hWnd, NULL, TRUE); 
          return 0;
        case WM_PAINT: 
          hdc = BeginPaint(hWnd, &ps);
          for(iCount_x = 0; iCount_x<(BLOCK*25); (iCount_x=iCount_x+BLOCK))
          {
            for(iCount_y =0; iCount_y<(BLOCK*15); (iCount_y=iCount_y+BLOCK))
            {
              // 배경 블록 출력
              if('#' == ucStage[0][iCount_y/BLOCK][iCount_x/BLOCK])
              {
                DrawBitmap(hdc, iCount_x, iCount_y, MyBitmap1); // 비트맵 출력
              }
              // 캐릭터 출력
              else if('@' == ucStage[0][iCount_y/BLOCK][iCount_x/BLOCK])
              {
                DrawBitmap(hdc, hero_x, hero_y, MyBitmap2); 
              }
              // 움직이는 블록 출력
              else if('$' == ucStage[0][iCount_y/BLOCK][iCount_x/BLOCK])
              {
                DrawBitmap(hdc, iCount_x, iCount_y, MyBitmap3); 
              }
            }
          }
          EndPaint(hWnd, &ps);
          return 0;
        case WM_DESTROY: // 운영체제로부터 들어온 메시지에 대한 처리 - 여기서는 윈도우가 파괴되었음을 알린다.
          DeleteObject(MyBitmap1); // 비트맵 해제
          DeleteObject(MyBitmap2); // 비트맵 해제
          DeleteObject(MyBitmap3); // 비트맵 해제
          PostQuitMessage(0); // WM_QUIT 메시지를 보냄
          return 0;
      }

      // switch 문에서 처리하지 않은 메시지를 처리
      return(DefWindowProc(hWnd, iMessage, wParam, lParam));
    }

    → 기본화면 출력


    -  구현해야 할 점
     → 케릭터가 이동시 배경 벽돌을 넘어가지 않게 한다.
     → 옮겨야 하는 벽돌의 위치로 캐릭터가 이동하면 벽돌은 캐릭터가 이동해온 방향과 같은 방향으로 한칸씩 이동한다.
     → 벽돌이 제일 오른쪽 창고에 지정한 위치로 도달하게 되면 게임이 클리어 되도록 한다.
    Posted by 동화다아아
    , |

    최근에 달린 댓글

    최근에 받은 트랙백

    글 보관함