F.R.I.D.A.Y.

지뢰찾기 - 그리기 툴 본문

DEV/Direct2D

지뢰찾기 - 그리기 툴

F.R.I.D.A.Y. 2021. 7. 3. 01:50
반응형

 지뢰찾기 그래픽 처리를 위한 구성


그리기 작업

 GUI 프로그래밍을 위해서 그리기 툴을 구성해봤다. 그리고, 해당 그리기 툴을 다른 곳에서도 이어서 사용할 수 있도록 그리기 정보를 담고 있는 객체를 생성 및 이들을 관리하는 클래스를 구성해봤다.

 

그리기 툴

DrawTool

 그래픽 엔진은 Direct2D를 이용했고, 이를 다른 프로그램에서 쉽게 이용할 수 있도록 정형화했다. 먼저 구성할 메서드는 다음과 같다.

  • OnPaint(DrawSet*)
  • OnSize

 위 두 메서드는 그리기 작업에 영향을 주는 WM_PAINT와 WM_SIZE 메시지가 들어왔을 때 해당 프로시저에서 각각 연결해주면 된다. OnPaint에 인자로 넘기는 <DrawSet>은 하단에 설명을 잇는다.

 

생성자

 ID2D1HwndRenderTarget을 생성할 때는 기본적으로 대상 윈도우의 핸들값(HWND)이 필요하다. 따라서 인자로 대상 윈도우의 핸들값을 받도록 구성되어 있다.

DrawTool(HWND hWnd);

 

내부 멤버

 DrawTool의 내부 멤버는 다음과 같다.

  • ID2D1Factory
  • ID2D1HwndRenderTarget
  • ID2D1SolidColorBrush

 ID2D1Factory의 경우, 내부적으로 모두 처리하므로 전혀 생각하지 않아도 된다. 또한, ID2D1HwndRenderTarget과 ID2D1SolidColorBrush의 경우 OnPaint 내부에서 그리기 정보 객체의 OnDraw를 호출할 때 넘겨주는 용도로 처리되며, 이 또한, 모두 DrawTool 내부에서 관리된다. 따라서 그리기 관련 객체는 메모리 관리를 생각하지 않아도 된다.

 

 

TextTool

 텍스트 출력에 필요한 DWrite 데이터를 처리한다. <DrawObjectText> 객체를 구성할 때 필요하므로 도형만 출력하는 경우라면 굳이 생성하지 않아도 된다.

 

 또한, 외부 데이터를 끌어다 쓸 필요가 없으므로 생성자 또한 기본 생성자로 제공된다.

 

메서드
CreateTextFormat(...)

 IDWriteTextFormat 객체를 반환한다. 인자로 두 개가 주어지며, 각각 폰트명과 텍스트의 출력 크기를 전달한다.

IDWriteTextFormat* CreateTextFormat(const wchar_t* fontName, float fontSize);

 


그리기 객체

DrawSet

 DrawSet은 그리기 객체를 관리하는 집합셋이다. DrawSet은 내부적으로 <IDrawObject> 객체를 배열 형식으로 관리하며, 포함하는 IDrawObject 객체는 DrawSet이 해제될 때 함께 해제되므로 외부에서 DrawSet을 처리할 때는 IDrawObject는 DrawSet 내부로 넘겨주기만 하면 된다.

 

생성자

 기본 생성자는 지원하지 않는다. 따라서 기본 크기를 입력해야한다.

DrawSet(size_t capacity);

 

 

포함 메서드

 DrawSet은 아래와 같은 메서드가 포함되어 있다. 기본적으로 그리기 작업이 완료되면 바로 삭제가 이루어지는 데이터이기 때문에 굳이 내부 요소를 선택 삭제하는 기능은 제공하지 않는다. 또한, 혹시모를 상황에 대비하여 요소 추가 전 내부 공간을 확인하므로 입력시 메모리 오버플로는 걱정하지 않도록 구현했다.

 

GetSize()

 현재 DrawSet에서 보관중인 IDrawObject 객체의 수를 반환한다.

 

AddItem()

 DrawSet 객체에 IDrawObject 객체를 포함시킬 때 사용한다. 이 함수는 연산자 오버로딩을 통해 다음처럼 사용할 수 있다.

// 연산자 오버로드
DrawSet& operator<<(IDrawObject* item){
	AddItem(item);
    return *this;
}

// 사용

DrawSet* dSet{10};
IDrawObject *SomeObj1, *SomeObj2, *SomeObj3;
// ...
dSet << SomeObj1 << SomeObj2 << SomeObj3;

 

 

 

 

GetItem(size_t idx)

 인자로 전달되는 인덱스에 알맞은 IDrawObject를 반환한다. 이 함수 또한 <AddItem()>과 마찬가지로 연산자 오버로딩이 되어있다.

IDrawObject* operator[](size_t idx){return GetItem(idx);}

DrawSet obj;
obj[0]; // 0번 인덱스 항목에 존재하는 IDrawObject* 데이터 반환

 

 

 

IDrawObject

 <DrawSet>에 포함될 데이터의 최상우 클래스이다. 기본적으로 추상클래스로 구성되어있기 때문에 직접적으로 객체를 생성할 수는 없다.[# 때문에 인터페이스 접두사 I가 이름에 붙었다. 이는 아래에서 소개할 다른 대상에도 동일하게 적용된다.] 다만, 최상위 추상 클래스인만큼, 다른 파생클래스를 해당 클래스의 포인터로 가리킬 수 있으며, 다형성을 지원할 수 있다.

 

 이 인터페이스로 파생되는 클래스는 다음과 같다.

  • IDrawObjectShape[# 도형 관련 클래스를 생성할 때 이 인터페이스로만 파생해 처리한다.]
  • DrawObjectText
  • DrawObjectRectangle[# IDrawObjectShape를 상속하며, super class로 인해 간접적으로 상속한다.]

 

메서드

 IDrawObject를 포함해 이를 상속해 만들어진 모든 파생클래스는 OnDraw 함수를 생성해야한다.

 

OnDraw(..)

 인자로 다음이 들어간다.

 <DrawTool> 객체를 생성하는 것으로 DrawTool 내부에서 자체적으로 생성 및 초기화를 진행한다. 또한, IDrawObject 객체 및 파생 클래스는 DrawSet에 포함되며, DrawSet의 사용은 DrawTool 객체로 전달되어 사용되므로 생성할 필요가 없다. OndDraw 메서드는 DrawTool::OnPaint 내부에서 아래와 같이 호출된다.

LRESULT Mine::DrawTool::OnPaint(DrawSet& obj)
{
	PAINTSTRUCT ps;
	HRESULT hr;
	BeginPaint(GetHwnd(), &ps);
	pRT->BeginDraw();

	for (size_t i = 0; i < obj.GetSize(); ++i) {
		obj[i]->OnDraw(pRT, pBrush);
	}
	
	hr = pRT->EndDraw();
	EndPaint(GetHwnd(), &ps);
	return hr;
}

 

 

 

IDrawObjectShape

 사각형, 삼각형 등의 도형을 그리기 위한 추상 클래스이다. 추상클래스로 만든 이유는 도형 채우기 및 외부 border 그리기를 한번에 처리하기 위함이었다.

 때문에 enum class로 inner와 border를 채울 것인지 선택하도록 옵션을 추가로 제공하고 있다.

 

 

DrawObjectRectangle

 사각형을 그리기 위한 그리기 데이터를 포함하는 클래스이다.

 

생성자

 생성자는 IDrawObjectShape와 같다

		DrawObjectRectangle(D2D1_POINT_2F pos, D2D1_SIZE_F size, DrawOption option, D2D1_COLOR_F innerColor, D2D1_COLOR_F borderColor)
			: IDrawObjectShape{pos, size, option, innerColor, borderColor}
            {}

 

DrawOption은 추상클래스 <IDrawObjectShape>에 정의되어 있으며, 이 클래스의 파생인 DrawObjectRectangle 또한 이 enum class를 가지고 있으므로 사용할 수 있다.

 

 

DrawObjectText

 텍스트 출력을 진행할 때 사용하는 클래스이다. 기본적으로 배경 출력이 필요했기 때문에 배경을 만들 것인지 선택하는 작업을 추가하지 않았다. 만일 해당 클래스에 변형을 가하지 않고 그대로 사용하려면 backgroundColor의 alpha 값을 0으로 넘겨주면 된다.

 

생성자

 생성자는 IDrawObject에서 두 개가 추가되었다.

		DrawObjectText(wchar_t* str, IDWriteTextFormat* pWTextFormat,
			D2D1_POINT_2F pos, D2D1_SIZE_F size, D2D1_COLOR_F textColor, D2D1_COLOR_F backgroundColor)

 처음 두 인자 str과 pWTextFormat은 각각 출력할 텍스트와 해당 텍스트를 출력할 때 사용할 설정이다.

 특히나 두 번째 인자인 IDWriteTextFormat*은 <TextTool>에서 CreateTextFormat 메서드를 이용해 간단히 생성할 수 있다.

 

 전달되는 IDWriteTextFormat은 DrawObjectText 객체가 파괴될 때 함께 처리가 되므로, 이 또한 생성해서 넘겨주기만 하면 된다.

		virtual ~DrawObjectText() {
			SafeRelease(pWTextFormat);
			if (text) {
				delete[] text;
				text = nullptr;
			}
		}

 파괴자 코드를 보면 SafeRelease 함수로 해당 객체를 지움으로써 메모리 누수를 방지하고 있다.

 


소스코드

 다음은 위 설명을 한 소스코드이다.

MineProejct.zip
0.00MB

 

# index

728x90
반응형

'DEV > Direct2D' 카테고리의 다른 글

지뢰찾기 - 윈도우 구성  (0) 2021.07.07
지뢰찾기 - 맵 데이터  (0) 2021.07.03
지뢰찾기  (0) 2021.06.28
물리엔진 - 벽 충돌 part2. 좌우 벽 구현  (0) 2021.05.14
물리엔진 - 좌우 이동  (0) 2021.05.14
Comments