DirectX 9.0c游戏开发手记之RPG编程自学日志之2: Preparing for the Book (准备工作)(上)

    本文由哈利_蜘蛛侠原创,转载请注明出处!有问题请联系[email protected]

 

    这一期我们正式进入主题了!不过在正式开始之前,得先告诉大家一些事情:

1、  网上没有找到此书(JimAdams的《Programming Role Playing Games with DirectX》第二版)的源代码。大家可以参考它的第一版的源代码,资源我已经在上一期最后分享给大家了;

2、  虽然和第一版使用DX 8相比,此书已经进步了,使用的是DX 9,但是和现在我们用的DirectX June 2010版的DirectX 9部分(属于DirectX 9.0c)区别还是蛮大的,有些代码根本编译不了。所以我就给它进行了适当的修改。另外,为了更加符合时代,我采用的是着色器(shader) 方法。到时候我会把自己修改后的能够编译的代码分享出来,大家敬请期待!

3、  有时候会插入书上的插图,不过由于年代久远的关系,很多书上的图现在不好找或者过时了,所以我会用更新的图来替换。

4、  这系列博客基本是我对此书的翻译,由于水平有限,错误及疏漏之处在所难免。我会尽量在我感觉有问题的地方注明的,但是也没法保证面面俱到,欢迎大家纠错啊!


    好的,现在先来学习第一章,名字叫做Preparing for the Book,也就是继续学习这本书之前所应该做的准备工作。

    这些准备工作具体包括:

1、  安装DirectX

2、  让你的编译器识别DirectX

3、  对于states和processes进行理解

4、  学会如何储存游戏数据

5、  建立应用程序框架

 

    而本章分为10小节,分别为:

1、 DirectX

2、 Setting Up the Compiler (设置编译器)

3、 General Windows Programming (一般的Windows编程)

4、 Understanding the Program Flow (理解程序流)

5、 Modular Programming

6、 Statesand Processes

7、 Handling Application Data (处理应用程序的数据)

8、 Buildingan Application Framework (构建一个应用程序框架)

9、 Structuringa Project (结构化一个项目)

10Wrapping UpPreparations (总结准备工作)

 

    顺便提一下:本书的前一版对于RPG的背景知识进行了比较详细的介绍,很值得一读,大家可以去看看!

 

    好啦,下面我们来讲书本的内容吧!

 

    前面两节内容很简单,基本上就是讲述前面提到的第1点和第2点的内容了,大家上网都能搜到,在此就不再赘述了。不过有问题的话还是欢迎大家来探讨。注意:我现在使用的编译器是Visual Studio 2013。

 

    下面我们来分别讲述剩下的各节的内容。内容有点多,会分三期讲述。

 

3部分:General Windows Programming

 

下面是原文翻译部分:

 

--------------------------------------------------------------------------------------------------------------------------

    好的,你安装了DirectX,你的编译器也设置好了,现在你准备好大干一场了!等一下我的朋友,在你进入RPG编程的王国闲逛之前你还是得先考虑一些个事情的。

首先也是最重要的,有一些跟Windows相关的话题是我想讨论的。这些话题包括了解线程和多线程编程、临界区和COM。我认为这些信息在你阅读此书的过程中将起到至关重要的作用(其实也未必……)

 

1.3.1 线程和多线程编程(Threads andMultithreading

 

    Windows 95向程序员们引入了使用多任务系统的概念(尽管Windows事实上并不是一个真正的多任务系统,因为它使用了抢占式多任务,而抢占式多任务处理很多程序的小碎片,并且一次只能处理一个)。这个概念就是你可以让多个进程 (processes)(应用程序)同时运行,每一个进程占用一部分处理时间(称为时间碎片)。

    多任务也让每个进程分解成分隔开的进程,称为线程 (threads)。每一个线程有它自己的目标,例如搜寻网络数据、处理用户输入或者在需要的时候播放声音。在一个应用程序中使用超过一个线程称为多线程编程 (multithreading)。

    在你的应用程序中创建额外的线程事实上并不困难。为了创建一个线程,你创建一个函数(使用一种特殊的函数原型)来包含你想要执行的代码。线程函数所需要用到的函数原型长成这个样子:

DWORD WINAPI ThreadProc(LPVOIDlpParameter);

实参数lpParameter是你创建该线程时提供的一个用户定义的指针,你可以通过调用CreateThread函数来实现这一点:

HANDLE CreateThread(
    LPSECURITY_ATTRIBUTES lpThreadAbilities, // NULL
    DWORD	dwStackSize,	// 0
    LPTHREAD_START_ROUTINE lpStartAddress,	// thread function
    LPVOID lpParameter,	// user supplied pointer – can be NULL
    DWORD dwCreationFlags,	// 0
    LPDWORD lpThreadId);		// receives thread identifier

 

注意:

    CreateThread函数的返回值是一个句柄,它必须在你用完它之后被释放,否则系统的资源不会被释放。我们通过调用函数CloseHandle来释放该线程所使用的资源:

CloseHandle(hThread);             // use handle received fromCreateThread

这是一个复杂的函数,所以我不会在这里讲述其细节,而是给你一个例子来看看。下面是一个简单的线程函数以及初始化该线程的函数调用:

// The custom thread function
DWORD WINAPI MyThread(LPVOID lpParameter)
{
    BOLL *Active;
    Active = (BOOL*)lpParameter;
    *Active = TRUE;	// flag thread as active

    // Insert custom code here

    // Terminate the thread
    *Active = FALSE;	// flag thread as no longer active
    ExitThread();	// special call to close thread
}

void InitThread()
{
    HANDLE hThread;
    DWORD ThreadId;
    BOOL Active;

    // Create the thread, passing a user-defined variable that
    // is used to store the status of the thread.
    hThread = CreateThread(NULL, 0,             \
        (LPTHREAD_START_ROUTINE)MyThread, (void*)&Active, \
        0, &ThreadId);

    // Wait for the thread to complete by continuously
    // checking the state of the flag.
    while(Active == TRUE);

    // Close the thread handle
    CloseHandle(hThread);
}

    前面的代码创建了一个线程,这个线程在CreateThread完成时立即执行。在创建函数调用的时候,你提供一个指向BOOL变量的指针,这个指针会跟踪这个线程的状态;它为TRUE则表示线程在活动中,为FALSE则表示线程不活动了。

    当线程的运行结束时,你把线程的状态标记为不再活动(通过在前面提到的BOOL变量中储存一个FALSE值)并且通过调用函数ExitThread来终止该线程,而该函数具有单独一个参数——该线程的终止码,或者更确切地说,这个线程为何而终止的参数。将ExitThread的参数设为0是安全的。

    基本上,一个线程就是一个与你的应用程序协作运行的函数。在第4章里你会发现更多关于如何使用线程的内容。

 

 

1.3.2 临界区 (CriticalSections)

 

    由于Windows是一个多任务系统,Windows应用程序可能会跑到别人的地盘,尤其是那些使用了多线程的应用程序。举例来说,如果一个线程在往一个数据结构里填充重要数据、但是另外一个线程改变了或者访问了这个数据,那么该咋办?

    有一种方法可以保证在需要的时候,只有一个线程具有完全的控制权,而这是通过使用临界区实现的。在活动状态下,临界区会阻挡所有试图来访问共享内存(应用程序的那部分由所有线程共同利用的内存)的线程,这样允许每一个线程来单独地改变应用程序的数据,而不需要担心其他线程的干扰。为了使用临界区,你必须首先声明并初始化一个:

CRITICAL_SECTION CriticalSection;
InitializeCriticalSection(&CriticalSection);


    到了这一步,你可以进入一个临界区,处理你的重要数据,然后离开临界区,如下例所示:

EnterCriticalSection(&CriticalSection);

// Do crucialdata processing here
LeaveCriticalSection(&CriticalSection);


    当你做完了临界区里的事情后(比如当应用程序关闭的时候),你通过调用以下语句来释放:

DeleteCriticalSection(&CriticalSection);


    虽然我很乐意阐述更多的使用临界区的细节,但是实在是没有必要。使用它们很简单,并且对于多线程的应用程序来说也是必需的。唯一要记住的准则是包含在临界区里的代码要能够很快地执行;因为你正在锁定系统的进程,而如果你的程序(在临界区内部的部分)花费太多时间的话,可能会导致系统崩溃。

 

……

(下面的部分讲述的是COMComponent Object Module,组件对象模型)部分,然而此书这部分讲得太难,过于复杂,其实现在我们用起来并没有这么繁琐。再次从略。不用担心,以后会有很多机会见识如何使用COM对象的。另外也可以参考“龙书”第二版。)

--------------------------------------------------------------------------------------------------------------------------

    

    好了,不知不觉已经讲了这么多了。看来一下子是讲不完第一章的呀!不过不用担心,我打算3期之内把这一章讲完。别看这一章是准备部分,其实内容一点也不简单呢!

 

你可能感兴趣的:(C++,RPG,游戏开发,DirectX,游戏编程)