module els { export class Scene extends GameObject { private static _instance: Scene; private editors: any; private _lastTick: number = 0; private _uigameobjectHash: any = {}; static TICK: number = 0.02; constructor() { super(); this._uigameobjectHash = {}; this._rendererComponent = new Renderer(); } static getInstance(): Scene { if (this._instance === undefined) this._instance = new Scene(); return this._instance; } get renderContainer() { return this._rendererComponent.renderer; } getGameobjectByUID(uid: number) { return this._uigameobjectHash[uid]; } //切换场景 switchScene(url: string, onComplete?: Function, thisObject?: any, debug?: boolean) { this.destroy(); RES.getResByUrl(url, (data) => { if (data) { this.editors = {}; this.name = data.name; let gameobjects:IGameObjectData[] = data.gameobjects; if (gameobjects) { let len: number = gameobjects.length; //执行初始化 for (let i: number = 0; i < len; i++){ this.parseGameObject(gameobjects[i]); } //呈现渲染 for (let i: number = 0; i < len; i++){ this.execRenderer(this._children[i]); } //---------------此时所有的游戏对象与组件都实始化完毕了--------------// //执行onAwake for (let i: number = 0; i < len; i++){ this.execAwake(this.children[i]); } //执行onStart for (let i: number = 0; i < len; i++){ this.execStart(this.children[i]); } window.dispatchEvent(new Event('componentsInstanceComplete')); } } this._lastTick = egret.getTimer(); //初始化渲染一次,这样避免等到下一帧才会进行渲染 this.onRender(); //开始执行帧频渲染 this.startRender(); //切换场景完成 if (onComplete) onComplete.apply(thisObject); }, thisObject, RES.ResourceItem.TYPE_JSON); } //解析游戏对象 private parseGameObject(objectdata: IGameObjectData) { let gameobject: GameObject = new GameObject(objectdata.name); gameobject.UID = objectdata.UID; //基于UID存储游戏对象 if (this._uigameobjectHash[objectdata.UID] === undefined) { this._uigameobjectHash[objectdata.UID] = gameobject; } //解析变换属性 for (let propkey in objectdata.transform) { gameobject[propkey] = objectdata.transform[propkey]; gameobject.transform[propkey] = objectdata.transform[propkey]; } //添加组件 let componentsdata:IComponentData[] = objectdata.components; let len: number = componentsdata.length; for (let j: number = 0; j < len; j++){ let compdata: IComponentData = componentsdata[j]; let compName: string = compdata.name; let compClass = egret.getDefinitionByName(compName); if (compClass) { let propdata = compdata.propertys; let compinst: Component = new compClass(); compinst.name = compName; compinst.gameobject = gameobject; for (let propkey in propdata) { compinst[propkey] = propdata[propkey]; } gameobject.addComponent(compinst); } else { console.error('游戏对象:'+gameobject.name+' 的组件:'+compName+" 无法被实例化!!"); } } //添加游戏对象 this.addChild(gameobject); //再计算游戏对象的子对象 let subgameobjects: IGameObjectData[] = objectdata.gameobjects; if (subgameobjects) { for (let i: number = 0, l: number = subgameobjects.length; i < l; i++){ this.parseGameObject(subgameobjects[i]); } } } private execAwake(gameobject:GameObject) { let components: Component[] = gameobject.components; if (!components) return; for (let i: number = 0, l: number = components.length; i < l; i++){ let component: Component = components[i]; component.onAwake(); component.onEnable(); } //执行子对象 let children: GameObject[] = gameobject.children; if (children) { for (let j: number = 0, jl: number = gameobject.children.length; j < jl; j++){ this.execAwake(gameobject.children[j]); } } } private execStart(gameobject: GameObject) { let components: Component[] = gameobject.components; if (components) { for (let i: number = 0, l: number = components.length; i < l; i++){ let component: Component = components[i]; if (!component.enabled) continue; component.onStart(); if (!component.enabled) component.onDisable(); } } //执行子对象 let children: GameObject[] = gameobject.children; if (children) { for (let j: number = 0, jl: number = gameobject.children.length; j < jl; j++){ this.execStart(gameobject.children[j]); } } } private execRenderer(gameobject: GameObject) { let rendererComponent: Renderer = gameobject.rendererComponent; if (!rendererComponent) return; let renderer = rendererComponent.renderer; if (!renderer) return; if (this.renderContainer instanceof egret.DisplayObjectContainer) { this.renderContainer.addChild(renderer); } renderer.touchEnabled = renderer.touchChildren = true; renderer.addEventListener(egret.TouchEvent.TOUCH_BEGIN, rendererComponent['onTouchEvent'].bind(rendererComponent), this); renderer.addEventListener(egret.TouchEvent.TOUCH_TAP, rendererComponent['onTouchEvent'].bind(rendererComponent), this); renderer.addEventListener(egret.TouchEvent.TOUCH_MOVE, rendererComponent['onTouchEvent'].bind(rendererComponent), this); renderer.addEventListener(egret.TouchEvent.TOUCH_RELEASE_OUTSIDE, rendererComponent['onTouchEvent'].bind(rendererComponent), this); renderer.addEventListener(egret.TouchEvent.TOUCH_ROLL_OUT, rendererComponent['onTouchEvent'].bind(rendererComponent), this); renderer.addEventListener(egret.TouchEvent.TOUCH_ROLL_OVER, rendererComponent['onTouchEvent'].bind(rendererComponent), this); //渲染子容器 if (!gameobject.children) return; for (let i: number = 0, l: number = gameobject.children.length; i < l; i++){ let subobject: GameObject = gameobject.children[i]; this.execRenderer(subobject); } } startRender(): void { if(!this.renderContainer.hasEventListener(egret.Event.ENTER_FRAME)) this.renderContainer.addEventListener(egret.Event.ENTER_FRAME, this.onRender, this); } stopRender(): void { this.renderContainer.removeEventListener(egret.Event.ENTER_FRAME, this.onRender, this); } private onRender(): void { let currentTick: number = egret.getTimer(); let tickTime: number = Scene.TICK; if (currentTick - this._lastTick >= tickTime) { for (let i: number = 0, l: number = this._children.length; i < l; i++){ let gameobject: GameObject = this._children[i]; gameobject.fixedUpdate(); } } for (let i: number = 0, l: number = this._children.length; i < l; i++){ let gameobject: GameObject = this._children[i]; gameobject['__render'](); } } destroy() { this.removeChildren(); } } }