第30讲 热点剖析(三):试试看,你也可以编写一款HTML5小游戏! 前两周,我分析了[HTML5的核心竞争力]以及[HTML5游戏的引擎]。选择好了HTML5引擎,我们就可以开始制作游戏了。

对于编写HTML5小游戏,你或许会很有兴趣,因为HTML5现在已然是一个潮流,而且利用引擎编写HTML5游戏已经变得相当方便。

如何选择一款引擎?

我选择的是比较容易上手的lufylengend引擎。为什么要选择这款引擎呢?因为它只需要下载一个压缩包,并且不需要特别繁琐的说明和设置就能直接上手,用作我们的教学示例是最合适的。

如果使用白鹭引擎或者Cocos-2d引擎这些比较有名的引擎,可能会有这些问题。

  • 这些引擎从工具到套件都非常成熟,你直接下载一个引擎启动器或者组件管理器,就可以一应俱全地在启动器里面下载,配置到默认路径。但是,这些工具拥有纷繁复杂的界面,你连上手都要费一段时间,更别说短时间内熟练使用并制作出一款游戏。
  • 这些引擎需要引入的库或者使用的方式极为系统,所以你需要系统地引入库文件,才可以使用。事实上我要做的示例,并不需要很多复杂的东西,你只需要跟我从头到尾走一遍,就能明白编写HTML5游戏是怎么回事。
  • 这些引擎需要别的工具支持,比如node.js。作为新手来说,光配置node.js就是一项比较麻烦的工作。所以我选择了lufylengend引擎这一个比较“单纯的”引擎来作为教学引擎。

几个简单的说明

你可以从这个地址下载最新版本:https://github.com/lufylegend/lufylegend.js/archive/lufylegend-1.10.1.zip 。下载下来的安装包大约有30M大,解压缩后有36M左右。解压缩后,我们会看到一系列的js文件。

我先对这些文件做一些说明,并且对最基础的编程流程做一个简单的梳理。

压缩包内包含lufylegend-版本号.js和lufylegend-版本号.min.js这两个完整版本,还有lufylegend-版本号.simple.js和lufylegend-版本号.simple.min.js这两个缩减版本,其中带min字样的是去除了回车和空格的压缩版本。如果你使用JavaScript编程,缩减版本对于你来说再熟悉不过的了。

其中,simple缩减版本与完整版本的区别在于,它将LBox2d、LQuadTree、LTransitionManager、LoadingSample1、LoadingSample2、LoadingSample3、LoadingSample4、LoadingSample5等几个类与HTML5引擎的常用部分分离,缩减了引擎的体积。如果需要用到被分离的部分功能的话,可以手动进行加载。

随后,可以在HTML代码中将legend引擎的库件引入。调用LInit函数,初始化库件。然后开始游戏代码的编写。剩下,你只需要有一款合适的IDE就可以开始编程了。

对制作HTML5游戏来说,你首先要做的是,将游戏场景在浏览器中呈现出来。把Windows的窗体,从系统客户端程序搬到浏览器上,呈现的窗体从可执行文件变成了浏览器。从这个角度讲,浏览器担负了应用层的工作,浏览器本身担负了解释程序,并且渲染的过程,所以,从理论上讲,相同的游戏类型和游戏内容,HTML5游戏的渲染速度是比不上客户端游戏的渲染速度的。

一起动手制作吧!

很凑巧的是,lufylengend引擎也拥有一款打飞机demo。我们只需要在lufylegend引擎目录的examples/demo下,找到barrage目录。

这一款打飞机的游戏,打开后是这个样子。

这和我们之前讲述的内容非常类似。那我就借解释一下这款游戏的代码,来教你制作。

在目录下,有一个index.html,这就是游戏的开始页面。在这个页面下,我们先来看一下部分代码。

如果你熟悉web编程,对于这些代码肯定非常熟悉。在开始的地方,我们看到载入的JavaScript代码是load_lufylegend.js,这个js文件包含在打飞机游戏的上一层目录,内部就只有一行代码。

document.write(‘ ‘);

我们看到,在这个js文件内,包含了lufylegend的原始引擎文件。至于为什么要这么做,为什么要使用两个文件包含引擎,是因为这样可以保持游戏代码的干净。如果你要修改引擎的包含路径,不需要修改游戏本体文件,只需要修改load_lufylegend.js包含路径即可。

而LGlobal.canTouch这段话的意思是,如果是移动版本的话,设置缩放模式为适应屏幕,并且为全屏,代码是: LSystem.screen(LStage.FULL_SCREEN)

最后,导入游戏脚本Main.js文件。

在Main.js里面,我们看到,它还包含了三个别的js文件,代码是这样。 imgData.push({type:”js”,path:”./js/Global.js”}); imgData.push({type:”js”,path:”./js/Bullet.js”}); imgData.push({type:”js”,path:”./js/Plain.js”});

它包含了一个共有类Global.js、子弹类Bullet.js以及飞机类Plain.js。之后的代码是这样的。

loadingLayer = new LoadingSample1(); addChild(loadingLayer);

其中LoadingSample1是“载入进度条”类,我们可以在下面的代码看到载入的实现。

LLoadManage.load( imgData, function(progress){ loadingLayer.setProgress(progress); }, function(result){ imglist = result; removeChild(loadingLayer); loadingLayer = null; gameInit(); } );

在载入结束后,就开始gameInit函数的调用,也就是游戏初始化。

function gameInit(event){ //游戏底层实例化 backLayer = new LSprite(); addChild(backLayer); ctrlLayer = new LSprite(); addChild(ctrlLayer);

LSprite是引擎的基本显示列表构造,里面包含了显示内容的列表节点,addChild就是将显示内容添加到节点列表。

//添加游戏背景 bitmapdata = new LBitmapData(imglist[“back”]); bitmap = new LBitmap(bitmapdata); backLayer.addChild(bitmap);

这几段代码就是将背景图片也添加到显示节点列表。

//得分显示 pointText = new LTextField(); pointText.color = “/#ffffff”; pointText.size = 20; pointText.text = point; backLayer.addChild(pointText)

这是一个得分的显示,所以需要新建一个文本类,并设置颜色和大小,并将之放到显示节点的列表。

//加入玩家 player = new Plain(“player”,0,200,600,[5]); backLayer.addChild(player);

我们需要新建一个玩家类。新建玩家,其实就是新建一个飞机类型,所以我们在这里看到一个plain类的创建。

这个创建函数的实现原型是这样的。 function Plain(name,belong,x,y,bullets)

你可能会觉得奇怪,Plain是什么意思,在它的demo里面,Plain是飞机的意思,然而可能是作者的一时疏忽或者是英文“捉急”,所以就把Plane写成了Plain。以下所有和飞机相关的代码都是Plain,虽然并不影响代码的运行,但是出于严谨考虑,我在这里更正一下,Plain等于Plane。

第一个参数是名字,第二个参数是飞机所属,表明是属于敌人还是玩家,随后两个参数(x,y)是飞机在2D画布上所显示的位置,最后一个bullets是子弹的数组。 //添加帧事件,开始游戏循环 backLayer.addEventListener(LEvent.ENTER_FRAME,onframe); //添加控制事件 backLayer.addEventListener(LMouseEvent.MOUSE_DOWN,ondown); backLayer.addEventListener(LMouseEvent.MOUSE_UP,onup); }

在初始化的最后,我们需要添加鼠标事件,将鼠标事件LMouseEvent的鼠标上下操作事件都放入到事件侦听函数内:addEventListener。

看到这里,你不禁会问,按照我们所教学的,游戏应该会有一个大循环来完成游戏的显示、操作等内容。那这个循环在哪里呢?

事实上这个循环,就在上面这串代码中。 backLayer.addEventListener(LEvent.ENTER_FRAME,onframe);

其中,LEvent为事件类。和传统客户端游戏不同,在HTML5游戏引擎中,循环采用了事件代码来完成,只要你在侦听器函数中注册了事件,都会一帧一帧不停地调度这个事件,以此达到循环的效果。

在这里,注册的侦听事件函数就是onframe函数。查看它的源代码你可以看到onframe函数的实现细节,我就不在这里进行阐述了。

小结

今天,我们使用lufylegend引擎剖析了HTML5游戏的编写方式。我来总结一下。

  • HTML5游戏的启动页是一个HTML文件。这个文件包含引擎的js文件。在其他别的引擎中,也是使用类似的方式来加载引擎。包含了引擎,就可以针对引擎所封装的接口进行游戏的开发。
  • HTML5游戏的循环方式和传统游戏的循环方式不同。由于HTML5游戏引擎绝大部分是使用JavaScript脚本编写的,而JS本身就是以事件驱动的方式来工作的,所以使用事件驱动是HTML5游戏引擎的一个很大特点。我们在事件侦听函数中注册一个事件函数,在这个函数内编写“游戏循环”内的代码,就能起到传统游戏循环的作用。
  • 在HTML5游戏中,我们几乎不需要关心图片的刷新或者清空操作。这些操作比之传统客户端游戏更为简洁,我们只需要关心游戏的图片呈现以及操作即可。

简单来说,HTML5游戏就是一种使用事件驱动模式并渲染在网页上的一种技术,省却了传统游戏的底层操控。你在制作的时候,可以把更多的关注点放在游戏逻辑和可玩性上。

最后,留一个小问题给你。

在类似这样的HTML5打飞机游戏中,碰撞检测是怎么做的呢?请结合我以前的讲过的内容给出一个答案。

欢迎留言说出你的看法。我在下一节的挑战中等你!

参考资料

https://learn.lianglianglee.com/%e4%b8%93%e6%a0%8f/%e4%bb%8e0%e5%bc%80%e5%a7%8b%e5%ad%a6%e6%b8%b8%e6%88%8f%e5%bc%80%e5%8f%91/%e7%ac%ac30%e8%ae%b2%20%e7%83%ad%e7%82%b9%e5%89%96%e6%9e%90%ef%bc%88%e4%b8%89%ef%bc%89%ef%bc%9a%e8%af%95%e8%af%95%e7%9c%8b%ef%bc%8c%e4%bd%a0%e4%b9%9f%e5%8f%af%e4%bb%a5%e7%bc%96%e5%86%99%e4%b8%80%e6%ac%beHTML5%e5%b0%8f%e6%b8%b8%e6%88%8f%ef%bc%81.md