『首先,请开始学习C++。』
嗯?什么?你说你会VB、会C语言?还有JAVA?ASP、SQL?让我再说一次:「请开始学习C++。」无论你之前学习过什么样的程序语言,请记得,现在我们谈论的是最适合用来开发游戏程序核心的程序语言。C++无庸置疑是目前功能最强大、效率最好、操作弹性最佳,也是最复杂难懂的语言。因此,C++用来开发游戏程序核心,至少在PC平台上,是最最合适的不二人选。
『OK,OK,我已经听到很多不以为然的声音了;请给我一点机会解释一下。』
C++是一个具备良好对象导向设计模式的一种语言,能相当完整的以「对象」为设计的着眼点来完成整个程序的分析及架构。在这里举一个实际应用上的例子:大家都知道,在3D的程序设计中,「向量」的使用是非常广泛且多面的,如果我们能以「对象导向」的观点设计出一个「向量对象类别」,那么在之后的使用上将会带来许多的便利性。怎么说呢?如果我们使用传统 structure-based 的设计模式来建立一个向量的新类别,我们通常会这样宣告:
typedef struct {
float x, y, z;
} Vector;
以此来表示一个自己定义的新类别 Vector,其内结构由 x、y、z 三个类别为浮点数的变量所组成。
「看起来还不错?」但是今天如果有需要做两个 Vector 类别的加减乘除呢?对不起,你必须一步一步的自己来做:
Vector vec1, vec2, vec3;
vec3.x = vec1.x + vec2.x;
vec3.y = vec1.y + vec2.y;
vec3.z = vec1.z + vec2.z;
「有没有更直觉的做法呢?」有的,在C++中,你可以自订类别的「运算子」来帮你更直觉化的完成这件事,例如:
operator+(Vector vec1, Vector vec2) {
vec3.x = vec1.x + vec2.x;
vec3.y = vec1.y + vec2.y;
vec3.z = vec1.z + vec2.z;
}
如此一来,以后在做 Vector 类别之间的加法时,只要简单的写:
vec3 = vec1 + vec2;
所有的工作,就由自订的加号运算子来帮助你完成,就像使用预设的加法运算子一样的直觉。在C++的语法中,你还可以为自订的「对象类别」,增加更多的「成员函式」;我们可以把「成员函式」看做是去定义一个「对象」的某种「行为」或「方法」,藉此来达成对象与外界的沟通桥梁。例如一个 Vector 常有可能会需要使用内积、外积或向量长度的计算;而其它加减乘除的运算,也都是 Vector 这个对象的「行为」或「方法」。当我们把这些功能写成 Vector 的成员函式之后,我们就能更加直觉的了解并使用这些方法,同时也在无形中增加了程序代码的可重复利用性。
对象导向及C++语言的威力还不仅止于此,在对象类别中所定义的各种函式都可以做到虚拟与多型的机制拓展,更进一步的提供了「继承」这项崭新的设计思维。何谓继承?所谓的继承,即是指对象架构的继承体系。如「人类」是属于「灵长类」下的一支,而「灵长类」又是属于「哺乳类动物」下的一支;于是我们可以说,所有灵长类的动物必定具备有哺乳类动物的特质,而所有的人类必定具备有灵长类动物的特质。这就是一种「继承」的架构。当我们在写程序时,若能依照架构由上而下的来定义对象类别,则必定能够节省很多的时间和力气,写出更好的程序。举一个例子来说明:如果今天我们要设计一个有关「质点」(particle) 的类别,要能够描述所有质点可能具备的特质及可能发生的行为,用C++的观点该如何来做?假设我的世界中会有三种质点:雪、火、雨。于是我们开始设计「雪」的对象类别…… 再来是「火」,…………… 最后还有「雨」。然后,我们可能会发现,其实这些质点会有许多共通的「本质」存在;不管是任何一种质点,我们都需要它存有:质点位置、质点大小、质点速度等等之类的资料。既然如此,我们何不把所有质点的共同特质抽离出来,成为一个抽象的 Particle 对象类别?如此一来,所有继承自它的对象类别 Snow、Fire、Rain 都可以拥有和 Particle 相同的「属性」及「特质」。然后再依不同质点的不同「行为」,个别去定义各自的成员函式。以后如果还需要定义其它种类的质点,只需要先从 Particle 继承而来,再来定义这个质点的不同之处就可以啦。 ([后注]:其实这里所举的「质点」这个例子,在实做上并不完全合适如此的继承架构。)
虽然它不是万灵药,但以对象导向的思维模式来写作程序,在多数的情况下,都是相当有利于每一个程序设计者的。而C++,正是包含了对象导向设计模式,目前最合适应用于PC平台游戏设计的程序语言。
『嗯?听起来好象真的很不错吧?』
很可惜的是,天下没有这么容易吃的午餐。既然C++有这么多的优点和这么强大的功能,那也就表示:C++是一种很难学习的程序语言。著名的作者侯捷在 Effective C++ 一书的译序中就曾提到:「C++是一种难学易用的语言!C++的难学,不仅在其广博的语法,以及语法背后的语意,以及语意背后的深层思维,以及深层思维背后的对象模型;C++的难学,还在于它提供了四种不同(但相辅相成)的程序设计思维模式:procedural-based, object-based, object-oriented, generic paradigm。」
因此在C++语言的学习曲线上,相较其它语言自然来的漫长许多。这通常是初学者真正第一个需要用力跨越的门槛。程序语言,并不是一种很直观的思维模式。没有人与生俱来就熟悉这种语言,要亲近它、学会它、熟练它,一步一步都是需要灌注时间和心力下去累积的。阅读真正值得一看再看的好书、做各种程序的写作练习、找个好老师学习,各种方法都是不能省略的。虽然在学习程序语言的过程中,会稍嫌单调无趣了些,但真正到了进阶的部分时,就会发现这个部分功力的重要性。无论写的是哪一种的程序,程序语言就是最重要的「内功心法」;如果内功未臻成熟,就急着练些花俏的武功招式,最后的结果就是程序 bug 连连,使出来的招式总在意料之外发生破绽。不可不慎之。
在学习程序语言的过程中,也应该熟悉一些基本的「数据结构」,如各种 linked list、queue、stack、tree 等等的用法;如果能够懂一些基本的「算法」概念,对以后程序的设计也会有不小的帮助。关于程序编译器 (compiler) 的选择,其实在目前这个阶段使用什么编译器都是没有差别的;而在之后学习「窗口程序设计」及各种 Graphics API 时,就需要从 MS Visual C++ 或 Borland C++ Builder 两者中择一了。我的建议是使用 MS Visual C++。毕竟是在 Windows 上开发程序、毕竟将来可能用到 MS 老大的 DirectX,在一开始的时候先用 MS 的编译器,可能比较不会碰到太多非预期内的麻烦问题。
[b]2.2、处理你的窗口[/b](Handle Your Window)
有了程序语言的基础之后呢?在你急着想学些3D的程序设计之前,先等一下,我们还得先拜拜码头:「先学会和我们可爱的 Windows 沟通沟通啰!」和 Windows 老大打好人际关系后,以后我们做起事来才会顺利的多。谁也不希望程序执行到半途,老是跑出「此程序执行无效,即将关闭」的蔚蓝画面吧?
『写程序归写程序,又关它 Windows 老大啥事了勒?』
话,不是这么说滴。我们要知道,所有计算机中的应用程序,都是建构在「操作系统」上面动作的;我们在 PC 上所写的游戏当然也算是应用程序的一种。而 Windows 正是扮演着「操作系统」这个角头老大的角色。由它来分配每个应用程序所可以使用到的内存以及 CPU,还有一般的键盘鼠标讯息也都是经由它来传送信息给应用程序的。所以啰,想在 Windows 上写作程序,当然需要先过这关啰。
『所以,现在有充分的理由开始学习 Windows SDK 啰。』
不,即使会使用 VB 来设计窗口应用程序,也并不代表真正了解窗口程序设计的意涵。我再说一次,直觉化如 VB 或 BCB 的拖拉点放「窗口组件」设计接口,也只是在你熟悉了窗口程序的核心概念之后,才能应用得宜、加速程序开发的。在那之前,好好的从基本的窗口程序写作开始学习起,才是最正确并且合适的做法。 对一个习惯了在 DOS 上开发写作应用程序的人来说,在学习窗口程序设计的过程中,一开始最无法适应的就是找不到 main() 这个程序的起始点;在 Windows programming 中,都是以 WinMain() 取代 main() 了。除此之外,还有很多一开始比较难以接受的新概念:什么是讯息循环?不可或缺的 WndProc() 又是做什么的?怎么输出文字?………… 相当多在 DOS 上的程序用法或函式,到了 Windows 上却不管用了。如今,要在 Windows 上写出一个最简单基本的 "Hello, World" 小程序,也约略要写 100 行左右的程序代码。不过也不用担心太多,只要找到一本好书做为学习的教材,就能够很快的进入状况、熟悉环境了。在此当然不得不推崇 Charles Petzold 原著的 Programming Windows 这本书,内容真可谓是钜细靡遗,书中还包括了每一个范例程序的完整程序代码,不论是书的厚度或内容,都是相当地具有「份量」;目前此书也已有中译本。
