
3.3 自定义场景
在3.1节已经介绍了导演、场景、精灵和图层的关系,并通过查看源码大致了解了启动一个场景所经过的流程。在3.2节实现菜单的内容中实际上已经自定义了一个场景MenuDemoScene,读者一定发现了,其实只是把HelloWorldScene的名字改成了MenuDemoScene,本节真正从头开始自定义一个场景,了解创建一个场景的所有过程。本节的所有代码均在MenuDemo项目中。

图3-5 开关菜单运行效果
3.3.1 创建场景脚本文件
根据Cocos中的编码习惯,一般把一个场景类放在一个JS脚本文件中,这有利于场景的统一管理。创建JS文件myScene.js,代码如下。

如代码所示,在脚本文件myScene.js中创建了一个场景MyScene,它继承自cc.Scene类,并调用了父类的_super()方法,所有创建的场景都需要继承自这个类,并调用_super()方法,这样才能拥有场景类的属性和方法。在Cocos2d-JS中,所有的JS类都会带有extend方法,子类可以通过extend方法实现继承关系,并在extend的参数中添加重写的代码。
3.3.2 添加图层到场景
只有一个场景是不行的,还需要在场景中放置负责元素显示和用户交互的图层,这样才能在游戏中展示画面。和添加场景一样,自定义的图层类需要继承自cc.Layer类,在构造方法中调用父类的_super()方法,在构造方法返回true,代码如下。

自定义图层时一定要记住调用父类的_super()方法,因为在Layer的构造方法中做了很多图层的初始化工作,如果不调用而直接重写构造方法,这些初始的过程将不会执行,并且会在控制台报如下错误。

从以上报错信息中可以看到在Layer类的初始化过程中出现了错误,导致游戏无法继续执行。
3.3.3 添加精灵到图层
当场景和图层都创建好时就可以往图层上添加游戏里缤纷多彩的元素了,那就是精灵,在Cocos中叫Sprite,在Cocos2d-JS中只需要创建cc.Sprite类就可以创建一个精灵。当然,如果用户对精灵有更多需求,也可以继承cc.Sprite类再次封装。
先添加一个精灵到创建好的图层中,如下代码所示,创建一个继承自Sprite的文本精灵控件cc.LabelTTF和一个以图片创建的Sprite精灵。

3.3.4 修改main.js入口场景
当自定义场景创建好之后,需要游戏在第一次进入时就加载用户自己创建的场景,从前面提到的内容可以知道,整个游戏的入口是main.js文件,第一个HelloWorldScene场景就是在这里加载的,可以直接把HelloWorldScene修改为自己创建的MyScene场景,代码如下。

如上面代码所示,已经在load resources的时候预加载了自己的MyScene场景,这样整个游戏的入口场景就是自定义场景了。
3.3.5 添加JS文件到project.json
或许到这里,读者认为一切就绪了,该写的代码都写了,但运行一下当前的项目,发现控制台报错了,报出如下错误信息。

从错误信息中发现Cocos并不认识所写的MyScene类。从main.js中可以看到,最后的代码cc.game.run()启动了游戏,再从run方法可以看到这是在CCBoot.js中实现的启动方法,当一层一层地查看源码后可以发现,引擎的启动类CCBoot.js解析了project.json,并加载了其中的配置,查看project.json文件如下。

第2章已经详细说明了project.json各项配置的作用,这里需要注意jsList这个配置,在CCBoot.js的启动过程中可以看到以下几行代码。

由此可知,项目中所有的JS文件都会通过jsList配置被引擎CCBoot.js所加载,因此在上面的项目运行中找不到MyScene也情有可原了,原来是没有在jsList中加入自定义的JS文件。添加myScene.js到jsList的代码如下。

这时再运行自定义的MyScene场景就不会有什么错了,能看到如图3-6所示的运行效果。

图3-6 自定义场景运行效果