@urso/core 0.6.2 → 0.6.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@urso/core",
3
- "version": "0.6.2",
3
+ "version": "0.6.4",
4
4
  "description": "HTML5 game engine",
5
5
  "main": "build/js/index.js",
6
6
  "author": "Megbrimef",
@@ -21,12 +21,14 @@ class ComponentsDebugFps {
21
21
  this.frames++;
22
22
 
23
23
  if (currentTime - this.lastUpdateTime < 1000)
24
- return
24
+ return;
25
25
 
26
26
  const fps = Math.round(1000 * this.frames / (currentTime - this.lastUpdateTime));
27
27
  this.lastUpdateTime = currentTime;
28
28
  this.frames = 0;
29
- this._coordsText.text = 'fps:' + fps;
29
+
30
+ const fpsData = Urso.scenes.getFpsData();
31
+ this._coordsText.text = `fps: ${fps}, sceneFps: ${fpsData.fps}, limit: ${fpsData.limit}`;
30
32
  };
31
33
 
32
34
  }
@@ -6,7 +6,11 @@ let ConfigMain = {
6
6
  extendingChain: ['Urso.Core'], //chain that will be set as Urso.Game
7
7
  defaultScene: 'play', //default scene to display
8
8
  useBinPath: false, // use assets from bin directory
9
- useTransport: false // use transport module for connetcting with server
9
+ useTransport: false, // use transport module for connetcting with server
10
+ fps: {
11
+ limit: 60, //max fps limit
12
+ optimizeLowPerformance: true //down to 30 fps if lower 60
13
+ }
10
14
  };
11
15
 
12
16
  module.exports = ConfigMain;
@@ -16,6 +16,13 @@ class ModulesInstancesController {
16
16
  this.removeMode = this.removeMode.bind(this);
17
17
  }
18
18
 
19
+ /**
20
+ * get class by Path
21
+ * @param {String} path
22
+ * @param {Boolean} [noModes]
23
+ * @param {String} [modeName]
24
+ * @returns {Class}
25
+ */
19
26
  getByPath(path, noModes, modeName) {
20
27
  let callback = (a) => {
21
28
  return a;
@@ -24,10 +31,19 @@ class ModulesInstancesController {
24
31
  return this._findClass({ path, callback, noModes, modeName });
25
32
  }
26
33
 
34
+ /**
35
+ * get current modes
36
+ * @returns {Array}
37
+ */
27
38
  getModes() {
28
39
  return this._modes;
29
40
  }
30
41
 
42
+ /**
43
+ * add mode to system
44
+ * @param {String} mode
45
+ * @returns {Boolean}
46
+ */
31
47
  addMode(mode) {
32
48
  if (this._modes.indexOf(mode) !== -1)
33
49
  return false;
@@ -40,8 +56,8 @@ class ModulesInstancesController {
40
56
  /**
41
57
  * remove mode from system
42
58
  * @param {String} mode
43
- * @param {Boolean} passiveMode - do not refresh styles
44
- * @returns
59
+ * @param {Boolean} [passiveMode] - do not refresh styles
60
+ * @returns {Boolean}
45
61
  */
46
62
  removeMode(mode, passiveMode) {
47
63
  let index = this._modes.indexOf(mode);
@@ -58,6 +74,14 @@ class ModulesInstancesController {
58
74
  return true;
59
75
  }
60
76
 
77
+ /**
78
+ * get class instance by path
79
+ * @param {String} path
80
+ * @param {mixed} [params]
81
+ * @param {Boolean} [noModes]
82
+ * @param {String} [modeName]
83
+ * @returns {Class | false}
84
+ */
61
85
  getInstance(path, params, noModes, modeName) {
62
86
  let callback = (classObject) => {
63
87
  if (typeof classObject !== "function") { //typeof class is a function
@@ -84,11 +108,20 @@ class ModulesInstancesController {
84
108
  return this._findClass({ path, callback, noModes, modeName });
85
109
  }
86
110
 
111
+ /**
112
+ * get uid for instance
113
+ * @returns {String}
114
+ */
87
115
  _getUid() {
88
116
  this._counter++;
89
117
  return 'instance' + this._counter;
90
118
  }
91
119
 
120
+ /**
121
+ * set common functions to instance
122
+ * @param {Class} classObject
123
+ * @param {String} path
124
+ */
92
125
  _setComonFunctions(classObject, path) {
93
126
  classObject.prototype.getInstance = this._entityGetInstance(path);
94
127
  classObject.prototype.addListener = this._entityAddListener;
@@ -96,6 +129,11 @@ class ModulesInstancesController {
96
129
  classObject.prototype.emit = this._entityEmit;
97
130
  }
98
131
 
132
+ /**
133
+ * set common entities functions to instance
134
+ * @param {Class} classObject
135
+ * @param {ClassInstance} callerObject
136
+ */
99
137
  _setComonEntityFunctions(classObject, callerObject) {
100
138
  if (callerObject.common && !classObject.common) { //components common
101
139
  classObject.common = callerObject.common;
@@ -106,6 +144,10 @@ class ModulesInstancesController {
106
144
  }
107
145
  }
108
146
 
147
+ /**
148
+ * launch default functions after creation
149
+ * @param {ClassInstance} instance
150
+ */
109
151
  _launchDefaultFunctions(instance) {
110
152
  //_subscribe
111
153
  if (instance && instance._subscribe)
@@ -118,6 +160,11 @@ class ModulesInstancesController {
118
160
  }
119
161
  }
120
162
 
163
+ /**
164
+ * entity get instance (with parent deps)
165
+ * @param {String} path
166
+ * @returns {Function}
167
+ */
121
168
  _entityGetInstance(path) {
122
169
  const entityPath = Urso.helper.initial(path.split('.')).join('.');
123
170
  const self = this;
@@ -138,6 +185,11 @@ class ModulesInstancesController {
138
185
  };
139
186
  }
140
187
 
188
+ /**
189
+ * add entity to caller class
190
+ * @param {ClassInstance} classObject
191
+ * @param {ClassInstance} callerObject
192
+ */
141
193
  _addEntityToClass(classObject, callerObject) {
142
194
  if (!callerObject.__entities)
143
195
  callerObject.__entities = [];
@@ -146,18 +198,32 @@ class ModulesInstancesController {
146
198
  callerObject.__entities.push(classObject);
147
199
  }
148
200
 
201
+ /**
202
+ * entity addListener function
203
+ */
149
204
  _entityAddListener() {
150
205
  Urso.observer.add.apply(Urso.observer, arguments);
151
206
  }
152
207
 
208
+ /**
209
+ * entity removeListener function
210
+ */
153
211
  _entityRemoveListener() {
154
212
  Urso.observer.remove.apply(Urso.observer, arguments);
155
213
  }
156
214
 
215
+ /**
216
+ * entity emit function
217
+ */
157
218
  _entityEmit() {
158
219
  Urso.observer.fire.apply(Urso.observer, arguments);
159
220
  }
160
221
 
222
+ /**
223
+ * find class by params
224
+ * @param {Object} params
225
+ * @returns {Class | false}
226
+ */
161
227
  _findClass(params) {
162
228
  //put all params exept callback in key
163
229
  let cacheKey = [
@@ -190,6 +256,12 @@ class ModulesInstancesController {
190
256
  return params.callback(this._cache[cacheKey]);
191
257
  }
192
258
 
259
+ /**
260
+ * get class by path
261
+ * @param {String} path
262
+ * @param {Boolean} [noModes]
263
+ * @returns {Class | false}
264
+ */
193
265
  _getClassByPath(path, noModes) {
194
266
  let pathArr = path.split('.');
195
267
  let entitiesArray = Urso.helper.mergeArrays(['Urso', 'Game'], pathArr);
@@ -199,7 +271,7 @@ class ModulesInstancesController {
199
271
  /**
200
272
  * check if object exist
201
273
  * @param {Object} entitiesArray like ['Urso', 'Game', 'Lib', 'Helper']
202
- * @returns {mixed}
274
+ * @returns {Class | false}
203
275
  */
204
276
  _checkPathExist(entitiesArray, noModes) {
205
277
  let currentTestObject = window;
@@ -235,6 +307,13 @@ class ModulesInstancesController {
235
307
  return currentTestObject;
236
308
  }
237
309
 
310
+ /**
311
+ * check path for modes
312
+ * @param {Object} currentTestObject
313
+ * @param {Array} entitiesArray
314
+ * @param {Number} entitiesIndex
315
+ * @returns {Class | false}
316
+ */
238
317
  _checkPathWithModes(currentTestObject, entitiesArray, entitiesIndex) {
239
318
  for (let mode of this._modes) {
240
319
  const capMode = Urso.helper.capitaliseFirstLetter(mode);
@@ -253,6 +332,13 @@ class ModulesInstancesController {
253
332
  return false;
254
333
  }
255
334
 
335
+ /**
336
+ * check path for mixins
337
+ * @param {Object} currentTestObject
338
+ * @param {Array} entitiesArray
339
+ * @param {Number} entitiesIndex
340
+ * @returns {Array}
341
+ */
256
342
  _getMixins(currentTestObject, entitiesArray, entitiesIndex) {
257
343
  const mixins = [];
258
344
 
@@ -21,6 +21,22 @@ class ModulesScenesController {
21
21
  this._service.display(name);
22
22
  }
23
23
 
24
+ /**
25
+ * get fps
26
+ * @returns {Number}
27
+ */
28
+ getFps() {
29
+ return this.getInstance('PixiWrapper').getFps();
30
+ }
31
+
32
+ /**
33
+ * get fps data
34
+ * @returns {Object}
35
+ */
36
+ getFpsData() {
37
+ return this.getInstance('PixiWrapper').getFpsData();
38
+ }
39
+
24
40
  /**
25
41
  * pause scene
26
42
  */
@@ -1,3 +1,6 @@
1
+ const NORMAL_FPS_COUNT = 60;
2
+ const LOW_PERFORMANCE_FPS_COUNT = 30;
3
+
1
4
  class ModulesScenesPixiWrapper {
2
5
  constructor() {
3
6
  this.singleton = true;
@@ -13,10 +16,17 @@ class ModulesScenesPixiWrapper {
13
16
  this._loopPaused = false;
14
17
  this._loopLastCall = 0;
15
18
 
16
- this.loop = this.loop.bind(this);
19
+ this._loop = this._loop.bind(this);
17
20
  this.passiveCallIntervalId = null;
18
21
 
19
22
  this._mouseCoords = { x: 0, y: 0 };
23
+
24
+
25
+ this._maxFPSLimit = Urso.config.fps.limit;
26
+ this._lastUpdateTime = 0;
27
+ this._frames = 0;
28
+ this._currentFPS = Urso.config.fps.limit;
29
+ this._lastTimeCheckFPS = 0;
20
30
  }
21
31
 
22
32
  init() {
@@ -35,7 +45,7 @@ class ModulesScenesPixiWrapper {
35
45
  this.interaction = new PIXI.InteractionManager(this.renderer);
36
46
 
37
47
  this._loaderScene = this.getInstance('Model');
38
- this._requestAnimFrame(this.loop);
48
+ this._requestAnimFrame(this._loop);
39
49
 
40
50
  this.getInstance('Resolutions');
41
51
  }
@@ -62,10 +72,112 @@ class ModulesScenesPixiWrapper {
62
72
  resume() {
63
73
  this._loopLastCall = Date.now();
64
74
  this._loopPaused = false;
65
- this.update();
75
+ this._update();
66
76
  PIXI.spine.settings.GLOBAL_AUTO_UPDATE = true;
67
77
  }
68
78
 
79
+ /**
80
+ * resize renderer
81
+ * @param {Number} width
82
+ * @param {Number} height
83
+ */
84
+ resize(width, height) {
85
+ this.renderer.resize(width, height);
86
+ };
87
+
88
+ /**
89
+ * hide canvas
90
+ */
91
+ hideCanvas() {
92
+ this.renderer.view.style.display = 'none';
93
+ }
94
+
95
+ /**
96
+ * show canvas
97
+ */
98
+ showCanvas() {
99
+ this.renderer.view.style.display = '';
100
+ }
101
+
102
+ /**
103
+ * set world scale
104
+ * @param {Number} x
105
+ * @param {Number} y
106
+ */
107
+ setWorldScale(x, y) {
108
+ this.world.scale.x = x;
109
+ this.world.scale.y = y;
110
+ }
111
+
112
+ /**
113
+ * set canvas width
114
+ * @param {Number} val
115
+ */
116
+ setCanvasWidth(val) {
117
+ this.renderer.view.style.width = val + 'px';
118
+ };
119
+
120
+ /**
121
+ * set canvas height
122
+ * @param {Number} val
123
+ */
124
+ setCanvasHeight(val) {
125
+ this.renderer.view.style.height = val + 'px';
126
+ };
127
+
128
+ /**
129
+ * get pixi world (main Container)
130
+ * @returns {Object}
131
+ */
132
+ getPixiWorld() {
133
+ return this.world;
134
+ }
135
+
136
+ /**
137
+ * set new scene
138
+ * @param {Object} model
139
+ */
140
+ setNewScene(model) {
141
+ this._createWorld();
142
+ this.currentScene = model;
143
+ }
144
+
145
+ /**
146
+ * get fps
147
+ * @returns {Number}
148
+ */
149
+ getFps() {
150
+ return this._currentFPS;
151
+ }
152
+
153
+ /**
154
+ * get fps data
155
+ * @returns {Object}
156
+ */
157
+ getFpsData() {
158
+ return {
159
+ fps: this._currentFPS,
160
+ limit: this._maxFPSLimit
161
+ }
162
+ }
163
+
164
+ /**
165
+ * get cached mouse coords
166
+ * @returns {Object}
167
+ */
168
+ getCachedMouseCoords() {
169
+ return this._mouseCoords;
170
+ }
171
+
172
+ /**
173
+ * generateTexture from object
174
+ * @param {Object} obj
175
+ * @returns {Object} - pixi.Texture
176
+ */
177
+ generateTexture(obj) {
178
+ return this.renderer.generateTexture(obj);
179
+ }
180
+
69
181
  _setPixiSettings() {
70
182
  PIXI.settings.SCALE_MODE = PIXI.SCALE_MODES.LINEAR;
71
183
  PIXI.settings.TEXT_RESOLUTION = 1;
@@ -107,19 +219,53 @@ class ModulesScenesPixiWrapper {
107
219
  return deltaTime * 60 / 1000;
108
220
  };
109
221
 
110
- loop() {
222
+ _loop() {
111
223
  if (this._loopStopped)
112
224
  return false;
113
225
 
114
- this._requestAnimFrame(this.loop);
226
+ this._requestAnimFrame(this._loop);
115
227
 
116
- if (!this._loopPaused)
117
- this.update();
228
+ if (!this._loopPaused) {
229
+ if (!this._fpsCheckAllowUpdate())
230
+ return;
231
+
232
+ this._update();
233
+ }
118
234
 
119
235
  return true;
120
236
  };
121
237
 
122
- update() {
238
+ _fpsCheckAllowUpdate() {
239
+ const currentTime = Urso.time.get();
240
+ this._updateCurrentFPS(currentTime);
241
+
242
+ //setup maxFPSLimit
243
+ if (Urso.config.fps.optimizeLowPerformance)
244
+ if (this._currentFPS < NORMAL_FPS_COUNT)
245
+ this._maxFPSLimit = LOW_PERFORMANCE_FPS_COUNT;
246
+ else
247
+ this._maxFPSLimit = Urso.config.fps.limit;
248
+
249
+ //check need update
250
+ if (currentTime - this._lastUpdateTime < ~~(1000 / this._maxFPSLimit))
251
+ return false;
252
+
253
+ this._lastUpdateTime = currentTime;
254
+ return true;
255
+ }
256
+
257
+ _updateCurrentFPS(currentTime) {
258
+ this._frames++;
259
+
260
+ if (currentTime - this._lastTimeCheckFPS < 1000)
261
+ return;
262
+
263
+ this._currentFPS = Math.round(1000 * this._frames / (currentTime - this._lastTimeCheckFPS));
264
+ this._lastTimeCheckFPS = currentTime;
265
+ this._frames = 0;
266
+ }
267
+
268
+ _update() {
123
269
  if (!this.currentScene)
124
270
  return;
125
271
 
@@ -135,41 +281,6 @@ class ModulesScenesPixiWrapper {
135
281
  this.renderer.render(this._root);
136
282
  };
137
283
 
138
- //size
139
- resize(width, height) {
140
- this.renderer.resize(width, height);
141
- };
142
-
143
- hideCanvas() {
144
- this.renderer.view.style.display = 'none';
145
- }
146
-
147
- showCanvas() {
148
- this.renderer.view.style.display = '';
149
- }
150
-
151
- setWorldScale(x, y) {
152
- this.world.scale.x = x;
153
- this.world.scale.y = y;
154
- }
155
-
156
- setCanvasWidth(val) {
157
- this.renderer.view.style.width = val + 'px';
158
- };
159
-
160
- setCanvasHeight(val) {
161
- this.renderer.view.style.height = val + 'px';
162
- };
163
-
164
- getPixiWorld() {
165
- return this.world;
166
- }
167
-
168
- setNewScene(model) {
169
- this._createWorld();
170
- this.currentScene = model;
171
- }
172
-
173
284
  _checkMouse() {
174
285
  let newCoords = this._getMouseCoords();
175
286
 
@@ -180,10 +291,6 @@ class ModulesScenesPixiWrapper {
180
291
  this.emit(Urso.events.MODULES_SCENES_MOUSE_NEW_POSITION, this._mouseCoords);
181
292
  };
182
293
 
183
- getCachedMouseCoords() {
184
- return this._mouseCoords;
185
- }
186
-
187
294
  _getMouseCoords() {
188
295
  const coords = {
189
296
  x: ~~(this.interaction.mouse.global.x / this.world.scale.x),
@@ -204,7 +311,7 @@ class ModulesScenesPixiWrapper {
204
311
  * reserve loop, when browser tab is inactive
205
312
  * @param {Boolean} isVisible
206
313
  */
207
- visibilityChangeHandler(isVisible) {
314
+ _visibilityChangeHandler(isVisible) {
208
315
  if (isVisible) {
209
316
  if (this.passiveCallIntervalId) {
210
317
  clearInterval(this.passiveCallIntervalId);
@@ -215,22 +322,13 @@ class ModulesScenesPixiWrapper {
215
322
 
216
323
  this.passiveCallIntervalId = setInterval(() => {
217
324
  if (!this._loopStopped && !this._loopPaused) {
218
- this.update();
325
+ this._update();
219
326
  }
220
327
  }, 16);
221
328
  }
222
329
 
223
- /**
224
- * generateTexture from object
225
- * @param {Object} obj
226
- * @returns {Object} - pixi.Texture
227
- */
228
- generateTexture(obj) {
229
- return this.renderer.generateTexture(obj);
230
- }
231
-
232
330
  _subscribeOnce() {
233
- this.addListener(Urso.events.EXTRA_BROWSEREVENTS_WINDOW_VISIBILITYCHANGE, this.visibilityChangeHandler.bind(this), true);
331
+ this.addListener(Urso.events.EXTRA_BROWSEREVENTS_WINDOW_VISIBILITYCHANGE, this._visibilityChangeHandler.bind(this), true);
234
332
  }
235
333
  }
236
334