[翻译]Akihabara 指南,第一部分:标题屏幕

翻序:Akihabara 是一个基于 HTML5 的 2D 游戏引擎,对 iphone 等移动平台有针对性优化。但是 Akihabara 本身文档并不十分充足,仅有一些例程参考。这个指南补充了这个不足,让学习 Akihabara 的陡峭曲线骤然平缓。在我作这个翻译的时候,作者已经完成了第四部分的编写。

原文:http://bostongamejams.com/akihabara-tutorials/akihabara-1/

Akihabara 指南,第一部分:标题屏幕

Darius Kazemi 编写于 2010 年五月 6 日

在这个连载的指南中,我们将向你演示如何使用基于 HTML5 和 JavaScript 的 Akihabara 框架来编写 8 向射击游戏。Akihabara 是一个利用 HTML5 功能帮助创建游戏的 Javascript 库。使用 HTML5 编写游戏最棒的事情是你可以在任何平台、任何支持 HTML5 的浏览器运行它。这包括 Chrome,Firefox,Safari 和 iPhone/iPad,WebOS 设备上的 WebKit 浏览器,或者其他移动平台。

在第一部分中,我们将逐步使用 Akihabara 的基本功能演示如何产生一个标题屏幕。

成品

这里查看本指南的成品:游戏“8by5”的标题屏幕。

安装 Akihabara

下载 Akihabara 1.1 并解压缩。Zip 文件中有一堆 Akihabara 的例子。那些值得等一会好好看看(也值得玩一下!),现在你只需要叫做 akihabara 的那个有一些按钮的图片和核心 JK 文件的目录。将 akihabara 目录放入项目目录中。然后用你喜欢的文本编辑器创建一个叫做 8by5.html 的空的文件,也放入项目目录中。最后,下载 font.pnglogo.png 保存它们到项目目录。项目目录现在应该包括 8by5.html,logo.png,font.png 和 akihabara 文件夹。

文档结构

打开 8by5.html 并创建基本的页面框架:

	<html>
	  <head>
	  </head>
	  <body></body>
	  <script>
	  </script>
	</html>

在 head 标签中包含所有需要用到的 Akihabara JS 文件,并且为不同的显示设备设置合适的缩放信息。游戏运行的所有代码放在 script 标签。保持 body 标签为空。

文档头

头部是引入所需的 JS 文件的地方。在 Akihabara 1.1 中,即便有部分确定不使用的功能,你也需要引入所有的 JS 文件。头部看起来应当像这样:

	<head>
	  <script type="text/javascript" src="akihabara/gbox.js"></script>
	  <script type="text/javascript" src="akihabara/iphopad.js"></script>
	  <script type="text/javascript" src="akihabara/trigo.js"></script>
	  <script type="text/javascript" src="akihabara/toys.js"></script>
	  <script type="text/javascript" src="akihabara/help.js"></script>
	  <script type="text/javascript" src="akihabara/tool.js"></script>
	  <script type="text/javascript" src="akihabara/gamecycle.js"></script>
	  <style>BODY { -webkit-user-select: none; margin: 0px }</style>
	  <meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;" />
	</head>

每个 script 标签告诉浏览器加载指定的 JavaScript 库。style 标签设置的 CSS 使得游戏在 WebKit(iPhone)中也可以渲染得很好。而 meta 标签设置了用于手机浏览器缩放的一些信息。

这里没有更多的头部信息了,所以让我们来看看游戏代码本身。

加载资源

从这里开始,我们开始讨论在 HTML 文档中,body 标签下面的主要的 script 标签里的代码。由于游戏主要是图像内容,我们需要在游戏开始前加载所有的资源。首先,我们创建游戏:

	var maingame;

这个作为存储所有游戏信息的全局变量放在脚本的最顶部,这样我们可以在任何函数中调用它。

现在,我们用一些魔法以确保资源在游戏前被加载。我们将使用 JavaScript 的 addEventListener 函数,像这样 window.addEventListener(eventType, functionName, useCapture);

这短代码让 JavaScript 在发生 eventType 类型的事件后,执行叫做 functionName 的函数。这里我们不关心 useCapture,只要知道这是一个布尔值,应当被设置为 false。在我们的游戏中,将使用的 eventType 叫做“load”。我们的事件监听像这样:

	window.addEventListener('load', loadResources, false);

这里是这段代码的作用:一旦浏览器完成加载 HTML 文档,它将执行 loadResources 函数。就这样。所以,现在我们应当定义 loadResources。下面的代码是完整的,先阅读一遍,然后我们一步一步来看。

	function loadResources() {
	  // 用 Akihabara 的默认设置初始化
	  // 标题 (显示在浏览器标题上)是我们传递给函数的参数
	  help.akihabaraInit('8by5');

	  // 这里告诉游戏在当前目录下寻找图像 ‘font.png’,并命名为 ‘font’
	  gbox.addImage('font', 'font.png');

	  // 对 logo 做同样的事情
	  gbox.addImage('logo', 'logo.png');

	  // 字体是通过图片来映射的,设置首字母,字母尺寸,一行的长度,还有水平和垂直的间隙
	  gbox.addFont({ id: 'small', image: 'font', firstletter: ' ', tileh: 8, tilew: 8, tilerow: 255, gapx: 0, gapy: 0 });

	  // ‘main’函数注册为回调:这也就是说“当我们完成了这些,调用它”
	  gbox.setCallback(main);

	  // 当所有的都完成了,‘loadAll’下载所有需要的资源。
	  gbox.loadAll();
	}

相当简单。我们使用了默认的初始化函数,help.akihabaraInit(…),并且传递了我们希望当作 HTML 文档标题的参数。调用 gbox.addImage(…) 加载字体和 logo。然后调用不能省略的,奇怪并且结构复杂的 gbox.addFont(…)。只需要知道这是“精灵字(sprite font)”,也就是说它看起来是一个数字、字幕和符号的大表格(在这个例子里是 font.png),并且被拆分成正确的顺序,以便知道哪个图像对应哪个字符。在我们的例子中,我们使用来自于 Akihabara 例子中的 8 x 8 像素的“精灵字”。

接下来的内容有些让人迷惑。调用了 gbox.setCallback(main),用于告诉 Akihabara 当 gbox.loadAll() 完成了资源加载,调用 main() 函数,以便开始游戏!最后,调用 gbox.loadAll() 加载资源并且调用刚才设置的回调函数。

现在,猛料来了

现在上路了,我们创建游戏循环并开始渲染到屏幕。首先,设置基本的 main 函数,这是所有游戏代码存在的地方。

	function main() {
	  gbox.setGroups(['game']);
	  maingame = gamecycle.createMaingame('game', 'game');

	  // 一会,我们将会在这里添加更多的代码

	  gbox.go();
	}

这个函数的第一行创建了一个叫做 “game” 的组。组用来确定游戏渲染的顺序。这个部分的指南只有一个组,所以我们并不需要过分担心它。但是最起码你要知道这是“渲染所有玩家组的内容在背景组之前,这样玩家总是在背景前面。”

接着一行用在最开始我们设置的全局变量 maingame 存储了一个具有状态机的游戏对象。它提供了游戏所必须的最基本的结构。调用 gamecycle.createMaingame 函数赋值 maingame 变量,使其保存所有的信息,如动画、主游戏、游戏结束、玩家死亡、游戏终止等等。我们传递了‘game’两次是为了让它知道主要操作的组,这些组就会有更高的优先权(由于我们只有一个组,所以我们还没有其他优先级)。

最后,我们调用 gbox.go() 告诉 Akihabara 执行游戏。

这时,你可以在浏览器里测试你的游戏,然后你会看到默认的标题屏幕:“GAME TITLE”。

这是因为 gamecycle.createMaingame 函数定义了默认的标题屏幕,并且足够聪明的知道标题屏幕是游戏首先应展示的。但是我们不需要默认的标题屏幕,谁会希望他们的游戏被叫做“GAME TITLE”呢?

自定义的标题屏幕

如果你深入到 gamecycle.js 中,你会发现一个叫做 gameTitleIntroAnimation() 的函数,它是真正渲染那个愚蠢的“GAME TITLE”的家伙。我们不会去直接修改 gamecycle.js —— 我们需要做的是重写这个函数,例如,用我们自己的函数替换默认的。幸运的是,在 JavaScript 中,重写一个函数你所需要做的只是使用“=”号重新定义它。将这些放在 gbox.go() 之前,替换 “我们将会在这里添加更多的代码”的注释:

	maingame.gameTitleIntroAnimation=function(reset) {
	  if (reset) {
	    toys.resetToy(this, 'rising');
	  }

	  gbox.blitFade(gbox.getBufferContext(),{ alpha: 1 });

	  toys.logos.linear(this, 'rising', {
	    image: 'logo',
	    sx:    gbox.getScreenW()/2-gbox.getImage('logo').width/2,
	    sy:    gbox.getScreenH(),
	    x:     gbox.getScreenW()/2-gbox.getImage('logo').width/2,
	    y:     20,
	    speed: 1
	  });
	};

if 条件仅仅在 reset 为 true 时执行,是介绍动画开始前的帧。这行说明在介绍动画开始前,让 toys 类了解一个叫做“rising”的本地数据,而rising 是 maingame 对象的一部分(这是第一个我们开始工作于 maingame 内部的地方)。

gbox.blitFade 函数仅仅是清除屏幕。toys.logos.linear 函数设置实际显示的动画。我们让他执行于 maingame 内(就像这个例子),使用我们另外设置的 rising 保存数据,然后传递一堆数据的一个结构给它。我们传递了图片(logo),sx 和 sy(logo 一开始初始的坐标)x 和 y (logo 最终结束的坐标),和移动的速度。告诉它图像叫做‘logo’,是最开始在 loadResources 中定义的。定义 sx 和 x 相同,这样图像在 y 坐标轴上移动,x 轴上不移动。设置屏幕宽度的一半减去 logo 宽度的一半,用来让 logo 显示在屏幕中间。然后定义 sy 跟屏幕高度相同(使得图片的顶部贴着屏幕的下边,使其不可见),y 等于 20。这使得 logo 从底部升起,直到屏幕上方 20 像素下的位置。

Hello, World

好,接下来!你可以在浏览器中打开这个 HTML 文件运行这个游戏,应当看到类似这样的内容。

你会发现,你可以按键盘上的“Z”键(在游戏中被绑定为“A”键)选择难度,然后游戏进入黑屏。这是因为 maingame 控制着游戏的整个流程,它自动产生了难度选择,然后让你进入到游戏中。由于我们还未对游戏本身进行任何的编码,所以除了黑暗,你看不到其他任何内容。

Akihabara 指南目录

Comments

4 responses to “[翻译]Akihabara 指南,第一部分:标题屏幕”

  1. […] reminiscences, some memories Just another boring day « [翻译]Akihabara 指南,第一部分:标题屏幕 3Jul [翻译]Akihabara 指南,第二部分:精灵的移动 […]

  2. […] [翻译]Akihabara 指南,第一部分:标题屏幕 […]

  3. […] 第一部分: 标题屏幕 第二部分: 移动一个精灵 第三部分: 基本的地图 第四部分: 卷动地图 […]

  4. Coki Avatar
    Coki

    我是在原文博客上看到你的回复然后连接过来的,非常开心国内也有人在研究这个啊!呵呵~非常感谢!以后还请多多指教了!
    能不能介绍一下您现在的研究成果了?或者介绍一下您看过的资料给我?

Leave a Reply

Your email address will not be published. Required fields are marked *