4、写一个游戏框架(一)
http://www.brighthub.com/internet/web-development/articles/40512.aspx
在知道了如何使用画布元素之后,接下来我教大家写一个框架,有了这个框架,我们就可以把它作为基础来创建游戏。在这第一部分,我们会介绍前两个文件/类。
编写代码之前,我们先来看一看随后几篇文章将致力于创建的示例Demo。表面上看起来,这个Demo跟第二篇文章里的那个没啥区别,但如果你看看后台(查看网页源代码)就会发现,为了更方便地创建这个最终效果,一个凝聚不少心血的基础框架已经写好了。

下面我们要介绍的JavaScript代码使用面向对象的方式来编写。对于没有编写过多少JavaScript代码的人来说,恐怕第一眼看到它们会觉得有点奇怪。如果你真的不太熟悉JavaScript的面向对象编程,建议通过Mozilla Developer Network的这个教程https://developer.mozilla.org/en/Introduction_to_Object-Oriented_JavaScript来补补课。这篇教程里解释了我们稍后会用到的一些编程技术。
从设计思想上来看,这个框架可以分成两部分:与底层的2D引擎交互的类(用于操作画布、控制渲染循环、处理输入等的代码)和用来创建对象以便构成游戏的类。前者可以归为引擎类,后者可以归为应用类。由于应用类要构建于引擎类之上,所以我们需要先来创建引擎类。
Main.js
如果你研究了前面例子中的代码,就会发现Main.js文件中包含了不少代码。
- /** 每秒多少帧
- @type Number
- */
- var FPS = 30;
- /** 两帧间间隔的秒数
- @type Number
- */
- var SECONDS_BETWEEN_FRAMES = 1 / FPS;
- /** GameObjectManager 实例的全局引用
- @type GameObjectManager
- */
- var g_GameObjectManager = null;
- /** 应用中用到的图像
- @type Image
- */
- var g_image = new Image();
- g_image.src = "jsplatformer3-smiley.jpg";
- // 将应用的入口设置为init函数
- window.onload = init;
- /**
- 应用的入口
- */
- function init()
- {
- new GameObjectManager().startupGameObjectManager();
- }
首先是定义全局变量的代码。然后,跟以前一样,当页面加载完毕后立即运行init函数。在init函数里,创建GameObjectManager类的实例。
这里在GameObjectManager类的实例上调用了startupGameObjectManager函数。这篇文章以及后面的几篇文章还将多次提到几个命名上具有startupClassName形式的函数。这些函数实际上充当了各自类的构造函数,这样做有两个原因。
首先,JavaScript不支持函数重载(至少不容易实现)。如果你想让一个类有多个构造函数,那么这就成了问题。而通过把构造工作分配给另一组函数(如startupClassName1、startupClassName2),就可以比较容易地定义构造类的不同方式了。
广州网站建设,网站建设,广州网页设计,广州网站设计
第二个原因(很大程度上也是个人的问题)是我经常会在构造函数中引用尚未定义的变量。这可能是我使用C++、Java和C#这些语言落下的毛病,在这些语言里,类变量在源代码中的位置对其在构造函数中的可见性没有影响。拿下面这个C#类为例:
- class Test
- {
- public void Test() {this.a = 5;}
- public int a;
- }
这些代码是合乎语法的,可以正常工作。下面再看看JavaScript中一个相同的例子:
- function Test()
- {
- this.a = 5;
- var a;
- }
这段代码的问题在于,局部变量a在我们把数值5赋给它的时候还不存在。只有运行到var a;这一行,变量a才存在。尽管这个例子有点故意编排的意味,但的确能够说明我所遇到的问题。通过把类的创建放到一个类似startupClassName这样的函数中完成,并且在构造函数中定义(但不初始化)局部变量,然后当我在这些构建函数中引用相应的局部变量时,就能够确保它们一定是存在的。