laya2.x的场景Scene和脚本Script

laya2.x UI类结构

新增加了一个Scene - > Sprite, Scene只有一个子类就是View,Dialog仍然继承View。

- Component也出现了变化:Component implements ISingletonElement, IDestroy。现在的Component变成了一个脚本的基类,它的子类有相对布局插件

   Widget,Script,CommonScript。之前的Component现在被重命名为UIComponent。

AnimationPlayerBase被重命名成为AnimationBase

 

laya1.0创建的UI:xxUI->View->Box->Component->Sprite

laya2.0创建的UI:xxUI->View->Scene->Sprite(创建时也可以选成Scene类型,xxUI->Scene->Sprite)

需要说明一下,现在创建的UI文件后缀名统一为.scene。

 

laya2.x的Scene类

 1 public function open(closeOther:Boolean = true, param:*=null):void{
 2   if(closeOther) closeAll();
 3   root.addChild(scene);
 4   onOpened(param);  
 5 }
 6 public function close():void{
 7   if(autoDestroyAtClosed) this.destory();
 8   else removeSelf();
 9   onClosed();  
10 }
11 
12 override public function destroy(destroyChild:Boolean = true):void{
13   _idMap = null;
14   super.destroy(destroyChild);
15   var list:Array = Scene.unDestroyedScenes;
16   for(var i:int = 0, n:int = list.length; i<n;i++){
17       if(lsit[i]===this){
18         list.splice(i,1);
19         return;
20       }
21    }
22 }
23 
24 //创建后,还未被销毁的场景列表,方便查看还未被销毁的场景列表,方便内存管理,本属性只读,请不要直接修改
25 public static var unDestroyedScenes:Array = [];
26 public function Scene(){
27    this._setBit(Const.NOT_READY,true);
28    unDestroyedScenes.push(this);
29    this._scene = this;
30    createChildren();
31 }
32 
33 public static function open(url:String,closeOther:Boolean = true,  complete:Handler = null, param:*=null):void{
34   load(url,Handler.create(null,_onSceneLoaded,[closeOther,complete,param]));
35 }
36 
37 private static function _onSceneLoaded(closeOther:Boolean,complete:Handler,param:*,scene:Scene):void{
38     scene.open(closeOther,param);
39     if (complete) complete.runWith(scene);
40 }
41 
42 public static funcion close(url:String,name:String= ""):Boolean{
43    var flag:Boolean = false;
44    var list:Array  = Scene.unDestroyedScenes;
45     for (var i:int=0,n:int=list.length;i<n;i++){
46      var scene:Scene = list[i];
47      if (scene.parent && scene.url === url && scene.name == name){
48     scene.close();
49     flag = true;
50        }
51     }
52     return flag;
53 }
54 
55 public static function closeAll():void {
56     var root:Sprite = Scene.root;
57     for (var i:int = 0, n:int = root.numChildren;i<n;i++){
58       var scene:Scene = root.getChildAt(0) as Scene;
59       if (scene is Scene) scene.close();
60    }
61 }
62 
63 public static function destroy(url:String,name:String=""):Boolean{
64   var flag:Boolean = false;
65   var list:Array = Scene.unDestroyedScenes;
66   for (var i:int=0,n:int=list.length;i<n;i++){
67        var scene:Scene = list[i];
68        if (scene.url ===url && scene.name == name){
69          scene.destroy();
70          flag = true;
71        }
72    }
73     return flag;
74 }
75 
76 public static function get root():Sprite{
77      if(!_root){
78        _root = Laya.stage.addChild(new Sprite()) as Sprite;
79        _root.name = "root";
80        Laya.stage.on("resize",null,resize);
81        function resize():void{
82            _root.size(Laya.stage.width, Laya.stage.height);
83            _root.event(Event.RESIZE);
84            }
85       resize();
86       }
87       return _root;
88 }

1. autoDestroyAtClosed : 场景被关闭后,是否自动销毁(销毁节点和使用到的资源),默认为false

在close方法中,可以看到if (autoDestroyAtClosed) this.destroy();

2.在open方法中,看到root.addChild(scene);,而在get root中看到_root = Laya.stage.addChild(new Sprite()) as Sprite,这说明所有打开的Scene都被添加到一个叫root的Sprite容器里,这个容器是直接放在stage上了。


3.参考一下官方例子中如何使用scene的:

1 static startScene:any = "test/Test2View.scene";
2 Laya.Scene.open(GameConfig.startScene);

这里直接调用static open方法,在里面调用了load方法

public static function load(url:String,complete:Handler = null):void{
      Laya.loader.resetProgress();
      var loader:SceneLoader = new SceneLoader();
      loader.on(Event.COMPLETE,null,create);
      loader.load(url);
      
      function create():void {
        var obj:Object = Loader.getRes(url);
        if(!obj) throw "Can not find scene:" + url;
        if(!obj.props) throw "Scene data is error:" + url;
         var runtime:String = obj.props.runtime ? obj.props.runtime : obj.type;
         var clas:*=ClassUtils.getClass(runtime);
         if(obj.props.renderType=="instance"){
                var scene:Scene = clas.instance || (clas.instance = new clas());
                } else {
                 scene = new clas();
               }
         if (scene && scene is Node){
               scene.url = rul;
               if (!scene._getBit(Const.NOT_READY)) complete.runWith(scene);
               else{
                    scene.on("onViewCreated",null,functon():void{
                          complete && complete.runWith(scene)
                          })
                          scene.createView(obj);
                     }
           }else{
                throw "Can not find scene:" + runtime;
            }
       }
}

 

 

牵涉到SceneLoader类

public static const LoadableExtensions:Object = {"scene":Loader.JSON}

这个映射会把test/Test2View.scene转化为去加载相应的json文件

 

Dialog

laya2.x创建的Dialog:xxDialogUI - > Dialog - > View - > Scene - > Sprite

Dialog会把Scene中默认的open方法覆盖掉,转交给DialogManager处理

//Dialog:
override public function open(closeOther:Boolean = true, param:* = null):void {
    _dealDragArea();
    _param=param;
    manager.open(this, closeOther, isShowEffect);
    manager.lock(false);
}

//DialogManager:
public class DialogManager extends Sprite

public function DialogManager() {
    this.mouseEnabled = maskLayer.mouseEnabled = true;
    this.zOrder = 1000;
    
    Laya.stage.addChild(this);
    Laya.stage.on(Event.RESIZE, this, _onResize);
    if (UIConfig.closeDialogOnSide) maskLayer.on("click", this, _closeOnSide);
    _onResize(null);
}

public function open(dialog:Dialog, closeOther:Boolean = false, showEffect:Boolean=false):void {
    if (closeOther) _closeAll();
    if (dialog.isPopupCenter) _centerDialog(dialog);
    addChild(dialog);
    if (dialog.isModal || this._getBit(Const.HAS_ZORDER)) Laya.timer.callLater(this, _checkMask);
    if (showEffect && dialog.popupEffect != null) dialog.popupEffect.runWith(dialog);
    else doOpen(dialog);
    event(Event.OPEN);
}

 

总结:可以把Scene看做是官方提供的一个场景管理器,像closeOther,closeAll,onOpened,onClosed都是很实用的。

实例:添加按钮切换场景

LayaAir2.x开发思路为组件化,脚本化,场景管理开发,项目采用scene管理方式,来管理场景,LayaAir已经对scene做了一系列方案,使得开发者无需考虑场景,关卡,页面的资源,内存管理,只需要单纯的调用接口,管理场景,其它的交给引擎去做,只需要专注游戏逻辑开发即可。

1.先新建一个脚本

 

 

 

2.在Start.scene中放一个按钮,就可以添加组件了,这样运行时,点击按钮,就会触发onClick方法打开box2d.scene场景。

 

 

 

3.按F9设置启动场景为Start.scene,现在运行后就能看到场景切换效果了。

 

 

 

4.在GameConfig的init方法中就可以看到

1 static init(){
2     var reg: Function = Laya.ClassUtils.regClass;
3     reg("script/Start.ts",Start);
4 }
5 //ClassUtils:
6 public static function regClass(className:String, classDef:*):void {
7     _classMap[className] = classDef;
8 }

 

 

注:参考文章https://www.jianshu.com/p/5701f9f854fa

 

posted @ 2022-02-14 12:10  举个栗子走天下  阅读(780)  评论(0编辑  收藏  举报