@combos-fun/engine 0.0.3 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/engine.cjs.js +54 -23
- package/dist/engine.cjs.js.map +1 -1
- package/dist/engine.cjs.prod.js +1 -1
- package/dist/engine.d.ts +13 -4
- package/dist/engine.esm.js +54 -23
- package/dist/engine.esm.js.map +1 -1
- package/package.json +2 -2
package/dist/engine.cjs.prod.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var e=require("eventemitter3"),t=require("lodash-es"),s=require("tslib"),r=require("@combos-fun/inspector-decorator"),o=require("resource-loader");function n(e){return e&&e.__esModule?e:{default:e}}var a,i=n(e);class c extends i.default{constructor(e){super(),this.started=!1;const t=this.constructor;this.name=t.componentName,this.__componentDefaultParams=e}}exports.OBSERVER_TYPE=void 0,(a=exports.OBSERVER_TYPE||(exports.OBSERVER_TYPE={})).ADD="ADD",a.REMOVE="REMOVE",a.CHANGE="CHANGE";const h={},p={},m={},d={};function l(e,t){h[e.gameObject.id]||(h[e.gameObject.id]={});const s=h[e.gameObject.id],r=e.name+"_"+t.join(",");if(s[r])return s[r];const o=t.length-1;let n=e;for(let e=0;e<o;e++)n=n[t[e]];return s[r]={property:n,key:t[o]},s[r]}function u({systemName:e,componentName:t,component:s,prop:r,type:o}){p[e]?.componentObserver?.add({component:s,prop:r,type:o,componentName:t})}function y({obj:e,key:s,prop:r,component:o,componentName:n}){if(void 0!==e)if(s in e){if(Object.defineProperty(e,`_${s}`,{enumerable:!1,writable:!0,value:e[s]}),r.deep&&t.isObject(e[s]))for(const t of Object.keys(e[s]))y({obj:e[s],key:t,prop:r,component:o,componentName:n});Object.defineProperty(e,s,{enumerable:!0,set(a){e[`_${s}`]!==a&&(e[`_${s}`]=a,function({prop:e,component:s,componentName:r}){for(const o in m){const n=(m[o]||{})[r];n&&(n.findIndex(s=>t.isEqual(s,e))>-1&&u({systemName:o,componentName:r,component:s,prop:e,type:exports.OBSERVER_TYPE.CHANGE}))}}({prop:r,component:o,componentName:n}))},get:()=>e[`_${s}`]})}else console.error(`prop ${s} not in component: ${n}, Can not observer`)}function f(e,t=e.name){for(const s in m){(m[s]||{})[t]&&p[s]?.componentObserver?.add({component:e,type:exports.OBSERVER_TYPE.REMOVE,componentName:t})}!function(e){e.gameObject&&delete h[e.gameObject.id]}(e)}class g extends c{constructor(){super(...arguments),this.name="Transform",this._parent=null,this.inScene=!1,this.children=[],this.position={x:0,y:0},this.size={width:0,height:0},this.origin={x:0,y:0},this.anchor={x:0,y:0},this.scale={x:1,y:1},this.skew={x:0,y:0},this.rotation=0}static{this.componentName="Transform"}init(e={}){const t=["position","size","origin","anchor","scale","skew"];for(const s of t)Object.assign(this[s],e[s]);this.rotation=e.rotation||this.rotation}set parent(e){e?e.addChild(this):this.parent&&this.parent.removeChild(this)}get parent(){return this._parent}addChild(e){if(e.parent===this){const t=this.children.findIndex(t=>t===e);this.children.splice(t,1)}else e.parent&&e.parent.removeChild(e);e._parent=this,this.children.push(e)}removeChild(e){const t=this.children.findIndex(t=>t===e);t>-1&&(this.children.splice(t,1),e._parent=null)}clearChildren(){this.children.length=0}}s.__decorate([r.type("vector2"),r.step(1)],g.prototype,"position",void 0),s.__decorate([r.type("size"),r.step(1)],g.prototype,"size",void 0),s.__decorate([r.type("vector2"),r.step(.1)],g.prototype,"origin",void 0),s.__decorate([r.type("vector2"),r.step(.1)],g.prototype,"anchor",void 0),s.__decorate([r.type("vector2"),r.step(.1)],g.prototype,"scale",void 0),s.__decorate([r.type("vector2"),r.step(.1)],g.prototype,"skew",void 0),s.__decorate([r.type("number"),r.step(.1)],g.prototype,"rotation",void 0);let E=0;class _{constructor(e,t){this._componentCache={},this.components=[],this.destroyed=!1,this._name=e,this.id=++E,this.addComponent(g,t)}get transform(){return this.getComponent(g)}get parent(){return this.transform&&this.transform.parent&&this.transform.parent.gameObject}get name(){return this._name}set scene(e){if(this._scene===e)return;const t=this._scene;if(this._scene=e,this.transform&&this.transform.children)for(const t of this.transform.children)t.gameObject.scene=e;e?e.addGameObject(this):t&&t.removeGameObject(this)}get scene(){return this._scene}addChild(e){if(e&&e.transform&&e!==this){if(!(e instanceof _))throw new Error("addChild only receive GameObject");if(!this.transform)throw new Error(`gameObject '${this.name}' has been destroy`);e.transform.parent=this.transform,e.scene=this.scene}}removeChild(e){return e instanceof _&&e.parent&&e.parent===this?(e.transform.parent=null,e.scene=null,e):e}addComponent(e,t){if(this.destroyed)return;const s=function(e){return e instanceof c?e.name:e instanceof Function?e.componentName:void 0}(e);if(this._componentCache[s])return;let r;if(e instanceof Function)r=new e(t);else{if(!(e instanceof c))throw new Error("addComponent recieve Component and Component Constructor");r=e}if(r.gameObject)throw new Error(`component has been added on gameObject ${r.gameObject.name}`);return r.gameObject=this,r.init&&r.init(r.__componentDefaultParams),function(e,t=e.name){for(const s in m)(m[s]||{})[t]&&p[s]?.componentObserver?.add({component:e,type:exports.OBSERVER_TYPE.ADD,componentName:t})}(r,r.name),function(e,t=e.name){if(t&&d[t]){if(!(e&&(s=e,s&&s.constructor&&"componentName"in s.constructor)))throw new Error("component param must be an instance of Component");var s;if(!e.gameObject||!e.gameObject.id)throw new Error("component should be add to a gameObject");for(const s of d[t]){const{property:r,key:o}=l(e,s.prop);y({obj:r,key:o,prop:s,component:e,componentName:t})}}}(r,r.name),this.components.push(r),this._componentCache[s]=r,r.awake&&r.awake(),r}removeComponent(e){let t;if("string"==typeof e?t=e:e instanceof c?t=e.name:e.componentName&&(t=e.componentName),"Transform"===t)throw new Error("Transform can't be removed");return this._removeComponent(t)}_removeComponent(e){const t=this.components.findIndex(({name:t})=>t===e);if(-1===t)return;const s=this.components.splice(t,1)[0];return delete this._componentCache[e],delete s.__componentDefaultParams,s.onDestroy&&s.onDestroy(),f(s,e),s.gameObject=void 0,s}getComponent(e){let t;return"string"==typeof e?t=e:e instanceof c?t=e.name:e.componentName&&(t=e.componentName),void 0!==this._componentCache[t]?this._componentCache[t]:void 0}remove(){if(this.parent)return this.parent.removeChild(this)}destroy(){if(this.transform){Array.from(this.transform.children).forEach(({gameObject:e})=>{e.destroy()}),this.remove(),this.transform.clearChildren();for(const e in this._componentCache)this._removeComponent(e);this.components.length=0,this.destroyed=!0}else console.error("Cannot destroy gameObject that have already been destroyed.")}}class b{constructor(){this.events=[]}add({component:e,prop:s,type:r,componentName:o}){if(r===exports.OBSERVER_TYPE.REMOVE){if(this.events.find(t=>t.component===e&&t.type===exports.OBSERVER_TYPE.ADD))return void(this.events=this.events.filter(t=>t.component!==e));this.events=this.events.filter(t=>t.component!==e)}const n=this.events.findIndex(o=>o.component===e&&t.isEqual(o.prop,s)&&o.type===r);n>-1&&this.events.splice(n,1),this.events.push({gameObject:e.gameObject,component:e,prop:s,type:r,componentName:o})}getChanged(){return this.events}get changed(){return this.events}clear(){const e=this.events;return this.events=[],e}}class R{constructor(e){this.started=!1,this.componentObserver=new b,this.__systemDefaultParams=e;const t=this.constructor;this.name=t.systemName}destroy(){this.componentObserver=null,this.__systemDefaultParams=null,this.onDestroy?.()}}const T=function(){let e=null;return e=Date.now?Date.now:()=>(new Date).getTime(),e}(),O={originTime:0,playbackRate:1};class S{constructor(e,t){e instanceof S&&(t=e,e={}),e=Object.assign({},O,e),t&&(this._parent=t),this._createTime=T(),this._timeMark=[{globalTime:this.globalTime,localTime:-e.originTime,entropy:-e.originTime,playbackRate:e.playbackRate,globalEntropy:0}],this._parent&&(this._timeMark[0].globalEntropy=this._parent.entropy),this._playbackRate=e.playbackRate}get globalTime(){return this.parent?this.parent.currentTime:T()-this._createTime}get parent(){return this._parent}get lastTimeMark(){return this._timeMark[this._timeMark.length-1]}markTime({time:e=this.currentTime,entropy:t=this.entropy,playbackRate:s=this.playbackRate}={}){const r={globalTime:this.globalTime,localTime:e,entropy:t,playbackRate:s,globalEntropy:this.globalEntropy};this._timeMark.push(r)}get currentTime(){const{localTime:e,globalTime:t}=this.lastTimeMark;return e+(this.globalTime-t)*this.playbackRate}set currentTime(e){this.markTime({time:e})}get globalEntropy(){return this._parent?this._parent.entropy:this.globalTime}get entropy(){const{entropy:e,globalEntropy:t}=this.lastTimeMark;return e+Math.abs((this.globalEntropy-t)*this.playbackRate)}set entropy(e){if(this.entropy>e){const t=this.seekTimeMark(e);this._timeMark.length=t+1}this.markTime({entropy:e})}fork(e){return new S(e,this)}seekGlobalTime(e){const t=this.seekTimeMark(e),s=this._timeMark[t],{entropy:r,playbackRate:o,globalTime:n}=s;return n+(e-r)/Math.abs(o)}seekLocalTime(e){const t=this.seekTimeMark(e),s=this._timeMark[t],{localTime:r,entropy:o,playbackRate:n}=s;return n>0?r+(e-o):r-(e-o)}seekTimeMark(e){const t=this._timeMark;let s=0,r=t.length-1;if(e<=t[s].entropy)return s;if(e>=t[r].entropy)return r;let o=Math.floor((s+r)/2);for(;o>s&&o<r;){if(e===t[o].entropy)return o;e<t[o].entropy?r=o:e>t[o].entropy&&(s=o),o=Math.floor((s+r)/2)}return s}get playbackRate(){return this._playbackRate}set playbackRate(e){e!==this.playbackRate&&(this.markTime({playbackRate:e}),this._playbackRate=e)}get paused(){if(0===this.playbackRate)return!0;let e=this.parent;for(;e;){if(0===e.playbackRate)return!0;e=e.parent}return!1}}const k={autoStart:!0,frameRate:60};class v{constructor(e){e=Object.assign({},k,e),this._frameCount=0,this._frameDuration=1e3/e.frameRate,this.autoStart=e.autoStart,this.frameRate=e.frameRate,this.timeline=new S({originTime:0,playbackRate:1}),this._lastFrameTime=this.timeline.currentTime,this._tickers=new Set,this._requestId=null,this._ticker=()=>{this._started&&(this._requestId=requestAnimationFrame(this._ticker),this.update())},this.autoStart&&this.start()}update(){const e=this.timeline.currentTime,t=e-this._lastFrameTime;if(t>=this._frameDuration){const s=e-t%this._frameDuration,r=s-this._lastFrameTime;this._lastFrameTime=s;const o={deltaTime:r,time:s,currentTime:s,frameCount:++this._frameCount,fps:Math.round(1e3/r)};for(const e of this._tickers)"function"==typeof e&&e(o)}}add(e){this._tickers.add(e)}remove(e){this._tickers.delete(e)}start(){this._started||(this._started=!0,this.timeline.playbackRate=1,this._requestId=requestAnimationFrame(this._ticker))}pause(){this._started=!1,this.timeline.playbackRate=0}setPlaybackRate(e){this.timeline.playbackRate=e}}class x extends _{constructor(e,t){super(e,t),this.gameObjects=[],this.scene=this}addGameObject(e){this.gameObjects.push(e),e.transform&&(e.transform.inScene=!0)}removeGameObject(e){const t=this.gameObjects.indexOf(e);-1!==t&&(e.transform&&(e.transform.inScene=!1),this.gameObjects.splice(t,1))}destroy(){this.scene=null,super.destroy(),this.gameObjects=null,this.canvas=null}}function L(e){if("systemName"in e){const t=e.systemName;if("string"==typeof t)return t}return"UnknownSystem"}var C;exports.LOAD_SCENE_MODE=void 0,(C=exports.LOAD_SCENE_MODE||(exports.LOAD_SCENE_MODE={})).SINGLE="SINGLE",C.MULTI_CANVAS="MULTI_CANVAS";const M=e=>{if((e instanceof R||e instanceof c)&&!e.started){e.started=!0;try{e.start&&e.start()}catch(t){e instanceof c?console.error(`${function(e){if("componentName"in e){const t=e.componentName;if("string"==typeof t)return t}return"UnknownComponent"}(e.constructor)} start error`,t):console.error(`${L(e.constructor)} start error`,t)}}};class P extends i.default{constructor({systems:e,frameRate:t=60,autoStart:s=!0,needScene:r=!0,onSystemsBootstrapComplete:o}={}){if(super(),this.playing=!1,this.started=!1,this.multiScenes=[],this.systems=[],this.ticker=new v({autoStart:!1,frameRate:t}),this.initTicker(),e&&e.length){const t=[...e];this.bootstrapSystemsAndMaybeStart(t,r,s,o)}else o?.(this)}async bootstrapSystemsAndMaybeStart(e,t,s,r){let o;try{for(const t of e)await this.addSystem(t);t&&this.loadScene(new x("scene")),s&&this.start()}catch(e){o=e,console.error("Game bootstrap failed",e)}finally{r?.(this,o)}}get scene(){return this._scene}set scene(e){this._scene=e}get gameObjects(){return(e=>{const t=e?.scene?.gameObjects||[],s=e?.multiScenes.map(({gameObjects:e})=>e);let r=[];for(const e of s)r=[...r,...e];return[...t,...r]})(this)}async addSystem(e,s){let r;if(e instanceof Function)r=new e(s);else{if(!(e instanceof R))return void console.warn("can only add System");r=e}if(!this.systems.find(e=>e.constructor===r.constructor)){r.game=this,r.init&&await Promise.resolve(r.init(r.__systemDefaultParams)),function(e,t){m[t.systemName]=t.observerInfo,p[t.systemName]=e}(r,r.constructor),function(e){const s=[];e instanceof Array?s.push(...e):s.push(e);for(const e of s)for(const s in e.observerInfo){d[s]=d[s]||[];const r=d[s];for(const o of e.observerInfo[s])-1===r.findIndex(e=>t.isEqual(e,o))&&d[s].push(o)}}(r.constructor);try{r.awake&&r.awake()}catch(e){console.error(`${L(r.constructor)} awake error`,e)}return this.systems.push(r),r}console.warn(`${L(r.constructor)} System has been added`)}removeSystem(e){if(!e)return;let t=-1;"string"==typeof e?t=this.systems.findIndex(t=>t.name===e):e instanceof Function?t=this.systems.findIndex(t=>t.constructor===e):e instanceof R&&(t=this.systems.findIndex(t=>t===e)),t>-1&&(this.systems[t].destroy&&this.systems[t].destroy(),this.systems.splice(t,1))}getSystem(e){return this.systems.find(t=>"string"==typeof e?t.name===e:t instanceof e)}pause(){this.playing&&(this.playing=!1,this.ticker.pause(),this.triggerPause())}start(){this.playing||(this.playing=!0,this.started=!0,this.ticker.start())}resume(){this.playing||(this.playing=!0,this.ticker.start(),this.triggerResume())}initTicker(){this.ticker.add(e=>{this.scene&&((e,t=[])=>{for(const s of t)for(const t of s.components)try{M(t),t.update&&t.update(e)}catch(e){console.error(`gameObject: ${s.name} ${t.name} update error`,e)}for(const s of t)for(const t of s.components)try{t.lateUpdate&&t.lateUpdate(e)}catch(e){console.error(`gameObject: ${s.name} ${t.name} lateUpdate error`,e)}})(e,this.gameObjects);for(const t of this.systems)try{M(t),t.update&&t.update(e)}catch(e){console.error(`${L(t.constructor)} update error`,e)}for(const t of this.systems)try{t.lateUpdate&&t.lateUpdate(e)}catch(e){console.error(`${L(t.constructor)} lateUpdate error`,e)}})}triggerResume(){(e=>{for(const t of e)for(const e of t.components)try{e.onResume&&e.onResume()}catch(s){console.error(`gameObject: ${t.name}, ${e.name}, onResume error`,s)}})(this.gameObjects);for(const e of this.systems)try{e.onResume&&e.onResume()}catch(t){console.error(`${L(e.constructor)}, onResume error`,t)}}triggerPause(){(e=>{for(const t of e)for(const e of t.components)try{e.onPause&&e.onPause()}catch(s){console.error(`gameObject: ${t.name}, ${e.name}, onResume error`,s)}})(this.gameObjects);for(const e of this.systems)try{e.onPause&&e.onPause()}catch(t){console.error(`${L(e.constructor)}, onPause error`,t)}}destroySystems(){for(const e of[...this.systems])this.removeSystem(e);this.systems.length=0}destroy(){this.removeAllListeners(),this.pause(),this.scene.destroy(),this.destroySystems(),this.ticker=null,this.scene=null,this.canvas=null,this.multiScenes=null}loadScene({scene:e,mode:t=exports.LOAD_SCENE_MODE.SINGLE,params:s={}}){if(e){switch(t){case exports.LOAD_SCENE_MODE.SINGLE:this.scene=e;break;case exports.LOAD_SCENE_MODE.MULTI_CANVAS:this.multiScenes.push(e)}this.emit("sceneChanged",{scene:e,mode:t,params:s})}}}function w(e,t){e.constructor.IDEProps||(e.constructor.IDEProps=[]),e.constructor.IDEProps.push(t)}function A(e={}){return function(t){if(!t.observerInfo){for(const t in e)for(const s in e[t]){let r;"string"==typeof e[t][s]&&(e[t][s]=[e[t][s]]),Array.isArray(e[t][s])&&(r={prop:e[t][s],deep:!1},e[t][s]=r),r=e[t][s],"string"==typeof r.prop&&(r.prop=[r.prop])}t.observerInfo=e}}}var I;exports.LOAD_EVENT=void 0,(I=exports.LOAD_EVENT||(exports.LOAD_EVENT={})).START="start",I.PROGRESS="progress",I.LOADED="loaded",I.COMPLETE="complete",I.ERROR="error";class N extends i.default{constructor({resource:e,resourceTotal:t}){super(),this.progress=0,this.resourceTotal=0,this.resourceLoadedCount=0,this.resource=e,this.resourceTotal=t,0===t&&this.resource.emit(exports.LOAD_EVENT.COMPLETE,this)}onStart(){this.resource.emit(exports.LOAD_EVENT.START,this)}onProgress(e){this.resourceLoadedCount++,this.progress=Math.floor(this.resourceLoadedCount/this.resourceTotal*100)/100,e.success?this.resource.emit(exports.LOAD_EVENT.LOADED,this,e):this.resource.emit(exports.LOAD_EVENT.ERROR,this,e),this.resource.emit(exports.LOAD_EVENT.PROGRESS,this,e),this.resourceLoadedCount===this.resourceTotal&&this.resource.emit(exports.LOAD_EVENT.COMPLETE,this)}}const D={AbstractLoadStrategy:o.AbstractLoadStrategy,AudioLoadStrategy:o.AudioLoadStrategy,ImageLoadStrategy:o.ImageLoadStrategy,XhrResponseType:o.XhrResponseType,MediaElementLoadStrategy:o.MediaElementLoadStrategy,VideoLoadStrategy:o.VideoLoadStrategy,XhrLoadStrategy:o.XhrLoadStrategy,Loader:o.Loader,Resource:o.Resource,ResourceType:o.ResourceType,ResourceState:o.ResourceState};var j;exports.RESOURCE_TYPE=void 0,(j=exports.RESOURCE_TYPE||(exports.RESOURCE_TYPE={})).IMAGE="IMAGE",j.SPRITE="SPRITE",j.SPRITE_ANIMATION="SPRITE_ANIMATION",j.AUDIO="AUDIO",j.VIDEO="VIDEO",o.XhrLoadStrategy.setExtensionXhrType("json",o.XhrResponseType.Json),o.XhrLoadStrategy.setExtensionXhrType("tex",o.XhrResponseType.Json),o.XhrLoadStrategy.setExtensionXhrType("ske",o.XhrResponseType.Json),o.XhrLoadStrategy.setExtensionXhrType("mp3",o.XhrResponseType.Buffer),o.XhrLoadStrategy.setExtensionXhrType("wav",o.XhrResponseType.Buffer),o.XhrLoadStrategy.setExtensionXhrType("aac",o.XhrResponseType.Buffer),o.XhrLoadStrategy.setExtensionXhrType("ogg",o.XhrResponseType.Buffer);const V={png:o.ImageLoadStrategy,jpg:o.ImageLoadStrategy,jpeg:o.ImageLoadStrategy,webp:o.ImageLoadStrategy,json:o.XhrLoadStrategy,tex:o.XhrLoadStrategy,ske:o.XhrLoadStrategy,audio:o.XhrLoadStrategy,video:o.VideoLoadStrategy};class $ extends i.default{constructor(e){super(),this.timeout=6e3,this.preProcessResourceHandlers=[],this.resourcesMap={},this.makeInstanceFunctions={},this.destroyInstanceFunctions={},this.promiseMap={},this.loaders=[],e&&"number"==typeof e.timeout&&(this.timeout=e.timeout)}loadConfig(e){this.addResource(e),this.preload()}loadSingle(e){return this.addResource([e]),this.getResource(e.name)}addResource(e){if(!e||e.length<1)console.warn("no resources");else for(const t of e)this.resourcesMap[t.name]?console.warn(t.name+" was already added"):(this.resourcesMap[t.name]=t,this.resourcesMap[t.name].data={})}addPreProcessResourceHandler(e){this.preProcessResourceHandlers.push(e)}removePreProcessResourceHandler(e){this.preProcessResourceHandlers.splice(this.preProcessResourceHandlers.indexOf(e),1)}preload(){const e=[];for(const t in this.resourcesMap){const s=this.resourcesMap[t];!s.preload||s.complete||this.promiseMap[t]||e.push(s.name)}this.progress=new N({resource:this,resourceTotal:e.length}),this.loadResource({names:e,preload:!0})}async getResource(e){return this.loadResource({names:[e]}),this.promiseMap[e]||Promise.resolve({})}async instance(e){const t=this.resourcesMap[e];return this.makeInstanceFunctions[t.type]&&await this.makeInstanceFunctions[t.type](t)}async destroy(e){await this._destroy(e)}async _destroy(e,t=!1){const s=this.resourcesMap[e];if(s){if(!t)try{this.destroyInstanceFunctions[s.type]&&await this.destroyInstanceFunctions[s.type](s)}catch(e){console.warn(`destroy resource ${s.name} error with '${e.message}'`)}delete this.promiseMap[e],s.data={},s.complete=!1,s.instance=void 0}}registerResourceType(e,t=e){if(exports.RESOURCE_TYPE[e])throw new Error(`The type ${e} already exists in RESOURCE_TYPE`);exports.RESOURCE_TYPE[e]=t}registerInstance(e,t){this.makeInstanceFunctions[e]=t}registerDestroy(e,t){this.destroyInstanceFunctions[e]=t}loadResource({names:e=[],preload:t=!1}){const s=e.filter(e=>!this.promiseMap[e]&&this.resourcesMap[e]);if(!s.length)return;const r={},o=this.getLoader(t);s.forEach(e=>{this.promiseMap[e]=new Promise(t=>r[e]=t);const s=this.resourcesMap[e];for(const e of this.preProcessResourceHandlers)e(s);for(const n in s.src){const a=s.src[n].type;"data"===a?(s.data[n]=s.src[n].data,this.doComplete(e,r[e],t)):o.add({url:s.src[n].url,name:`${s.name}_${n}`,strategy:V[a],metadata:{key:n,name:s.name,resolves:r}})}}),o.load()}async doComplete(e,t,s=!1){const r=this.resourcesMap[e],o={name:e,resource:this.resourcesMap[e],success:!0};if(this.checkAllLoaded(e))try{r.instance=await this.instance(e),r.complete=!0,s&&this.progress.onProgress(o),t(r)}catch(e){console.error(e),r.complete=!1,s&&(o.errMsg=e.message,o.success=!1,this.progress.onProgress(o)),t({})}}checkAllLoaded(e){const t=this.resourcesMap[e];return Array.from(Object.keys(t.src)).every(e=>t.data[e])}getLoader(e=!1){let t=this.loaders.find(({loading:e})=>!e);return t||(t=new o.Loader,this.loaders.push(t)),e&&t.onStart.once(()=>{this.progress.onStart()}),t.onLoad.add((t,s)=>{this.onLoad({preload:e,resource:s})}),t.onError.add((t,s,r)=>{this.onError({errMsg:t,resource:r,preload:e})}),t.onComplete.once(()=>{t.onLoad.detachAll(),t.onError.detachAll(),t.reset()}),t}async onLoad({preload:e=!1,resource:t}){const{metadata:{key:s,name:r,resolves:o},data:n}=t;this.resourcesMap[r].data[s]=n,this.doComplete(r,o[r],e)}async onError({errMsg:e,preload:t=!1,resource:s}){const{metadata:{name:r,resolves:o}}=s;if(this._destroy(r,!0),o[r]({}),t){const t={name:r,resource:this.resourcesMap[r],success:!1,errMsg:e};this.progress.onProgress(t)}}}const X=new $,G={IDEProp:w,componentObserver:A},U="__VERSION__";console.log(`@combos-fun/engine version: ${U}`),exports.Component=c,exports.Game=P,exports.GameObject=_,exports.IDEProp=w,exports.RESOURCE_TYPE_STRATEGY=V,exports.Scene=x,exports.System=R,exports.Transform=g,exports.componentObserver=A,exports.decorators=G,exports.resource=X,exports.resourceLoader=D,exports.version=U;
|
|
1
|
+
"use strict";var e=require("eventemitter3"),t=require("lodash-es"),s=require("tslib"),r=require("@combos-fun/inspector-decorator"),o=require("resource-loader");function n(e){return e&&e.__esModule?e:{default:e}}var a,i=n(e);class c extends i.default{constructor(e){super(),this.started=!1;const t=this.constructor;this.name=t.componentName,this.__componentDefaultParams=e}}exports.OBSERVER_TYPE=void 0,(a=exports.OBSERVER_TYPE||(exports.OBSERVER_TYPE={})).ADD="ADD",a.REMOVE="REMOVE",a.CHANGE="CHANGE";const p={},h={},m={},d={};function u(e,t){p[e.gameObject.id]||(p[e.gameObject.id]={});const s=p[e.gameObject.id],r=e.name+"_"+t.join(",");if(s[r])return s[r];const o=t.length-1;let n=e;for(let e=0;e<o;e++)n=n[t[e]];return s[r]={property:n,key:t[o]},s[r]}function l({systemName:e,componentName:t,component:s,prop:r,type:o}){h[e]?.componentObserver?.add({component:s,prop:r,type:o,componentName:t})}function y({obj:e,key:s,prop:r,component:o,componentName:n}){if(void 0!==e)if(s in e){if(Object.defineProperty(e,`_${s}`,{enumerable:!1,writable:!0,value:e[s]}),r.deep&&t.isObject(e[s]))for(const t of Object.keys(e[s]))y({obj:e[s],key:t,prop:r,component:o,componentName:n});Object.defineProperty(e,s,{enumerable:!0,set(a){e[`_${s}`]!==a&&(e[`_${s}`]=a,function({prop:e,component:s,componentName:r}){for(const o in m){const n=(m[o]||{})[r];n&&(n.findIndex(s=>t.isEqual(s,e))>-1&&l({systemName:o,componentName:r,component:s,prop:e,type:exports.OBSERVER_TYPE.CHANGE}))}}({prop:r,component:o,componentName:n}))},get:()=>e[`_${s}`]})}else console.error(`prop ${s} not in component: ${n}, Can not observer`)}function f(e,t=e.name){for(const s in m){(m[s]||{})[t]&&h[s]?.componentObserver?.add({component:e,type:exports.OBSERVER_TYPE.REMOVE,componentName:t})}!function(e){e.gameObject&&delete p[e.gameObject.id]}(e)}class g extends c{constructor(){super(...arguments),this.name="Transform",this._parent=null,this.inScene=!1,this.children=[],this.position={x:0,y:0},this.size={width:0,height:0},this.origin={x:0,y:0},this.anchor={x:0,y:0},this.scale={x:1,y:1},this.skew={x:0,y:0},this.rotation=0}static{this.componentName="Transform"}init(e={}){const t=["position","size","origin","anchor","scale","skew"];for(const s of t)Object.assign(this[s],e[s]);this.rotation=e.rotation||this.rotation}set parent(e){e?e.addChild(this):this.parent&&this.parent.removeChild(this)}get parent(){return this._parent}addChild(e){if(e.parent===this){const t=this.children.findIndex(t=>t===e);this.children.splice(t,1)}else e.parent&&e.parent.removeChild(e);e._parent=this,this.children.push(e)}removeChild(e){const t=this.children.findIndex(t=>t===e);t>-1&&(this.children.splice(t,1),e._parent=null)}clearChildren(){this.children.length=0}}s.__decorate([r.type("vector2"),r.step(1)],g.prototype,"position",void 0),s.__decorate([r.type("size"),r.step(1)],g.prototype,"size",void 0),s.__decorate([r.type("vector2"),r.step(.1)],g.prototype,"origin",void 0),s.__decorate([r.type("vector2"),r.step(.1)],g.prototype,"anchor",void 0),s.__decorate([r.type("vector2"),r.step(.1)],g.prototype,"scale",void 0),s.__decorate([r.type("vector2"),r.step(.1)],g.prototype,"skew",void 0),s.__decorate([r.type("number"),r.step(.1)],g.prototype,"rotation",void 0);let E=0;class _{constructor(e,t){this._componentCache={},this.components=[],this.destroyed=!1,this._name=e,this.id=++E,this.addComponent(g,t)}get transform(){return this.getComponent(g)}get parent(){return this.transform&&this.transform.parent&&this.transform.parent.gameObject}get name(){return this._name}set scene(e){if(this._scene===e)return;const t=this._scene;if(this._scene=e,this.transform&&this.transform.children)for(const t of this.transform.children)t.gameObject.scene=e;e?e.addGameObject(this):t&&t.removeGameObject(this)}get scene(){return this._scene}addChild(e){if(e&&e.transform&&e!==this){if(!(e instanceof _))throw new Error("addChild only receive GameObject");if(!this.transform)throw new Error(`gameObject '${this.name}' has been destroy`);e.transform.parent=this.transform,e.scene=this.scene}}removeChild(e){return e instanceof _&&e.parent&&e.parent===this?(e.transform.parent=null,e.scene=null,e):e}addComponent(e,t){if(this.destroyed)return;const s=function(e){return e instanceof c?e.name:e instanceof Function?e.componentName:void 0}(e);if(this._componentCache[s])return;let r;if(e instanceof Function)r=new e(t);else{if(!(e instanceof c))throw new Error("addComponent recieve Component and Component Constructor");r=e}if(r.gameObject)throw new Error(`component has been added on gameObject ${r.gameObject.name}`);return r.gameObject=this,r.init&&r.init(r.__componentDefaultParams),function(e,t=e.name){for(const s in m)(m[s]||{})[t]&&h[s]?.componentObserver?.add({component:e,type:exports.OBSERVER_TYPE.ADD,componentName:t})}(r,r.name),function(e,t=e.name){if(t&&d[t]){if(!(e&&(s=e,s&&s.constructor&&"componentName"in s.constructor)))throw new Error("component param must be an instance of Component");var s;if(!e.gameObject||!e.gameObject.id)throw new Error("component should be add to a gameObject");for(const s of d[t]){const{property:r,key:o}=u(e,s.prop);y({obj:r,key:o,prop:s,component:e,componentName:t})}}}(r,r.name),this.components.push(r),this._componentCache[s]=r,r.awake&&r.awake(),r}removeComponent(e){let t;if("string"==typeof e?t=e:e instanceof c?t=e.name:e.componentName&&(t=e.componentName),"Transform"===t)throw new Error("Transform can't be removed");return this._removeComponent(t)}_removeComponent(e){const t=this.components.findIndex(({name:t})=>t===e);if(-1===t)return;const s=this.components.splice(t,1)[0];return delete this._componentCache[e],delete s.__componentDefaultParams,s.onDestroy&&s.onDestroy(),f(s,e),s.gameObject=void 0,s}getComponent(e){let t;return"string"==typeof e?t=e:e instanceof c?t=e.name:e.componentName&&(t=e.componentName),void 0!==this._componentCache[t]?this._componentCache[t]:void 0}remove(){if(this.parent)return this.parent.removeChild(this)}destroy(){if(this.transform){Array.from(this.transform.children).forEach(({gameObject:e})=>{e.destroy()}),this.remove(),this.transform.clearChildren();for(const e in this._componentCache)this._removeComponent(e);this.components.length=0,this.destroyed=!0}else console.error("Cannot destroy gameObject that have already been destroyed.")}}class b{constructor(){this.events=[]}add({component:e,prop:s,type:r,componentName:o}){if(r===exports.OBSERVER_TYPE.REMOVE){if(this.events.find(t=>t.component===e&&t.type===exports.OBSERVER_TYPE.ADD))return void(this.events=this.events.filter(t=>t.component!==e));this.events=this.events.filter(t=>t.component!==e)}const n=this.events.findIndex(o=>o.component===e&&t.isEqual(o.prop,s)&&o.type===r);n>-1&&this.events.splice(n,1),this.events.push({gameObject:e.gameObject,component:e,prop:s,type:r,componentName:o})}getChanged(){return this.events}get changed(){return this.events}clear(){const e=this.events;return this.events=[],e}}class T{constructor(e){this.started=!1,this.componentObserver=new b,this.__systemDefaultParams=e;const t=this.constructor;this.name=t.systemName}destroy(){this.componentObserver=null,this.__systemDefaultParams=null,this.onDestroy?.()}}const R=function(){let e=null;return e=Date.now?Date.now:()=>(new Date).getTime(),e}(),O={originTime:0,playbackRate:1};class S{constructor(e,t){e instanceof S&&(t=e,e={}),e=Object.assign({},O,e),t&&(this._parent=t),this._createTime=R(),this._timeMark=[{globalTime:this.globalTime,localTime:-e.originTime,entropy:-e.originTime,playbackRate:e.playbackRate,globalEntropy:0}],this._parent&&(this._timeMark[0].globalEntropy=this._parent.entropy),this._playbackRate=e.playbackRate}get globalTime(){return this.parent?this.parent.currentTime:R()-this._createTime}get parent(){return this._parent}get lastTimeMark(){return this._timeMark[this._timeMark.length-1]}markTime({time:e=this.currentTime,entropy:t=this.entropy,playbackRate:s=this.playbackRate}={}){const r={globalTime:this.globalTime,localTime:e,entropy:t,playbackRate:s,globalEntropy:this.globalEntropy};this._timeMark.push(r)}get currentTime(){const{localTime:e,globalTime:t}=this.lastTimeMark;return e+(this.globalTime-t)*this.playbackRate}set currentTime(e){this.markTime({time:e})}get globalEntropy(){return this._parent?this._parent.entropy:this.globalTime}get entropy(){const{entropy:e,globalEntropy:t}=this.lastTimeMark;return e+Math.abs((this.globalEntropy-t)*this.playbackRate)}set entropy(e){if(this.entropy>e){const t=this.seekTimeMark(e);this._timeMark.length=t+1}this.markTime({entropy:e})}fork(e){return new S(e,this)}seekGlobalTime(e){const t=this.seekTimeMark(e),s=this._timeMark[t],{entropy:r,playbackRate:o,globalTime:n}=s;return n+(e-r)/Math.abs(o)}seekLocalTime(e){const t=this.seekTimeMark(e),s=this._timeMark[t],{localTime:r,entropy:o,playbackRate:n}=s;return n>0?r+(e-o):r-(e-o)}seekTimeMark(e){const t=this._timeMark;let s=0,r=t.length-1;if(e<=t[s].entropy)return s;if(e>=t[r].entropy)return r;let o=Math.floor((s+r)/2);for(;o>s&&o<r;){if(e===t[o].entropy)return o;e<t[o].entropy?r=o:e>t[o].entropy&&(s=o),o=Math.floor((s+r)/2)}return s}get playbackRate(){return this._playbackRate}set playbackRate(e){e!==this.playbackRate&&(this.markTime({playbackRate:e}),this._playbackRate=e)}get paused(){if(0===this.playbackRate)return!0;let e=this.parent;for(;e;){if(0===e.playbackRate)return!0;e=e.parent}return!1}}const k={autoStart:!0,frameRate:60};class v{constructor(e){e=Object.assign({},k,e),this._frameCount=0,this._frameDuration=1e3/e.frameRate,this.autoStart=e.autoStart,this.frameRate=e.frameRate,this.timeline=new S({originTime:0,playbackRate:1}),this._lastFrameTime=this.timeline.currentTime,this._tickers=new Set,this._requestId=null,this._ticker=()=>{this._started&&(this._requestId=requestAnimationFrame(this._ticker),this.update())},this.autoStart&&this.start()}update(){const e=this.timeline.currentTime,t=e-this._lastFrameTime;if(t>=this._frameDuration){const s=e-t%this._frameDuration,r=s-this._lastFrameTime;this._lastFrameTime=s;const o={deltaTime:r,time:s,currentTime:s,frameCount:++this._frameCount,fps:Math.round(1e3/r)};for(const e of this._tickers)"function"==typeof e&&e(o)}}add(e){this._tickers.add(e)}remove(e){this._tickers.delete(e)}start(){this._started||(this._started=!0,this.timeline.playbackRate=1,this._requestId=requestAnimationFrame(this._ticker))}pause(){this._started=!1,this.timeline.playbackRate=0}setPlaybackRate(e){this.timeline.playbackRate=e}}class x extends _{constructor(e,t){super(e,t),this.gameObjects=[],this.scene=this}addGameObject(e){this.gameObjects.push(e),e.transform&&(e.transform.inScene=!0)}removeGameObject(e){const t=this.gameObjects.indexOf(e);-1!==t&&(e.transform&&(e.transform.inScene=!1),this.gameObjects.splice(t,1))}destroy(){this.scene=null,super.destroy(),this.gameObjects=null,this.canvas=null}}function L(e){if("systemName"in e){const t=e.systemName;if("string"==typeof t)return t}return"UnknownSystem"}var M;exports.LOAD_SCENE_MODE=void 0,(M=exports.LOAD_SCENE_MODE||(exports.LOAD_SCENE_MODE={})).SINGLE="SINGLE",M.MULTI_CANVAS="MULTI_CANVAS";const C=e=>{if((e instanceof T||e instanceof c)&&!e.started){e.started=!0;try{e.start&&e.start()}catch(t){e instanceof c?console.error(`${function(e){if("componentName"in e){const t=e.componentName;if("string"==typeof t)return t}return"UnknownComponent"}(e.constructor)} start error`,t):console.error(`${L(e.constructor)} start error`,t)}}};class w extends i.default{constructor({systems:e,frameRate:t=60,autoStart:s=!0,needScene:r=!0,onSystemsBootstrapComplete:o,pluginInitNotifyTargetOrigin:n="*"}={}){if(super(),this.playing=!1,this.started=!1,this.multiScenes=[],this.systems=[],this.pluginInitNotifyTargetOrigin="*",this.pluginInitNotifyTargetOrigin=n,this.ticker=new v({autoStart:!1,frameRate:t}),this.initTicker(),e&&e.length){const t=[...e];this.bootstrapSystemsAndMaybeStart(t,r,s,o)}else o?.(this)}async bootstrapSystemsAndMaybeStart(e,t,s,r){let o;try{for(const t of e)await this.addSystem(t);t&&this.loadScene(new x("scene")),s&&this.start()}catch(e){o=e,console.error("Game bootstrap failed",e)}finally{r?.(this,o)}}get scene(){return this._scene}set scene(e){this._scene=e}get gameObjects(){return(e=>{const t=e?.scene?.gameObjects||[],s=e?.multiScenes.map(({gameObjects:e})=>e);let r=[];for(const e of s)r=[...r,...e];return[...t,...r]})(this)}async addSystem(e,s){let r;if(e instanceof Function)r=new e(s);else{if(!(e instanceof T))return void console.warn("can only add System");r=e}if(!this.systems.find(e=>e.constructor===r.constructor)){r.game=this,r.init&&await Promise.resolve(r.init(r.__systemDefaultParams)),function(e,t="*"){if("undefined"==typeof window)return;if(!window.parent||window.parent===window)return;const s={type:"combos-game:plugin-init-success",systemName:e};try{window.parent.postMessage(s,t)}catch{}}(L(r.constructor),this.pluginInitNotifyTargetOrigin),function(e,t){m[t.systemName]=t.observerInfo,h[t.systemName]=e}(r,r.constructor),function(e){const s=[];e instanceof Array?s.push(...e):s.push(e);for(const e of s)for(const s in e.observerInfo){d[s]=d[s]||[];const r=d[s];for(const o of e.observerInfo[s])-1===r.findIndex(e=>t.isEqual(e,o))&&d[s].push(o)}}(r.constructor);try{r.awake&&r.awake()}catch(e){console.error(`${L(r.constructor)} awake error`,e)}return this.systems.push(r),r}console.warn(`${L(r.constructor)} System has been added`)}removeSystem(e){if(!e)return;let t=-1;"string"==typeof e?t=this.systems.findIndex(t=>t.name===e):e instanceof Function?t=this.systems.findIndex(t=>t.constructor===e):e instanceof T&&(t=this.systems.findIndex(t=>t===e)),t>-1&&(this.systems[t].destroy&&this.systems[t].destroy(),this.systems.splice(t,1))}getSystem(e){return this.systems.find(t=>"string"==typeof e?t.name===e:t instanceof e)}pause(){this.playing&&(this.playing=!1,this.ticker.pause(),this.triggerPause())}start(){this.playing||(this.playing=!0,this.started=!0,this.ticker.start())}resume(){this.playing||(this.playing=!0,this.ticker.start(),this.triggerResume())}initTicker(){this.ticker.add(e=>{this.scene&&((e,t=[])=>{for(const s of t)for(const t of s.components)try{C(t),t.update&&t.update(e)}catch(e){console.error(`gameObject: ${s.name} ${t.name} update error`,e)}for(const s of t)for(const t of s.components)try{t.lateUpdate&&t.lateUpdate(e)}catch(e){console.error(`gameObject: ${s.name} ${t.name} lateUpdate error`,e)}})(e,this.gameObjects);for(const t of this.systems)try{C(t),t.update&&t.update(e)}catch(e){console.error(`${L(t.constructor)} update error`,e)}for(const t of this.systems)try{t.lateUpdate&&t.lateUpdate(e)}catch(e){console.error(`${L(t.constructor)} lateUpdate error`,e)}})}triggerResume(){(e=>{for(const t of e)for(const e of t.components)try{e.onResume&&e.onResume()}catch(s){console.error(`gameObject: ${t.name}, ${e.name}, onResume error`,s)}})(this.gameObjects);for(const e of this.systems)try{e.onResume&&e.onResume()}catch(t){console.error(`${L(e.constructor)}, onResume error`,t)}}triggerPause(){(e=>{for(const t of e)for(const e of t.components)try{e.onPause&&e.onPause()}catch(s){console.error(`gameObject: ${t.name}, ${e.name}, onResume error`,s)}})(this.gameObjects);for(const e of this.systems)try{e.onPause&&e.onPause()}catch(t){console.error(`${L(e.constructor)}, onPause error`,t)}}destroySystems(){for(const e of[...this.systems])this.removeSystem(e);this.systems.length=0}destroy(){this.removeAllListeners(),this.pause(),this.scene.destroy(),this.destroySystems(),this.ticker=null,this.scene=null,this.canvas=null,this.multiScenes=null}loadScene({scene:e,mode:t=exports.LOAD_SCENE_MODE.SINGLE,params:s={}}){if(e){switch(t){case exports.LOAD_SCENE_MODE.SINGLE:this.scene=e;break;case exports.LOAD_SCENE_MODE.MULTI_CANVAS:this.multiScenes.push(e)}this.emit("sceneChanged",{scene:e,mode:t,params:s})}}}function N(e,t){e.constructor.IDEProps||(e.constructor.IDEProps=[]),e.constructor.IDEProps.push(t)}function I(e={}){return function(t){if(!t.observerInfo){for(const t in e)for(const s in e[t]){let r;"string"==typeof e[t][s]&&(e[t][s]=[e[t][s]]),Array.isArray(e[t][s])&&(r={prop:e[t][s],deep:!1},e[t][s]=r),r=e[t][s],"string"==typeof r.prop&&(r.prop=[r.prop])}t.observerInfo=e}}}var P;exports.LOAD_EVENT=void 0,(P=exports.LOAD_EVENT||(exports.LOAD_EVENT={})).START="start",P.PROGRESS="progress",P.LOADED="loaded",P.COMPLETE="complete",P.ERROR="error";class A extends i.default{constructor({resource:e,resourceTotal:t}){super(),this.progress=0,this.resourceTotal=0,this.resourceLoadedCount=0,this.resource=e,this.resourceTotal=t,0===t&&this.resource.emit(exports.LOAD_EVENT.COMPLETE,this)}onStart(){this.resource.emit(exports.LOAD_EVENT.START,this)}onProgress(e){this.resourceLoadedCount++,this.progress=Math.floor(this.resourceLoadedCount/this.resourceTotal*100)/100,e.success?this.resource.emit(exports.LOAD_EVENT.LOADED,this,e):this.resource.emit(exports.LOAD_EVENT.ERROR,this,e),this.resource.emit(exports.LOAD_EVENT.PROGRESS,this,e),this.resourceLoadedCount===this.resourceTotal&&this.resource.emit(exports.LOAD_EVENT.COMPLETE,this)}}const D={AbstractLoadStrategy:o.AbstractLoadStrategy,AudioLoadStrategy:o.AudioLoadStrategy,ImageLoadStrategy:o.ImageLoadStrategy,XhrResponseType:o.XhrResponseType,MediaElementLoadStrategy:o.MediaElementLoadStrategy,VideoLoadStrategy:o.VideoLoadStrategy,XhrLoadStrategy:o.XhrLoadStrategy,Loader:o.Loader,Resource:o.Resource,ResourceType:o.ResourceType,ResourceState:o.ResourceState};var j;exports.RESOURCE_TYPE=void 0,(j=exports.RESOURCE_TYPE||(exports.RESOURCE_TYPE={})).IMAGE="IMAGE",j.SPRITE="SPRITE",j.SPRITE_ANIMATION="SPRITE_ANIMATION",j.AUDIO="AUDIO",j.VIDEO="VIDEO",o.XhrLoadStrategy.setExtensionXhrType("json",o.XhrResponseType.Json),o.XhrLoadStrategy.setExtensionXhrType("tex",o.XhrResponseType.Json),o.XhrLoadStrategy.setExtensionXhrType("ske",o.XhrResponseType.Json),o.XhrLoadStrategy.setExtensionXhrType("mp3",o.XhrResponseType.Buffer),o.XhrLoadStrategy.setExtensionXhrType("wav",o.XhrResponseType.Buffer),o.XhrLoadStrategy.setExtensionXhrType("aac",o.XhrResponseType.Buffer),o.XhrLoadStrategy.setExtensionXhrType("ogg",o.XhrResponseType.Buffer);const V={png:o.ImageLoadStrategy,jpg:o.ImageLoadStrategy,jpeg:o.ImageLoadStrategy,webp:o.ImageLoadStrategy,json:o.XhrLoadStrategy,tex:o.XhrLoadStrategy,ske:o.XhrLoadStrategy,audio:o.XhrLoadStrategy,video:o.VideoLoadStrategy};class $ extends i.default{constructor(e){super(),this.timeout=6e3,this.preProcessResourceHandlers=[],this.resourcesMap={},this.makeInstanceFunctions={},this.destroyInstanceFunctions={},this.promiseMap={},this.loaders=[],e&&"number"==typeof e.timeout&&(this.timeout=e.timeout)}loadConfig(e){this.addResource(e),this.preload()}loadSingle(e){return this.addResource([e]),this.getResource(e.name)}addResource(e){if(!e||e.length<1)console.warn("no resources");else for(const t of e)this.resourcesMap[t.name]?console.warn(t.name+" was already added"):(this.resourcesMap[t.name]=t,this.resourcesMap[t.name].data={})}addPreProcessResourceHandler(e){this.preProcessResourceHandlers.push(e)}removePreProcessResourceHandler(e){this.preProcessResourceHandlers.splice(this.preProcessResourceHandlers.indexOf(e),1)}preload(){const e=[];for(const t in this.resourcesMap){const s=this.resourcesMap[t];!s.preload||s.complete||this.promiseMap[t]||e.push(s.name)}this.progress=new A({resource:this,resourceTotal:e.length}),this.loadResource({names:e,preload:!0})}async getResource(e){return this.loadResource({names:[e]}),this.promiseMap[e]||Promise.resolve({})}async instance(e){const t=this.resourcesMap[e];return this.makeInstanceFunctions[t.type]&&await this.makeInstanceFunctions[t.type](t)}async destroy(e){await this._destroy(e)}async _destroy(e,t=!1){const s=this.resourcesMap[e];if(s){if(!t)try{this.destroyInstanceFunctions[s.type]&&await this.destroyInstanceFunctions[s.type](s)}catch(e){console.warn(`destroy resource ${s.name} error with '${e.message}'`)}delete this.promiseMap[e],s.data={},s.complete=!1,s.instance=void 0}}registerResourceType(e,t=e){if(exports.RESOURCE_TYPE[e])throw new Error(`The type ${e} already exists in RESOURCE_TYPE`);exports.RESOURCE_TYPE[e]=t}registerInstance(e,t){this.makeInstanceFunctions[e]=t}registerDestroy(e,t){this.destroyInstanceFunctions[e]=t}loadResource({names:e=[],preload:t=!1}){const s=e.filter(e=>!this.promiseMap[e]&&this.resourcesMap[e]);if(!s.length)return;const r={},o=this.getLoader(t);s.forEach(e=>{this.promiseMap[e]=new Promise(t=>r[e]=t);const s=this.resourcesMap[e];for(const e of this.preProcessResourceHandlers)e(s);for(const n in s.src){const a=s.src[n].type;"data"===a?(s.data[n]=s.src[n].data,this.doComplete(e,r[e],t)):o.add({url:s.src[n].url,name:`${s.name}_${n}`,strategy:V[a],metadata:{key:n,name:s.name,resolves:r}})}}),o.load()}async doComplete(e,t,s=!1){const r=this.resourcesMap[e],o={name:e,resource:this.resourcesMap[e],success:!0};if(this.checkAllLoaded(e))try{r.instance=await this.instance(e),r.complete=!0,s&&this.progress.onProgress(o),t(r)}catch(e){console.error(e),r.complete=!1,s&&(o.errMsg=e.message,o.success=!1,this.progress.onProgress(o)),t({})}}checkAllLoaded(e){const t=this.resourcesMap[e];return Array.from(Object.keys(t.src)).every(e=>t.data[e])}getLoader(e=!1){let t=this.loaders.find(({loading:e})=>!e);return t||(t=new o.Loader,this.loaders.push(t)),e&&t.onStart.once(()=>{this.progress.onStart()}),t.onLoad.add((t,s)=>{this.onLoad({preload:e,resource:s})}),t.onError.add((t,s,r)=>{this.onError({errMsg:t,resource:r,preload:e})}),t.onComplete.once(()=>{t.onLoad.detachAll(),t.onError.detachAll(),t.reset()}),t}async onLoad({preload:e=!1,resource:t}){const{metadata:{key:s,name:r,resolves:o},data:n}=t;this.resourcesMap[r].data[s]=n,this.doComplete(r,o[r],e)}async onError({errMsg:e,preload:t=!1,resource:s}){const{metadata:{name:r,resolves:o}}=s;if(this._destroy(r,!0),o[r]({}),t){const t={name:r,resource:this.resourcesMap[r],success:!1,errMsg:e};this.progress.onProgress(t)}}}const X=new $,G={IDEProp:N,componentObserver:I},U="__VERSION__";console.log(`@combos-fun/engine version: ${U}`),exports.Component=c,exports.Game=w,exports.GameObject=_,exports.IDEProp=N,exports.RESOURCE_TYPE_STRATEGY=V,exports.Scene=x,exports.System=T,exports.Transform=g,exports.componentObserver=I,exports.decorators=G,exports.resource=X,exports.resourceLoader=D,exports.version=U;
|
package/dist/engine.d.ts
CHANGED
|
@@ -385,8 +385,8 @@ declare class Ticker {
|
|
|
385
385
|
|
|
386
386
|
/** Plugin registration shape */
|
|
387
387
|
interface PluginStruct {
|
|
388
|
-
Components?: typeof Component[];
|
|
389
|
-
Systems?: typeof System[];
|
|
388
|
+
Components?: (typeof Component)[];
|
|
389
|
+
Systems?: (typeof System)[];
|
|
390
390
|
}
|
|
391
391
|
interface GameParams {
|
|
392
392
|
/** isn't game will auto start */
|
|
@@ -397,6 +397,11 @@ interface GameParams {
|
|
|
397
397
|
systems?: System[];
|
|
398
398
|
/** whether or not need to create scene */
|
|
399
399
|
needScene?: boolean;
|
|
400
|
+
/**
|
|
401
|
+
* `postMessage` targetOrigin when notifying parent after each system `init` (default `'*'`).
|
|
402
|
+
* Only used when `window.parent` exists and differs from `window`.
|
|
403
|
+
*/
|
|
404
|
+
pluginInitNotifyTargetOrigin?: string;
|
|
400
405
|
/**
|
|
401
406
|
* Called after async system bootstrap finishes (constructor path with non-empty `systems`),
|
|
402
407
|
* i.e. after all `addSystem`/`init` work and optional `loadScene` / `start`.
|
|
@@ -448,7 +453,11 @@ declare class Game extends EventEmitter {
|
|
|
448
453
|
ticker: Ticker;
|
|
449
454
|
/** Systems alled to this game */
|
|
450
455
|
systems: System[];
|
|
451
|
-
|
|
456
|
+
/**
|
|
457
|
+
* Passed to `postMessage` when reporting `COMBOS_GAME_PLUGIN_INIT_SUCCESS` to `window.parent`.
|
|
458
|
+
*/
|
|
459
|
+
pluginInitNotifyTargetOrigin: string;
|
|
460
|
+
constructor({ systems, frameRate, autoStart, needScene, onSystemsBootstrapComplete, pluginInitNotifyTargetOrigin, }?: GameParams);
|
|
452
461
|
/** When `systems` is passed in the constructor, run async `init` for each before `loadScene` / `start`. */
|
|
453
462
|
private bootstrapSystemsAndMaybeStart;
|
|
454
463
|
/**
|
|
@@ -494,7 +503,7 @@ declare class Game extends EventEmitter {
|
|
|
494
503
|
destroySystems(): void;
|
|
495
504
|
/** Destroy game instance */
|
|
496
505
|
destroy(): void;
|
|
497
|
-
loadScene({ scene, mode, params }: LoadSceneParams): void;
|
|
506
|
+
loadScene({ scene, mode, params, }: LoadSceneParams): void;
|
|
498
507
|
}
|
|
499
508
|
|
|
500
509
|
interface SystemConstructor<T extends System = System> {
|
package/dist/engine.esm.js
CHANGED
|
@@ -948,21 +948,46 @@ class Scene extends GameObject {
|
|
|
948
948
|
}
|
|
949
949
|
}
|
|
950
950
|
|
|
951
|
+
/**
|
|
952
|
+
* Sent to `window.parent` after each `System.init` completes during `Game.addSystem`
|
|
953
|
+
* (when running inside an iframe and parent differs from self).
|
|
954
|
+
*/
|
|
955
|
+
const COMBOS_GAME_PLUGIN_INIT_SUCCESS = "combos-game:plugin-init-success";
|
|
956
|
+
/**
|
|
957
|
+
* Notifies the embedding page that a system (plugin) finished async/sync `init`.
|
|
958
|
+
*/
|
|
959
|
+
function postParentPluginInitSuccess(systemName, targetOrigin = "*") {
|
|
960
|
+
if (typeof window === "undefined")
|
|
961
|
+
return;
|
|
962
|
+
if (!window.parent || window.parent === window)
|
|
963
|
+
return;
|
|
964
|
+
const payload = {
|
|
965
|
+
type: COMBOS_GAME_PLUGIN_INIT_SUCCESS,
|
|
966
|
+
systemName,
|
|
967
|
+
};
|
|
968
|
+
try {
|
|
969
|
+
window.parent.postMessage(payload, targetOrigin);
|
|
970
|
+
}
|
|
971
|
+
catch {
|
|
972
|
+
/* ignore cross-origin or detached frame */
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
|
|
951
976
|
function systemClassName(ctor) {
|
|
952
|
-
if (
|
|
977
|
+
if ("systemName" in ctor) {
|
|
953
978
|
const sn = ctor.systemName;
|
|
954
|
-
if (typeof sn ===
|
|
979
|
+
if (typeof sn === "string")
|
|
955
980
|
return sn;
|
|
956
981
|
}
|
|
957
|
-
return
|
|
982
|
+
return "UnknownSystem";
|
|
958
983
|
}
|
|
959
984
|
function componentClassName(ctor) {
|
|
960
|
-
if (
|
|
985
|
+
if ("componentName" in ctor) {
|
|
961
986
|
const cn = ctor.componentName;
|
|
962
|
-
if (typeof cn ===
|
|
987
|
+
if (typeof cn === "string")
|
|
963
988
|
return cn;
|
|
964
989
|
}
|
|
965
|
-
return
|
|
990
|
+
return "UnknownComponent";
|
|
966
991
|
}
|
|
967
992
|
var LOAD_SCENE_MODE;
|
|
968
993
|
(function (LOAD_SCENE_MODE) {
|
|
@@ -987,7 +1012,7 @@ const triggerStart = (obj) => {
|
|
|
987
1012
|
}
|
|
988
1013
|
}
|
|
989
1014
|
};
|
|
990
|
-
const getAllGameObjects = game => {
|
|
1015
|
+
const getAllGameObjects = (game) => {
|
|
991
1016
|
const mainSceneGameObjects = game?.scene?.gameObjects || [];
|
|
992
1017
|
const gameObjectsArray = game?.multiScenes.map(({ gameObjects }) => gameObjects);
|
|
993
1018
|
let otherSceneGameObjects = [];
|
|
@@ -1019,7 +1044,7 @@ const gameObjectLoop = (e, gameObjects = []) => {
|
|
|
1019
1044
|
}
|
|
1020
1045
|
}
|
|
1021
1046
|
};
|
|
1022
|
-
const gameObjectResume = gameObjects => {
|
|
1047
|
+
const gameObjectResume = (gameObjects) => {
|
|
1023
1048
|
for (const gameObject of gameObjects) {
|
|
1024
1049
|
for (const component of gameObject.components) {
|
|
1025
1050
|
try {
|
|
@@ -1031,7 +1056,7 @@ const gameObjectResume = gameObjects => {
|
|
|
1031
1056
|
}
|
|
1032
1057
|
}
|
|
1033
1058
|
};
|
|
1034
|
-
const gameObjectPause = gameObjects => {
|
|
1059
|
+
const gameObjectPause = (gameObjects) => {
|
|
1035
1060
|
for (const gameObject of gameObjects) {
|
|
1036
1061
|
for (const component of gameObject.components) {
|
|
1037
1062
|
try {
|
|
@@ -1044,7 +1069,7 @@ const gameObjectPause = gameObjects => {
|
|
|
1044
1069
|
}
|
|
1045
1070
|
};
|
|
1046
1071
|
class Game extends EventEmitter {
|
|
1047
|
-
constructor({ systems, frameRate = 60, autoStart = true, needScene = true, onSystemsBootstrapComplete, } = {}) {
|
|
1072
|
+
constructor({ systems, frameRate = 60, autoStart = true, needScene = true, onSystemsBootstrapComplete, pluginInitNotifyTargetOrigin = "*", } = {}) {
|
|
1048
1073
|
super();
|
|
1049
1074
|
/**
|
|
1050
1075
|
* State of game
|
|
@@ -1055,6 +1080,11 @@ class Game extends EventEmitter {
|
|
|
1055
1080
|
this.multiScenes = [];
|
|
1056
1081
|
/** Systems alled to this game */
|
|
1057
1082
|
this.systems = [];
|
|
1083
|
+
/**
|
|
1084
|
+
* Passed to `postMessage` when reporting `COMBOS_GAME_PLUGIN_INIT_SUCCESS` to `window.parent`.
|
|
1085
|
+
*/
|
|
1086
|
+
this.pluginInitNotifyTargetOrigin = "*";
|
|
1087
|
+
this.pluginInitNotifyTargetOrigin = pluginInitNotifyTargetOrigin;
|
|
1058
1088
|
this.ticker = new Ticker({ autoStart: false, frameRate });
|
|
1059
1089
|
this.initTicker();
|
|
1060
1090
|
if (systems && systems.length) {
|
|
@@ -1073,7 +1103,7 @@ class Game extends EventEmitter {
|
|
|
1073
1103
|
await this.addSystem(system);
|
|
1074
1104
|
}
|
|
1075
1105
|
if (needScene) {
|
|
1076
|
-
this.loadScene(new Scene(
|
|
1106
|
+
this.loadScene(new Scene("scene"));
|
|
1077
1107
|
}
|
|
1078
1108
|
if (autoStart) {
|
|
1079
1109
|
this.start();
|
|
@@ -1081,7 +1111,7 @@ class Game extends EventEmitter {
|
|
|
1081
1111
|
}
|
|
1082
1112
|
catch (e) {
|
|
1083
1113
|
error = e;
|
|
1084
|
-
console.error(
|
|
1114
|
+
console.error("Game bootstrap failed", e);
|
|
1085
1115
|
}
|
|
1086
1116
|
finally {
|
|
1087
1117
|
onComplete?.(this, error);
|
|
@@ -1114,10 +1144,10 @@ class Game extends EventEmitter {
|
|
|
1114
1144
|
system = S;
|
|
1115
1145
|
}
|
|
1116
1146
|
else {
|
|
1117
|
-
console.warn(
|
|
1147
|
+
console.warn("can only add System");
|
|
1118
1148
|
return;
|
|
1119
1149
|
}
|
|
1120
|
-
const hasTheSystem = this.systems.find(item => {
|
|
1150
|
+
const hasTheSystem = this.systems.find((item) => {
|
|
1121
1151
|
return item.constructor === system.constructor;
|
|
1122
1152
|
});
|
|
1123
1153
|
if (hasTheSystem) {
|
|
@@ -1128,6 +1158,7 @@ class Game extends EventEmitter {
|
|
|
1128
1158
|
if (system.init) {
|
|
1129
1159
|
await Promise.resolve(system.init(system.__systemDefaultParams));
|
|
1130
1160
|
}
|
|
1161
|
+
postParentPluginInitSuccess(systemClassName(system.constructor), this.pluginInitNotifyTargetOrigin);
|
|
1131
1162
|
setSystemObserver(system, system.constructor);
|
|
1132
1163
|
initObserver(system.constructor);
|
|
1133
1164
|
try {
|
|
@@ -1147,14 +1178,14 @@ class Game extends EventEmitter {
|
|
|
1147
1178
|
if (!system)
|
|
1148
1179
|
return;
|
|
1149
1180
|
let index = -1;
|
|
1150
|
-
if (typeof system ===
|
|
1151
|
-
index = this.systems.findIndex(s => s.name === system);
|
|
1181
|
+
if (typeof system === "string") {
|
|
1182
|
+
index = this.systems.findIndex((s) => s.name === system);
|
|
1152
1183
|
}
|
|
1153
1184
|
else if (system instanceof Function) {
|
|
1154
|
-
index = this.systems.findIndex(s => s.constructor === system);
|
|
1185
|
+
index = this.systems.findIndex((s) => s.constructor === system);
|
|
1155
1186
|
}
|
|
1156
1187
|
else if (system instanceof System) {
|
|
1157
|
-
index = this.systems.findIndex(s => s === system);
|
|
1188
|
+
index = this.systems.findIndex((s) => s === system);
|
|
1158
1189
|
}
|
|
1159
1190
|
if (index > -1) {
|
|
1160
1191
|
this.systems[index].destroy && this.systems[index].destroy();
|
|
@@ -1167,8 +1198,8 @@ class Game extends EventEmitter {
|
|
|
1167
1198
|
* @returns system instance
|
|
1168
1199
|
*/
|
|
1169
1200
|
getSystem(S) {
|
|
1170
|
-
return this.systems.find(system => {
|
|
1171
|
-
if (typeof S ===
|
|
1201
|
+
return this.systems.find((system) => {
|
|
1202
|
+
if (typeof S === "string") {
|
|
1172
1203
|
return system.name === S;
|
|
1173
1204
|
}
|
|
1174
1205
|
else {
|
|
@@ -1210,7 +1241,7 @@ class Game extends EventEmitter {
|
|
|
1210
1241
|
* 4. call lastUpdate method on all system
|
|
1211
1242
|
*/
|
|
1212
1243
|
initTicker() {
|
|
1213
|
-
this.ticker.add(e => {
|
|
1244
|
+
this.ticker.add((e) => {
|
|
1214
1245
|
this.scene && gameObjectLoop(e, this.gameObjects);
|
|
1215
1246
|
for (const system of this.systems) {
|
|
1216
1247
|
try {
|
|
@@ -1274,7 +1305,7 @@ class Game extends EventEmitter {
|
|
|
1274
1305
|
this.canvas = null;
|
|
1275
1306
|
this.multiScenes = null;
|
|
1276
1307
|
}
|
|
1277
|
-
loadScene({ scene, mode = LOAD_SCENE_MODE.SINGLE, params = {} }) {
|
|
1308
|
+
loadScene({ scene, mode = LOAD_SCENE_MODE.SINGLE, params = {}, }) {
|
|
1278
1309
|
if (!scene) {
|
|
1279
1310
|
return;
|
|
1280
1311
|
}
|
|
@@ -1286,7 +1317,7 @@ class Game extends EventEmitter {
|
|
|
1286
1317
|
this.multiScenes.push(scene);
|
|
1287
1318
|
break;
|
|
1288
1319
|
}
|
|
1289
|
-
this.emit(
|
|
1320
|
+
this.emit("sceneChanged", { scene, mode, params });
|
|
1290
1321
|
}
|
|
1291
1322
|
}
|
|
1292
1323
|
|