第十章 Project Setup and Window Initialization

第十章 Project Setup and Window Initialization

本章主要讲述建立一个渲染引擎所需要的基础知识。包括创建一个Visual Studio工程,实现游戏循环,并最终在显示器上显示一个窗口。

A New Beginning

本章正式开始讲解C++编程(本书中使用C++集中讲解DirectX API的章节),重要的是,不要期望能迅速学会渲染一些场景到屏幕上。简单地说,要学会这些需要一段时间。首先需要花时间建立一些基础框架,在多个工程中重用代码的时候就会体现出这么做的好处。如果你更喜欢使用本书配套网站中的现有代码,并跳过部分章节直接开始实际的渲染工作,也可以。但是,如果你对基础系统框架是如何开发的感兴趣,你就会觉得接下来几章的内容非常有用。
另外,学习这些章节的内容需要你已经熟悉C++编程和Visual Studio的使用,但并不需要熟练编写Windows应用程序。因此,一开始会讲解工程的设置,这样在后面的章节中你就能自己完成工程的设置。

Projet Setup

接下来几章要开发的渲染引擎分为两个Visual Studio工程,包括一个Library工程和一个Game工程。其中Library工程包含了用于任意数量的游戏或者渲染应用程序的常用代码。而Game工程则是包含了特定应用程序的代码。

Directory Structure

给所有的工程建立一个目录结构是一个好的建议。表10.1中列出了本书配套代码的目录结构。

表10.1 Project Directory Structure

Project Creation

要使用这种目录结构,先在build目录里面创建一个空的Visual Studio solution(Visual Studio解决方案)。然后在Solution Explorer anel中右键点击该solution,并在弹出菜单上选择 Add-->New Project,会启动Add New Project Wizard(新建工程向导)。
如图10.1所示,选择Win32 Project模板,并填写工程的namt和location选项。

图10.1 The Visual Studio 2013 Add New Project Wizard.
选择OK就会启动Win32 Application Wizard(Win32应用程序设置向导)。对于Library工程,application type项选择Static Library,additional options中选择Empty Project(如图10.2所示)。在图10.2所示的设置中,precompiled headers被禁用了;如果你要用使用precompiled headers(用于提高编译速度),只需要勾选该选项。

图10.2 The Visual Studio 2013 Win32 Application Wizard.
再次执行同样的步骤创建一个Game project,但是在application type中选择Windows Applicaiton项。

Project Build Order

接下来,设置正确的编译顺序,在Solution Explorer panel中右键点击solution或者其中一个project,并在弹出菜单中选择 Project Dependencies。应该把Library project设置为Game project的依赖项,这样配置就可以在编译Game project之前先编译Library project(如图10.3所示)。

图10.3 The Visual Studio 2013 Project Dependencies dialog box.

注意
一种替代使用Project Dependencies对话框,手动设置Library project作为Game project项的方法是,使用Visual Studio 2013的 Common Properties中的 References对话框。使用这种方法,需要把Library project指定为Game project的reference。想要了解更多关于project references的信息可以浏览MSDN在线文档。

Include Directories

为了使projects在编译时能够找到DirectX的头文件,需要在project配置中指定一些文件路径。为些,在Solution Explorer panel中右键点击Library project并在弹出菜单中选择 Propertiees打开Property Pages。切换到 Configuration Propertiees(配置属性)-->C/C++-->General,然后参照图10.4,编译 Additional Include Directories。确保在debut和release选项中都进行了配置。

图10.4 The Visual Studio 2013 Additional Include Directories dialog box.
安装了Windows SDK之后,就可以使用宏$(WindowsSDK_IncludePath)。另外两个路径表示Effects11和DirectXTK库的路径。把Effects11和DirectXTK解压到external目录下,或者修改include directory为这些库的安装路径。

注意
回顾一下第三章中关于Effects 11和DirectX Tool Kit库的讨论。这两个库都是以源码的形式发布的,使用之前需要自己编译。就像上面所讲的,需要把编译好的库文件放到external目录中,或者Game和Library projects可以直接访问的其他目录中。

在Game project中重复这些路径配置,并增加一个路径:
$(SolutionDir)..\source\Library
这个配置允许Game project中的source files(源文件)直接包含Library project中的header files(头文件)。

警告
除非project中已经包含至少一个.cpp文件,否则 Configuration Propertiees下面的C/C++选项页不会显示。如果是自己创建工程(而不是直接使用本书配套代码),那么Library project现在还没有包含任何.cpp文件,因此C/C++选项页会被隐藏。为了使用该选项显示出来,可以在Library project中创建一个临时的.cpp格式空文件。在开始添加代码时,就可以把临时文件删除。

Linking Libraries

下面开始配置链接选项,打开Game project的Property Pages,转到 Configuration Properties-->Linker-->Input选项页。参照表10.2,编辑 Additional Dependencies部分的依赖库文件。注意一下debug和release配置项的区别。在debug配置选项中,Effects11和Library的库文件名的末尾带有一个字母d,表示这些是debug模式下编译的。这是一种常用的转换方式,以便于把debug和release库文件放到同一个输出目录中。图10.5显示了Visual Studio中设置Additional Dependencies的对话框。

表格10.2 Game Project Input Libraries

图10.5 The Visual Studio 2013 Additional Dependencies dialog box.
与指定头文件包含路径一样,也要在Visual Studio中指定库文件的包含路径。这些路径由 Additional Library Directories编辑项指定,该选项位于Property Pages对话框的 Configuration Properties-->Linker-->General选项页中。编辑该路径,使其与图10.6所示的一样。与之前一样,对debug和release选项都要进行配置,同时要注意DirectXTK库的debug和release版位于不同的路径。

图10.6 The Visual Studio 2013 Additional Library Directories dialog box.

注意: 在Visual Studio 2013的Configuration Properties-->VC++Directories选项页中的Include Directories和Library Directories选项中已经包含了$(WindowsSDK_IncludePath),所以上面配置路径时,该路径可以不用再添加了。

Final Project Settings

只需要再增加一点点配置,就可以开始编译projects。由于Library project与Game project相互独立(允许多个Game projects使用),因此需要把Library编译的输出存放到多个projects共同使用的目录下面。所有projects所有的solution目录就是一个共同的目录,可以把编译生成的.lib文件放到该路径的某个目录下面,比如$(SolutionDir)..\lib。可以把Library project的输出目录配置为该目录,或者通过一个post-build event把.lib文件拷贝到该目录中。一个build event只是列系列DOS批处理命令,可以在编译之前或编译之后触发。选择 Configuration Properties-->Build Events就可以看到这些设置,然后在 Command Line中编辑一个具体的event。图10.7显示了一个post-build event,该event用于把编译输出的.lib文件拷贝到Game project可以直接访问的目录下(在Game project中已经配置好了该目录)。

图10.7 The Visual Studio 2013 Post-Build Event/Command Line dialog boxes.
如果你希望Library project的debug编译选项下使用一个不同的输出文件名(比如Libraryd.lib),需要在Properties Pages对话框的
Configuration Properties-->Ganeral选项页中修改 Target Name项。
最后,接下章节中所有的代码都使用Unicode strings。需要在 Configuration Properties-->General选项页中对 Character Set项选择 Use Unicode Character Set

注意
通过折叠Library和Game projects,可以简化这些配置,但是这样的话就无法方便地重用公共代码。接下来几章的例子都是建立在这些配置的基础上,这些配置允许每个例子都可以独立的运行。
在你自己创建工程时,可以使用自己喜欢的配置方式。

Application Startup

现在,工程都可以配置完成了,可以开始添加代码了。首先在Game project中添加一个Program.cpp文件,该文件中包含应用程序的入口点WinMain()函数。Windows应用程序使用WinMain()作为入口函数,而不是传统的main()函数。
列表10.1列出了用于所有后面章节例子的基础代码。
列表10.1 The Program.cpp File
#include <memory>
#include "GameException.h"
#include "Game.h"

#if defined(DEBUG) || defined(_DEBUG)
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#endif

using namespace Library;

int WINAPI WinMain(HINSTANCE instance, HINSTANCE previousInstance, LPSTR commandLine, int showCommand)
{
#if defined(DEBUG) | defined(_DEBUG)
    _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
#endif

    std::unique_ptr<Game> game(new Game(instance, L"RenderingClass", L"Real-Time 3D Rendering", showCommand));

    try
    {
        game->Run();
    }
    catch (GameException ex)
    {
        MessageBox(game->WindowHandle(), ex.whatw().c_str(), game->WindowTitle().c_str(), MB_ABORTRETRYIGNORE);
    }

    return 0;
}

代码中包含了头文件<memory>,用于支持std::unique_ptr智能指针,该类型的智能指针表示当指针离开作用域时,就会释放指向的对象。另外两个包含文件是用于支持在Library project中创建的Game和GameException类。稍候将介绍Game类。类GameException是对std::exception的扩展。这两个类的代码没有在这里列出,可以在配套网站上找到。
接下来,讨论条件编译选项中包含的头文件<crtdbg.h>,用于支持CRT debug library。当该debug library可用时,那么在程序退出时,任何内存泄漏都会在Visual Studio的Output panel中列出。调用函数_CrtSetDbgFlag()就会启用debug library。
在WinMain()函数声明的前面,有一个using namespace的指令。本书中编写的渲染引擎代码全部封装在一个命名为Library的C++命名空间中(例如,类Game和类GameException)。所有关于例子的代码都在Game project中,而且封装在Rendering命名空间中。如果你还不熟悉命名空间,建议多熟悉一下;命名空间属于light side of the Force(意思是好的一面)的一部分
WinMain()函数的参数主要与window initialization有关,在Game类中会处理window initialization。因此,这些参数值都作为Game类的构造函数参数进行传递。很快就会讨论window initialization相关的代码。使用commandLine参数,可以从DOS命令行或者Windows快捷启动时向入口函数传递信息。
WinMain()函数中的代码非常少。通过Game类的实例对象调用Game::Run()函数,该调用语句被封装在一个try/catch块中,当Game:Run()调用出现异常时,就会弹出一个message box。Run()主要是执行应用程序的 game loop


注意
本书中所编写的代码主要是针对Windows平台,在基础代码中会发现很多专门用于Windows的引用。同样会遇到名称各样的Visual Studio语言扩展,使用其他编程环境的读者可能会对此感到不适应。我选择这种方法是为了避免跨平台的复杂性,因为本书的重点是讲述rendering。只需要一点点修改,本书中使用的框架就可以应用在Windows RT和Xbox One平台。如果再多修改一点,还可以变成独立的graphic API(可以支持DirectX或OpenGL)。
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值