这是我参与更文挑战的第8天,活动详情查看: 更文挑战
前言
游戏场景切换是很多开发者在开发过程中必不可少的一个环节,当项目中有两个或两个以上的游戏场景时,怎样管理这些场景,能够使它们之间的切换更加方便呢?今天就为大家介绍场景切换管理类的切换方法和单例的使用方法。备注本篇文章使用的是 egret 引擎,语言是TS。
场景管理
1.首先创建一个所有场景的父类Scene
Scene类主要是为了方便管理场景,此类是一个抽象类,子类必须继承此类并实现onComplete()抽象方法才能进行场景的切换。
// egret引擎
abstract class Scene extends eui.Component{
public constructor() {
super();
// 监听组件创建完毕 也就是场景的外观创建完毕
this.addEventListener(eui.UIEvent.CREATION_COMPLETE,this.onComplete,this);
}
protected abstract onComplete();
}
复制代码
2.场景管理器SceneManger
所有场景的切换,弹出关闭都是由SceneManger类来控制,这样方便对场景进行统一管理。
①.使用单例模式
SceneManger类需要使用到单例模式,单例模式是一种常用的软件设计模式,其定义是单例对象的类只能允许一个实例存在。
class SceneManager {
private static _manager:SceneManager;
public static get Instance(){
if( SceneManager._manager==null){
SceneManager._manager = newSceneManager();
}
return SceneManager._manager;
}
public constructor() {
}
}
复制代码
②.控制场景切换的方法
changeScene()方法:当舞台上有场景时,会先将当前场景从舞台移除,再添加新场景到舞台上;当舞台还没有场景时,会直接添加到舞台上。
public rootLayer:eui.UILayer;//起始场景
private currentScene:Scene;//需要显示的场景
private pop_scene:Scene;//弹出场景层
//切换场景
public changeScene(s:Scene){
if(this.currentScene){
this.rootLayer.removeChild(this.currentScene);
this.currentScene = null;
}
this.rootLayer.addChild(s);
this.currentScene = s;
}
复制代码
③.弹出场景和关闭弹出场景
弹出场景不会使底层场景消失,而是直接在当前场景上再显示一个场景出来(主要用于设置面板之类的)。在弹出场景时先调用了一次关闭场景层,防止还没关闭场景层又点击了弹出场景层。
//弹出场景层
public pushScene(s:Scene){
this.popScene();
if(!this.pop_scene){
this.rootLayer.addChild(s);
this.pop_scene = s;
}
}
//关闭场景层
public popScene(){
if(this.pop_scene){
this.rootLayer.removeChild(this.pop_scene);
this.pop_scene = null;
}
}
复制代码
在入口文件 Main.ts 中引入场景管理类 SceneManage。首先将Main.ts中createGameScene()方法中的代码删掉,再调用下面的方法,将this定为起始场景(舞台)。
SceneManager.Instance.rootLayer = this;
复制代码
使用eui创建三个场景和一个弹出场景,eui创建的三个场景,分别为:
- 开始场景(StartScene.exml),
- 游戏场景(GameScene.exml),
- 结束场景(EndScene.exml)。
这里我们可以使用eui创建弹出层,eui文件创建完成之后需在终端中输入egret build编译项目,这时会在default.thm.json 文件中生成皮肤对应的skinName。
开始场景(StartScene.ts)、游戏场景(GameScene.ts),结束场景(EndScene.ts)对应的TS文件如图。
由于StartScene类继承自Scene抽象类,所以在此类中必须得实现onComplete()方法,示例代码如下:
class StartScene extends Scene {
public btn_tc: eui.Label;//弹出层按钮
public btn_qh2: eui.Label;//切换场景
public constructor() {
super();
//指定开始场景对应的皮肤文件StartScene.exml
this.skinName ="resource/game/StartScene.exml";
}
//实现父类的onComplete方法
protected onComplete() {
//设置两个Label为可点击
this.btn_tc.touchEnabled =true;
this.btn_qh2.touchEnabled =true;
//添加点击事件
this.btn_tc.addEventListener(egret.TouchEvent.TOUCH_TAP, this.onTaptc,this);
this.btn_qh2.addEventListener(egret.TouchEvent.TOUCH_TAP,this.onTapqiehuan, this);
}
//弹出场景
private onTaptc(){
}
private onTapqiehuan(){
}
}
复制代码
游戏场景(GameScene),结束场景(EndScene)对应的ts文件基本与开始场景一致。游戏初始化时在Main.ts中的createGameScene()方法添加开始游戏场景(StartScene),切换场景时调用SceneManager.Instance.changeScene()即可;注意:此处参数为一个场景实例。
let s1:StartScene = new StartScene();
SceneManager.Instance.changeScene(s1);
复制代码
弹出场景层方法。在对应的点击事件中调用pushScene()方法。
let tc:Tanchu = new Tanchu();
SceneManager.Instance.pushScene(tc);//添加场景弹出层
复制代码
如果需要关闭弹出场景层,在弹出场景层的类中调用popScene()方法。
SceneManager.Instance.popScene();//移除场景层
复制代码
总结
我在这篇文章只是介绍了场景的引擎场景管理,纵观市场上的游戏,基本都是单例设计模式,无论是laya或白鹭,或cocos,这些框架里的场景管理都是创建场景管理类(应该没有人每次都new和remove吧),但是框架本身没有考虑UI资源的管理类和切换,而这些最消耗内存和性能的部分交给了开发者去做。场景类、UI类的资源管理和性能优化。