@vpmedia/phaser 1.0.1 → 1.0.2
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/phaser.cjs.LICENSE.txt +1 -1
- package/dist/phaser.js.LICENSE.txt +1 -1
- package/package.json +2 -3
- package/src/index.js +99 -0
- package/src/phaser/core/animation.js +355 -0
- package/src/phaser/core/animation_manager.js +238 -0
- package/src/phaser/core/animation_parser.js +130 -0
- package/src/phaser/core/array_set.js +108 -0
- package/src/phaser/core/cache.js +558 -0
- package/src/phaser/core/const.js +106 -0
- package/src/phaser/core/device.js +67 -0
- package/src/phaser/core/device_util.js +386 -0
- package/src/phaser/core/dom.js +207 -0
- package/src/phaser/core/event_manager.js +243 -0
- package/src/phaser/core/factory.js +74 -0
- package/src/phaser/core/frame.js +75 -0
- package/src/phaser/core/frame_data.js +84 -0
- package/src/phaser/core/frame_util.js +31 -0
- package/src/phaser/core/game.js +412 -0
- package/src/phaser/core/input.js +401 -0
- package/src/phaser/core/input_button.js +102 -0
- package/src/phaser/core/input_handler.js +687 -0
- package/src/phaser/core/input_mouse.js +289 -0
- package/src/phaser/core/input_mspointer.js +197 -0
- package/src/phaser/core/input_pointer.js +427 -0
- package/src/phaser/core/input_touch.js +157 -0
- package/src/phaser/core/loader.js +946 -0
- package/src/phaser/core/loader_parser.js +105 -0
- package/src/phaser/core/raf.js +46 -0
- package/src/phaser/core/raf_fb.js +75 -0
- package/src/phaser/core/raf_to.js +34 -0
- package/src/phaser/core/scale_manager.js +806 -0
- package/src/phaser/core/scene.js +66 -0
- package/src/phaser/core/scene_manager.js +310 -0
- package/src/phaser/core/signal.js +175 -0
- package/src/phaser/core/signal_binding.js +69 -0
- package/src/phaser/core/sound.js +538 -0
- package/src/phaser/core/sound_manager.js +365 -0
- package/src/phaser/core/stage.js +108 -0
- package/src/phaser/core/time.js +203 -0
- package/src/phaser/core/timer.js +276 -0
- package/src/phaser/core/timer_event.js +21 -0
- package/src/phaser/core/tween.js +329 -0
- package/src/phaser/core/tween_data.js +258 -0
- package/src/phaser/core/tween_easing.js +316 -0
- package/src/phaser/core/tween_manager.js +185 -0
- package/src/phaser/core/world.js +18 -0
- package/src/phaser/display/bitmap_text.js +322 -0
- package/src/phaser/display/button.js +194 -0
- package/src/phaser/display/canvas/buffer.js +36 -0
- package/src/phaser/display/canvas/graphics.js +227 -0
- package/src/phaser/display/canvas/masker.js +39 -0
- package/src/phaser/display/canvas/pool.js +121 -0
- package/src/phaser/display/canvas/renderer.js +123 -0
- package/src/phaser/display/canvas/tinter.js +141 -0
- package/src/phaser/display/canvas/util.js +151 -0
- package/src/phaser/display/display_object.js +597 -0
- package/src/phaser/display/graphics.js +723 -0
- package/src/phaser/display/graphics_data.js +27 -0
- package/src/phaser/display/graphics_data_util.js +14 -0
- package/src/phaser/display/group.js +227 -0
- package/src/phaser/display/image.js +288 -0
- package/src/phaser/display/sprite_batch.js +15 -0
- package/src/phaser/display/sprite_util.js +248 -0
- package/src/phaser/display/text.js +1089 -0
- package/src/phaser/display/webgl/abstract_filter.js +25 -0
- package/src/phaser/display/webgl/base_texture.js +68 -0
- package/src/phaser/display/webgl/blend_manager.js +35 -0
- package/src/phaser/display/webgl/earcut.js +647 -0
- package/src/phaser/display/webgl/earcut_node.js +28 -0
- package/src/phaser/display/webgl/fast_sprite_batch.js +242 -0
- package/src/phaser/display/webgl/filter_manager.js +46 -0
- package/src/phaser/display/webgl/filter_texture.js +61 -0
- package/src/phaser/display/webgl/graphics.js +618 -0
- package/src/phaser/display/webgl/graphics_data.js +42 -0
- package/src/phaser/display/webgl/mask_manager.js +36 -0
- package/src/phaser/display/webgl/render_texture.js +81 -0
- package/src/phaser/display/webgl/renderer.js +234 -0
- package/src/phaser/display/webgl/shader/complex.js +74 -0
- package/src/phaser/display/webgl/shader/fast.js +97 -0
- package/src/phaser/display/webgl/shader/normal.js +225 -0
- package/src/phaser/display/webgl/shader/primitive.js +72 -0
- package/src/phaser/display/webgl/shader/strip.js +77 -0
- package/src/phaser/display/webgl/shader_manager.js +89 -0
- package/src/phaser/display/webgl/sprite_batch.js +320 -0
- package/src/phaser/display/webgl/stencil_manager.js +170 -0
- package/src/phaser/display/webgl/texture.js +117 -0
- package/src/phaser/display/webgl/texture_util.js +32 -0
- package/src/phaser/display/webgl/util.js +74 -0
- package/src/phaser/geom/circle.js +186 -0
- package/src/phaser/geom/ellipse.js +65 -0
- package/src/phaser/geom/line.js +190 -0
- package/src/phaser/geom/matrix.js +147 -0
- package/src/phaser/geom/point.js +164 -0
- package/src/phaser/geom/polygon.js +141 -0
- package/src/phaser/geom/rectangle.js +306 -0
- package/src/phaser/geom/rounded_rectangle.js +36 -0
- package/src/phaser/geom/util/circle.js +115 -0
- package/src/phaser/geom/util/ellipse.js +30 -0
- package/src/phaser/geom/util/line.js +130 -0
- package/src/phaser/geom/util/matrix.js +48 -0
- package/src/phaser/geom/util/point.js +276 -0
- package/src/phaser/geom/util/polygon.js +24 -0
- package/src/phaser/geom/util/rectangle.js +212 -0
- package/src/phaser/geom/util/rounded_rectangle.js +28 -0
- package/src/phaser/util/math.js +279 -0
- package/src/phaser/util/string.js +26 -0
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author Andras Csizmadia <andras@vpmedia.hu>
|
|
3
|
+
* @author Richard Davey <rich@photonstorm.com>
|
|
4
|
+
* @copyright Copyright (c) 2018-present Richard Davey, Photon Storm Ltd., Andras Csizmadia <andras@vpmedia.hu> (www.vpmedia.hu)
|
|
5
|
+
*/
|
|
6
|
+
import ArraySet from './array_set';
|
|
7
|
+
import Signal from './signal';
|
|
8
|
+
import Sound from './sound';
|
|
9
|
+
|
|
10
|
+
export default class {
|
|
11
|
+
|
|
12
|
+
constructor(game) {
|
|
13
|
+
this.game = game;
|
|
14
|
+
this.onSoundDecode = new Signal();
|
|
15
|
+
this.onVolumeChange = new Signal();
|
|
16
|
+
this.onMute = new Signal();
|
|
17
|
+
this.onUnMute = new Signal();
|
|
18
|
+
this.context = null;
|
|
19
|
+
this.baseLatency = 0; // https://developer.mozilla.org/en-US/docs/Web/API/AudioContext/baseLatency
|
|
20
|
+
this.usingWebAudio = false;
|
|
21
|
+
this.usingAudioTag = false;
|
|
22
|
+
this.noAudio = false;
|
|
23
|
+
this.connectToMaster = true;
|
|
24
|
+
this.touchLocked = false;
|
|
25
|
+
this.muteOnPause = true;
|
|
26
|
+
this._codeMuted = false;
|
|
27
|
+
this._muted = false;
|
|
28
|
+
this._unlockSource = null;
|
|
29
|
+
this._volume = 1;
|
|
30
|
+
this._sounds = [];
|
|
31
|
+
this._watchList = new ArraySet();
|
|
32
|
+
this._watching = false;
|
|
33
|
+
this._watchCallback = null;
|
|
34
|
+
this._watchContext = null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
boot() {
|
|
38
|
+
if (window.PhaserRegistry && window.PhaserRegistry.audioContext) {
|
|
39
|
+
this.context = window.PhaserRegistry.audioContext;
|
|
40
|
+
} else if (window.AudioContext) {
|
|
41
|
+
try {
|
|
42
|
+
this.context = new window.AudioContext();
|
|
43
|
+
} catch (error) {
|
|
44
|
+
this.context = null;
|
|
45
|
+
this.usingWebAudio = false;
|
|
46
|
+
this.touchLocked = false;
|
|
47
|
+
}
|
|
48
|
+
} else if (window.webkitAudioContext) {
|
|
49
|
+
try {
|
|
50
|
+
/* eslint-disable new-cap */
|
|
51
|
+
this.context = new window.webkitAudioContext();
|
|
52
|
+
} catch (error) {
|
|
53
|
+
this.context = null;
|
|
54
|
+
this.usingWebAudio = false;
|
|
55
|
+
this.touchLocked = false;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (this.context === null || (this.context && this.context.createGain === undefined && this.context.createGainNode === undefined)) {
|
|
59
|
+
// No Web Audio support - how about legacy Audio?
|
|
60
|
+
if (window.Audio === undefined) {
|
|
61
|
+
this.noAudio = true;
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
this.usingAudioTag = true;
|
|
65
|
+
} else {
|
|
66
|
+
this.usingWebAudio = true;
|
|
67
|
+
this.baseLatency = this.context.baseLatency || (256 / (this.context.sampleRate || 44100));
|
|
68
|
+
if (this.context.createGain === undefined) {
|
|
69
|
+
this.masterGain = this.context.createGainNode();
|
|
70
|
+
} else {
|
|
71
|
+
this.masterGain = this.context.createGain();
|
|
72
|
+
}
|
|
73
|
+
this.masterGain.gain.value = 1;
|
|
74
|
+
this.masterGain.connect(this.context.destination);
|
|
75
|
+
if (this.context.state === 'suspended') {
|
|
76
|
+
this.game.input.onUp.addOnce(this.resumeWebAudio, this);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (!this.noAudio && !this.game.device.cocoonJS && (this.game.device.iOS || this.game.device.android)) {
|
|
80
|
+
this.game.input.addTouchLockCallback(this.unlock, this, true);
|
|
81
|
+
this.touchLocked = true;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
resumeWebAudio() {
|
|
86
|
+
if (this.usingWebAudio && this.context.state === 'suspended') {
|
|
87
|
+
this.context.resume();
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
unlock() {
|
|
92
|
+
if (this.noAudio || !this.touchLocked || this._unlockSource !== null) {
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
// Global override (mostly for Audio Tag testing)
|
|
96
|
+
if (this.usingAudioTag) {
|
|
97
|
+
this.touchLocked = false;
|
|
98
|
+
this._unlockSource = null;
|
|
99
|
+
} else if (this.usingWebAudio) {
|
|
100
|
+
// Create empty buffer and play it
|
|
101
|
+
// The SoundManager.update loop captures the state of it and then resets touchLocked to false
|
|
102
|
+
const buffer = this.context.createBuffer(1, 1, 22050);
|
|
103
|
+
this._unlockSource = this.context.createBufferSource();
|
|
104
|
+
this._unlockSource.buffer = buffer;
|
|
105
|
+
this._unlockSource.connect(this.context.destination);
|
|
106
|
+
if (this._unlockSource.start === undefined) {
|
|
107
|
+
this._unlockSource.noteOn(0);
|
|
108
|
+
} else {
|
|
109
|
+
this._unlockSource.start(0);
|
|
110
|
+
}
|
|
111
|
+
this.resumeWebAudio();
|
|
112
|
+
}
|
|
113
|
+
// We can remove the event because we've done what we needed (started the unlock sound playing)
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
stopAll() {
|
|
118
|
+
if (this.noAudio) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
for (let i = 0; i < this._sounds.length; i += 1) {
|
|
122
|
+
if (this._sounds[i]) {
|
|
123
|
+
this._sounds[i].stop();
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
pauseAll() {
|
|
129
|
+
if (this.noAudio) {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
for (let i = 0; i < this._sounds.length; i += 1) {
|
|
133
|
+
if (this._sounds[i]) {
|
|
134
|
+
this._sounds[i].pause();
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
resumeAll() {
|
|
140
|
+
if (this.noAudio) {
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
for (let i = 0; i < this._sounds.length; i += 1) {
|
|
144
|
+
if (this._sounds[i]) {
|
|
145
|
+
this._sounds[i].resume();
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
decode(key, sound = null) {
|
|
151
|
+
const soundData = this.game.cache.getSoundData(key);
|
|
152
|
+
if (soundData) {
|
|
153
|
+
if (this.game.cache.isSoundDecoded(key) === false) {
|
|
154
|
+
this.game.cache.updateSound(key, 'isDecoding', true);
|
|
155
|
+
const scope = this;
|
|
156
|
+
try {
|
|
157
|
+
this.context.decodeAudioData(soundData, (buffer) => {
|
|
158
|
+
if (buffer) {
|
|
159
|
+
scope.game.cache.decodedSound(key, buffer);
|
|
160
|
+
scope.onSoundDecode.dispatch(key, sound);
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
} catch (e) {
|
|
164
|
+
// pass
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
setDecodedCallback(files, callback, callbackContext) {
|
|
171
|
+
if (typeof files === 'string') {
|
|
172
|
+
files = [files];
|
|
173
|
+
}
|
|
174
|
+
this._watchList.reset();
|
|
175
|
+
for (let i = 0; i < files.length; i += 1) {
|
|
176
|
+
if (files[i] instanceof Sound) {
|
|
177
|
+
if (!this.game.cache.isSoundDecoded(files[i].key)) {
|
|
178
|
+
this._watchList.add(files[i].key);
|
|
179
|
+
}
|
|
180
|
+
} else if (!this.game.cache.isSoundDecoded(files[i])) {
|
|
181
|
+
this._watchList.add(files[i]);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
// All decoded already?
|
|
185
|
+
if (this._watchList.total === 0) {
|
|
186
|
+
this._watching = false;
|
|
187
|
+
callback.call(callbackContext);
|
|
188
|
+
} else {
|
|
189
|
+
this._watching = true;
|
|
190
|
+
this._watchCallback = callback;
|
|
191
|
+
this._watchContext = callbackContext;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
update() {
|
|
196
|
+
if (this.noAudio) {
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
if (this.touchLocked && this._unlockSource !== null && (this._unlockSource.playbackState === this._unlockSource.PLAYING_STATE || this._unlockSource.playbackState === this._unlockSource.FINISHED_STATE)) {
|
|
200
|
+
this.touchLocked = false;
|
|
201
|
+
this._unlockSource = null;
|
|
202
|
+
this.resumeWebAudio();
|
|
203
|
+
} else if (this.usingWebAudio && this.context.state === 'interrupted') {
|
|
204
|
+
this.context.resume();
|
|
205
|
+
}
|
|
206
|
+
for (let i = 0; i < this._sounds.length; i += 1) {
|
|
207
|
+
this._sounds[i].update();
|
|
208
|
+
}
|
|
209
|
+
if (this._watching) {
|
|
210
|
+
let key = this._watchList.first;
|
|
211
|
+
while (key) {
|
|
212
|
+
if (this.game.cache.isSoundDecoded(key)) {
|
|
213
|
+
this._watchList.remove(key);
|
|
214
|
+
}
|
|
215
|
+
key = this._watchList.next;
|
|
216
|
+
}
|
|
217
|
+
if (this._watchList.total === 0) {
|
|
218
|
+
this._watching = false;
|
|
219
|
+
this._watchCallback.call(this._watchContext);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
add(key, volume = 1, loop = false, connect = this.connectToMaster) {
|
|
225
|
+
const sound = new Sound(this.game, key, volume, loop, connect);
|
|
226
|
+
this._sounds.push(sound);
|
|
227
|
+
return sound;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
remove(sound) {
|
|
231
|
+
let i = this._sounds.length;
|
|
232
|
+
while (i) {
|
|
233
|
+
i -= 1;
|
|
234
|
+
if (this._sounds[i] === sound) {
|
|
235
|
+
this._sounds[i].destroy(false);
|
|
236
|
+
this._sounds.splice(i, 1);
|
|
237
|
+
return true;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return false;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
removeByKey(key) {
|
|
244
|
+
let i = this._sounds.length;
|
|
245
|
+
let removed = 0;
|
|
246
|
+
while (i) {
|
|
247
|
+
i -= 1;
|
|
248
|
+
if (this._sounds[i].key === key) {
|
|
249
|
+
this._sounds[i].destroy(false);
|
|
250
|
+
this._sounds.splice(i, 1);
|
|
251
|
+
removed += 1;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
return removed;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
play(key, volume = 1, loop = false) {
|
|
258
|
+
if (this.noAudio) {
|
|
259
|
+
return null;
|
|
260
|
+
}
|
|
261
|
+
const sound = this.add(key, volume, loop);
|
|
262
|
+
sound.play();
|
|
263
|
+
return sound;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
setMute() {
|
|
267
|
+
if (this._muted) {
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
this._muted = true;
|
|
271
|
+
if (this.usingWebAudio) {
|
|
272
|
+
this._muteVolume = this.masterGain.gain.value;
|
|
273
|
+
this.masterGain.gain.value = 0;
|
|
274
|
+
}
|
|
275
|
+
// Loop through sounds
|
|
276
|
+
for (let i = 0; i < this._sounds.length; i += 1) {
|
|
277
|
+
if (this._sounds[i].usingAudioTag) {
|
|
278
|
+
this._sounds[i].mute = true;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
this.onMute.dispatch();
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
unsetMute() {
|
|
285
|
+
if (!this._muted || this._codeMuted) {
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
this._muted = false;
|
|
289
|
+
if (this.usingWebAudio) {
|
|
290
|
+
this.masterGain.gain.value = this._muteVolume;
|
|
291
|
+
}
|
|
292
|
+
// Loop through sounds
|
|
293
|
+
for (let i = 0; i < this._sounds.length; i += 1) {
|
|
294
|
+
if (this._sounds[i].usingAudioTag) {
|
|
295
|
+
this._sounds[i].mute = false;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
this.onUnMute.dispatch();
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
destroy() {
|
|
302
|
+
this.stopAll();
|
|
303
|
+
for (let i = 0; i < this._sounds.length; i += 1) {
|
|
304
|
+
if (this._sounds[i]) {
|
|
305
|
+
this._sounds[i].destroy();
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
this._sounds = [];
|
|
309
|
+
this.onSoundDecode.dispose();
|
|
310
|
+
if (this.context) {
|
|
311
|
+
if (window.PhaserRegistry) {
|
|
312
|
+
window.PhaserRegistry.audioContext = this.context;
|
|
313
|
+
} else if (this.context.close) {
|
|
314
|
+
this.context.close();
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
get mute() {
|
|
320
|
+
return this._muted;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
set mute(value) {
|
|
324
|
+
if (value || false) {
|
|
325
|
+
if (this._muted) {
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
this._codeMuted = true;
|
|
329
|
+
this.setMute();
|
|
330
|
+
} else {
|
|
331
|
+
if (!this._muted) {
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
this._codeMuted = false;
|
|
335
|
+
this.unsetMute();
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
get volume() {
|
|
340
|
+
return this._volume;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
set volume(value) {
|
|
344
|
+
if (value < 0) {
|
|
345
|
+
value = 0;
|
|
346
|
+
} else if (value > 1) {
|
|
347
|
+
value = 1;
|
|
348
|
+
}
|
|
349
|
+
if (this._volume !== value) {
|
|
350
|
+
this._volume = value;
|
|
351
|
+
if (this.usingWebAudio) {
|
|
352
|
+
this.masterGain.gain.value = value;
|
|
353
|
+
} else {
|
|
354
|
+
// Loop through the sound cache and change the volume of all html audio tags
|
|
355
|
+
for (let i = 0; i < this._sounds.length; i += 1) {
|
|
356
|
+
if (this._sounds[i].usingAudioTag) {
|
|
357
|
+
this._sounds[i].updateGlobalVolume(value);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
this.onVolumeChange.dispatch(value);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author Andras Csizmadia <andras@vpmedia.hu>
|
|
3
|
+
* @author Richard Davey <rich@photonstorm.com>
|
|
4
|
+
* @copyright Copyright (c) 2018-present Richard Davey, Photon Storm Ltd., Andras Csizmadia <andras@vpmedia.hu> (www.vpmedia.hu)
|
|
5
|
+
*/
|
|
6
|
+
import Matrix from '../geom/matrix';
|
|
7
|
+
import DisplayObject from '../display/display_object';
|
|
8
|
+
import { setUserSelect, setTouchAction } from '../display/canvas/util';
|
|
9
|
+
import { valueToColor } from '../util/math';
|
|
10
|
+
import { SCALE_LINEAR, SCALE_NEAREST } from './const';
|
|
11
|
+
|
|
12
|
+
export default class extends DisplayObject {
|
|
13
|
+
|
|
14
|
+
constructor(game) {
|
|
15
|
+
super();
|
|
16
|
+
this.game = game;
|
|
17
|
+
this.name = '_stage_root';
|
|
18
|
+
this.worldTransform = new Matrix();
|
|
19
|
+
this.currentRenderOrderID = 0;
|
|
20
|
+
this._bgColor = {
|
|
21
|
+
r: 0,
|
|
22
|
+
g: 0,
|
|
23
|
+
b: 0,
|
|
24
|
+
a: 0,
|
|
25
|
+
color: 0,
|
|
26
|
+
rgba: '#000000',
|
|
27
|
+
};
|
|
28
|
+
if (!game.config.transparent) {
|
|
29
|
+
// transparent = 0,0,0,0 - otherwise r,g,b,1
|
|
30
|
+
this._bgColor.a = 1;
|
|
31
|
+
}
|
|
32
|
+
if (game.config.backgroundColor && !this.game.config.transparent) {
|
|
33
|
+
this.setBackgroundColor(game.config.backgroundColor);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
setBackgroundColor(color) {
|
|
38
|
+
if (this.game.config.transparent) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
valueToColor(color, this._bgColor);
|
|
42
|
+
// For gl.clearColor (canvas uses _bgColor.rgba)
|
|
43
|
+
this._bgColor.r /= 255;
|
|
44
|
+
this._bgColor.g /= 255;
|
|
45
|
+
this._bgColor.b /= 255;
|
|
46
|
+
this._bgColor.a = 1;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
boot() {
|
|
50
|
+
setUserSelect(this.game.canvas, 'none');
|
|
51
|
+
setTouchAction(this.game.canvas, 'none');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
preUpdate() {
|
|
55
|
+
this.currentRenderOrderID = 0;
|
|
56
|
+
// This can't loop in reverse, we need the renderOrderID to be in sequence
|
|
57
|
+
for (let i = 0; i < this.children.length; i += 1) {
|
|
58
|
+
this.children[i].preUpdate();
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
update() {
|
|
63
|
+
let i = this.children.length;
|
|
64
|
+
while (i) {
|
|
65
|
+
i -= 1;
|
|
66
|
+
this.children[i].update();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
postUpdate() {
|
|
71
|
+
for (let i = 0; i < this.children.length; i += 1) {
|
|
72
|
+
this.children[i].postUpdate();
|
|
73
|
+
}
|
|
74
|
+
this.updateTransform();
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
updateTransform() {
|
|
78
|
+
this.worldAlpha = 1;
|
|
79
|
+
for (let i = 0; i < this.children.length; i += 1) {
|
|
80
|
+
this.children[i].updateTransform();
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
destroy() {
|
|
85
|
+
this.exists = false;
|
|
86
|
+
this.game = null;
|
|
87
|
+
this.worldTransform = null;
|
|
88
|
+
this._bgColor = null;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
get backgroundColor() {
|
|
92
|
+
return this._bgColor.color;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
set backgroundColor(value) {
|
|
96
|
+
this.setBackgroundColor(value);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
get smoothed() {
|
|
100
|
+
return window.PhaserRegistry.TEXTURE_SCALE_MODE === SCALE_LINEAR;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
set smoothed(value) {
|
|
104
|
+
window.PhaserRegistry.TEXTURE_SCALE_MODE = value ? SCALE_LINEAR : SCALE_NEAREST;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author Andras Csizmadia <andras@vpmedia.hu>
|
|
3
|
+
* @author Richard Davey <rich@photonstorm.com>
|
|
4
|
+
* @copyright Copyright (c) 2018-present Richard Davey, Photon Storm Ltd., Andras Csizmadia <andras@vpmedia.hu> (www.vpmedia.hu)
|
|
5
|
+
*/
|
|
6
|
+
import Timer from './timer';
|
|
7
|
+
|
|
8
|
+
export default class {
|
|
9
|
+
|
|
10
|
+
constructor(game) {
|
|
11
|
+
this.game = game;
|
|
12
|
+
this.time = 0;
|
|
13
|
+
this.prevTime = 0;
|
|
14
|
+
this.now = 0;
|
|
15
|
+
this.elapsed = 0;
|
|
16
|
+
this.elapsedMS = 0;
|
|
17
|
+
this.physicsElapsed = 1 / 60;
|
|
18
|
+
this.physicsElapsedMS = (1 / 60) * 1000;
|
|
19
|
+
this.desiredFpsMult = 1.0 / 60;
|
|
20
|
+
this._desiredFps = 60;
|
|
21
|
+
this.suggestedFps = this.desiredFps;
|
|
22
|
+
this.slowMotion = 1.0;
|
|
23
|
+
this.advancedTiming = false;
|
|
24
|
+
this.frames = 0;
|
|
25
|
+
this.fps = 0;
|
|
26
|
+
this.fpsMin = 1000;
|
|
27
|
+
this.fpsMax = 0;
|
|
28
|
+
this.msMin = 1000;
|
|
29
|
+
this.msMax = 0;
|
|
30
|
+
this.pauseDuration = 0;
|
|
31
|
+
this.timeToCall = 0;
|
|
32
|
+
this.timeExpected = 0;
|
|
33
|
+
this.events = new Timer(this.game, false);
|
|
34
|
+
this._frameCount = 0;
|
|
35
|
+
this._elapsedAccumulator = 0;
|
|
36
|
+
this._started = 0;
|
|
37
|
+
this._timeLastSecond = 0;
|
|
38
|
+
this._pauseStarted = 0;
|
|
39
|
+
this._justResumed = false;
|
|
40
|
+
this._timers = [];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
boot() {
|
|
44
|
+
this._started = Date.now();
|
|
45
|
+
this.time = Date.now();
|
|
46
|
+
this.events.start();
|
|
47
|
+
this.timeExpected = this.time;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
add(timer) {
|
|
51
|
+
this._timers.push(timer);
|
|
52
|
+
return timer;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
create(autoDestroy = true) {
|
|
56
|
+
const timer = new Timer(this.game, autoDestroy);
|
|
57
|
+
this._timers.push(timer);
|
|
58
|
+
return timer;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
removeAll() {
|
|
62
|
+
for (let i = 0; i < this._timers.length; i += 1) {
|
|
63
|
+
this._timers[i].destroy();
|
|
64
|
+
}
|
|
65
|
+
this._timers = [];
|
|
66
|
+
this.events.removeAll();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
refresh() {
|
|
70
|
+
const previousDateNow = this.time;
|
|
71
|
+
// this.time always holds a Date.now value
|
|
72
|
+
this.time = Date.now();
|
|
73
|
+
// Adjust accordingly.
|
|
74
|
+
this.elapsedMS = this.time - previousDateNow;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
update(time) {
|
|
78
|
+
const previousDateNow = this.time;
|
|
79
|
+
// this.time always holds a Date.now value
|
|
80
|
+
this.time = Date.now();
|
|
81
|
+
// Adjust accordingly.
|
|
82
|
+
this.elapsedMS = this.time - previousDateNow;
|
|
83
|
+
// 'now' is currently still holding the time of the last call, move it into prevTime
|
|
84
|
+
this.prevTime = this.now;
|
|
85
|
+
// update 'now' to hold the current time
|
|
86
|
+
// this.now may hold the RAF high resolution time value if RAF is available (otherwise it also holds Date.now)
|
|
87
|
+
this.now = time;
|
|
88
|
+
// elapsed time between previous call and now - this could be a high resolution value
|
|
89
|
+
this.elapsed = this.now - this.prevTime;
|
|
90
|
+
if (this.game.raf._isSetTimeOut) {
|
|
91
|
+
// console.log('Time isSet', this._desiredFps, 'te', this.timeExpected, 'time', time);
|
|
92
|
+
// time to call this function again in ms in case we're using timers instead of RequestAnimationFrame to update the game
|
|
93
|
+
this.timeToCall = Math.floor(Math.max(0, (1000.0 / this._desiredFps) - (this.timeExpected - time)));
|
|
94
|
+
// time when the next call is expected if using timers
|
|
95
|
+
this.timeExpected = time + this.timeToCall;
|
|
96
|
+
// console.log('Time expect', this.timeExpected);
|
|
97
|
+
}
|
|
98
|
+
if (this.advancedTiming) {
|
|
99
|
+
this.updateAdvancedTiming();
|
|
100
|
+
}
|
|
101
|
+
// Paused but still running?
|
|
102
|
+
if (!this.game.paused) {
|
|
103
|
+
// Our internal Phaser.Timer
|
|
104
|
+
this.events.update(this.time);
|
|
105
|
+
if (this._timers.length) {
|
|
106
|
+
this.updateTimers();
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
updateTimers() {
|
|
112
|
+
let i = 0;
|
|
113
|
+
let len = this._timers.length;
|
|
114
|
+
while (i < len) {
|
|
115
|
+
if (this._timers[i].update(this.time)) {
|
|
116
|
+
i += 1;
|
|
117
|
+
} else {
|
|
118
|
+
// Timer requests to be removed
|
|
119
|
+
this._timers.splice(i, 1);
|
|
120
|
+
len -= 1;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
updateAdvancedTiming() {
|
|
126
|
+
// count the number of time.update calls
|
|
127
|
+
this._frameCount += 1;
|
|
128
|
+
this._elapsedAccumulator += this.elapsed;
|
|
129
|
+
// occasionally recalculate the suggestedFps based on the accumulated elapsed time
|
|
130
|
+
if (this._frameCount >= this._desiredFps * 2) {
|
|
131
|
+
// this formula calculates suggestedFps in multiples of 5 fps
|
|
132
|
+
this.suggestedFps = Math.floor(200 / (this._elapsedAccumulator / this._frameCount)) * 5;
|
|
133
|
+
this._frameCount = 0;
|
|
134
|
+
this._elapsedAccumulator = 0;
|
|
135
|
+
}
|
|
136
|
+
this.msMin = Math.min(this.msMin, this.elapsed);
|
|
137
|
+
this.msMax = Math.max(this.msMax, this.elapsed);
|
|
138
|
+
this.frames += 1;
|
|
139
|
+
if (this.now > this._timeLastSecond + 1000) {
|
|
140
|
+
this.fps = Math.round((this.frames * 1000) / (this.now - this._timeLastSecond));
|
|
141
|
+
this.fpsMin = Math.min(this.fpsMin, this.fps);
|
|
142
|
+
this.fpsMax = Math.max(this.fpsMax, this.fps);
|
|
143
|
+
this._timeLastSecond = this.now;
|
|
144
|
+
this.frames = 0;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
gamePaused() {
|
|
149
|
+
this._pauseStarted = Date.now();
|
|
150
|
+
this.events.pause();
|
|
151
|
+
let i = this._timers.length;
|
|
152
|
+
while (i) {
|
|
153
|
+
i -= 1;
|
|
154
|
+
this._timers[i]._pause();
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
gameResumed() {
|
|
159
|
+
this.time = Date.now();
|
|
160
|
+
this.pauseDuration = this.time - this._pauseStarted;
|
|
161
|
+
this.events.resume();
|
|
162
|
+
let i = this._timers.length;
|
|
163
|
+
while (i) {
|
|
164
|
+
i -= 1;
|
|
165
|
+
this._timers[i]._resume();
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
totalElapsedSeconds() {
|
|
170
|
+
return (this.time - this._started) * 0.001;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
elapsedSince(since) {
|
|
174
|
+
return this.time - since;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
elapsedSecondsSince(since) {
|
|
178
|
+
return (this.time - since) * 0.001;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
reset() {
|
|
182
|
+
this._started = this.time;
|
|
183
|
+
this.removeAll();
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
destroy() {
|
|
187
|
+
this.reset();
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
get desiredFps() {
|
|
191
|
+
return this._desiredFps;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
set desiredFps(value) {
|
|
195
|
+
this._desiredFps = value;
|
|
196
|
+
// Set the physics elapsed time... this will always be 1 / this.desiredFps
|
|
197
|
+
// because we're using fixed time steps in game.update
|
|
198
|
+
this.physicsElapsed = 1 / value;
|
|
199
|
+
this.physicsElapsedMS = this.physicsElapsed * 1000;
|
|
200
|
+
this.desiredFpsMult = 1.0 / value;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
}
|