在编程教程中,经常看到基于已完成项目的示例。这本身并没有什么问题,但作者往往没有提供清晰的框架代码,这些代码没有特定于他们游戏的冗余代码。他们可能会保留自己的类和绘制代码,但认为这些代码最好放在自己的教程中,解释如何构建那个游戏。因此,本教程的目的是提供一个最低限度的代码基础,供在此基础上构建。
将从<canvas>
标签开始。这将在屏幕中心放置一个800x600的画布。"id"选项很重要,因为它是JavaScript文件将用来与之交互的名称。
如果浏览器不支持HTML5,<canvas>
标签之间的文本可以替换为希望显示的任何内容。如果无法在画布上绘制,那么画布就没有意义,因此为游戏创建一个JavaScript文件(叫做xong.js)。需要页面能够调用这个脚本,所以让在头部包含它。
现在变量和类定义是页面的全局命名空间的一部分。据所知,没有办法将代码放入不同的命名空间,所以在多个文件中命名变量、函数等时要小心;在一个文件中定义变量X,然后在另一个文件中命名变量X,当包含这两个文件时,会产生奇怪的结果。
让看看一个基本的游戏循环,放在js文件中。
var _canvas = null;
var _buffer = null;
var canvas = null;
var buffer = null;
function Game(){
this.gameLoop = null;
var self = this;
this.Init = function(){
_canvas = document.getElementById('canvas');
if (_canvas && _canvas.getContext){
canvas = _canvas.getContext('2d');
_buffer = document.createElement('canvas');
_buffer.width = _canvas.width;
_buffer.height = _canvas.height;
buffer = _buffer.getContext('2d');
buffer.strokeStyle = "rgb(255, 255, 255)";
buffer.fillStyle = "rgb(255, 255, 255)";
buffer.font = "bold 25px sans-serif";
}
}
this.Run = function(){
if (canvas != null){
self.gameLoop = setInterval(self.Loop, 50);
}
}
this.Update = function(){
// Update Objects
}
this.Draw = function(){
buffer.clearRect(0, 0, _buffer.width, _buffer.height);
canvas.clearRect(0, 0, _canvas.width, _canvas.height);
// Draw Code
canvas.drawImage(_buffer, 0, 0);
}
this.Loop = function(){
self.Update();
self.Draw();
}
}
这段代码相当长,所以将逐块解释。在顶部有4个变量。前两个是接口(画布接口和缓冲区接口),后两个是将用来实际与画布上下文和缓冲区上下文交互的变量。
接下来定义了一个名为Game的类。如果像一样对JavaScript不熟悉,那么“一切都是函数”的概念一开始可能会有点令人困惑。
在类内部,有两个变量和五个函数。gameLoop变量在将游戏循环设置为定期运行后持有游戏循环,稍后会解释。
Init函数应该在调用Run之前调用;它设置了画布、缓冲区、对象等。首先,它通过其id从页面中获取画布上下文。接下来确保它成功完成了这一点,并且可以与画布交互。
将上下文存储到canvas变量中,并对屏幕缓冲区执行相同的步骤,确保使其大小相同。最后可以为缓冲区设置一些选项,如font、fillStyle(填充原语的颜色)和strokeStyle(空心原语的颜色)。
Run函数相当简单。如果画布成功加载,将Loop函数设置为每50毫秒调用一次。将其存储在一个变量中,有点像一个线程。
Update函数是更新游戏逻辑的地方。
Draw不需要太多解释。首先清除缓冲区和画布,然后在缓冲区上绘制内容,最后将缓冲区绘制到画布上。
最后有Loop函数,它简单地调用Update和Draw函数。
最后一步是将所有内容放在一起。