基于Html5的游戏框架
最近在网上发现一个Htm5游戏框架l的教程,最开始看的是中文的教程,虽然是翻译大家(为之漫笔)翻译的,但是后面觉得不过瘾,还是喜欢看英文原版的,顺便锻炼自己的英语,为专四准备准备。现在把他翻译出来,供自己查阅和各位大牛指错。本文的翻译可能掺杂了自己对程序的理解,望指错。
首先介绍一下这个游戏基本的结构介绍一下。这个框架一共有八个类,main.js,GameObjectManager.js,ApplicationManager.js,Player.js,RepeatingGameObject.js,AnimateGameObject.js,VisualGameObject.js,GameObject.js.
类之间的关系是:
main.js是这个框架的主要类,其中定义的一些全局变量,同时也是程序的一个入口,正如大多数程序一样,我们设置当页面一旦加载完毕就执行初始化函数,在初始化函数中创建了一个GameObjectManager的新的实例。你会注意到我们对新的GameObjectManager实例调用startupGameObjectManager 函数。startupClassName函数将会在后续多个类中见到,这一类函数有效的充当了类的构造函数,这样做的主要原因是javascript不支持重载函数,至少是不容易的,当你的类有不止一个构造函数时,这在实现上就存在较大的问题。所以这时将构造函数变形为其他方式的函数就变成了一个不错了选择,例如 startupClassName1, startupClassName2
var FPS =30;
var SECONDS_BETWEEN_FRAMES =1/ FPS;
var g_GameObjectManager =null;
var g_image =new Image();
g_image.src ="images/jsplatformer3-smiley.jpg";
var g_run_left =new Image();
g_run_left.src ="images/run_left.png";
var g_run_right =new Image();
g_run_right.src ="images/run_right.png";
var g_idle_left =new Image();
g_idle_left.src ="images/idle_left.png";
/** 被程序应用的图片
@type Image
*/
var g_idle_right =new Image();
g_idle_right.src ="images/idle_right.png";
var g_back0 =new Image();
g_back0.src ="images/jsplatformer4_b0.png";
var g_back1 =new Image();
g_back1.src ="images/jsplatformer4_b1.png";
var g_back2 =new Image();
g_back2.src ="images/jsplatformer4_b2.png";
window.onload = init;
function init() {
new GameObjectManager().startupGameObjectManager();
}
首先我们拥有一个GameObjectManager类。GameObjectManager是一个引擎类,它管理着Canvas的绘画操作和给GameObject分配事件。类的初始化工作将在startupGameObjectManager函数中完成。 在startupGameObjectManager函数中主要完成了下面三个功能:(1)对GameObjectManager实例的全局引用 g_GameObjectManager将被更新来指向新的实例。(2)涉及的canvas和绘图环境将会被存储,在这里还用到了游戏中的常用的双缓冲机制(双缓冲机制)。接着我们创建了一个startupApplicationManager 的新的实例并调用startupApplicationManager 函数初始化这个类。(3)最后我们重复的调用draw函数,这个函数被用作我们的渲染循环。 draw函数最开始清除了绘画环境,接着是对所有的game objects进行更新,最后绘画所有的game objects
this.draw = function () { // calculate the time since the last frame //计算从上一帧到现在的时间 var thisFrame = new Date().getTime(); var dt = (thisFrame - this.lastFrame) / 1000; this.lastFrame = thisFrame; // 清理绘画环境 if (this.canvasSupported) { this.backBufferContext2D.clearRect(0, 0, this.backBuffer.width, this.backBuffer.height); this.context2D.clearRect(0, 0, this.canvas.width, this.canvas.height); // 首先更新所用的game objects for (x in this.gameObjects) { //判断这个game object有没有update这个属性 if (this.gameObjects[x].update) { this.gameObjects[x].update(dt, this.backBufferContext2D, this.xScroll, this.yScroll); } } // 然后绘画所有的game objects for (x in this.gameObjects) { //判断game object这个对象有没有draw这个属性 if (this.gameObjects[x].draw) { this.gameObjects[x].draw(dt, this.backBufferContext2D, this.xScroll, this.yScroll); } } //这里就利用了双缓冲技术,将后台缓冲表现在canvas上面 this.context2D.drawImage(this.backBuffer, 0, 0); } };
在GameObjectManager还完成了对一些鼠标事件的绑定。
this.keyDown =function (event) {
for (x inthis.gameObjects) {
//首先判断该对象有没有keyDown的属性,如果有责执行对象所对应的函数
if (this.gameObjects[x].keyDown) {
this.gameObjects[x].keyDown(event);
}
}
}
this.keyUp =function (event) {
for (x inthis.gameObjects) {
if (this.gameObjects[x].keyUp) {
this.gameObjects[x].keyUp(event);
}
}
}
这两个类介绍完后,就轮到游戏框架的主要部分了,我在分析后得出了一个类的层次,由于才疏学浅,可能画得图有些不规范,望各位指出错误。
我们首先从ApplicationManager.js开始看,在GameObjectManager中有一句
// 创建一个新的ApplicationManager this.applicationManager = new ApplicationManager().startupApplicationManager();
实际上就是实例化一个ApplicationManager实例,并调用startupApplicationManager来初始化这个实例,在startupApplicationManager函数中又实例化了两个类,RepeatingGameObject和Player类。
RepeatingGameObject类:由上面的类图可以得知,RepeatingGameObject继承自VisualGameObject和GameObject两个类,在ApplicationManager中实例化RepeatingGameObject时调用了startupRepeatingGameObject函数,在这个函数中首先调用了VisualGameObject的初始化函数startupVisualGameObject,调用这个函数的目的是通过调用GameObject类的startupGameObject函数将这个对象加入到g_GameObjectManager数组中。
this.startupRepeatingGameObject =function (image, x, y, z, width, height, scrollFactor) {
this.startupVisualGameObject(image, x, y, z);
this.width = width;
this.height = height;
this.scrollFactor = scrollFactor;
returnthis;
}
this.startupVisualGameObject =function (/**image*/image, /**Number*/x, /**Number*/y, /**Number*/z) {
this.startupGameObject(x, y, z);
this.image = image;
returnthis;
}
this.startupGameObject =function (/**Number*/x, /**Number*/y, /**Number*/z) {
this.zOrder = z;
this.x = x;
this.y = y;
g_GameObjectManager.addGameObject(this);
returnthis;
}
在调用了startupVisualGameObject函数后,startupRepeatingGameObject函数还设置了一下属性,这里不得不说的是scrollFactor属性。scrollFactor属性是用来改变通过draw函数传递过来的xScroll,yScroll的值的,通过设置scroFactor比其他对象的小那么它的运动速度就更小,这样就会造成更加遥远的对象的假象。