Marble Maze 샘플 기본 사항
이 항목에서는 프로젝트가 Windows 런타임 환경에서 Visual C++를 사용하는 방법, 프로젝트를 만들고 구성하는 방법, 프로젝트 빌드 방법 등 Marble Maze 프로젝트의 기본 특성에 대해 설명합니다. 또한 코드에 사용되는 여러 규칙에 대해서도 설명합니다.
참고 항목
이 문서에 해당하는 샘플 코드는 DirectX Marble Maze 게임 샘플에 있습니다.
다음은 이 문서에서 UWP(유니버설 Windows 플랫폼) 게임을 계획하고 개발할 경우 설명하는 몇 가지 핵심 사항입니다.
- Visual Studio의 DirectX 11 앱(유니버설 Windows - C++/CX) 템플릿을 사용하여 DirectX UWP 게임을 만듭니다.
- Windows 런타임 클래스와 인터페이스를 제공하므로 최신의 개체 지향 방식으로 UWP 앱을 개발할 수 있습니다.
- 개체 참조에 캐럿(^) 기호를 사용하여 Windows 런타임 변수의 수명을 관리하고, Microsoft::WRL::ComPtr을 사용하여 COM 개체의 수명을 관리하고, std::shared_ptr 또는 std::unique_ptr을 사용하여 다른 모든 힙 할당 C++ 개체의 수명을 관리합니다.
- 결과 코드 대신 예외 처리를 사용하여 예기치 않은 오류를 처리하는 경우가 대부분입니다.
- 앱에서 오류를 찾는 데 도움이 되도록 SAL 주석을 코드 분석 도구와 함께 사용합니다.
Visual Studio 프로젝트 만들기
샘플을 다운로드하여 압축을 푼 경우 Visual Studio에서 MarbleMaze_VS2017.sln 파일(C++ 폴더에서)을 열어 코드를 직접 확인할 수 있습니다.
Marble Maze용 Visual Studio 프로젝트를 생성할 때 기존 프로젝트를 시작했습니다. 그러나 DirectX UWP 게임에 필요한 기본 기능을 제공하는 기존 프로젝트가 없는 경우 작동하는 기본 3D 응용 프로그램을 제공하는 Visual Studio DirectX 11 앱(유니버설 Windows - C++/CX) 템플릿을 기준으로 프로젝트를 만드는 것이 좋습니다. 이렇게 하려면 다음 단계를 수행하세요.
Visual Studio 2019에서 파일 > 새로 만들기 > 프로젝트...를 선택합니다.
새 프로젝트 만들기 창에서 DirectX 11 앱(유니버설 Windows - C++/CX)를 선택합니다. 이 옵션이 표시되지 않으면 필요한 구성 요소가 설치되어 있지 않은 것일 수 있습니다. 추가적인 구성 요소 설치 방법에 대한 내용은 작업과 구성 요소를 추가하거나 제거하여 Visual Studio 2019 수정을 참조하세요.
- 다음을 선택한 후 Project 이름, 저장할 파일의 위치 및 솔루션 이름 입력하고 만들기를 선택합니다.
DirectX 11 앱(유니버설 Windows - C++/CX) 템플릿의 한 가지 중요한 프로젝트 설정은 /ZW 옵션으로, 프로그램이 Windows 런타임 언어 확장을 사용할 수 있도록 합니다. 이 옵션은 Visual Studio 템플릿을 사용하는 경우 기본 사용하도록 설정됩니다. Visual Studio에서 컴파일러 옵션을 설정하는 방법에 대한 자세한 내용은 컴파일러 및 링커 옵션(C++/CX)을 참조하세요.
주의 /ZW 옵션은 /clr 같은 옵션과 호환되지 않습니다. /clr의 경우 동일한 Visual C++ 프로젝트에서 .NET Framework 및 Windows 런타임을 둘 다 대상으로 지정할 수 없다는 의미입니다.
Microsoft Store에서 가져오는 모든 UWP 앱은 앱 패키지 형태로 제공됩니다. 앱 패키지에는 앱에 대한 정보가 포함된 패키지 매니페스트가 포함되어 있습니다. 예를 들어, 앱의 기능(즉, 보호된 시스템 리소스 또는 사용자 데이터에 필요한 액세스)을 지정할 수 있습니다. 앱에 특정 기능이 필요하다고 판단될 경우, 패키지 매니페스트를 사용하여 필요한 기능을 선언합니다. 매니페스트를 사용하면 지원되는 디바이스 회전, 타일 이미지, 시작 화면과 같은 프로젝트 속성을 지정할 수도 있습니다. 프로젝트에서 Package.appxmanifest를 열어 매니페스트를 편집할 수 있습니다. 앱 패키지에 대한 자세한 내용은 패키징 앱을 참조하세요.
게임 빌드, 배포, 실행
Visual Studio 맨 위에 있는 드롭다운 메뉴의 녹색 재생 버튼 왼쪽에서 배포 구성을 선택합니다. 디바이스의 아키텍처(32비트는 x86, 64비트는 x64) 및 로컬 컴퓨터를 대상으로 하는 디버그로 설정하는 것이 좋습니다. 원격 컴퓨터 또는 USB를 통해 연결된 디바이스에서 테스트할 수도 있습니다. 그런 다음 녹색 재생 버튼을 클릭하여 디바이스를 빌드하고 배포합니다.
게임 제어
터치, 가속도계, 게임 컨트롤러 또는 마우스를 사용하여 Marble Maze를 제어할 수 있습니다.
- 컨트롤러의 방향 패드를 사용하여 활성 메뉴 항목을 변경합니다.
- 터치, 컨트롤러의 A 버튼이나 시작 버튼 또는 마우스를 사용하여 메뉴 항목을 선택합니다.
- 터치, 가속도계, 왼쪽 엄지스틱 또는 마우스를 사용하여 미로를 기울입니다.
- 터치, 또는 컨트롤러의 A 버튼 또는 시작 버튼 또는 마우스를 사용하여 최고 점수 테이블 등의 메뉴를 닫습니다.
- 컨트롤러의 시작 버튼 또는 키보드의 P 키를 사용하여 게임을 중지하거나 다시 시작합니다.
- 컨트롤러의 뒤로 버튼 또는 키보드의 홈 키를 사용하여 게임을 재시작합니다.
- 최소 점수 테이블이 표시될 때 컨트롤러의 뒤로 버튼 또는 키보드의 Home 키를 사용하여 모든 점수를 지웁니다.
코드 규칙
Windows Runtime은 특수한 애플리케이션 환경에서만 실행되는 UWP 앱을 만드는 데 사용할 수 있는 프로그래밍 인터페이스입니다. 이러한 앱은 인증된 기능, 데이터 형식 및 디바이스를 사용하고 Microsoft Store에서 배포됩니다. 가장 낮은 수준에서 Windows 런타임 ABI(애플리케이션 이진 인터페이스)로 구성됩니다. ABI는 JavaScript, .NET 언어, Visual C++와 같은 여러 프로그래밍 언어에서 Windows 런타임 API에 액세스할 수 있도록 하는 하위 수준 이진 계약입니다.
JavaScript 및 .NET에서 Windows 런타임 API를 호출하기 위해 해당 언어에는 각 언어 환경과 관련된 프로젝션이 필요합니다. JavaScript 또는 .NET에서 Windows 런타임 API를 호출할 경우 프로젝션을 호출하고, 이 프로젝션은 기본 ABI 함수를 호출합니다. C++에서 직접 ABI 함수를 호출할 수 있더라도, Microsoft는 C++에 대한 프로젝션도 제공하기 때문에 Windows 런타임 API를 훨씬 더 간단하게 사용할 수 있지만 기본 고성능을 얻을 수 있습니다. Microsoft는 특히 Windows 런타임 프로젝션을 지원하는 Visual C++에 언어 확장을 제공합니다. 이러한 언어 확장의 대부분은 C++/CLI 언어의 구문과 유사합니다. 그러나 네이티브 앱은 CLR(공용 언어 런타임)을 대상으로 하는 대신 해당 구문을 사용하여 Windows 런타임 대상으로 합니다. 개체 참조 또는 hat(^) 한정자는 참조 계산을 통해 런타임 개체를 자동 삭제할 수 있으므로 이 새 구문의 중요한 부분입니다. AddRef 및 릴리스와 같은 메서드를 호출하여 Windows 런타임 개체의 수명을 관리하는 대신, 다른 구성 요소가 개체를 참조하지 않을 때(예: 범위를 벗어나거나 모든 참조를 nullptr로 설정한 경우) 런타임에서 개체를 삭제합니다. Visual C++를 사용하여 UWP 앱을 생성하는 또 다른 중요한 부분은 ref new 키워드. 참조 계산 Windows 런타임 개체를 생성하려면 new 대신 ref new를 사용합니다. 자세한 내용은 형식 시스템(C++/CX)을 참조하세요.
Important
Windows 런타임 개체를 만들거나 Windows 런타임 구성 요소를 만드는 경우 ^ 및 ref new만 사용하면 됩니다. Windows 런타임을 사용하지 않는 핵심 애플리케이션 코드를 작성할 때 표준 C++ 구문을 사용할 수 있습니다.
Marble Maze는 ^을 Microsoft::WRL::ComPtr과 함께 사용하여 힙 할당 개체를 관리하고 메모리 누수를 최소화합니다. ^을 사용하여 Windows 런타임 변수의 수명을 관리하고, ComPtr을 사용하여 COM 변수의 수명을 관리하고(예: DirectX를 사용하는 경우), std::shared_ptr 또는 std::unique_ptr을 사용하여 다른 모든 힙 할당 C++ 개체의 수명을 관리하는 것이 좋습니다.
C++ UWP 앱에서 사용할 수 있는 언어 확장에 대한 자세한 내용은 Visual C++ 언어 참조(C++/CX)를 참조하세요.
오류 처리
Marble Maze는 예기치 않은 오류를 처리하는 기본 방법으로 예외 처리를 사용합니다. 게임 코드는 일반적으로 HRESULT 값과 같은 로깅 또는 오류 코드를 사용하여 오류를 나타내지만 예외 처리에는 두 가지 기본 이점이 있습니다. 첫째, 코드를 더 쉽게 읽고 유지관리할 수 있습니다. 코드 관점에서 예외 처리는 오류를 해당 오류를 처리할 수 있는 루틴으로 전파하는 보다 효율적인 방법입니다. 일반적으로 오류 코드를 사용하려면 각 함수가 오류를 명시적으로 전파해야 합니다. 두 번째 장점은 예외가 발생할 때 중단되도록 Visual Studio 디버거를 구성하여 오류의 위치 및 컨텍스트에서 즉시 중지할 수 있다는 것입니다. 또한 Windows 런타임 예외 처리를 광범위하게 사용합니다. 따라서 코드에서 예외 처리를 사용하여 모든 오류 처리를 하나의 모델로 결합할 수 있습니다.
오류 처리 모델에서 다음 규칙을 사용하는 것을 권장합니다.
예외를 사용하여 예기치 않은 오류를 전달합니다.
예외를 사용하여 코드 흐름을 제어하지 마세요.
안전하게 처리하고 복구할 수 있는 예외만 포착합니다. 그렇지 않으면 예외를 포착하지 않고 앱이 종료되도록 허용합니다.
HRESULT를 반환하는 DirectX 루틴을 호출하는 경우 DX::ThrowIfFailed 함수를 사용합니다. 이 함수는 DirectXHelper.h에 정의되어 있습니다. 제공된 HRESULT가 오류 코드인 경우 ThrowIfFailed에서 예외가 발생합니다. 예를 들어 E\_POINTER인 경우 ThrowIfFailed에서 Platform::NullReferenceException이 발생합니다.
ThrowIfFailed를 사용하는 경우 다음 예제와 같이 코드 가독성을 향상시키기 위해 DirectX 호출을 별도의 줄에 배치합니다.
// Identify the physical adapter (GPU or card) this device is running on. ComPtr<IDXGIAdapter> dxgiAdapter; DX::ThrowIfFailed( dxgiDevice->GetAdapter(&dxgiAdapter) );
예기치 않은 오류에는 HRESULT를 사용하지 않는 것이 좋지만 코드 흐름을 제어하는 데 예외 처리를 사용하지 않는 것이 더 중요합니다. 따라서 코드 흐름을 제어하는 데 필요한 경우 HRESULT 반환 값을 사용하는 것이 좋습니다.
SAL 주석
앱에서 오류를 찾는 데 도움이 되도록 SAL 주석을 코드 분석 도구와 함께 사용합니다.
Microsoft SAL(소스 코드 주석 언어)을 사용하여 함수에서 해당 매개 변수를 사용하는 방법에 주석을 달거나 설명할 수 있습니다. SAL 주석은 반환 값도 설명합니다. SAL 주석은 C/C++ 코드 분석 도구와 함께 작동하여 C 및 C++ 소스 코드에서 가능한 결함을 검색합니다. 이 도구를 통해 보고되는 일반적인 코딩 오류에는 버퍼 오버런, 초기화되지 않은 메모리, null 포인터 역참조, 메모리 및 리소스 누수 등이 포함됩니다.
BasicLoader.h에 선언되어 있는 BasicLoader::LoadMesh 메서드를 고려합니다. 이 메서드는 _In_
을 사용하여 filename을 입력 매개 변수(따라서 읽기만 수행됨)로 지정하고, _Out_
을 사용하여 vertexBuffer 및 indexBuffer를 출력 매개 변수(따라서 쓰기만 수행됨)로 지정하고, _Out_opt_
를 사용하여 vertexCount 및 indexCount를 선택적 출력 매개 변수(쓰기도 가능함)로 지정합니다. vertexCount 및 indexCount는 선택적 출력 매개 변수이므로 nullptr로 허용됩니다. C/C++ 코드 분석 도구는 이 메서드에 대한 호출을 검사하여 전달하는 매개 변수가 이러한 조건을 충족하는지 확인합니다.
void LoadMesh(
_In_ Platform::String^ filename,
_Out_ ID3D11Buffer** vertexBuffer,
_Out_ ID3D11Buffer** indexBuffer,
_Out_opt_ uint32* vertexCount,
_Out_opt_ uint32* indexCount
);
앱에서 코드 분석을 수행하려면 메뉴 모음에서 빌드 > 솔루션에서 코드 분석 실행을 선택합니다. 코드 분석에 대한 자세한 내용은 코드 분석을 사용하여 C/C++ 코드 품질 분석을 참조하세요.
전체 사용 가능한 주석 목록은 sal.h에 정의되어 있습니다. 자세한 내용은 SAL 주석을 참조하세요.
다음 단계
Marble Maze 응용 프로그램 코드가 구조화되는 방식 및 DirectX UWP 앱의 구조가 기존 데스크톱 응용 프로그램의 구조와 어떻게 다른지에 대한 자세한 내용은 Marble Maze 응용 프로그램 구조를 참조하세요.
관련 항목