티스토리 뷰

Project

#002 : Unlight Copycat [DAY #01]

BaeMinCheon 2018. 2. 22. 20:51

Project Note #002


Unlight Copycat DAY #01

개요

  • Window API의 일종인 pclaf를 활용해 게임을 만드는 과정을 정리합니다.
  • 참고
    ※ https://github.com/BaeMinCheon/unlight-copycat (Github, "v0.1.0" 커밋)

환경

  • Visual Studio 2015 Professional
  • Windows 10 Home
  • pclaf (C/C++)

Window API를 활용해 어떤 게임을 만들어볼까 생각을 하던 도중, 최근에 서비스 종료를 한 Unlight가 떠올랐습니다. 일관성 있는 디자인과 단순한 조작감으로 즐겨 했던 웹게임이었습니다(어떤 게임인지 궁금하신 분은 아래의 영상을 참고해주세요). 이 게임을 따라 만들어보는 것도 재미있을 것 같아 시작하게 되었습니다.



그리고 최근 접하게 된 pclaf라는 Window API 라이브러리를 사용해보면서 굉장히 편리하다고 느껴, 본 프로젝트에 적용하게 되었습니다. 난해하고 복잡한 Window API를 적당히 추상화시켜 정리한 것이 마음에 드는 라이브러리입니다. 또한 Visual Studio는 제한되는 기능에 걸리는 일이 종종 있어 기존 Community 에디션에서 Professional 에디션으로 변경했습니다(교내인증소프트웨어로 지원을 받았습니다).


그럼 본격적으로 시작해보겠습니다. 무엇부터 만들어야할지 생각해봅시다. 우선 pclaf 라이브러리는 Application이라는 클래스를 지원하는데, 해당 클래스를 상속받으면 기본적인 윈도우의 속성을 갖춘 클래스를 얻게 됩니다. 메시지 루프, 프로시저 등의 복잡하고 반복되는 코드들에 대해서는 건너뛸 수 있습니다. 본 프로젝트에서는 GameWindow라는 클래스를 만들어 사용하겠습니다(소스코드는 본문에 작성하기에는 비효율적이므로, Github을 참고해주세요).


pclaf에서의 윈도우 생성

  • Application을 상속받는 클래스 작성
    ※ 최소한 생성자는 구현해야 합니다.
  • 해당 클래스의 객체를 int mainLAF() 내에서 생성
    ※ 본 함수는 프로그램의 시작점입니다.
  • 해당 객체의 run()을 호출


위의 과정은 GameWindow.h와 GameWindow.cpp에서 참고할 수 있습니다. 단순히 생성자만 구현해도, 적어도 빈 화면이 출력되는 윈도우를 만들 수 있습니다. 윈도우를 만드는 일은 벌써 끝냈군요. 그럼 다음으로 해야할 일을 생각해봅시다.


Unlight는 메뉴가 없는 게임이 아니었습니다. 메인 화면에서 여러 가지 버튼을 눌러 해당 메뉴로 들어가 서로 다른 출력을 보고 작업을 수행할 수 있었습니다. 즉, 게임 내부의 시퀀스를 나눌 필요가 있습니다. 게임의 상태를 하나만 정의하고 그 안에 욱여넣는 것보다는 의미있게 분할하는 것이 만들기도 관리하기도 더 편하겠죠 ?


Sequence라는 클래스를 만듭니다. 다형성을 살리기 위해, 모든 시퀀스들을 이 클래스의 자식 클래스로 작성하고 이 클래스의 포인터로 접근하는 것이 좋겠네요. 지금은 그리기와 마우스 입력에 대한 함수들만 작성합니다(draw() leftClick() doubleClick() rightClick()). 그리고 Sequence를 상속받는 Main Quest Battle 클래스도 작성해줍니다.


위의 과정은 Sequence.h와 Sequence.cpp에서 참고할 수 있습니다. 그럼 이번에는 방금 만든 시퀀스들을 간단하게 변환시켜봅니다. 추후에는 버튼을 만들어서 시퀀스 변환을 구현하겠지만, 지금은 마우스 입력으로 처리해봅시다. 시퀀스 클래스들을 저장할 vector를 GameWindow의 정적 멤버변수로 작성하고, Sequence 클래스의 leftClick()에서 시퀀스를 가리키는 인덱스값(sequenceIndex)에 변화를 주는 내용을 작성합니다. 그리고 자식 클래스의 leftClick()에서 부모 클래스인 Sequence의 leftClick()을 호출합시다(자식 시퀀스 클래스의 leftClick()에 각각 정의하는 것이 정석이겠지만, 지금 작성하는 내용은 동일하기 때문에 굳이 그럴 필요는 없습니다).


pclaf에서의 마우스 입력

  • mouseDown() : 마우스 왼쪽 클릭이 입력되면 호출
  • mouseMDown() : 마우스 중간 클릭이 입력되면 호출
    ※ 휠 버튼 입력을 말합니다.
  • mouseRDown() : 마우스 오른쪽 클릭이 입력되면 호출
  • doubleClick() : 마우스 왼쪽에 대한 더블 클릭이 입력되면 호출


그럼 이제 각 시퀀스의 leftClick()이 실행되면 시퀀스들을 담는 sequenceVector의 인덱스값이 변경됩니다. 각 시퀀스의 leftClick()을 호출하기 위해, Application을 상속받은 GameWindow의 mouseDown()에 각 시퀀스의 leftClick()을 호출하는 내용을 작성합니다. 이렇게 하면 마우스 왼쪽 클릭이 입력될 때마다 GameWindow의 mouseDown()이 호출되고 내부에서 각 시퀀스의 leftClick()이 호출될 것입니다.


pclaf에서의 화면 출력

  • Update() : 기존 화면을 남긴 상태에서, paint()를 호출
  • clearAndUpdate() : 기존 화면을 지우고(하얀 바탕으로 만들고), paint()를 호출
  • paint() : 윈도우 생성 직후 및 위의 함수들이 사용되었을 때 호출


그러고 보니 별도의 출력을 하지않으면 시퀀스가 바뀌는 줄 모르겠군요. 지금은 간단하게 구분만 하기 위해 문구를 출력해봅시다. 각 시퀀스의 draw()에 출력할 내용을 wout()과 setpos()을 이용해 작성합니다. 그 다음 GameWindow의 paint()에서 각 시퀀스의 draw()를 호출하는 코드를 작성합니다.


pclaf에서의 문자(열) 출력

  • wout() : Application을 상속받은 클래스의 객체에서 멤버함수로 사용가능
  • setpos() : wout()으로 출력될 위치를 지정
  • [윈도우객체].wout() << setpos(x, y) << TEXT("...");의 구조로 사용


이제 paint()가 호출될 때마다 각 시퀀스의 draw()가 호출되어 구분할 수 있겠군요. 실제로 실행해보면 마우스를 클릭할 때마다 문구가 바뀌는 것을 확인할 수 있습니다. 이로써 시퀀스를 나누고 각 시퀀스마다의 입출력을 따로하는 구조를 완성했습니다. 이 다음으로는 버튼을 만드는 과정을 진행해보겠습니다. 이상으로 DAY #01 노트를 마칩니다.

'Project' 카테고리의 다른 글

#006 : Unlight Copycat [DAY #05]  (0) 2018.02.26
#005 : Unlight Copycat [DAY #04]  (0) 2018.02.25
#004 : Unlight Copycat [DAY #03]  (0) 2018.02.25
#003 : Unlight Copycat [DAY #02]  (0) 2018.02.23
#001 : Mole Catch  (0) 2018.01.28
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함