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

카테고리

분류 전체보기 (176)
잡담 (1)
IT 기기-리뷰&뉴스 (7)
리뷰 - 도서 (1)
리뷰 - 영상 (0)
리뷰 - 그림/음악 (1)
내장형 하드웨어 (163)
Total635,284
Today31
Yesterday129
- 소코반은 여기저기 흩어져 있는 짐을 밀어서 창고에 순서대로 쌓는 게임이다.
- 소스 작성(제작 중)
#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 동화다아아

댓글을 달아 주세요

최근에 달린 댓글

최근에 받은 트랙백

글 보관함