@urso/core 0.9.4-dev → 0.9.6-dev

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/README.md CHANGED
@@ -17,211 +17,759 @@ require('./app/config/load'); // your game application
17
17
 
18
18
  window.onload = Urso.runGame; //run game
19
19
  ```
20
+ ### Table of Contents ###
21
+ 1. Getting Started
22
+ 2. Project Structure
23
+ 3. Engine Architecture and Launch Process
24
+ 4. Objects Required for Game Launch
25
+ 5. Scenes, Scene Sizes, Templates, Components and Simple Objects
26
+ 6. Component Connection and Organization
27
+ 7. Object Visibility Order (Layers)
28
+ 8. Working with Scene Objects (Search, Selectors)
29
+ 9. Event Routers and Event-Driven Model (Observer)
30
+ 10. Dynamic Scene Object Creation
31
+ 11. Working with Classes and Entities
32
+ 12. Adding Sound and Sound/Event Mapping Configuration
33
+ 13. LazyLoad Mechanism (Asset Loading Groups)
34
+ 14. States Manager and Components.StateDriven
35
+ 15. LayersSwitcher Component
36
+ 16. Modifications and Mixins
37
+ 17. Transitions for Objects
38
+ 18. Game Text Localization
39
+ 19. Transport
40
+ 20. Additional Reference Sections
41
+ 20.1. Core Modules (Lib)
42
+ 20.2. Additional Information about Templates and Scenes
43
+ 20.3. Practical Recommendations, Debugging, Profiling
44
+ 20.4. Examples and API Reference (Compatible Elements)
45
+ 21. Extra (BrowserEvents, PixiPatch)
46
+ 22. Types (Urso.types)
47
+ 23. Events (Urso.events)
48
+ 24. Practical Patterns and Recommendations
49
+ 25. Optimization and Debugging
50
+ 26. FAQ
51
+ 27. Examples from A to Z
52
+ 28. API Reference
53
+ 29. Appendices
54
+ 30. Code Examples
55
+ 31. Links
56
+
57
+ 1. Getting Started
58
+ ------------------
59
+ After cloning the repository locally, you need to install all game dependencies before launching.
60
+
61
+ Game dependencies are installed with commands:
62
+ - yarn
63
+ - npm install
64
+
65
+ After installing dependencies, to launch the game you need to execute:
66
+ - yarn start
67
+ - npm run start
68
+
69
+ 2. Project Structure
70
+ --------------------
71
+ Game source code and resources are located in:
72
+ - src/app — source code (application)
73
+ - src/assets — resources (assets)
74
+
75
+ Each game must include:
76
+ - src/app/config/load.js — connection of all modules (js files), as well as game inheritance chain specification.
77
+ - src/app/config/main.js — setting important game parameters (name, default scene).
78
+ - src/js/index.js — application entry point. Engine code is connected through dependencies, load.js and main.js of the game. Once all engine files are loaded, you need to launch the application using Urso.runGame() function (usually on window.onload).
79
+
80
+ 3. Engine Architecture and Launch Process
81
+ ------------------------------------------
82
+ The game depends on Core by default.
83
+
84
+ Core consists of:
85
+ - Third-party libraries (Pixi, Howler...).
86
+ - Set of interfaces to these libraries.
87
+ - Transport module.
88
+ - Base components.
89
+ - Sound logic and button states.
90
+ - Game launch logic (Urso.Core.App).
91
+
92
+ After game launch begins, Core, going through established dependencies, will create all namespaces, all necessary objects and methods for game operation (see src/js/app.js in Core repository). Then it will call the run method.
93
+
94
+ Urso.Game assembly occurs based on extendingChain config (ConfigMain)
95
+ For example, if we defined game files in App namespace (window.Urso.App) then extendingChain should look as follows:
96
+ Urso.config.extendingChain = ['Urso.Core', 'Urso.App'];
97
+
98
+ Urso.runGame method in turn will begin loading the default scene using the scene manager.
99
+
100
+ 4. Objects Required for Game Launch
101
+ ------------------------------------
102
+ - Urso.helper — contains a set of helper methods for developer convenience (see src/js/lib/helper.js in Core repository).
103
+ - Urso.observer — provides event-driven model operation (see src/js/modules/observer in Core repository).
104
+ - Urso.cache — provides work with loaded resources (see src/js/lib/cache.js in Core repository).
105
+ - Urso.device — contains a set of methods for getting data from the device on which the game is running (see src/js/lib/device.js in Core repository).
106
+ - Urso.loader — wrapper class over standard PIXI resource loader (see src/js/lib/loader.js in Core repository).
107
+ - Urso.localData — provides work with local storage inside the game (see src/js/lib/localData.js in Core repository).
108
+ - Urso.assets — contains resource loading logic (see src/js/modules/assets in Core repository).
109
+ - Urso.logic — contains event router logic (see src/js/modules/logic in Core repository).
110
+ - Urso.objects — scene object creation logic (see src/js/modules/objects in Core repository).
111
+ - Urso.scenes — scene manager responsible for creating, displaying, scene transitions (see src/js/modules/scenes in Core repository).
112
+ - Urso.soundManager — manager for working with sounds (see src/js/modules/soundManager in Core repository).
113
+ - Urso.statesManager — manager for working with states (see src/js/modules/statesManager in Core repository).
114
+ - Urso.template — templating engine that provides work with templates (see src/js/modules/template in Core repository).
115
+ - Urso.browserEvents — browser event translator to game (see src/js/extra/browserEvents.js in Core repository).
116
+
117
+ 5. Scenes, Scene Sizes, Templates, Components and Simple Objects
118
+ ----------------------------------------------------------------
119
+ Scene — a set of objects that are present on screen and display some specific game state (main menu, loading screen, game level).
120
+
121
+ Canvas will occupy maximum available space on the page, based on proportions set in ModulesScenesResolutionsConfig, and parent scene container sizes (virtual pixels) will be determined based on ModulesScenesResolutionsConfig parameters.
122
+
123
+ If adaptive parameter is set to true, then canvas will occupy all available space, and scene sizes will be no less than specified, but one side may be increased to occupy maximum available space on the page. In this case adaptiveConfig starts working. You can set stretching boundaries for each orientation in it.
124
+
125
+ How the scene should look is described in the scene template (for example src/app/templates/scenes/play.js).
126
+
127
+ Template — includes descriptions of styles, resources and objects (simple and components) that need to be created.
128
+
129
+ A separate template group from the list of assets and objects is possible, for example src/app/templates/groups/testGroup.js, and displaying this group on the scene (see src/app/templates/scenes/play.js).
130
+
131
+ Styles are implemented through classes similar to CSS classes. Adding a class to an object automatically applies properties described in styles to it. You can use parameters for objects in styles and control them.
132
+
133
+ Assets — all resources in the game (images, text blocks, buttons, etc.). Asset set automatically gets into the loading list. Asset parameters are located (see src/js/modules/assets/baseModel in Core repository). Asset access is performed, for example, by key specified in asset group.
134
+
135
+ Simple objects — objects such as image, text, container, spine, etc. (see src/js/modules/objects/models in Core repository).
136
+
137
+ When creating a scene object, the templating engine collects all necessary assets and adds them to loading. After loading completion, scene manager begins creating all objects and components. Once components and objects are created — the scene is displayed on screen.
138
+
139
+ Built-in Components
140
+ - Loader — loading progress display
141
+ - Debug — debug metrics
142
+ - Fullscreen — fullscreen mode switching
143
+ - DeviceRotate — UI management with "wrong" orientation
144
+ - StateDriven — base state manager dependent component
145
+ - LayersSwitcher, SoundInitialPopup — service/utility (when available)
146
+
147
+ General best practices for components
148
+ - Don't interact between components directly — only through Observer
149
+ - Local subscriptions
150
+ - Selectors for searching inside component through this.common.find/One/All
151
+
152
+ 6. Component Connection and Organization
153
+ ----------------------------------------
154
+ To add a component, in src/app/config/load.js you need to specify the path to component name and in the component folder specify all files that need to be loaded into the game.
20
155
 
21
- ### Beginning ###
22
- Having cloned the repository to yourself locally, you must install all the game dependencies before starting.
156
+ Example:
157
+ - In src/app/config/load.js specify require('../components/_info'); where components folder name with components.
158
+ - _info — file where all js-files of current component are connected.
23
159
 
24
- Game dependencies are installing with yarn or npm install commands.
160
+ Components can consist of multiple simple objects, contain different logic, perform actions depending on game events. Component implements MVC-pattern modification, where:
161
+ - controller — external interface and event handlers (subscriptions).
162
+ - service — logic.
163
+ - view — interaction with scene objects.
164
+ - template — set of simple objects related to component.
165
+
166
+ Each component must contain controller; other files are added optionally, depending on the task.
25
167
 
26
- After installing the dependencies, you need to run the command yarn start or npm run start to start the game.
27
-
28
- ### How its working? ###
29
- The source code and assets of the game are located in src/app and src/assets.
168
+ Component interaction rules:
169
+ - Components should not independently interact with other components or know about their existence.
170
+ - Components can use helper libraries directly, for example, Urso.localData and Urso.helper. Communication with other entities should occur through events (Urso.observer).
30
171
 
31
- Each game must necessarily include the following:
32
- - src/app/config/load.js - connecting all modules (js files), as well as specifying the inheritance chain of the game.
33
- - src/app/config/main.js - important parameters for the game (name, scene by default)
34
- - src/js/index.js is the entry point of the application. The engine code is connected there through the dependencies, load.js and main.js of the game. As soon as all the engine files are loaded, you need to launch the application using the Urso.runGame() function (usually on window.onload)
172
+ Urso.localData object (cache) where you can write and get parameters for further work:
173
+ - Urso.localData.set(key, value) parameter writing.
174
+ - Urso.localData.get(name) value getting.
35
175
 
36
- The default game relies on Core.
176
+ 7. Object Visibility Order (Layers)
177
+ ------------------------------------
178
+ All objects have their visibility order — layer on scene. Each object can be behind or in front of another object.
37
179
 
38
- Core is: third-party libraries (Pixi, Howler ...), interfaces to these libraries, a transport module, a base component, logic for sounds and buttons states, and logic for launching a game (Urso.Core.App).
180
+ Order is implemented as follows:
181
+ - Top object specified in code (in object list, for example on scene) will be behind the object specified below it in the list — i.e., in the background.
39
182
 
40
- After starting the game, Core will create all the namespaces, all the necessary objects and methods for the game to work (see src/js/app.js in the Core repository). Next, it will call the run method.
41
-
42
- ### Objects required to run the game: ###
43
- - Urso.helper - contains a set of helper methods for the convenience of the developer (see src/js/lib/helper.js in the Core repository);
44
- - Urso.observer - provides an event-driven model of the game (see src/js/modules/observer in the Core repository);
45
- - Urso.cache - provides work with loaded resources (see src/js/lib/cache.js in the Core repository);
46
- - Urso.device - contains a set of methods for receiving data from the device on which the game is running (see src/js/lib/device.js in the Core repository);
47
- - Urso.loader - wrapper class over the standard PIXI resource loader (see src/js/lib/loader.js in the Core repository);
48
- - Urso.localData - provides work with local storage inside the game (see src/js/lib/localData.js in the Core repository);
49
- - Urso.assets - contains the logic for working with resource loading (see src/js/modules/assets in the Core repository);
50
- - Urso.logic - contains the logic of event routers (see src/js/modules/logic in the Core repository);
51
- - Urso.objects - the logic for creating scene objects (see src/js/modules/objects in the Core repository);
52
- - Urso.scenes - scene manager responsible for creating, displaying, scene transitions (see src/js/modules/scenes in the Core repository);
53
- - Urso.soundManager - manager for working with sounds (see src/js/modules/soundManager in the Core repository);
54
- - Urso.statesManager - a manager for working states (see src/js/modules/statesManager in the Core repository);
55
- - Urso.template - template engine that provides work with templates (see src/js/modules/template in the Core repository);
56
- - Urso.browserEvents - translator of browser events into the game (see src/js/extra/browserEvents.js in the Core repository);
183
+ 8. Working with Scene Objects (Search, Selectors)
184
+ --------------------------------------------------
185
+ Tools for working with scene objects (and from console):
186
+ - this.common.find returns false/object/collection (Urso.find('selector') for console access).
187
+ - this.common.findOne returns false/object (Urso.findOne('^name') for console access).
188
+ - this.common.findAll('.class') returns false/collection (Urso.findAll('.class') for console access).
57
189
 
58
- The Urso.runGame method, in turn, will start loading the default scene using the scene manager.
59
-
60
-
61
- ### Scenes, templates, components and simple objects ###
62
- Scene (scene) - a set of objects that are present on the screen and display some specific state of the game (main menu, loading screen, level in the game).
190
+ Search area:
191
+ - this.common.find() — search inside current component.
192
+ - Urso.find() — search at entire game level.
63
193
 
64
- How the scene should look is described in the template (for example src/app/templates/scenes/play.js).
194
+ Search modifier first symbol of passed argument:
195
+ - '^' — search by name;
196
+ - '.' — search by class;
197
+ - '#' — search by identifier (id);
198
+ - '' — if not specified, search by object type.
65
199
 
66
- Template (templates) - Template includes descriptions of styles, resources and objects (simple and components) that need to be created.
200
+ Selector combination of modifier and searched name. Example: '.logo' will search for objects that have 'logo' in class.
67
201
 
68
- Styles are implemented through classes, similar to classes in CSS.
202
+ Combined selectors:
203
+ - Urso.find('^nameContainer .classText') — search in '^nameContainer' object for objects with 'classText' class at any nesting level.
69
204
 
70
- Adding a class to an object automatically applies the properties described in the styles to it.
205
+ 9. Event Routers and Event-Driven Model (Observer)
206
+ ---------------------------------------------------
207
+ Event routers, using Urso.observer, control the state of entire game and individual components.
71
208
 
72
- The set of assets is automatically added to the download list.
209
+ The engine has a set of ready events (see src/js/modules/observer/events.js in Core repository).
73
210
 
74
- For objects, the procedure for creating them on the scene is described.
211
+ Core implements event router:
212
+ - Sounds — router controlling sound playback (see src/js/modules/logic/sounds in Core repository).
213
+ Similarly, you can organize logic of other entities.
75
214
 
76
- The template itself cannot change the states of objects.
215
+ Working with event-driven model is performed by methods:
216
+ - this.addListener('event.name', callback, isGlobal) — subscription.
217
+ - this.removeListener('event.name', callback, isGlobal) — unsubscription.
218
+ - this.emit('event.name', params, delay) — event generation.
77
219
 
78
- Components - Components can consist of many simple objects and unlike templates, their state can be controlled by event routers via Urso.observer.
220
+ Explanations:
221
+ - First argument — event name.
222
+ - Second — function called when event triggers.
223
+ - Third argument isGlobal — interception mode: locally (within current scene) or globally (for all scenes).
79
224
 
80
- Components should not independently interact with other components or be aware of their existence.
225
+ Recommendations:
226
+ - Perform subscription in _subscribeOnce method (call when creating class instance). Method will be called automatically when creating class using Urso.getInstance(...) class factory.
227
+ - At component level subscribe in controller.
228
+ - For components it's desirable to use local subscription.
81
229
 
82
- Components know and can use directly only helper libraries such as Urso.localData and Urso.helper. Communication with other entities should occur through events (Urso.observer).
230
+ Console access:
231
+ - Urso.observer.add — analog of this.addListener.
232
+ - Urso.observer.remove — analog of this.removeListener.
233
+ - Urso.observer.fire — analog of this.emit.
83
234
 
84
- The component implements a modification of the mvc pattern, where:
85
-
86
- - controller should contain only the external interface and event handlers (event subscriptions);
87
- - service contains all the logic;
88
- - view interacts with scene objects;
89
- - template contains a set of simple objects that refer to this component
90
-
91
- Simple objects (src/js/modules/objects/models) - Objects such as image, text, container, spine, etc.
92
-
93
- When creating a scene object, the template engine collects all the necessary assets and adds them to the download.
94
-
95
- After the download is complete, the scene manager starts creating all objects and components.
96
-
97
- As soon as the components and objects are created, the scene is displayed on the screen.
98
-
99
- Changes to the global state of the game and individual components occur in event routers. Also available is Urso.statesManager for switching game states through a set of Action objects.
100
-
101
-
102
- ### Event routers and working with the event-driven model (observer) ###
103
- Working with the event-driven model is carried out by the following methods:
104
- - this.addListener('event.name', callback, isGlobal) - used to subscribe to event 'event.name'.
105
- - this.removeListener('event.name', callback, isGlobal) - used to unsubscribe from event 'event.name'.
106
-
107
- The first argument is the name of the event.
108
-
109
- The second argument is a method (function) that will be executed in case of an event triggering.
110
-
111
- The event can be intercepted locally (within the current scene) and globally (for all scenes). Regulated by the third argument (isGlobal) when subscribing.
112
-
113
- It is recommended to subscribe inside the special functions _subscribe or _subscribeOnce, which are automatically called when the class is instantiated.
114
-
115
- At the component level, we recommend that you subscribe at the controller level.
116
-
117
- - this.emit('event.name', params, delay) - used to generate event 'event.name'.
118
-
119
- From the console observer is available with commands:
120
- - Urso.observer.add - analog of this.addListener for access from the console
121
- - Urso.observer.remove - analog of this.removeListener for console access
122
- - Urso.observer.fire - analogue of this.emit for access from the console
123
-
124
- It is desirable to use only local subscriptions for components.
125
-
126
-
127
- ### States Manager ###
128
- The state manager uses a collection of Action objects (src\js\modules\statesManager\configStates.js) and optionally StateDriven components.
129
-
130
- Action logic objects are described in src\js\modules\statesManager\configActions.js.
131
-
132
- When an attempt is made to activate an Action, the guard method is run, which returns true if the Action can be activated or false if not.
133
-
134
- If the StateDriven component is used, it automatically registers its guard with the state manager and there is no need to override the guard in the Action.
135
-
136
-
137
- States are configured by specifying the name of the state and the type of transition between Action:
138
- ```js
139
- STATE_NAME : { action: 'action_name' } // the state contains one Action and ends after it ends.
140
- ```
141
-
142
- ```js
143
- STATE_NAME : {
144
- all: [
145
- { action: 'action_0_name' },
146
- { action: 'action_1_name' }
147
- ]
148
- } // state contains a collection of Action and is completed after all Actions have completed.
149
- ```
150
-
151
- ```js
152
- STATE_NAME : {
153
- race: [
154
- { action: 'action_0_name' },
155
- { action: 'action_1_name' }
156
- ]
157
- } // the state contains a collection of Action and is completed after any Action has completed and all others have completed via terminateEvents.
158
- ```
159
-
160
- ```js
161
- STATE_NAME : {
162
- sequence: [
163
- { action: 'action_0_name' },
164
- { action: 'action_1_name' }
165
- ]
166
- } // the state contains the Action collection and is completed after all Actions are executed one by one
167
- ```
168
-
169
- terminateEvents - these are events leading to a quick termination of the component's logic.
170
-
171
- ### Event routers ###
172
- Event routers using Urso.observer manage both the state of the entire game and the state of individual components.
173
-
174
- Core implements two event routers:
175
- - Buttons - an event router that manages the state of buttons (see src/js/modules/logic/buttons in the Core repository);
176
- - Sounds - an event router that controls the playback of sounds (see src/js/modules/logic/sounds in the Core repository);
177
-
178
- ### Working with scene objects ###
179
- To work with scene objects (and from the console), you need to use the following tools:
180
- - this.common.find returns false/object/collection (Urso.find('selector') for console access);
181
- - this.common.findOne returns false/object (Urso.findOne('^name') for console access);
182
- - this.common.findAll('.class') returns false/collection (Urso.findAll('.class') for console access);
183
-
184
- The search modifier is the first character of the passed argument.
185
-
186
- The following modifiers are available:
187
- - '^' - Search by name (name);
188
- - '.' - Search by class (class);
189
- - '#' - Search by identifier (id);
235
+ 10. Dynamic Scene Object Creation
236
+ ----------------------------------
237
+ Objects can be created dynamically (for example, in components).
238
+
239
+ To create an object call Urso.objects.create with object parameters (first argument) and parent object (second argument, optional). If parent is not passed, object is created in root object (world).
240
+
241
+ Example:
242
+ Urso.objects.create(
243
+ {
244
+ type: Urso.types.objects.IMAGE,
245
+ assetKey: assetKey,
246
+ y: 250
247
+ },
248
+ someParentObject
249
+ );
190
250
 
191
- Given that objects can contain other objects, combinations of selectors are also available - Urso.find ('^nameContainer .classText').
251
+ 11. Working with Classes and Entities
252
+ -------------------------------------
253
+ Class access:
254
+ - this.getInstance('View') — returns object (instance) of View class of the same namespace. That is, for Components.Test.Controller returns object of Components.Test.View class.
255
+ - Urso.getInstance('Modules.Observer.Controller') — returns object (instance) of Observer.Controller class.
256
+ - Urso.getByPath('Modules.Observer.Controller') — returns reference to Observer.Controller class constructor.
192
257
 
193
- The search will search in an object named ^nameContainer for objects with class classText, and at any nesting level.
194
-
195
- ### Dynamically creating scene objects ###
196
- In order to create an object on the scene, you need to call the Urso.objects.create function and pass the desired object parameters to it as the first parameter and the parent object as the second.
258
+ These methods accept parameter path to needed class. Example:
259
+ - Urso.getInstance('Components.Button.Template') — get object of Button.Template class.
260
+ - Urso.getInstance('Components.Button.Template').objects array of objects defined in Template file.
261
+
262
+ Internal calls:
263
+ - In any class you can call this.getInstance('Template') to get Template instance of the same entity.
264
+
265
+ 12. Adding Sound and Sound/Event Mapping Configuration
266
+ -------------------------------------------------------
267
+ Sounds can be added for any game events: background music, button click sound, etc. Sounds are used as assets added to asset group.
268
+
269
+ Recommended approach — Atlas: set where necessary sounds are in one track; logic launches needed segment by name.
270
+
271
+ Sound logic is located (see src/js/modules/logic/config/sounds in Core repository).
272
+
273
+ Adding sound configuration:
274
+ - Create game file src/app/modules/logic/config/sounds.js.
275
+ - In sounds.js file in getSoundsConfig() method return object where property is group name and value is array of objects with parameters.
276
+
277
+ Record parameters:
278
+ - soundKey: 'backgroundTheme' — access key to sound asset.
279
+ - event: 'sounds.backgroundTheme.play' — event at which sound performs action (for example, playback).
280
+ - action — action: 'play', 'stop', 'pause', 'resume', 'fade'.
281
+ - relaunch: true — allow sound restart.
282
+ - loop: true — looped playback.
283
+
284
+ Action "fade" (volume dynamics):
285
+ - startSound (default false) — starts sound before fade execution.
286
+ - fadeDuration (default 200) — volume change duration.
287
+ - fadeTo (default 1) — final volume (0..1).
288
+
289
+ Example:
290
+ - In button logic create event this.emit('sounds.buttonMenu.play'), and in sounds.js config subscribe this event to needed soundKey/action.
291
+
292
+ { soundKey: 'sound1', event: 'sound1.play.once', action: 'play' },
293
+ { soundKey: 'sound_check', event: 'soundCheck.play.once', action: 'play' },
294
+ { soundKey: 'sound_check', event: 'soundCheck.stop', action: 'stop' },
295
+ { soundKey: 'sound_check', event: 'soundCheck.pause', action: 'pause' },
296
+ { soundKey: 'sound_check', event: 'soundCheck.resume', action: 'resume' },
297
+ { soundKey: 'sound_check', event: 'soundCheck.play.loop', action: 'play', relaunch: true, loop: true }
298
+
299
+ 13. LazyLoad Mechanism (Asset Loading Groups)
300
+ ----------------------------------------------
301
+ Urso.assets — resource loading logic (see src/js/modules/assets in Core repository).
302
+
303
+ Loading order:
304
+ - All assets without loadingGroup specification are loaded first by _startLoad method and have initial: 0 (see src/js/modules/assets/service in Core repository).
305
+ - Then groups are loaded by _startLazyLoad method by their loadingGroup.
306
+
307
+ Events:
308
+ - Upon group loading completion loader.start launches event Urso.events.MODULES_ASSETS_GROUP_LOADED (see src/js/modules/assets/service).
309
+ - Upon all groups loading completion — event Urso.events.MODULES_ASSETS_LAZYLOAD_FINISHED.
310
+
311
+ Prioritization:
312
+ - Group queue corresponds to order in lazyLoadGroups array (see src/js/modules/assets/config in Core repository).
313
+ - Example: loadingGroup: "lazy" and "afterLazy"; in config this.loadingGroups = { initial: 0, lazy: "lazy", afterLazy: "afterLazy" }, and this.lazyLoadGroups = [ this.loadingGroups.lazy, this.loadingGroups.afterLazy ] — priority "lazy", then "afterLazy".
314
+
315
+ 14. States Manager and Components.StateDriven
316
+ ----------------------------------------------
317
+ States manager — connection of logical module (Modules.States) controlling active states and their actions, and components inherited from base state-dependent component (Components.StateDriven).
197
318
 
198
- If the parent object is not passed, the object will be created in the root object (world)
319
+ Urso.statesManager manager for working with states (see src/js/modules/statesManager in Core repository).
199
320
 
200
- For example:
201
- ```js
202
- Urso.objects.create(
203
- {
204
- type: Urso.types.objects.IMAGE,
205
- assetKey: assetKey,
206
- y: 250
207
- },
208
- someParentObject
209
- );
210
- ```
321
+ States are launched sequentially after previous one completion. Or, if nextState key is set, then transition occurs to first state that passed guard in this array. Action launches if guard passes, which checks launch possibility.
211
322
 
212
- ### Working with classes and entities ###
213
- To work with classes, the following are used:
214
- - Urso.getInstance ('Modules.Observer.Controller') returns an object (instance) of the Observer.Controller class
215
- - Urso.getPath ('Modules.Observer.Controller') returns a reference to the constructor of the Observer.Controller class
323
+ States and transitions (see src\js\modules\statesManager\configStates.js):
324
+ - State can contain one action completes after its completion.
325
+ - State can contain multiple actions completes by transition rule.
216
326
 
217
- These two methods also support any number of modifiers, which allows more flexibility in applying the desired class in a specific environment.
327
+ Transition types:
328
+ - all — state completes after all actions execution.
329
+ - race — completes after any action completion; others complete through terminate.
330
+ - sequence — completes after all actions execution in order.
218
331
 
219
- For example, if you apply the modifier 'mobile', then Urso.getInstance ('Modules.Observer.Controller') will look for the constructor first in Modules.Observer.Mobile.Controller. If no such constructor is found, then the “default option” Modules.Observer.Controller will be returned;
332
+ Early completion:
333
+ - States can be completed early through terminate (see src\js\modules\statesManager\action.js).
334
+
335
+ configStates fragment:
336
+ STATE_NAME : { action: 'action_name' }
337
+ STATE_NAME : { all: [ { action: 'action_0_name' }, { action: 'action_1_name' } ] }
338
+ STATE_NAME : { race: [ { action: 'action_0_name' }, { action: 'action_1_name' } ] }
339
+ STATE_NAME : { sequence: [ { action: 'action_0_name' }, { action: 'action_1_name' } ] }
220
340
 
221
- Also, any class inside itself can call the following construction this.getInstance ('View'), which will return the desired class of the same entity, in our case it is a View instance
341
+ Components.StateDriven (see src/js/components/stateDriven):
342
+ - Has configStates — state entry checks (guard).
343
+ - Has configActions — actions for launch.
344
+ - Component implementation is made using _subscribeOnce method, so when inheriting from it, make sure to use super._subscribeOnce() call in your own _subscribeOnce method.
345
+
346
+ Component code example:
347
+ configStates = {
348
+
349
+ SHOW_MENU: {
350
+ guard: () => { return Urso.localData.get('states.allow.SHOW_MENU') },
351
+ },
352
+ };
353
+
354
+ configActions = {
355
+
356
+ menuOpenAction: {
357
+ guard: () => { return Urso.localData.get('spaceKey.input.blocked') }, // check if buttons are blocked
358
+ run: (finishCallback) => { this._changeVisibility(true), finishCallback() }, // execute if guard returned true
359
+ },
360
+
361
+ menuCloseMouseAction: {
362
+ run: (finishCallback) => { this._changeVisibility(false), finishCallback() }
363
+ terminate: () => { log('closed by menu button on screen') }, // output information how menu was closed.
364
+ },
365
+
366
+ menuCloseEscAction: {
367
+ run: (finishCallback) => { this._changeVisibility(false), finishCallback() }
368
+ terminate: () => { log('closed by Esc key on keyboard') }, // output information how menu was closed.
369
+ },
370
+ };
371
+
372
+ - SHOW_MENU state: actions — menuOpenAction (open), menuCloseEscAction (close by Esc), menuCloseButtonAction (close by button).
373
+ - After closing — transition nextState: ['WAIT'].
374
+ - In component controller state entry check (SHOW_MENU) through configStates; in configActions — open/close logic.
375
+
376
+ 15. LayersSwitcher Component
377
+ ----------------------------
378
+ Component for enabling and disabling layers in game (see urso\core\src\js\components\layersSwitcher).
379
+
380
+ Files:
381
+ - config.js — layer list and selectors for control.
382
+ - controller.js — component logic.
383
+
384
+ Subscription:
385
+ - controller.js is subscribed to event Urso.events.COMPONENTS_LAYERS_SWITCHER_SWITCH with parameter 'groupName' — name of enabled layer selector set.
386
+
387
+ Behavior:
388
+ - When event triggers, component makes all layers from managed layers list invisible and leaves only selected layer objects visible.
389
+
390
+ Configuration:
391
+ - this.allLayers[] — list of selectors of all managed objects.
392
+ - this.groupsLayers{} — enabled layer dependencies: key — group name; value — selector array.
393
+
394
+ this.groupsLayers example:
395
+ {
396
+ 'mainElements': ['^logo', '^mainButton', '.baseGame'],
397
+ 'background': ['.background'],
398
+ }
399
+
400
+ 16. Modifications and Mixins
401
+ -----------------------------
402
+ Modifications — code files executed instead of standard ones under certain condition.
403
+
404
+ Example of modifications connection in component info file:
405
+ Controller: require('./controller.js'),
406
+ Template: require('./template.js'),
407
+ modifications: { Desktop: { Controller: require('./modifications/desktop/controller.js') } }
408
+
409
+ If Urso.getInstancesModes() contains Desktop, controller from modifications/desktop/controller.js will be loaded. Otherwise — standard Controller.
410
+
411
+ Mixins — methods for reuse in different unrelated classes.
412
+
413
+ Mixin connection (similar to modifications):
414
+ mixins: { Desktop: { Controller: require('./mixins/desktop/controller.js') } }
415
+
416
+ If Urso.getInstancesModes() contains Desktop — method from mixin ('./mixins/desktop/controller.js') will execute in component Controller.
417
+
418
+ 17. Transitions for Objects
419
+ ----------------------------
420
+ Transition — smooth transformation (see src\js\modules\objects\baseModel.js in Core repository).
421
+
422
+ Parameters:
423
+ - transitionDelay — delay (ms) before transition start (optional).
424
+ - transitionDuration — transition duration.
425
+ - transitionProperty — list of keys whose change initiates transition.
426
+
427
+ Example:
428
+ transitionDelay: 1000
429
+ transitionDuration: 2000
430
+ transitionProperty: "alpha x y"
431
+
432
+ Changing:
433
+ - object.alpha = 1 (appearance) or 0 (disappearance).
434
+ - object.x = 200; object.y = 300 (diagonal movement).
435
+ You can set one coordinate for axis movement.
436
+
437
+ 18. Game Text Localization
438
+ ---------------------------
439
+ Text translation to different languages is performed through JSON localization files for each language. Structure: translation key — text.
440
+
441
+ Example:
442
+ "RULES_HEADER": "First Level",
443
+ "RULES": "Rules",
444
+ "MY_BET_ITEM_TIME": "Time",
445
+ "Bet": "Bet"
446
+
447
+ Usage:
448
+ - In text object add localeId parameter with translation key. In this case localization will be pulled automatically.
449
+ - Connect json localization file in assets.
450
+ - Execute command Urso.core.i18n.setLocale(localeKey), where localeKey — json localization file name.
451
+
452
+ 18.2. Code Usage
453
+ - Urso.i18n.get(localeId, localeVariables?)
454
+ - Urso.i18n.setLocale(localeKey)
455
+ - Urso.i18n.loadAndSetLocale(localeKey, pathToLocaleJson)
456
+
457
+ 18.3. UI Auto-update
458
+ - Use localeId instead of text in text objects
459
+ - Listen to language change event (Urso.events.MODULES_I18N_NEW_LOCALE_WAS_SET) and update texts
460
+
461
+ 19. Transport
462
+ -------------
463
+ 19.1. Connection Type Support
464
+ - websocket, xhr (by configuration)
465
+
466
+ 19.2. Configuration
467
+ - useTransport: true/false (ConfigMain)
468
+ - autoReconnect: boolean,
469
+ - reconnectTimeout: number in ms,
470
+ - type: websocket | xhr
471
+ - host: string
472
+
473
+ 19.3. ModulesTransportDecorator Decorator
474
+ - toServer/toFront
475
+
476
+ 20. Additional Reference Sections
477
+
478
+ 20.1. Core Modules (Lib)
479
+ - helper — utilities (for example, parseGetParams, waitForDomElement, arraysGetUniqElements, replaceAll, recursiveGet, mergeObjectsRecursive).
480
+ - cache — get/has/set/remove/clear.
481
+ - device — device data (isMobile/tablet/desktop; getScreenSize/Width/Height; getOrientation; getPixelRatio).
482
+ - loader — PIXI.Loader overlay: add(key,url), load(cb), onProgress.add(cb).
483
+ - localData — local key-value storage.
484
+ - logger — logging levels: ERROR, WARNING, INFO, LOG (level is set in configuration and can be overridden through URL parameter).
485
+ - math, time, tween, objectPool, composition — service utilities/infrastructure.
486
+
487
+ 20.2. Additional Information about Templates and Scenes
488
+ - Template consists of styles, resource list (assets) and object tree (objects).
489
+ - Control methods are available for scenes, including scene switching, FPS getting, pause/resume.
490
+
491
+ 20.3. Practical Recommendations, Debugging, Profiling
492
+ - For event work clear domain naming is recommended: ui.*, game.*, modules.*, components.*.
493
+ - For assets — grouping and lazyLoad; for weak devices — FPS limitation (config.fps.limit) and optimizeLowPerformance mode.
494
+ - For sound consider tab visibility rules (browser event handling).
495
+ - Debug component — for FPS/metrics monitoring
496
+
497
+ 21. Extra (BrowserEvents, PixiPatch)
498
+ ------------------------------------
499
+ 21.1. BrowserEvents
500
+ - Browser event translation (resize, visibilitychange, input) to engine events: EXTRA_BROWSEREVENTS_*
501
+ - Provides scene/sound/render reaction
502
+
503
+ 21.2. PixiPatch
504
+ - PIXI fixes/extensions
505
+
506
+ 22. Types (Urso.types)
507
+ ----------------------
508
+ 22.1. assets
509
+ - ATLAS, AUDIOSPRITE, BITMAPFONT, CONTAINER, FONT, IMAGE, JSON, JSONATLAS, SOUND, SPINE, HTML
510
+
511
+ 22.2. objects
512
+ Object types (Urso.types.objects)
513
+ - ATLASIMAGE, BITMAPTEXT, BUTTON, BUTTONCOMPOSITE, CHECKBOX, COLLECTION, COMPONENT, CONTAINER, DRAGCONTAINER, EMITTER, EMITTERFX, GRAPHICS, GROUP, HITAREA, IMAGE, IMAGESANIMATION, MASK, NINESLICEPLANE, SCROLLBOX, SLIDER, SPINE, TEXT, TEXTINPUT, TOGGLE, WORLD
514
+
515
+ Creation
516
+ - Urso.objects.create(params, parent?)
517
+
518
+ Example:
519
+ Urso.objects.create({
520
+ type: Urso.types.objects.IMAGE,
521
+ assetKey: 'logo',
522
+ x: 100, y: 100, name: 'logo'
523
+ }, someParent);
524
+
525
+ Search
526
+ - this.common.find / findOne / findAll
527
+ - Urso.find / findOne / findAll (console)
528
+ - Selectors: ^name, .class, #id; combined: '^container .className'
529
+
530
+ Base model properties (ModulesObjectsBaseModel)
531
+ - Position, scale, anchors, visibility, alpha, angle, sizes, classes/identifiers (can be found in setupParams)
532
+
533
+ Specific object model properties contain all base model properties as well as their own properties, which can be found in model setupParams.
534
+
535
+ Specialized objects
536
+ - Button/Toggle/Checkbox/Slider — interactive; Scrollbox — scrolling; Spine — animation; Emitter — particles; NineSlicePlane — adaptive panels; Text/TextInput/BitmapText — text
537
+
538
+ 22.3. Other Enumerations
539
+ - Screen orientations: Urso.device.ScreenOrientation.LANDSCAPE/ PORTRAIT
540
+ - Engine constants
541
+
542
+ 23. Events (Urso.events)
543
+ ------------------------
544
+ 23.1. System Event Examples
545
+ - MODULES_SCENES_NEW_SCENE_INIT
546
+ - EXTRA_BROWSEREVENTS_WINDOW_RESIZE
547
+ - MODULES_ASSETS_LOAD_PROGRESS
548
+
549
+ 23.2. Naming Conventions
550
+ - module.domain.action
551
+ - ui.*, game.*, sound.*, scenes.*, assets.*, transport.*
552
+
553
+ 24. Practical Patterns and Recommendations
554
+ -------------------------------------------
555
+ 24.1. Abstraction Layers
556
+ - Logic — in services/routers
557
+ - Presentation — in View and templates
558
+ - Controller — only API/subscriptions
559
+
560
+ 24.2. Selectors
561
+ - Use ^, #, . and combinations
562
+ - Don't overload search — cache references to frequently used objects
563
+
564
+ 24.3. Events
565
+ - Minimize global subscriptions
566
+ - Remove subscriptions on destruction
567
+
568
+ 24.4. Performance
569
+ - Group resources
570
+ - Tune fps and quality
571
+ - Use audiosprites and atlases
572
+ - Disable invisible containers
573
+
574
+ 24.5. Asset Organization
575
+ - Coordinate keys and paths
576
+ - Include webp when supported
577
+ - Control name intersections in atlases
578
+
579
+ 24.6. Sound
580
+ - Keep sound and event mapping config centralized
581
+
582
+ 24.7. States
583
+ - Break complex states into all/race/sequence combinations
584
+ - Use terminateEvents for graceful parallel Action stopping
585
+
586
+ 25. Optimization and Debugging
587
+ -------------------------------
588
+ 25.1. Debug Component
589
+ - FPS display, draw calls, object count
590
+ - Coordinate switcher
591
+
592
+ 25.2. Profiling
593
+ - scenes.getFps(), getFpsData()
594
+ - Logger with levels
595
+ - Custom profiler when needed
596
+
597
+ 25.3. Memory and Cache
598
+ - Watch large textures/sprites
599
+ - Use LibObjectPool for object reuse
600
+
601
+ 25.4. Build
602
+ - Debug build:dev; minimize build:prod
603
+
604
+ 26. FAQ
605
+ -------
606
+ - How to launch game? — see Quick Start: index.js + load.js + runGame
607
+ - Where to connect modules? — config/load.js
608
+ - How to add scene? — create template and register scene in Template/Scenes
609
+ - How to play sound on event? — add record in modules/logic/config/sounds.js and emit event
610
+ - How to find object? — this.common.find/One/All or Urso.find*/ selectors ^ . #
611
+ - How to configure asset quality? — through Urso.assets.updateQuality/ setQuality and qualityFactors config
612
+
613
+ 27. Examples from A to Z
614
+ ------------------------
615
+ 27.1. Mini-menu + game transition
616
+ - main.js: defaultScene = 'menu'
617
+ - load.js: require('./scenes/menu'); require('./scenes/game');
618
+ - In Menu template: PLAY button calls Urso.scenes.display('game')
619
+
620
+ 27.2. Dynamic object creation
621
+ Urso.objects.create({ type: Urso.types.objects.TEXT, text: 'Hello', x: 100, y: 100 });
622
+
623
+ 27.3. Selectors
624
+ Urso.find('^container .className'); Urso.findOne('#uniqueId'); Urso.findAll('.buttonClass');
625
+
626
+ 27.4. Events
627
+ this.addListener('game.start', handler); this.emit('game.start', { level: 1 });
628
+
629
+ 27.5. States
630
+ STATE: { sequence: [ { action: 'a0' }, { action: 'a1' } ] }
631
+
632
+ 27.6. Sound on event
633
+ sounds.js: { soundKey: 'sfxClick', event: 'ui.click', action: 'play' }
634
+ emit: this.emit('ui.click')
635
+
636
+ 27.7. Lazy asset loading
637
+ - Add group to lazyLoadGroups
638
+ - When needed call loading from logic/component
639
+
640
+ 27.8. Fullscreen mode
641
+ emit('fullscreen.toggle')
642
+
643
+ 27.9. Debug
644
+ Add Debug component to scene for monitoring
645
+
646
+ 28. API Reference
647
+ -----------------
648
+ 28.1. Core/Global
649
+ - Urso.runGame()
650
+ - Urso.getInstance(path, ...modifiers)
651
+ - Urso.getByPath(path, ...modifiers)
652
+ - Urso.find / findOne / findAll
653
+
654
+ 28.2. Observer
655
+ - addListener(name, cb, isGlobal?)
656
+ - removeListener(name, cb, isGlobal?)
657
+ - emit(name, params?, delay?)
658
+
659
+ 28.3. Assets/Loader/Cache
660
+ - assets.preload(assets, onComplete, onProgress?, onError?)
661
+ - assets.loadGroup(groupName, onComplete, onProgress?, onError?)
662
+ - loader.add(key, url); loader.load(cb); loader.onProgress.add(cb)
663
+ - cache.get/has/set/remove/clear
664
+
665
+ 28.4. Objects
666
+ - objects.create(params, parent?)
667
+ - Model properties: position, scale, anchor, visibility, etc.
668
+
669
+ 28.5. Scenes
670
+ - scenes.display(name), getFps(), getFpsData(), pause(), resume()
671
+
672
+ 28.6. I18n
673
+ - Urso.i18n.get(localeId, localeVariables?)
674
+ - Urso.i18n.setLocale(localeKey)
675
+ - Urso.i18n.loadAndSetLocale(localeKey, pathToLocaleJson)
676
+
677
+ 28.7. Device
678
+ - isMobile/tablet/desktop/touch
679
+ - getScreenWidth/Height(), getOrientation(), getPixelRatio()
680
+
681
+ 28.8. Logger
682
+ - error/warning/info/log; levels through defaultLogLevel
683
+
684
+ 29. Appendices
685
+ --------------
686
+ 29.1. Naming Conventions
687
+ - Event names: domain.action.detail (for example, sound.play.click, ui.button.play.click)
688
+ - Object names: clear and unique for findOne '^name'
689
+ - Object classes: '.class-name' reflects role/style
690
+
691
+ 29.2. Release Checklist
692
+ - Loading groups and lazyLoad checked
693
+ - Asset quality chosen for devices
694
+ - Sound config matches actual assets
695
+ - Logs and levels reduced for production
696
+ - Performance on target devices measured
697
+
698
+ 30. Code Examples
699
+ -----------------
700
+ index.js
701
+
702
+ require("@urso/core");
703
+ require("./app/config/load");
704
+ window.onload = Urso.runGame;
705
+
706
+ config/main.js
707
+ //overriding core config
708
+ Urso.config.extendingChain = ['Urso.Core', 'Urso.App'];
709
+ Urso.config.title = 'SomeGame';
710
+ Urso.config.appVersion = '1.11.10'; //game anticache get param
711
+ Urso.config.defaultScene = 'play'; //default game scene for urso engine
712
+
713
+ config/load.js
714
+
715
+ window.Urso.App = {
716
+ Components: {
717
+ Bg: {
718
+ Controller: require('./../components/bg/controller.js'),
719
+ Template: require('./../components/bg/template.js'),
720
+ },
721
+ Intro: {
722
+ Controller: require('./../components/intro/controller.js'),
723
+ Template: require('./../components/intro/template.js'),
724
+ },
725
+ LayersSwitcher: {
726
+ Config: require('./../components/layersSwitcher/config.js') //config for core LayersSwitcher component
727
+ },
728
+ SoundsInit: {
729
+ Controller: require('./../components/soundsInit/controller.js'),
730
+ },
731
+ },
732
+ Modules: {
733
+ I18n: {
734
+ Config: require('./../modules/i18n/config.js')
735
+ },
736
+ Logic: {
737
+ Controller: require('./../modules/logic/controller'),
738
+ Main: require('./../modules/logic/main'),
739
+ Config: {
740
+ Sounds: require('./../modules/logic/config/sounds.js') //sounds router
741
+ }
742
+ },
743
+ Observer: {
744
+ Events: require('../modules/observer/events') //custom events config
745
+ },
746
+ Scenes: {
747
+ ResolutionsConfig: require('./../modules/scenes/resolutionsConfig.js'),
748
+ }
749
+ },
750
+ Templates: {
751
+ Scenes: {
752
+ Play: require('./../templates/scenes/play.js')
753
+ },
754
+ Groups: {
755
+ AtlasLoadGroup: require('./../templates/groups/atlasLoadGroup.js'),
756
+ RestAssetsLoadGroup: require('./../templates/groups/restAssetsLoadGroup.js'),
757
+ }
758
+ },
759
+ };
760
+
761
+ require('./main.js');
762
+
763
+ 31. Links
764
+ ---------
765
+ - https://ursojs.io/examples.html
766
+ - https://github.com/megbrimef/urso-examples
767
+ - https://github.com/megbrimef/urso
768
+ - https://github.com/megbrimef/urso-slot-base
769
+ - https://discord.gg/JauD9CbDHA
222
770
 
223
771
 
224
772
  ### License ###
225
773
  By Lancecat Games
226
774
 
227
- This content is released under the (http://opensource.org/licenses/MIT) MIT License.
775
+ This content is released under the (http://opensource.org/licenses/MIT) MIT License.