pixi-rainman-game-engine 0.3.41 → 0.3.42-beta.1
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/Rainman/appConfig.js +1 -0
- package/dist/Rainman/types.d.ts +1 -0
- package/dist/SettingsUI/components/AutoplaySettings/index.jsx +14 -1
- package/dist/application/SoundManager/SoundManager.d.ts +32 -3
- package/dist/application/SoundManager/SoundManager.js +168 -49
- package/dist/components/AbstractMainContainer/AbstractMainContainer.js +4 -0
- package/dist/components/GambleGame/GambleGame.js +5 -1
- package/dist/components/messageBox/MessageBox.d.ts +11 -0
- package/dist/components/messageBox/MessageBox.js +20 -0
- package/dist/connectivity/serverData.d.ts +1 -0
- package/dist/controllers/AbstractController.js +13 -2
- package/dist/controllers/UiController.d.ts +7 -1
- package/dist/controllers/UiController.js +17 -1
- package/dist/loading/AbstractLoadingContainer.js +1 -1
- package/dist/stores/SettingsStore.d.ts +13 -0
- package/dist/stores/SettingsStore.js +26 -0
- package/dist/utils/common/sound.js +10 -9
- package/dist/winComponents/TexturedText.d.ts +2 -0
- package/dist/winComponents/TexturedText.js +13 -0
- package/package.json +1 -1
package/dist/Rainman/types.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import i18next from "i18next";
|
|
|
4
4
|
import { observer } from "mobx-react-lite";
|
|
5
5
|
import React from "react";
|
|
6
6
|
import { COMPONENTS } from "../../../components";
|
|
7
|
+
import { RainMan } from "../../../Rainman";
|
|
7
8
|
import { UI_ITEMS } from "../../../utils";
|
|
8
9
|
import { useStores } from "../../hooks";
|
|
9
10
|
import { CloseModalButton } from "../CloseModalButton";
|
|
@@ -11,11 +12,18 @@ import { RichLimitingSlider } from "../RichLimitingSlider";
|
|
|
11
12
|
import { SpeedButtonWithHeader, SwitchWithHeader } from "../SwitchWithHeader";
|
|
12
13
|
const initialAutoSpinCount = 10;
|
|
13
14
|
const availableAutoSpinLimits = [10, 20, 50, 70, 100];
|
|
15
|
+
const infiniteAutoSpinCount = 1000000;
|
|
14
16
|
export const AutoplaySettings = observer(() => {
|
|
15
17
|
const { settingStore } = useStores();
|
|
18
|
+
const infinityAutoplayEnabled = RainMan.config.enableInfinityAutoplay;
|
|
16
19
|
const updateLimitsBounds = (newLimit) => {
|
|
20
|
+
settingStore.setInfinitySpinsEnabled(false);
|
|
17
21
|
setAutoSpinsCount(newLimit);
|
|
18
22
|
};
|
|
23
|
+
const enableInfinityAutoplay = () => {
|
|
24
|
+
settingStore.setInfinitySpinsEnabled(true);
|
|
25
|
+
setAutoSpinsCount(infiniteAutoSpinCount);
|
|
26
|
+
};
|
|
19
27
|
const { singleWinExceeds, balancedIncreased, balancedDecreased, howManyAutoSpinsLeft, infinitySpinsEnabled, setSingleWinExceeds, setBalancedIncreased, setBalancedDecreased, setAutoSpinsCount, resetAutoplaySettings } = settingStore;
|
|
20
28
|
return (<div className="autoplay-settings">
|
|
21
29
|
<CloseModalButton layerId={UI_ITEMS.autoplay}/>
|
|
@@ -23,9 +31,14 @@ export const AutoplaySettings = observer(() => {
|
|
|
23
31
|
<h2>{i18next.t("autoPlay")}</h2>
|
|
24
32
|
</div>
|
|
25
33
|
<div className="autoplay-settings__stop-limits">
|
|
26
|
-
{availableAutoSpinLimits.map((limiter, index) => (<button key={`${limiter}${index}`} value={limiter} className={`autoplay-settings__limit ${limiter === howManyAutoSpinsLeft
|
|
34
|
+
{availableAutoSpinLimits.map((limiter, index) => (<button key={`${limiter}${index}`} value={limiter} className={`autoplay-settings__limit ${!infinitySpinsEnabled && limiter === howManyAutoSpinsLeft
|
|
35
|
+
? "autoplay-settings__limit--active"
|
|
36
|
+
: ""} middle`} onClick={(event) => updateLimitsBounds(Number(event.currentTarget.value))}>
|
|
27
37
|
<p>{limiter}</p>
|
|
28
38
|
</button>))}
|
|
39
|
+
{infinityAutoplayEnabled && (<button value="infinity" className={`autoplay-settings__limit ${infinitySpinsEnabled ? "autoplay-settings__limit--active" : ""} right`} onClick={enableInfinityAutoplay}>
|
|
40
|
+
<p>∞</p>
|
|
41
|
+
</button>)}
|
|
29
42
|
</div>
|
|
30
43
|
<div className="separator"/>
|
|
31
44
|
<div className="autoplay-settings__title">
|
|
@@ -16,7 +16,11 @@ export declare class SoundManagerInstance implements SpeedAdapterInterface<Sound
|
|
|
16
16
|
readonly speedLevelMapper: SpeedLevelDirectory<SoundOverrides>;
|
|
17
17
|
private musicCatalogue;
|
|
18
18
|
private currentAmbientTrack;
|
|
19
|
+
private currentAmbientOffset;
|
|
20
|
+
private loadedSoundAssets;
|
|
21
|
+
private audioContextRecoveryPromise;
|
|
19
22
|
constructor();
|
|
23
|
+
private loadSound;
|
|
20
24
|
/**
|
|
21
25
|
* Function for loading sounds into pixi
|
|
22
26
|
* @public
|
|
@@ -37,7 +41,7 @@ export declare class SoundManagerInstance implements SpeedAdapterInterface<Sound
|
|
|
37
41
|
* @returns {void}
|
|
38
42
|
*/
|
|
39
43
|
stopPlayingFxSounds(): void;
|
|
40
|
-
|
|
44
|
+
pauseSoundsForPageHide(): void;
|
|
41
45
|
/**
|
|
42
46
|
* Function for resuming and pausing sound in game
|
|
43
47
|
* @public
|
|
@@ -61,7 +65,19 @@ export declare class SoundManagerInstance implements SpeedAdapterInterface<Sound
|
|
|
61
65
|
getVolumeLevel(soundName: SoundTrack): number;
|
|
62
66
|
private isAmbientTrack;
|
|
63
67
|
private getOppositeAmbientTrack;
|
|
68
|
+
private getCurrentAmbientTrack;
|
|
64
69
|
private getSound;
|
|
70
|
+
private getAmbientPlaybackOffset;
|
|
71
|
+
private trackAmbientPlaybackProgress;
|
|
72
|
+
/**
|
|
73
|
+
* Saves active ambient position before the browser interrupts WebAudio playback.
|
|
74
|
+
* @public
|
|
75
|
+
* @returns {void}
|
|
76
|
+
*/
|
|
77
|
+
captureAmbientPlaybackPositionForPageHide(): void;
|
|
78
|
+
private isIOSWebAudioRuntime;
|
|
79
|
+
private recreatePixiSoundContext;
|
|
80
|
+
private recreatePixiSoundContextOnce;
|
|
65
81
|
stopAmbientMusic(): void;
|
|
66
82
|
/**
|
|
67
83
|
* Function for resuming all sounds in game
|
|
@@ -76,6 +92,19 @@ export declare class SoundManagerInstance implements SpeedAdapterInterface<Sound
|
|
|
76
92
|
* @returns {void}
|
|
77
93
|
*/
|
|
78
94
|
restoreAmbientPlayback(): void;
|
|
95
|
+
/**
|
|
96
|
+
* Recreates the active ambient WebAudio source after iOS app interruptions.
|
|
97
|
+
* Existing Pixi instances can report isPlaying=true even when the native audio pipeline is silent.
|
|
98
|
+
* @private
|
|
99
|
+
* @returns {void}
|
|
100
|
+
*/
|
|
101
|
+
private restartAmbientPlaybackAfterInterruption;
|
|
102
|
+
/**
|
|
103
|
+
* Restores ambient playback after page visibility change or iOS app interruption.
|
|
104
|
+
* @public
|
|
105
|
+
* @returns {boolean} True when audio context is ready after recovery.
|
|
106
|
+
*/
|
|
107
|
+
restorePlaybackAfterPageHide(): Promise<boolean>;
|
|
79
108
|
/**
|
|
80
109
|
* Function for pausing all sounds in game
|
|
81
110
|
* If sound is not playing, it will be skipped
|
|
@@ -121,13 +150,13 @@ export declare class SoundManagerInstance implements SpeedAdapterInterface<Sound
|
|
|
121
150
|
/**
|
|
122
151
|
* Function that resumes sounds and music when game is back in focus.
|
|
123
152
|
* @public
|
|
124
|
-
* @returns {
|
|
153
|
+
* @returns {Promise<boolean>} True when audio context is running.
|
|
125
154
|
*/
|
|
126
155
|
resumeAudioContext(): Promise<boolean>;
|
|
127
156
|
/**
|
|
128
157
|
* Function that resumes sounds and music when game is back in focus.
|
|
129
158
|
* @public
|
|
130
|
-
* @returns {
|
|
159
|
+
* @returns {Promise<boolean>} True when audio context and ambient recovery are ready.
|
|
131
160
|
*/
|
|
132
161
|
resumeOnFocus(): Promise<boolean>;
|
|
133
162
|
/**
|
|
@@ -31,9 +31,25 @@ export class SoundManagerInstance {
|
|
|
31
31
|
};
|
|
32
32
|
musicCatalogue = new Map();
|
|
33
33
|
currentAmbientTrack = null;
|
|
34
|
+
currentAmbientOffset = 0;
|
|
35
|
+
loadedSoundAssets = {};
|
|
36
|
+
audioContextRecoveryPromise = null;
|
|
34
37
|
constructor() {
|
|
35
38
|
this.overrides = this.speedLevelMapper.slow;
|
|
36
39
|
}
|
|
40
|
+
loadSound(soundName, url) {
|
|
41
|
+
return new Promise((resolve) => {
|
|
42
|
+
const sound = Sound.from({
|
|
43
|
+
url,
|
|
44
|
+
autoPlay: false,
|
|
45
|
+
preload: true,
|
|
46
|
+
volume: this.getVolumeLevel(soundName),
|
|
47
|
+
loaded: () => resolve()
|
|
48
|
+
});
|
|
49
|
+
sound.name = soundName;
|
|
50
|
+
this.musicCatalogue.set(soundName, sound);
|
|
51
|
+
});
|
|
52
|
+
}
|
|
37
53
|
/**
|
|
38
54
|
* Function for loading sounds into pixi
|
|
39
55
|
* @public
|
|
@@ -41,22 +57,13 @@ export class SoundManagerInstance {
|
|
|
41
57
|
* @returns {Promise<void>} - promise that resolves when all sounds are loaded
|
|
42
58
|
*/
|
|
43
59
|
async loadSounds(assets) {
|
|
60
|
+
this.loadedSoundAssets = { ...assets };
|
|
44
61
|
const loadingSoundsPromises = [];
|
|
45
62
|
for (const [soundName, url] of Object.entries(assets)) {
|
|
46
63
|
if (!url) {
|
|
47
64
|
continue;
|
|
48
65
|
}
|
|
49
|
-
loadingSoundsPromises.push(
|
|
50
|
-
const sound = Sound.from({
|
|
51
|
-
url,
|
|
52
|
-
autoPlay: false,
|
|
53
|
-
preload: true,
|
|
54
|
-
volume: this.getVolumeLevel(soundName),
|
|
55
|
-
loaded: () => resolve()
|
|
56
|
-
});
|
|
57
|
-
sound.name = soundName;
|
|
58
|
-
this.musicCatalogue.set(soundName, sound);
|
|
59
|
-
}));
|
|
66
|
+
loadingSoundsPromises.push(this.loadSound(soundName, url));
|
|
60
67
|
}
|
|
61
68
|
await Promise.allSettled(loadingSoundsPromises);
|
|
62
69
|
}
|
|
@@ -94,19 +101,16 @@ export class SoundManagerInstance {
|
|
|
94
101
|
sound.stop();
|
|
95
102
|
}
|
|
96
103
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
}
|
|
108
|
-
this.stopAmbientMusic();
|
|
109
|
-
this.stopPlayingFxSounds();
|
|
104
|
+
pauseSoundsForPageHide() {
|
|
105
|
+
this.musicCatalogue.forEach((sound, soundName) => {
|
|
106
|
+
if (!sound.isPlaying || sound.paused) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
if (soundName === SoundTracks.freeSpinsMusic || soundName === SoundTracks.music) {
|
|
110
|
+
this.currentAmbientTrack = soundName;
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
sound.pauseAll();
|
|
110
114
|
}
|
|
111
115
|
/**
|
|
112
116
|
* Function for resuming and pausing sound in game
|
|
@@ -150,12 +154,15 @@ export class SoundManagerInstance {
|
|
|
150
154
|
return;
|
|
151
155
|
}
|
|
152
156
|
}
|
|
153
|
-
sound.play({
|
|
157
|
+
const instance = sound.play({
|
|
154
158
|
singleInstance: true,
|
|
155
159
|
loop: soundsToLoop.includes(soundName),
|
|
156
160
|
volume: this.getVolumeLevel(soundName),
|
|
157
161
|
speed: soundName === "cardDrawing" ? 0.8 : 1
|
|
158
162
|
});
|
|
163
|
+
if (this.isAmbientTrack(soundName) && !(instance instanceof Promise)) {
|
|
164
|
+
this.trackAmbientPlaybackProgress(soundName, sound, instance);
|
|
165
|
+
}
|
|
159
166
|
}
|
|
160
167
|
/**
|
|
161
168
|
* Returns the volume level for a given sound track.
|
|
@@ -178,10 +185,86 @@ export class SoundManagerInstance {
|
|
|
178
185
|
getOppositeAmbientTrack(soundName) {
|
|
179
186
|
return soundName === SoundTracks.freeSpinsMusic ? SoundTracks.music : SoundTracks.freeSpinsMusic;
|
|
180
187
|
}
|
|
188
|
+
getCurrentAmbientTrack() {
|
|
189
|
+
return (this.currentAmbientTrack ??
|
|
190
|
+
(RainMan.settingsStore.isFreeSpinsStarted ? SoundTracks.freeSpinsMusic : SoundTracks.music));
|
|
191
|
+
}
|
|
181
192
|
getSound(soundName) {
|
|
182
193
|
const overrideSoundName = this.overrides[soundName];
|
|
183
194
|
return this.musicCatalogue.get(overrideSoundName ?? soundName);
|
|
184
195
|
}
|
|
196
|
+
getAmbientPlaybackOffset(sound) {
|
|
197
|
+
if (!sound.isPlayable || !Number.isFinite(sound.duration) || sound.duration <= 0) {
|
|
198
|
+
return 0;
|
|
199
|
+
}
|
|
200
|
+
return this.currentAmbientOffset % sound.duration;
|
|
201
|
+
}
|
|
202
|
+
trackAmbientPlaybackProgress(soundName, sound, instance) {
|
|
203
|
+
if (!sound.isPlayable || sound.duration <= 0) {
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
instance.on("progress", (progress) => {
|
|
207
|
+
if (this.currentAmbientTrack !== soundName || !Number.isFinite(progress)) {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
this.currentAmbientOffset = (progress * sound.duration) % sound.duration;
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Saves active ambient position before the browser interrupts WebAudio playback.
|
|
215
|
+
* @public
|
|
216
|
+
* @returns {void}
|
|
217
|
+
*/
|
|
218
|
+
captureAmbientPlaybackPositionForPageHide() {
|
|
219
|
+
if (!RainMan.settingsStore.isSoundStarted || !RainMan.settingsStore.shouldPlayAmbientMusic) {
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
const ambientTrack = this.getCurrentAmbientTrack();
|
|
223
|
+
const ambientSound = this.getSound(ambientTrack);
|
|
224
|
+
const ambientInstance = ambientSound?.instances.find((instance) => Number.isFinite(instance.progress) && instance.progress > 0);
|
|
225
|
+
if (!ambientSound || !ambientInstance || !ambientSound.isPlayable || ambientSound.duration <= 0) {
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
this.currentAmbientTrack = ambientTrack;
|
|
229
|
+
this.currentAmbientOffset = (ambientInstance.progress * ambientSound.duration) % ambientSound.duration;
|
|
230
|
+
}
|
|
231
|
+
isIOSWebAudioRuntime() {
|
|
232
|
+
const userAgent = navigator.userAgent;
|
|
233
|
+
const platform = navigator.platform;
|
|
234
|
+
return /iPad|iPhone|iPod/.test(userAgent) || (platform === "MacIntel" && navigator.maxTouchPoints > 1);
|
|
235
|
+
}
|
|
236
|
+
async recreatePixiSoundContext() {
|
|
237
|
+
if (this.audioContextRecoveryPromise) {
|
|
238
|
+
return this.audioContextRecoveryPromise;
|
|
239
|
+
}
|
|
240
|
+
this.audioContextRecoveryPromise = this.recreatePixiSoundContextOnce().finally(() => {
|
|
241
|
+
this.audioContextRecoveryPromise = null;
|
|
242
|
+
});
|
|
243
|
+
return this.audioContextRecoveryPromise;
|
|
244
|
+
}
|
|
245
|
+
async recreatePixiSoundContextOnce() {
|
|
246
|
+
if (!Object.keys(this.loadedSoundAssets).length) {
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
this.musicCatalogue.forEach((sound) => sound.destroy());
|
|
250
|
+
this.musicCatalogue.clear();
|
|
251
|
+
try {
|
|
252
|
+
sound.context.destroy();
|
|
253
|
+
}
|
|
254
|
+
catch (error) {
|
|
255
|
+
console.error("Could not destroy Pixi sound context", error);
|
|
256
|
+
}
|
|
257
|
+
sound.init();
|
|
258
|
+
sound.disableAutoPause = false;
|
|
259
|
+
const loadingSoundsPromises = [];
|
|
260
|
+
for (const [soundName, url] of Object.entries(this.loadedSoundAssets)) {
|
|
261
|
+
if (!url) {
|
|
262
|
+
continue;
|
|
263
|
+
}
|
|
264
|
+
loadingSoundsPromises.push(this.loadSound(soundName, url));
|
|
265
|
+
}
|
|
266
|
+
await Promise.allSettled(loadingSoundsPromises);
|
|
267
|
+
}
|
|
185
268
|
stopAmbientMusic() {
|
|
186
269
|
this.stop(SoundTracks.music);
|
|
187
270
|
this.stop(SoundTracks.freeSpinsMusic);
|
|
@@ -196,23 +279,8 @@ export class SoundManagerInstance {
|
|
|
196
279
|
if (!RainMan.settingsStore.isSoundStarted) {
|
|
197
280
|
return;
|
|
198
281
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
sound.resume();
|
|
202
|
-
}
|
|
203
|
-
if (RainMan.settingsStore.shouldPlayAmbientMusic &&
|
|
204
|
-
!RainMan.settingsStore.isFreeSpinsPlayEnabled &&
|
|
205
|
-
soundName === SoundTracks.music &&
|
|
206
|
-
sound.paused) {
|
|
207
|
-
sound.resume();
|
|
208
|
-
}
|
|
209
|
-
if (RainMan.settingsStore.shouldPlayAmbientMusic &&
|
|
210
|
-
RainMan.settingsStore.isFreeSpinsPlayEnabled &&
|
|
211
|
-
soundName === SoundTracks.freeSpinsMusic &&
|
|
212
|
-
sound.paused) {
|
|
213
|
-
sound.resume();
|
|
214
|
-
}
|
|
215
|
-
});
|
|
282
|
+
sound.resumeAll();
|
|
283
|
+
this.restoreAmbientPlayback();
|
|
216
284
|
}
|
|
217
285
|
/**
|
|
218
286
|
* Restores currently active ambient loop if browser dropped it while page was inactive.
|
|
@@ -227,10 +295,62 @@ export class SoundManagerInstance {
|
|
|
227
295
|
this.stopAmbientMusic();
|
|
228
296
|
return;
|
|
229
297
|
}
|
|
230
|
-
const ambientTrack = this.
|
|
231
|
-
(RainMan.settingsStore.isFreeSpinsStarted ? SoundTracks.freeSpinsMusic : SoundTracks.music);
|
|
298
|
+
const ambientTrack = this.getCurrentAmbientTrack();
|
|
232
299
|
this.play(ambientTrack);
|
|
233
300
|
}
|
|
301
|
+
/**
|
|
302
|
+
* Recreates the active ambient WebAudio source after iOS app interruptions.
|
|
303
|
+
* Existing Pixi instances can report isPlaying=true even when the native audio pipeline is silent.
|
|
304
|
+
* @private
|
|
305
|
+
* @returns {void}
|
|
306
|
+
*/
|
|
307
|
+
restartAmbientPlaybackAfterInterruption() {
|
|
308
|
+
if (!RainMan.settingsStore.isSoundStarted) {
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
if (!RainMan.settingsStore.shouldPlayAmbientMusic) {
|
|
312
|
+
this.stopAmbientMusic();
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
const ambientTrack = this.getCurrentAmbientTrack();
|
|
316
|
+
const ambientSound = this.getSound(ambientTrack);
|
|
317
|
+
if (!ambientSound) {
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
this.stop(this.getOppositeAmbientTrack(ambientTrack));
|
|
321
|
+
ambientSound.stop();
|
|
322
|
+
this.currentAmbientTrack = ambientTrack;
|
|
323
|
+
const instance = ambientSound.play({
|
|
324
|
+
singleInstance: true,
|
|
325
|
+
loop: soundsToLoop.includes(ambientTrack),
|
|
326
|
+
start: this.getAmbientPlaybackOffset(ambientSound),
|
|
327
|
+
volume: this.getVolumeLevel(ambientTrack),
|
|
328
|
+
speed: 1
|
|
329
|
+
});
|
|
330
|
+
if (!(instance instanceof Promise)) {
|
|
331
|
+
this.trackAmbientPlaybackProgress(ambientTrack, ambientSound, instance);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Restores ambient playback after page visibility change or iOS app interruption.
|
|
336
|
+
* @public
|
|
337
|
+
* @returns {boolean} True when audio context is ready after recovery.
|
|
338
|
+
*/
|
|
339
|
+
async restorePlaybackAfterPageHide() {
|
|
340
|
+
if (!RainMan.settingsStore.isSoundStarted) {
|
|
341
|
+
return false;
|
|
342
|
+
}
|
|
343
|
+
sound.resumeAll();
|
|
344
|
+
if (this.isIOSWebAudioRuntime()) {
|
|
345
|
+
await this.recreatePixiSoundContext();
|
|
346
|
+
}
|
|
347
|
+
const isAudioContextRunning = await this.resumeAudioContext();
|
|
348
|
+
if (!isAudioContextRunning) {
|
|
349
|
+
return false;
|
|
350
|
+
}
|
|
351
|
+
this.restartAmbientPlaybackAfterInterruption();
|
|
352
|
+
return true;
|
|
353
|
+
}
|
|
234
354
|
/**
|
|
235
355
|
* Function for pausing all sounds in game
|
|
236
356
|
* If sound is not playing, it will be skipped
|
|
@@ -238,7 +358,7 @@ export class SoundManagerInstance {
|
|
|
238
358
|
* @returns {void}
|
|
239
359
|
*/
|
|
240
360
|
pauseAll() {
|
|
241
|
-
|
|
361
|
+
sound.pauseAll();
|
|
242
362
|
}
|
|
243
363
|
/**
|
|
244
364
|
* Function for stopping all sounds in game
|
|
@@ -288,7 +408,7 @@ export class SoundManagerInstance {
|
|
|
288
408
|
/**
|
|
289
409
|
* Function that resumes sounds and music when game is back in focus.
|
|
290
410
|
* @public
|
|
291
|
-
* @returns {
|
|
411
|
+
* @returns {Promise<boolean>} True when audio context is running.
|
|
292
412
|
*/
|
|
293
413
|
async resumeAudioContext() {
|
|
294
414
|
const pixiSoundContext = sound.context;
|
|
@@ -307,7 +427,7 @@ export class SoundManagerInstance {
|
|
|
307
427
|
/**
|
|
308
428
|
* Function that resumes sounds and music when game is back in focus.
|
|
309
429
|
* @public
|
|
310
|
-
* @returns {
|
|
430
|
+
* @returns {Promise<boolean>} True when audio context and ambient recovery are ready.
|
|
311
431
|
*/
|
|
312
432
|
async resumeOnFocus() {
|
|
313
433
|
if (!RainMan.settingsStore.isSoundStarted) {
|
|
@@ -317,8 +437,7 @@ export class SoundManagerInstance {
|
|
|
317
437
|
if (!isAudioContextRunning) {
|
|
318
438
|
return false;
|
|
319
439
|
}
|
|
320
|
-
this.
|
|
321
|
-
return true;
|
|
440
|
+
return this.restorePlaybackAfterPageHide();
|
|
322
441
|
}
|
|
323
442
|
/**
|
|
324
443
|
* Returns information if audio context is ready to play sounds.
|
|
@@ -563,6 +563,10 @@ export class AbstractMainContainer extends Container {
|
|
|
563
563
|
this.messageBox.visible = true;
|
|
564
564
|
RainMan.settingsStore.isGambleGameActive = false;
|
|
565
565
|
this._controller.updateGambleValues(RainMan.settingsStore.gambleGameWin);
|
|
566
|
+
if (RainMan.settingsStore.gambleGameWin > 0) {
|
|
567
|
+
RainMan.settingsStore.useTakeAction?.();
|
|
568
|
+
}
|
|
569
|
+
RainMan.settingsStore.disableSpecialButtons();
|
|
566
570
|
this.gambleGame = null;
|
|
567
571
|
}
|
|
568
572
|
this.hideOverlay();
|
|
@@ -88,6 +88,8 @@ export class GambleGame extends Container {
|
|
|
88
88
|
this.redButton.setOnClick(() => this.handleGamblePlay("red"));
|
|
89
89
|
this.blackButton.setOnClick(() => this.handleGamblePlay("black"));
|
|
90
90
|
this.collectButton.setOnClick(() => {
|
|
91
|
+
SoundManager.stop("cardDrawing");
|
|
92
|
+
SoundManager.play("music");
|
|
91
93
|
RainMan.settingsStore.gambleGameWin = this.lastWinAmount;
|
|
92
94
|
RainMan.componentRegistry.get(BUTTONS.gamble).flipDisabledFlag(true);
|
|
93
95
|
SoundManager.play("cardCollect");
|
|
@@ -210,8 +212,10 @@ export class GambleGame extends Container {
|
|
|
210
212
|
this.card.state.addAnimation(0, "idle", true, 0);
|
|
211
213
|
await this.loseDoubleAndWinFields();
|
|
212
214
|
window.setTimeout(() => {
|
|
215
|
+
SoundManager.stop("cardDrawing");
|
|
216
|
+
SoundManager.play("music");
|
|
213
217
|
this.closeGame();
|
|
214
|
-
},
|
|
218
|
+
}, 500);
|
|
215
219
|
}
|
|
216
220
|
}
|
|
217
221
|
/**
|
|
@@ -34,6 +34,8 @@ export declare class MessageBox extends Container {
|
|
|
34
34
|
private possibleWinShown;
|
|
35
35
|
private incentiveMessageShown;
|
|
36
36
|
private winLineIndicatorShown;
|
|
37
|
+
private winLineIndicatorXOffset;
|
|
38
|
+
private winLineIndicatorYOffset;
|
|
37
39
|
constructor();
|
|
38
40
|
/**
|
|
39
41
|
* Updates the incentive text displayed in the message box.
|
|
@@ -84,6 +86,15 @@ export declare class MessageBox extends Container {
|
|
|
84
86
|
* @returns {void}
|
|
85
87
|
*/
|
|
86
88
|
hideWinLineIndicator(): void;
|
|
89
|
+
/**
|
|
90
|
+
* Sets the offset of the win line indicator along the x and y axes. Each time winLineIndicator is shown,
|
|
91
|
+
* the indicator is positioned at the current offset.
|
|
92
|
+
* @public
|
|
93
|
+
* @param {number} xOffset - The amount to move the win line indicator along the x-axis.
|
|
94
|
+
* @param {number} yOffset - The amount to move the win line indicator along the y-axis.
|
|
95
|
+
* @returns {void}
|
|
96
|
+
*/
|
|
97
|
+
setWinWinLineIndicatorOffset(xOffset?: number, yOffset?: number): void;
|
|
87
98
|
/**
|
|
88
99
|
* Function for resizing message box
|
|
89
100
|
* It sets the scale of the message box to the global minimum ratio.
|
|
@@ -39,6 +39,8 @@ export class MessageBox extends Container {
|
|
|
39
39
|
possibleWinShown = false;
|
|
40
40
|
incentiveMessageShown = false;
|
|
41
41
|
winLineIndicatorShown = false;
|
|
42
|
+
winLineIndicatorXOffset = 0;
|
|
43
|
+
winLineIndicatorYOffset = 0;
|
|
42
44
|
constructor() {
|
|
43
45
|
super();
|
|
44
46
|
this.name = MessageBox.registryName;
|
|
@@ -165,6 +167,18 @@ export class MessageBox extends Container {
|
|
|
165
167
|
this.winLineIndicator = undefined;
|
|
166
168
|
}
|
|
167
169
|
}
|
|
170
|
+
/**
|
|
171
|
+
* Sets the offset of the win line indicator along the x and y axes. Each time winLineIndicator is shown,
|
|
172
|
+
* the indicator is positioned at the current offset.
|
|
173
|
+
* @public
|
|
174
|
+
* @param {number} xOffset - The amount to move the win line indicator along the x-axis.
|
|
175
|
+
* @param {number} yOffset - The amount to move the win line indicator along the y-axis.
|
|
176
|
+
* @returns {void}
|
|
177
|
+
*/
|
|
178
|
+
setWinWinLineIndicatorOffset(xOffset, yOffset) {
|
|
179
|
+
this.winLineIndicatorXOffset += xOffset ?? 0;
|
|
180
|
+
this.winLineIndicatorYOffset += yOffset ?? 0;
|
|
181
|
+
}
|
|
168
182
|
/**
|
|
169
183
|
* Function for resizing message box
|
|
170
184
|
* It sets the scale of the message box to the global minimum ratio.
|
|
@@ -334,6 +348,12 @@ export class MessageBox extends Container {
|
|
|
334
348
|
};
|
|
335
349
|
this.winLineIndicator = new WinLineIndicator(winLineTextStyle, getImageForSymbolId, message, symbolIds);
|
|
336
350
|
this.winLineIndicator.y = 50;
|
|
351
|
+
if (this.winLineIndicatorXOffset) {
|
|
352
|
+
this.winLineIndicator.x = this.winLineIndicatorXOffset;
|
|
353
|
+
}
|
|
354
|
+
if (this.winLineIndicatorYOffset) {
|
|
355
|
+
this.winLineIndicator.y = this.winLineIndicatorYOffset;
|
|
356
|
+
}
|
|
337
357
|
this.winLineIndicatorShown = true;
|
|
338
358
|
this.centerTextOnX(this.winLineIndicator);
|
|
339
359
|
this.addChild(this.winLineIndicator);
|
|
@@ -311,6 +311,7 @@ export class AbstractController {
|
|
|
311
311
|
if (RainMan.componentRegistry.has(BUTTONS.gamble)) {
|
|
312
312
|
this.buttonsEventManager.initGambleButton(() => {
|
|
313
313
|
RainMan.settingsStore.isGambleGameAvailable = false;
|
|
314
|
+
SoundManager.stopAll();
|
|
314
315
|
this.mainContainer.invokeGambleGame();
|
|
315
316
|
}, !RainMan.settingsStore.isGambleGameAvailable ||
|
|
316
317
|
RainMan.settingsStore.isPlayingAnyAction ||
|
|
@@ -841,6 +842,13 @@ export class AbstractController {
|
|
|
841
842
|
this.uiController.totalNumberOfFreeSpins += this.getBoughtNumberOfFreeSpins();
|
|
842
843
|
RainMan.componentRegistry.getIfExists(FreeSpinButton.registryName)?.setInteractivity(false);
|
|
843
844
|
RainMan.settingsStore.setIsFreeSpinBought(false);
|
|
845
|
+
if (this.speedLevelBeforeFreeSpins === null) {
|
|
846
|
+
this.speedLevelBeforeFreeSpins = RainMan.settingsStore.currentSpeed;
|
|
847
|
+
}
|
|
848
|
+
RainMan.settingsStore.setIsTemporarySpeed(false);
|
|
849
|
+
RainMan.componentRegistry.setSpeedLevel(SPEED_LEVELS.slow);
|
|
850
|
+
this.uiController.updateShownSpeedLevel(SPEED_LEVELS.slow);
|
|
851
|
+
this.disableSpeedButton(false);
|
|
844
852
|
}
|
|
845
853
|
/**
|
|
846
854
|
* This function is responsible for getting the number of free spins bought
|
|
@@ -903,6 +911,7 @@ export class AbstractController {
|
|
|
903
911
|
logInfo("Take action can't be performed");
|
|
904
912
|
return;
|
|
905
913
|
}
|
|
914
|
+
this.shouldPlayNextSpin = false;
|
|
906
915
|
if (this.currentlyPlayedAction !== undefined) {
|
|
907
916
|
this.changeGamePhase(gamePhases.STOPPING_HANDLING_ACTIONS);
|
|
908
917
|
this.stopPlayingSymbolsStreak();
|
|
@@ -913,7 +922,7 @@ export class AbstractController {
|
|
|
913
922
|
if (takeData.status.code === 200) {
|
|
914
923
|
RainMan.settingsStore.isTakeActionAvailable = false;
|
|
915
924
|
logInfo(`💰 Round ${takeData.round_number} ended with balance:`, takeData.balance);
|
|
916
|
-
this.uiController.
|
|
925
|
+
await this.uiController.animateCurrentBalance(takeData.balance);
|
|
917
926
|
}
|
|
918
927
|
else {
|
|
919
928
|
RainMan.settingsStore.isTakeActionAvailable = true;
|
|
@@ -1219,7 +1228,9 @@ export class AbstractController {
|
|
|
1219
1228
|
}
|
|
1220
1229
|
await this.performActionsAfterSpin();
|
|
1221
1230
|
this.freeSpinsWin = gambleWinAmount > 0 ? gambleWinAmount : null;
|
|
1222
|
-
|
|
1231
|
+
if (!RainMan.globals.isSuperBonusGameEnabled) {
|
|
1232
|
+
this.gambleGameEnabler(gambleWinAmount);
|
|
1233
|
+
}
|
|
1223
1234
|
if (RainMan.settingsStore.isAutoplayEnabled ||
|
|
1224
1235
|
(RainMan.settingsStore.howManyFreeSpinsLeft !== 0 && this.shouldAutoplayFreeSpins)) {
|
|
1225
1236
|
this.handleAutoplayLogic();
|
|
@@ -149,7 +149,6 @@ export declare class UiController {
|
|
|
149
149
|
updateShownPossibleWin(): void;
|
|
150
150
|
/**
|
|
151
151
|
* Shows game pays in a bottom panel, if exists
|
|
152
|
-
* @param amount
|
|
153
152
|
* @public
|
|
154
153
|
* @returns {void}
|
|
155
154
|
*/
|
|
@@ -189,6 +188,13 @@ export declare class UiController {
|
|
|
189
188
|
* @returns {Promise<void>}
|
|
190
189
|
*/
|
|
191
190
|
updateDisplayedBalance(amount: number): Promise<void>;
|
|
191
|
+
/**
|
|
192
|
+
* Function for animating current balance to a final value.
|
|
193
|
+
* @public
|
|
194
|
+
* @param {number} finalBalance - final balance to display
|
|
195
|
+
* @returns {Promise<void>}
|
|
196
|
+
*/
|
|
197
|
+
animateCurrentBalance(finalBalance: number): Promise<void>;
|
|
192
198
|
/**
|
|
193
199
|
* Function for resetting win amount
|
|
194
200
|
* @public
|
|
@@ -216,7 +216,6 @@ export class UiController {
|
|
|
216
216
|
}
|
|
217
217
|
/**
|
|
218
218
|
* Shows game pays in a bottom panel, if exists
|
|
219
|
-
* @param amount
|
|
220
219
|
* @public
|
|
221
220
|
* @returns {void}
|
|
222
221
|
*/
|
|
@@ -282,6 +281,23 @@ export class UiController {
|
|
|
282
281
|
async updateDisplayedBalance(amount) {
|
|
283
282
|
this.promisesToSetBalances.push(RainMan.componentRegistry.get(COMPONENTS.creditText).update(amount));
|
|
284
283
|
}
|
|
284
|
+
/**
|
|
285
|
+
* Function for animating current balance to a final value.
|
|
286
|
+
* @public
|
|
287
|
+
* @param {number} finalBalance - final balance to display
|
|
288
|
+
* @returns {Promise<void>}
|
|
289
|
+
*/
|
|
290
|
+
async animateCurrentBalance(finalBalance) {
|
|
291
|
+
const balanceDiff = ceilToDecimal(finalBalance - this._currentBalance);
|
|
292
|
+
this._currentBalance = finalBalance;
|
|
293
|
+
if (balanceDiff === 0) {
|
|
294
|
+
this.setDisplayedBalance();
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
const animationPromise = RainMan.componentRegistry.get(COMPONENTS.creditText).update(balanceDiff);
|
|
298
|
+
this.promisesToSetBalances.push(animationPromise);
|
|
299
|
+
await animationPromise;
|
|
300
|
+
}
|
|
285
301
|
/**
|
|
286
302
|
* Function for resetting win amount
|
|
287
303
|
* @public
|
|
@@ -24,7 +24,7 @@ export class AbstractLoadingContainer extends Container {
|
|
|
24
24
|
this.name = "loadingContainer";
|
|
25
25
|
this.x = 0;
|
|
26
26
|
this.y = 0;
|
|
27
|
-
this.loaderContainer = new SpriteLoadingContainer("./assets/images/materials/texture.
|
|
27
|
+
this.loaderContainer = new SpriteLoadingContainer("./assets/images/materials/texture.webp");
|
|
28
28
|
this.presentationFinishedPromise = new Promise((resolve) => {
|
|
29
29
|
this.resolvePresentationFinished = resolve;
|
|
30
30
|
});
|
|
@@ -113,6 +113,12 @@ export declare class SettingsStore {
|
|
|
113
113
|
* @returns {void}
|
|
114
114
|
*/
|
|
115
115
|
disableSpecialButtons(): void;
|
|
116
|
+
/**
|
|
117
|
+
* Enables special buttons like gamble and take.
|
|
118
|
+
* @public
|
|
119
|
+
* @returns {void}
|
|
120
|
+
*/
|
|
121
|
+
enableSpecialButtons(): void;
|
|
116
122
|
/**
|
|
117
123
|
* Swaps the bet change disabled flag.
|
|
118
124
|
* @public
|
|
@@ -338,6 +344,13 @@ export declare class SettingsStore {
|
|
|
338
344
|
* @returns {void}
|
|
339
345
|
*/
|
|
340
346
|
setAutoSpinsCount(count: number): void;
|
|
347
|
+
/**
|
|
348
|
+
* Setter for the infinite autoplay flag
|
|
349
|
+
* @public
|
|
350
|
+
* @param {boolean} newState new state for infinite autoplay
|
|
351
|
+
* @returns {void}
|
|
352
|
+
*/
|
|
353
|
+
setInfinitySpinsEnabled(newState: boolean): void;
|
|
341
354
|
/**
|
|
342
355
|
* Setter for the autoplay enabled flag
|
|
343
356
|
* @public
|
|
@@ -79,6 +79,7 @@ export class SettingsStore {
|
|
|
79
79
|
initialAutoplaySettingsState = {
|
|
80
80
|
onAnyWin: false,
|
|
81
81
|
howManyAutoSpinsLeft: INITIAL_AUTO_SPIN_COUNT,
|
|
82
|
+
infinitySpinsEnabled: false,
|
|
82
83
|
singleWinExceeds: 0,
|
|
83
84
|
balancedIncreased: 0,
|
|
84
85
|
balancedDecreased: 0,
|
|
@@ -185,6 +186,21 @@ export class SettingsStore {
|
|
|
185
186
|
RainMan.componentRegistry.get(BUTTONS.take).flipDisabledFlag(true);
|
|
186
187
|
}
|
|
187
188
|
}
|
|
189
|
+
/**
|
|
190
|
+
* Enables special buttons like gamble and take.
|
|
191
|
+
* @public
|
|
192
|
+
* @returns {void}
|
|
193
|
+
*/
|
|
194
|
+
enableSpecialButtons() {
|
|
195
|
+
if (RainMan.componentRegistry.has(BUTTONS.gamble)) {
|
|
196
|
+
RainMan.settingsStore.isGambleGameAvailable = true;
|
|
197
|
+
RainMan.componentRegistry.get(BUTTONS.gamble).flipDisabledFlag(false);
|
|
198
|
+
}
|
|
199
|
+
if (RainMan.componentRegistry.has(BUTTONS.take)) {
|
|
200
|
+
RainMan.settingsStore.isTakeActionAvailable = true;
|
|
201
|
+
RainMan.componentRegistry.get(BUTTONS.take).flipDisabledFlag(false);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
188
204
|
/**
|
|
189
205
|
* Swaps the bet change disabled flag.
|
|
190
206
|
* @public
|
|
@@ -576,6 +592,15 @@ export class SettingsStore {
|
|
|
576
592
|
setAutoSpinsCount(count) {
|
|
577
593
|
this.howManyAutoSpinsLeft = count;
|
|
578
594
|
}
|
|
595
|
+
/**
|
|
596
|
+
* Setter for the infinite autoplay flag
|
|
597
|
+
* @public
|
|
598
|
+
* @param {boolean} newState new state for infinite autoplay
|
|
599
|
+
* @returns {void}
|
|
600
|
+
*/
|
|
601
|
+
setInfinitySpinsEnabled(newState) {
|
|
602
|
+
this.infinitySpinsEnabled = newState;
|
|
603
|
+
}
|
|
579
604
|
/**
|
|
580
605
|
* Setter for the autoplay enabled flag
|
|
581
606
|
* @public
|
|
@@ -713,6 +738,7 @@ export class SettingsStore {
|
|
|
713
738
|
resetAutoplaySettings() {
|
|
714
739
|
this.onAnyWin = this.initialAutoplaySettingsState.onAnyWin;
|
|
715
740
|
this.howManyAutoSpinsLeft = this.initialAutoplaySettingsState.howManyAutoSpinsLeft;
|
|
741
|
+
this.infinitySpinsEnabled = this.initialAutoplaySettingsState.infinitySpinsEnabled;
|
|
716
742
|
this.singleWinExceeds = this.initialAutoplaySettingsState.singleWinExceeds;
|
|
717
743
|
this.balancedIncreased = this.initialAutoplaySettingsState.balancedIncreased;
|
|
718
744
|
this.balancedDecreased = this.initialAutoplaySettingsState.balancedDecreased;
|
|
@@ -16,15 +16,16 @@ const interruptedAudioResume = () => {
|
|
|
16
16
|
window.addEventListener("touchend", resumeAudioOnInterruption, { once: true, passive: true });
|
|
17
17
|
};
|
|
18
18
|
/**
|
|
19
|
-
*
|
|
19
|
+
* Clears pending foreground recovery when the page goes to the background.
|
|
20
|
+
* Pixi handles the actual pause state through its WebAudio auto-pause flow.
|
|
20
21
|
* @returns {void}
|
|
21
22
|
*/
|
|
22
|
-
const
|
|
23
|
+
const prepareAudioForPageHide = () => {
|
|
23
24
|
isResumingAudio = false;
|
|
24
25
|
shouldResumeAudioOnInterruption = false;
|
|
25
26
|
removeInterruptedAudioResumeListeners();
|
|
26
27
|
if (RainMan.settingsStore.isSoundEnabled()) {
|
|
27
|
-
SoundManager.
|
|
28
|
+
SoundManager.captureAmbientPlaybackPositionForPageHide();
|
|
28
29
|
}
|
|
29
30
|
};
|
|
30
31
|
/**
|
|
@@ -71,19 +72,19 @@ function resumeAudioOnInterruption() {
|
|
|
71
72
|
*/
|
|
72
73
|
const handleVisibilityChange = () => {
|
|
73
74
|
if (document.hidden) {
|
|
74
|
-
|
|
75
|
+
prepareAudioForPageHide();
|
|
75
76
|
return;
|
|
76
77
|
}
|
|
77
|
-
|
|
78
|
+
resumeAudio();
|
|
78
79
|
};
|
|
79
80
|
/**
|
|
80
81
|
* Sets up audio states for tab switches and iOS app interruptions.
|
|
81
82
|
* @returns {void}
|
|
82
83
|
*/
|
|
83
84
|
export const loadSoundsOnTabChange = () => {
|
|
84
|
-
sound.disableAutoPause =
|
|
85
|
+
sound.disableAutoPause = false;
|
|
85
86
|
document.addEventListener("visibilitychange", handleVisibilityChange);
|
|
86
|
-
window.addEventListener("pagehide", () =>
|
|
87
|
-
window.addEventListener("pageshow", () =>
|
|
88
|
-
window.addEventListener("focus", () =>
|
|
87
|
+
window.addEventListener("pagehide", () => prepareAudioForPageHide());
|
|
88
|
+
window.addEventListener("pageshow", () => resumeAudio());
|
|
89
|
+
window.addEventListener("focus", () => resumeAudio());
|
|
89
90
|
};
|
|
@@ -25,6 +25,8 @@ export declare class TexturedText extends UpdatableValueComponent {
|
|
|
25
25
|
* @returns {void}
|
|
26
26
|
*/
|
|
27
27
|
randomizeSet(value: number, _possibleValues: number[]): void;
|
|
28
|
+
adjustTextureSpriteLength(): void;
|
|
29
|
+
set(newValue: number): void;
|
|
28
30
|
/**
|
|
29
31
|
* Plays the animation for the text element
|
|
30
32
|
* @public
|
|
@@ -18,6 +18,7 @@ export class TexturedText extends UpdatableValueComponent {
|
|
|
18
18
|
this.registryName = registryName;
|
|
19
19
|
this.valueTextComponent.style = { ...this.valueTextComponent.style, fontSize: 120, padding: 50 };
|
|
20
20
|
this.valueTextComponent.anchor.set(0.5, 0.5);
|
|
21
|
+
this.updateFontSize();
|
|
21
22
|
if (textureName) {
|
|
22
23
|
this.textureSprite = new TilingSprite(getTexture(textureName), this.valueTextComponent.width, this.valueTextComponent.height);
|
|
23
24
|
this.textureSprite.scale.set(1.1);
|
|
@@ -48,6 +49,17 @@ export class TexturedText extends UpdatableValueComponent {
|
|
|
48
49
|
this.valueTextComponent.style.fontSize = -10 * new MoneyText(value).toString().length + this.baseFontSize;
|
|
49
50
|
super.update(value, 1);
|
|
50
51
|
}
|
|
52
|
+
adjustTextureSpriteLength() {
|
|
53
|
+
if (!this.textureSprite) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
this.textureSprite.width = this.valueTextComponent.width;
|
|
57
|
+
this.textureSprite.height = this.valueTextComponent.height;
|
|
58
|
+
}
|
|
59
|
+
set(newValue) {
|
|
60
|
+
super.set(newValue);
|
|
61
|
+
this.adjustTextureSpriteLength();
|
|
62
|
+
}
|
|
51
63
|
/**
|
|
52
64
|
* Plays the animation for the text element
|
|
53
65
|
* @public
|
|
@@ -89,5 +101,6 @@ export class TexturedText extends UpdatableValueComponent {
|
|
|
89
101
|
*/
|
|
90
102
|
updateFontSize() {
|
|
91
103
|
this.valueTextComponent.style.fontSize = -10 * super.value.length + this.baseFontSize;
|
|
104
|
+
this.adjustTextureSpriteLength();
|
|
92
105
|
}
|
|
93
106
|
}
|
package/package.json
CHANGED