이 항목에서는 Marble Maze 프로젝트의 기본 특성(예: Windows 런타임 환경에서 Visual C++을 사용하는 방법, 생성 및 구조화 방법 및 빌드 방법)에 대해 설명합니다. 또한 이 항목에서는 코드에 사용되는 몇 가지 규칙에 대해서도 설명합니다.
비고
이 문서에 해당하는 샘플 코드는 DirectX Marble Maze 게임 샘플에 존재합니다.
다음은 UWP(유니버설 Windows 플랫폼) 게임을 계획하고 개발할 때 이 문서에서 설명하는 몇 가지 핵심 사항입니다.
- Visual Studio에서 DirectX 11 앱(유니버설 Windows - C++/CX) 템플릿을 사용하여 DirectX UWP 게임을 만듭니다.
- Windows 런타임은 보다 최신의 개체 지향 방식으로 UWP 앱을 개발할 수 있도록 클래스와 인터페이스를 제공합니다.
- Hat(^) 기호와 함께 개체 참조를 사용하여 Microsoft::WRL::ComPtr
Windows 런타임 변수의 수명을 관리하고, 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 수정
참조하세요.
새 프로젝트
- 다음을 선택하고 프로젝트 이름, 파일이 저장될 위치, 솔루션 이름을 입력한 다음 만들기를 선택합니다.
DirectX 11 앱(유니버설 Windows - C++/CX) 템플릿의 중요한 프로젝트 설정 중 하나는 프로그램이 Windows 런타임 언어 확장을 사용할 수 있도록 하는 /ZW 옵션입니다. 이 옵션은 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 키를 사용하여 게임을 일시 중지하거나 다시 시작합니다.
- 컨트롤러의 뒤로 단추 또는 키보드의 홈 키를 사용하여 게임을 다시 시작합니다.
- 높은 점수 테이블이 표시되면, 컨트롤러의 뒤로 버튼이나 키보드의 홈 키를 눌러 모든 점수를 지웁니다.
코드 규칙
Windows 런타임은 특수 애플리케이션 환경에서만 실행되는 UWP 앱을 만드는 데 사용할 수 있는 프로그래밍 인터페이스입니다. 이러한 앱은 권한 있는 함수, 데이터 형식 및 디바이스를 사용하며 Microsoft Store에서 배포됩니다. 가장 낮은 수준에서 Windows 런타임은 ABI(애플리케이션 이진 인터페이스)로 구성됩니다. ABI는 JavaScript, .NET 언어 및 Visual C++와 같은 여러 프로그래밍 언어에서 Windows 런타임 API에 액세스할 수 있도록 하는 하위 수준 이진 계약입니다.
JavaScript 및 .NET에서 Windows 런타임 API를 호출하려면 해당 언어에 각 언어 환경과 관련된 프로젝션이 필요합니다. JavaScript 또는 .NET에서 Windows 런타임 API를 호출할 때 프로젝션을 호출하고, 이 프로젝션은 기본 ABI 함수를 호출합니다. C++에서 직접 ABI 함수를 호출할 수 있지만 Microsoft는 고성능을 유지하면서 Windows 런타임 API를 훨씬 더 간단하게 사용할 수 있도록 하기 때문에 C++에 대한 프로젝션도 제공합니다. 또한 Microsoft는 Windows 런타임 프로젝션을 특별히 지원하는 Visual C++에 언어 확장을 제공합니다. 이러한 언어 확장의 대부분은 C++/CLI 언어의 구문과 유사합니다. 그러나 네이티브 앱은 CLR(공용 언어 런타임)을 대상으로 하는 대신 이 구문을 사용하여 Windows 런타임을 대상으로 합니다. 개체 참조 또는 hat(^) 한정자는 참조 계산을 통해 런타임 개체를 자동으로 삭제할 수 있으므로 이 새 구문의 중요한 부분입니다. AddRef 및 Release 같은 메서드를 호출하여 Windows 런타임 개체의 수명을 관리하는 대신, 다른 구성 요소가 개체를 참조하지 않을 때(예: 범위를 벗어나거나 모든 참조를 nullptr설정할 때) 런타임이 개체를 삭제합니다. Visual C++를 사용하여 UWP 앱을 만드는 또 다른 중요한 부분은 ref new 키워드입니다. Windows 런타임 개체를 참조 계산하여 만들 때는 new 대신 ref new을 사용하십시오. 자세한 내용은 형식 시스템(C++/CX)참조하세요.
중요합니다
Windows 런타임 개체를 만들거나 Windows 런타임 구성 요소를 만들 때만 ^ 및 ref 새 사용해야 합니다. 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 런타임은 예외 처리를 광범위하게 사용합니다. 따라서 코드에서 예외 처리를 사용하여 모든 오류 처리를 하나의 모델로 결합할 수 있습니다.
오류 처리 모델에서 다음 규칙을 사용하는 것이 좋습니다.
예외를 사용하여 예기치 않은 오류를 전달합니다.
예외를 사용하여 코드 흐름을 제어하지 마세요.
안전하게 처리하고 복구할 수 있는 예외만 catch합니다. 그렇지 않으면 예외를 catch하지 않고 앱이 종료되도록 허용합니다.
DirectX 루틴을 호출하여 HRESULT을 반환하는 경우, DX::ThrowIfFailed 함수를 사용합니다. 이 함수는 DirectXHelper.h정의됩니다. throwIfFailed
제공된 HRESULT 오류 코드인 경우 예외를 throw합니다. 예를 들어, 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_을 사용하여 파일명을 입력 매개변수(따라서 읽기 전용)로 지정하고, _Out_을 사용하여 꼭짓점 버퍼 및 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 애플리케이션 구조
관련 항목
- Marble Maze 애플리케이션 구조
- C++ 및 DirectX UWP 게임인 Marble Maze 개발