diff --git a/gulp/html.js b/gulp/html.js index f05f3680..d9c65664 100644 --- a/gulp/html.js +++ b/gulp/html.js @@ -76,15 +76,23 @@ function gulptasksHTML($, gulp, buildFolder) { // Do not need to preload in app or standalone if (!hasLocalFiles) { // Preload essentials - const preloads = ["fonts/GameFont.woff2"]; + const preloads = [ + "res/fonts/GameFont.woff2", + "async-resources.css", + "res/sounds/music/theme-short.mp3", + ]; preloads.forEach(src => { const preloadLink = document.createElement("link"); preloadLink.rel = "preload"; - preloadLink.href = cachebust("res/" + src); + preloadLink.href = cachebust(src); if (src.endsWith(".woff2")) { preloadLink.setAttribute("crossorigin", "anonymous"); preloadLink.setAttribute("as", "font"); + } else if (src.endsWith(".css")) { + preloadLink.setAttribute("as", "style"); + } else if (src.endsWith(".mp3")) { + preloadLink.setAttribute("as", "audio"); } else { preloadLink.setAttribute("as", "image"); } diff --git a/src/css/adinplay.scss b/src/css/adinplay.scss index 79b7542e..9707a502 100644 --- a/src/css/adinplay.scss +++ b/src/css/adinplay.scss @@ -60,7 +60,6 @@ } & { - /* @load-async */ background: rgba($mainBgColor, 0.9) uiResource("loading.svg") center center / #{D(60px)} no-repeat; } } diff --git a/src/css/common.scss b/src/css/common.scss index 7cc072ce..f4946e9d 100644 --- a/src/css/common.scss +++ b/src/css/common.scss @@ -398,7 +398,6 @@ canvas { vertical-align: middle; & { - /* @load-async */ background: uiResource("loading.svg") center center / contain no-repeat; } } @@ -483,7 +482,6 @@ canvas { } & { - /* @load-async */ background: uiResource("loading.svg") center center / #{D(40px)} no-repeat; } } diff --git a/src/css/ingame_hud/dialogs.scss b/src/css/ingame_hud/dialogs.scss index e349cfcf..412a1911 100644 --- a/src/css/ingame_hud/dialogs.scss +++ b/src/css/ingame_hud/dialogs.scss @@ -142,7 +142,6 @@ opacity: 0.4; } & { - /* @load-async */ background: uiResource("icons/close.png") center center / 80% no-repeat; } } @@ -292,7 +291,7 @@ content: " "; display: inline-block; background: rgba(#fff, 0.6); - @include InlineAnimation(3s linear) { + @include InlineAnimation(1s linear) { 0% { width: 100%; } diff --git a/src/css/resources.scss b/src/css/resources.scss index f904210a..2d1e46ae 100644 --- a/src/css/resources.scss +++ b/src/css/resources.scss @@ -75,12 +75,10 @@ $languages: en, de, cs, da, et, es-419, fr, it, pt-BR, sv, tr, el, ru, uk, zh-TW @each $language in $languages { [data-languageicon="#{$language}"] { - /* @load-async */ background-image: uiResource("languages/#{$language}.svg") !important; } } .steam_dlbtn_0 { - /* @load-async */ background-image: uiResource("steam_link_btn/0.png") !important; } diff --git a/src/css/states/keybindings.scss b/src/css/states/keybindings.scss index 4aa2fc7b..991d2af4 100644 --- a/src/css/states/keybindings.scss +++ b/src/css/states/keybindings.scss @@ -36,12 +36,10 @@ background: transparent center center / 40% no-repeat; opacity: 0.9; &.editKeybinding { - /* @load-async */ background-image: uiResource("icons/edit_key.png"); } &.resetKeybinding { - /* @load-async */ background-image: uiResource("icons/reset_key.png"); } diff --git a/src/css/states/main_menu.scss b/src/css/states/main_menu.scss index 4e403bd3..5d677782 100644 --- a/src/css/states/main_menu.scss +++ b/src/css/states/main_menu.scss @@ -23,7 +23,6 @@ pointer-events: all; cursor: pointer; & { - /* @load-async */ background: uiResource("icons/main_menu_settings.png") center center / contain no-repeat; } transition: opacity 0.12s ease-in-out; @@ -35,7 +34,6 @@ } .exitAppButton { - /* @load-async */ background-image: uiResource("icons/main_menu_exit.png"); background-size: 90%; } @@ -350,7 +348,6 @@ opacity: 0.5; background: transparent center center/ 80% no-repeat; & { - /* @load-async */ background-image: uiResource("icons/edit_key.png") !important; } @include DarkThemeInvert; @@ -501,10 +498,6 @@ // @include S(width, 20px); - // & { - // /* @load-async */ - // background-image: uiResource("res/ui/icons/mods_white.png") !important; - // } background-position: center center; background-size: D(15px); background-color: $modsColor !important; @@ -574,7 +567,6 @@ button.resumeGame { background-color: #44484a; & { - /* @load-async */ background-image: uiResource("icons/play.png"); } } @@ -585,7 +577,6 @@ background-color: transparent; & { - /* @load-async */ background-image: uiResource("icons/download.png"); } @include S(width, 15px); @@ -609,7 +600,6 @@ @include IncreasedClickArea(0px); & { - /* @load-async */ background-image: uiResource("icons/delete.png"); } @include S(width, 15px); @@ -630,7 +620,6 @@ @include IncreasedClickArea(2px); & { - /* @load-async */ background-image: uiResource("icons/edit_key.png"); } @include S(width, 10px); @@ -724,7 +713,6 @@ overflow: hidden; & { - /* @load-async */ background: #fff uiResource("wegame_isbn_rating.jpg") center center / contain no-repeat; } } @@ -791,11 +779,9 @@ @include S(height, 50px); background: center center / 80% no-repeat; &.githubLogo { - /* @load-async */ background-image: uiResource("main_menu/github.png"); } &.discordLogo { - /* @load-async */ background-image: uiResource("main_menu/discord.png"); background-size: 95%; } @@ -837,15 +823,12 @@ transition: background-color 0.12s ease-in-out; &.redditLink { - /* @load-async */ background-image: uiResource("main_menu/reddit.svg"); } &.changelog { - /* @load-async */ background-image: uiResource("main_menu/changelog.svg"); } &.helpTranslate { - /* @load-async */ background-image: uiResource("main_menu/translate.svg"); } } diff --git a/src/css/states/mobile_warning.scss b/src/css/states/mobile_warning.scss index 315be57f..aa4922a1 100644 --- a/src/css/states/mobile_warning.scss +++ b/src/css/states/mobile_warning.scss @@ -31,7 +31,6 @@ height: 80px; min-height: 40px; & { - /* @load-async */ background: uiResource("steam_link_btn/0.png") center center / contain no-repeat; } overflow: hidden; diff --git a/src/css/states/mods.scss b/src/css/states/mods.scss index e09391f8..eb958082 100644 --- a/src/css/states/mods.scss +++ b/src/css/states/mods.scss @@ -77,7 +77,6 @@ opacity: 0.2; } &::before { - /* @load-async */ background-image: uiResource("res/ui/icons/mods.png") !important; } } diff --git a/src/css/states/puzzle_menu.scss b/src/css/states/puzzle_menu.scss index 44f5d7ce..ad326c49 100644 --- a/src/css/states/puzzle_menu.scss +++ b/src/css/states/puzzle_menu.scss @@ -247,7 +247,6 @@ @include DarkThemeInvert; & { - /* @load-async */ background-image: uiResource("icons/delete.png") !important; } } @@ -275,7 +274,6 @@ @include DarkThemeInvert; & { - /* @load-async */ background: uiResource("icons/puzzle_plays.png") #{D(2px)} #{D(2.5px)} / #{D( 8px )} #{D(8px)} no-repeat; @@ -293,7 +291,6 @@ @include DarkThemeInvert; & { - /* @load-async */ background: uiResource("icons/puzzle_upvotes.png") #{D(2px)} #{D(2.4px)} / #{D( 9px )} #{D(9px)} no-repeat; @@ -349,14 +346,12 @@ opacity: 0.1; & { - /* @load-async */ background: uiResource("icons/puzzle_complete_indicator.png") center center / contain no-repeat; } } @include DarkThemeOverride { &::after { - /* @load-async */ background: uiResource("icons/puzzle_complete_indicator_inverse.png") center center / contain no-repeat; } diff --git a/src/css/states/settings.scss b/src/css/states/settings.scss index 81632b07..8435a418 100644 --- a/src/css/states/settings.scss +++ b/src/css/states/settings.scss @@ -202,7 +202,6 @@ @include S(padding-right, 15px); & { - /* @load-async */ background: #fff uiResource("icons/enum_selector.png") calc(100% - #{D(5px)}) calc(50% + #{D(1px)}) / #{D(15px)} no-repeat; } @@ -244,7 +243,6 @@ background-color: $darkModeControlsBackground; & { - /* @load-async */ background-image: uiResource("icons/enum_selector_white.png"); } color: #ddd; diff --git a/src/css/textual_game_state.scss b/src/css/textual_game_state.scss index d5967523..6e3fad30 100644 --- a/src/css/textual_game_state.scss +++ b/src/css/textual_game_state.scss @@ -27,7 +27,6 @@ @include S(margin-right, 10px); @include S(margin-left, -5px); & { - /* @load-async */ background: uiResource("icons/state_back_button.png") center center / 70% no-repeat; } } diff --git a/src/js/core/background_resources_loader.js b/src/js/core/background_resources_loader.js index 2081a9f0..99948850 100644 --- a/src/js/core/background_resources_loader.js +++ b/src/js/core/background_resources_loader.js @@ -78,6 +78,8 @@ export class BackgroundResourcesLoader { // Avoid loading stuff twice this.spritesLoaded = []; this.soundsLoaded = []; + this.atlasesLoaded = []; + this.cssLoaded = []; } getNumAssetsLoaded() { @@ -122,7 +124,6 @@ export class BackgroundResourcesLoader { logger.log("⏰ Finish load: main menu"); this.mainMenuReady = true; this.signalMainMenuLoaded.dispatch(); - this.internalStartLoadingEssentialsForBareGame(); }); } @@ -161,6 +162,10 @@ export class BackgroundResourcesLoader { } internalPreloadCss(name) { + if (this.cssLoaded.includes(name)) { + return; + } + this.cssLoaded.push(name); return new Promise((resolve, reject) => { const link = document.createElement("link"); @@ -225,10 +230,16 @@ export class BackgroundResourcesLoader { for (let i = 0; i < atlases.length; ++i) { const atlas = atlases[i]; + if (this.atlasesLoaded.includes(atlas)) { + // Already loaded + continue; + } + this.atlasesLoaded.push(atlas); + promises.push( Loader.preloadAtlas(atlas) .catch(err => { - logger.warn("Failed to load atlas:", atlas.sourceFileName); + logger.warn("Failed to load atlas:", atlas.sourceFileName, err); }) .then(() => { this.numAssetsLoaded++; @@ -236,19 +247,9 @@ export class BackgroundResourcesLoader { ); } - return ( - Promise.all(promises) - - // // Remove some pressure by waiting a bit - // .then(() => { - // return new Promise(resolve => { - // setTimeout(resolve, 200); - // }); - // }) - .then(() => { - this.numAssetsToLoadTotal = 0; - this.numAssetsLoaded = 0; - }) - ); + return Promise.all(promises).then(() => { + this.numAssetsToLoadTotal = 0; + this.numAssetsLoaded = 0; + }); } } diff --git a/src/js/core/modal_dialog_elements.js b/src/js/core/modal_dialog_elements.js index 5af7d9d1..e90f322d 100644 --- a/src/js/core/modal_dialog_elements.js +++ b/src/js/core/modal_dialog_elements.js @@ -178,7 +178,7 @@ export class Dialog { const timeout = setTimeout(() => { button.classList.remove("timedButton"); arrayDeleteValue(this.timeouts, timeout); - }, 3000); + }, 1000); this.timeouts.push(timeout); } if (isEnter || isEscape) { diff --git a/src/js/platform/sound.js b/src/js/platform/sound.js index d43c76c2..be004b38 100644 --- a/src/js/platform/sound.js +++ b/src/js/platform/sound.js @@ -32,10 +32,13 @@ export const MUSIC = { // The theme always depends on the standalone only, even if running the full // version in the browser theme: G_IS_STANDALONE ? "theme-full" : "theme-short", - menu: "menu", }; -if (G_IS_STANDALONE || G_IS_DEV) { +if (G_IS_STANDALONE) { + MUSIC.menu = "menu"; +} + +if (G_IS_STANDALONE) { MUSIC.puzzle = "puzzle-full"; } @@ -152,7 +155,7 @@ export class SoundInterface { } else if (this.music[key]) { return this.music[key].load(); } else { - logger.error("Sound/Music by key not found:", key); + logger.warn("Sound/Music by key not found:", key); return Promise.resolve(); } } diff --git a/src/js/states/ingame.js b/src/js/states/ingame.js index 108028a4..399617e2 100644 --- a/src/js/states/ingame.js +++ b/src/js/states/ingame.js @@ -237,17 +237,21 @@ export class InGameState extends GameState { */ stage3CreateCore() { if (this.switchStage(GAME_LOADING_STATES.s3_createCore)) { - logger.log("Creating new game core"); - this.core = new GameCore(this.app); + logger.log("Waiting for resources to load"); - this.core.initializeRoot(this, this.savegame, this.gameModeId); + this.app.backgroundResourceLoader.getPromiseForBareGame().then(() => { + logger.log("Creating new game core"); + this.core = new GameCore(this.app); - if (this.savegame.hasGameDump()) { - this.stage4bResumeGame(); - } else { - this.app.gameAnalytics.handleGameStarted(); - this.stage4aInitEmptyGame(); - } + this.core.initializeRoot(this, this.savegame, this.gameModeId); + + if (this.savegame.hasGameDump()) { + this.stage4bResumeGame(); + } else { + this.app.gameAnalytics.handleGameStarted(); + this.stage4aInitEmptyGame(); + } + }); } } diff --git a/src/js/states/main_menu.js b/src/js/states/main_menu.js index e6905778..a4fcb406 100644 --- a/src/js/states/main_menu.js +++ b/src/js/states/main_menu.js @@ -315,6 +315,9 @@ export class MainMenuState extends GameState { } onEnter(payload) { + const app = this.app; + setTimeout(() => app.backgroundResourceLoader.internalStartLoadingEssentialsForBareGame(), 10); + this.dialogs = new HUDModalDialogs(null, this.app); const dialogsElement = document.body.querySelector(".modalDialogParent"); this.dialogs.initializeToElement(dialogsElement); diff --git a/src/js/states/preload.js b/src/js/states/preload.js index 2b8815c5..cfec7875 100644 --- a/src/js/states/preload.js +++ b/src/js/states/preload.js @@ -163,7 +163,7 @@ export class PreloadState extends GameState { .then(() => this.setStatus("Downloading resources")) .then(() => { - return this.app.backgroundResourceLoader.getPromiseForBareGame(); + return this.app.backgroundResourceLoader.getPromiseForMainMenu(); }) .then(() => this.setStatus("Checking changelog"))