diff --git a/gulp/gulpfile.js b/gulp/gulpfile.js index d87ba792..dd532cd7 100644 --- a/gulp/gulpfile.js +++ b/gulp/gulpfile.js @@ -189,7 +189,7 @@ function serve({ standalone }) { gulp.watch("../res_built/atlas/*.json", ["imgres.atlas"]); // Watch the build folder and reload when anything changed - const extensions = ["html", "js", "png", "jpg", "svg", "mp3", "ico", "woff2", "json"]; + const extensions = ["html", "js", "png", "gif", "jpg", "svg", "mp3", "ico", "woff2", "json"]; gulp.watch(extensions.map(ext => path.join(buildFolder, "**", "*." + ext))).on("change", function (e) { return gulp.src(e.path).pipe(browserSync.reload({ stream: true })); }); diff --git a/gulp/image-resources.js b/gulp/image-resources.js index b01ca400..90268517 100644 --- a/gulp/image-resources.js +++ b/gulp/image-resources.js @@ -5,7 +5,7 @@ const path = require("path"); const nonImageResourcesGlobs = ["../res/**/*.woff2", "../res/*.ico", "../res/**/*.webm"]; // Globs for ui resources -const imageResourcesGlobs = ["../res/**/*.png", "../res/**/*.svg", "../res/**/*.jpg"]; +const imageResourcesGlobs = ["../res/**/*.png", "../res/**/*.svg", "../res/**/*.jpg", "../res/**/*.gif"]; function gulptasksImageResources($, gulp, buildFolder) { // Lossless options @@ -17,6 +17,10 @@ function gulptasksImageResources($, gulp, buildFolder) { $.imagemin.optipng({ optimizationLevel: 3, }), + $.imageminGifsicle({ + optimizationLevel: 3, + colors: 128, + }), ]; // Lossy options @@ -36,6 +40,10 @@ function gulptasksImageResources($, gulp, buildFolder) { $.imagemin.optipng({ optimizationLevel: 3, }), + $.imageminGifsicle({ + optimizationLevel: 3, + colors: 128, + }), ]; // Where the resources folder are @@ -124,6 +132,7 @@ function gulptasksImageResources($, gulp, buildFolder) { path.join(buildFolder, "res", "ui", "**", "*.png"), path.join(buildFolder, "res", "ui", "**", "*.jpg"), path.join(buildFolder, "res", "ui", "**", "*.svg"), + path.join(buildFolder, "res", "ui", "**", "*.gif"), ], { read: false } ) diff --git a/gulp/package.json b/gulp/package.json index c4ab10c4..f2d542a8 100644 --- a/gulp/package.json +++ b/gulp/package.json @@ -70,6 +70,7 @@ "css-mqpacker": "^7.0.0", "cssnano": "^4.1.10", "electron-packager": "^14.0.6", + "imagemin-gifsicle": "^7.0.0", "faster.js": "^1.1.0", "glob": "^7.1.3", "gulp": "^3.9.1", diff --git a/gulp/yarn.lock b/gulp/yarn.lock index 7389e868..8e92a91f 100644 --- a/gulp/yarn.lock +++ b/gulp/yarn.lock @@ -3412,6 +3412,15 @@ cross-spawn@^5.0.1: shebang-command "^1.2.0" which "^1.2.9" +cross-spawn@^7.0.0: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + cross-zip@^2.1.5: version "2.1.6" resolved "https://registry.yarnpkg.com/cross-zip/-/cross-zip-2.1.6.tgz#344d3ba9488609942987d815bb84860cff3d9491" @@ -4875,6 +4884,21 @@ execa@^1.0.0: signal-exit "^3.0.0" strip-eof "^1.0.0" +execa@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/execa/-/execa-4.0.2.tgz#ad87fb7b2d9d564f70d2b62d511bee41d5cbb240" + integrity sha512-QI2zLa6CjGWdiQsmSkZoGtDx2N+cQIGb3yNolGTdjSQzydzLgYYf8LRuagp7S7fPimjcrzUDSUFd/MgzELMi4Q== + dependencies: + cross-spawn "^7.0.0" + get-stream "^5.0.0" + human-signals "^1.1.1" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.0" + onetime "^5.1.0" + signal-exit "^3.0.2" + strip-final-newline "^2.0.0" + executable@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/executable/-/executable-1.1.0.tgz#877980e9112f3391066da37265de7ad8434ab4d9" @@ -5738,7 +5762,7 @@ get-stream@^4.0.0, get-stream@^4.1.0: dependencies: pump "^3.0.0" -get-stream@^5.1.0: +get-stream@^5.0.0, get-stream@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.1.0.tgz#01203cdc92597f9b909067c3e656cc1f4d3c4dc9" integrity sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw== @@ -5767,6 +5791,16 @@ gifsicle@^4.0.0: execa "^1.0.0" logalot "^2.0.0" +gifsicle@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/gifsicle/-/gifsicle-5.1.0.tgz#08f878e9048c70adf046185115a6350516a1fdc0" + integrity sha512-hQsOH7yjC7fMokntysN6f2QuxrnX+zmKKKVy0sC3Vhtnk8WrOxLdfH/Z2PNn7lVVx+1+drzIeAe8ufcmdSC/8g== + dependencies: + bin-build "^3.0.0" + bin-wrapper "^4.0.0" + execa "^4.0.0" + logalot "^2.0.0" + glob-all@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/glob-all/-/glob-all-3.1.0.tgz#8913ddfb5ee1ac7812656241b03d5217c64b02ab" @@ -6859,6 +6893,11 @@ https-browserify@^1.0.0: resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= +human-signals@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" + integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== + iconv-lite@0.4.24, iconv-lite@^0.4.17, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" @@ -6912,6 +6951,15 @@ imagemin-gifsicle@^6.0.1: gifsicle "^4.0.0" is-gif "^3.0.0" +imagemin-gifsicle@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/imagemin-gifsicle/-/imagemin-gifsicle-7.0.0.tgz#1a7ab136a144c4678657ba3b6c412f80805d26b0" + integrity sha512-LaP38xhxAwS3W8PFh4y5iQ6feoTSF+dTAXFRUEYQWYst6Xd+9L/iPk34QGgK/VO/objmIlmq9TStGfVY2IcHIA== + dependencies: + execa "^1.0.0" + gifsicle "^5.0.0" + is-gif "^3.0.0" + imagemin-jpegtran@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/imagemin-jpegtran/-/imagemin-jpegtran-6.0.0.tgz#c8d3bcfb6ec9c561c20a987142854be70d90b04f" @@ -8700,6 +8748,11 @@ merge-stream@^1.0.0: dependencies: readable-stream "^2.0.1" +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + merge2@^1.2.3: version "1.3.0" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.3.0.tgz#5b366ee83b2f1582c48f87e47cf1a9352103ca81" @@ -8810,7 +8863,7 @@ mimic-fn@^1.0.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== -mimic-fn@^2.0.0: +mimic-fn@^2.0.0, mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== @@ -9312,6 +9365,13 @@ npm-run-path@^2.0.0: dependencies: path-key "^2.0.0" +npm-run-path@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + "npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0, npmlog@^4.0.2: version "4.1.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" @@ -9533,6 +9593,13 @@ onetime@^2.0.0: dependencies: mimic-fn "^1.0.0" +onetime@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.0.tgz#fff0f3c91617fe62bb50189636e99ac8a6df7be5" + integrity sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q== + dependencies: + mimic-fn "^2.1.0" + open@^0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/open/-/open-0.0.5.tgz#42c3e18ec95466b6bf0dc42f3a2945c3f0cad8fc" @@ -9997,6 +10064,11 @@ path-key@^2.0.0, path-key@^2.0.1: resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= +path-key@^3.0.0, path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + path-parse@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" @@ -12038,11 +12110,23 @@ shebang-command@^1.2.0: dependencies: shebang-regex "^1.0.0" +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + shebang-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + shelljs@^0.6.0: version "0.6.1" resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.6.1.tgz#ec6211bed1920442088fe0f70b2837232ed2c8a8" @@ -12680,6 +12764,11 @@ strip-eof@^1.0.0: resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + strip-indent@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" @@ -13973,6 +14062,13 @@ which@1, which@^1.1.1, which@^1.2.14, which@^1.2.9, which@^1.3.1: dependencies: isexe "^2.0.0" +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + wide-align@^1.1.0: version "1.1.3" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" diff --git a/res/ui/interactive_tutorial.noinline/1_1_extractor.gif b/res/ui/interactive_tutorial.noinline/1_1_extractor.gif new file mode 100644 index 00000000..c7208ac2 Binary files /dev/null and b/res/ui/interactive_tutorial.noinline/1_1_extractor.gif differ diff --git a/res/ui/interactive_tutorial.noinline/1_2_conveyor.gif b/res/ui/interactive_tutorial.noinline/1_2_conveyor.gif new file mode 100644 index 00000000..db59bfd4 Binary files /dev/null and b/res/ui/interactive_tutorial.noinline/1_2_conveyor.gif differ diff --git a/res/ui/interactive_tutorial.noinline/1_3_expand.gif b/res/ui/interactive_tutorial.noinline/1_3_expand.gif new file mode 100644 index 00000000..9c655ab1 Binary files /dev/null and b/res/ui/interactive_tutorial.noinline/1_3_expand.gif differ diff --git a/src/css/ingame_hud/blueprint_placer.scss b/src/css/ingame_hud/blueprint_placer.scss index acf66087..e1cf06ef 100644 --- a/src/css/ingame_hud/blueprint_placer.scss +++ b/src/css/ingame_hud/blueprint_placer.scss @@ -5,7 +5,7 @@ transform: translateX(-50%); color: #333; z-index: 9999; - background: rgba(0, 10, 20, 0.5); + background: $ingameHudBg; @include S(padding, 5px); display: flex; flex-direction: column; diff --git a/src/css/ingame_hud/building_placer.scss b/src/css/ingame_hud/building_placer.scss index 0548390b..99c4d654 100644 --- a/src/css/ingame_hud/building_placer.scss +++ b/src/css/ingame_hud/building_placer.scss @@ -10,7 +10,7 @@ @include S(width, 240px); @include S(grid-column-gap, 5px); - background: rgba(#333438, 0.8); + background: $ingameHudBg; grid-template-columns: 1fr auto; grid-template-rows: auto 1fr; @@ -108,7 +108,8 @@ .variant { grid-row: 2 / 3; @include S(border-radius, $globalBorderRadius); - background: rgba(0, 10, 20, 0.2); + background: rgba($ingameHudBg, 0.3); + opacity: 0.5; display: inline-flex; vertical-align: top; position: relative; @@ -117,7 +118,8 @@ @include S(grid-gap, 10px); &.active { - background-color: rgba(74, 163, 223, 0.6); + opacity: 1; + background-color: rgba($colorBlueBright, 0.8); } $iconSize: 25px; diff --git a/src/css/ingame_hud/debug_info.scss b/src/css/ingame_hud/debug_info.scss index 37e3a07c..f370d04e 100644 --- a/src/css/ingame_hud/debug_info.scss +++ b/src/css/ingame_hud/debug_info.scss @@ -1,8 +1,9 @@ #ingame_HUD_DebugInfo { position: absolute; @include S(bottom, 5px); - @include S(left, 5px); + @include S(right, 5px); + text-align: right; font-size: 15px; display: flex; line-height: 15px; diff --git a/src/css/ingame_hud/interactive_tutorial.scss b/src/css/ingame_hud/interactive_tutorial.scss new file mode 100644 index 00000000..d4fb58e1 --- /dev/null +++ b/src/css/ingame_hud/interactive_tutorial.scss @@ -0,0 +1,50 @@ +#ingame_HUD_InteractiveTutorial { + position: absolute; + @include S(left, 10px); + @include S(bottom, 10px); + + @include StyleBelowWidth(1430px) { + @include S(bottom, 10px + 40px); + } + + @include S(width, 150px); + + background: $ingameHudBg; + @include S(padding, 4px); + color: #eee; + display: flex; + flex-direction: column; + + @include MakeAnimationWrappedEvenOdd(0.5s ease-in-out) { + 0% { + } + + 50% { + transform: translateX(-100%); + } + + 100% { + } + } + + .title { + color: #fff; + opacity: 0.5; + @include SuperSmallText; + text-transform: uppercase; + } + + .desc { + @include SuperSmallText; + strong { + color: $colorBlueBright; + font-weight: bold; + } + } + + .helperGif { + @include S(margin-top, 5px); + @include S(height, 150px); + background: center center / contain no-repeat; + } +} diff --git a/src/css/ingame_hud/mass_selector.scss b/src/css/ingame_hud/mass_selector.scss index 5ccbf86a..ddd2d40a 100644 --- a/src/css/ingame_hud/mass_selector.scss +++ b/src/css/ingame_hud/mass_selector.scss @@ -3,8 +3,7 @@ @include S(top, 50px); left: 50%; transform: translateX(-50%); - background: rgba(lighten(#f77, 5), 0.95); - @include S(border-radius, $globalBorderRadius); + background: $ingameHudBg; @include S(padding, 6px, 10px); @include SuperSmallText; color: #fff; diff --git a/src/css/ingame_hud/tutorial_hints.scss b/src/css/ingame_hud/tutorial_hints.scss index 55603c4e..ad1096af 100644 --- a/src/css/ingame_hud/tutorial_hints.scss +++ b/src/css/ingame_hud/tutorial_hints.scss @@ -66,7 +66,7 @@ } &.enlarged { - background: rgba(50, 60, 70, 0.9); + background: $ingameHudBg; left: 50%; bottom: 50%; transform: translate(-50%, 50%); @@ -81,7 +81,7 @@ bottom: -1000px; z-index: 0; - background: rgba(50, 60, 70, 0.3); + background: rgba($ingameHudBg, 0.3); } .header { diff --git a/src/css/main.scss b/src/css/main.scss index 46fdab9c..10bf384e 100644 --- a/src/css/main.scss +++ b/src/css/main.scss @@ -49,6 +49,7 @@ @import "ingame_hud/watermark"; @import "ingame_hud/blueprint_placer"; @import "ingame_hud/waypoints"; +@import "ingame_hud/interactive_tutorial"; // prettier-ignore $elements: @@ -69,6 +70,7 @@ ingame_HUD_Notifications, ingame_HUD_MassSelector, ingame_HUD_DebugInfo, ingame_HUD_EntityDebugger, +ingame_HUD_InteractiveTutorial, ingame_HUD_TutorialHints, ingame_HUD_buildings_toolbar, ingame_HUD_BlueprintPlacer, @@ -79,9 +81,9 @@ ingame_HUD_Watermark, ingame_HUD_BetaOverlay, // Dialogs -ingame_HUD_UnlockNotification, ingame_HUD_Shop, ingame_HUD_Statistics, +ingame_HUD_UnlockNotification, ingame_HUD_SettingsMenu, ingame_HUD_ModalDialogs; diff --git a/src/css/variables.scss b/src/css/variables.scss index 03213900..5f056a00 100644 --- a/src/css/variables.scss +++ b/src/css/variables.scss @@ -34,8 +34,7 @@ $colorGreenBright: #66bb6a; $colorBlueBright: rgb(74, 163, 223); $colorRedBright: #ef5072; $themeColor: #393747; -$ingameHudBg: rgba($accentColorBright, 0.1); -$ingameHudBorder: #{D(1.5px)} solid $accentColorDark; +$ingameHudBg: rgba(#333438, 0.9); $text3dColor: #f4ffff; diff --git a/src/js/core/background_resources_loader.js b/src/js/core/background_resources_loader.js index 28d414f2..ff99d23c 100644 --- a/src/js/core/background_resources_loader.js +++ b/src/js/core/background_resources_loader.js @@ -10,7 +10,10 @@ import { AtlasDefinition, atlasFiles } from "./atlas_definitions"; const logger = createLogger("background_loader"); -const essentialMainMenuSprites = ["logo.png", ...G_ALL_UI_IMAGES.filter(src => src.startsWith("ui/"))]; +const essentialMainMenuSprites = [ + "logo.png", + ...G_ALL_UI_IMAGES.filter(src => src.startsWith("ui/") && src.indexOf(".gif") < 0), +]; const essentialMainMenuSounds = [ SOUNDS.uiClick, SOUNDS.uiError, @@ -21,7 +24,7 @@ const essentialMainMenuSounds = [ ]; const essentialBareGameAtlases = atlasFiles; -const essentialBareGameSprites = G_ALL_UI_IMAGES; +const essentialBareGameSprites = G_ALL_UI_IMAGES.filter(src => src.indexOf(".gif") < 0); const essentialBareGameSounds = [MUSIC.theme]; const additionalGameSprites = []; diff --git a/src/js/game/hud/hud.js b/src/js/game/hud/hud.js index e1f1dbbf..e16431c3 100644 --- a/src/js/game/hud/hud.js +++ b/src/js/game/hud/hud.js @@ -31,6 +31,7 @@ import { HUDWaypoints } from "./parts/waypoints"; /* dev:start */ import { TrailerMaker } from "./trailer_maker"; +import { HUDInteractiveTutorial } from "./parts/interactive_tutorial"; /* dev:end */ export class GameHUD { @@ -87,6 +88,7 @@ export class GameHUD { } if (this.root.app.settings.getAllSettings().offerHints) { this.parts.tutorialHints = new HUDPartTutorialHints(this.root); + this.parts.interactiveTutorial = new HUDInteractiveTutorial(this.root); } const frag = document.createDocumentFragment(); diff --git a/src/js/game/hud/parts/interactive_tutorial.js b/src/js/game/hud/parts/interactive_tutorial.js new file mode 100644 index 00000000..40273638 --- /dev/null +++ b/src/js/game/hud/parts/interactive_tutorial.js @@ -0,0 +1,81 @@ +import { BaseHUDPart } from "../base_hud_part"; +import { makeDiv } from "../../../core/utils"; +import { GameRoot } from "../../root"; +import { MinerComponent } from "../../components/miner"; +import { DynamicDomAttach } from "../dynamic_dom_attach"; +import { TrackedState } from "../../../core/tracked_state"; +import { cachebust } from "../../../core/cachebust"; +import { T } from "../../../translations"; + +const tutorialsByLevel = [ + // Level 1 + [ + // 1.1. place an extractor + { + id: "1_1_extractor", + condition: /** @param {GameRoot} root */ root => { + return root.entityMgr.getAllWithComponent(MinerComponent).length === 0; + }, + }, + // 1.2. connect to hub + { + id: "1_2_conveyor", + condition: /** @param {GameRoot} root */ root => { + return root.hubGoals.getCurrentGoalDelivered() === 0; + }, + }, + // 1.3 wait for completion + { + id: "1_3_expand", + condition: () => true, + }, + ], +]; + +export class HUDInteractiveTutorial extends BaseHUDPart { + createElements(parent) { + this.element = makeDiv( + parent, + "ingame_HUD_InteractiveTutorial", + ["animEven"], + ` + Tutorial + ` + ); + + this.elementDescription = makeDiv(this.element, null, ["desc"]); + this.elementGif = makeDiv(this.element, null, ["helperGif"]); + } + + initialize() { + this.domAttach = new DynamicDomAttach(this.root, this.element); + this.currentHintId = new TrackedState(this.onHintChanged, this); + } + + onHintChanged(hintId) { + this.elementDescription.innerHTML = T.ingame.interactiveTutorial.hints[hintId]; + this.elementGif.style.backgroundImage = + "url('" + cachebust("res/ui/interactive_tutorial.noinline/" + hintId + ".gif") + "')"; + this.element.classList.toggle("animEven"); + this.element.classList.toggle("animOdd"); + } + + update() { + // Compute current hint + const thisLevelHints = tutorialsByLevel[this.root.hubGoals.level - 1]; + let targetHintId = null; + + if (thisLevelHints) { + for (let i = 0; i < thisLevelHints.length; ++i) { + const hint = thisLevelHints[i]; + if (hint.condition(this.root)) { + targetHintId = hint.id; + break; + } + } + } + + this.currentHintId.set(targetHintId); + this.domAttach.update(!!targetHintId); + } +} diff --git a/src/js/game/hud/parts/tutorial_hints.js b/src/js/game/hud/parts/tutorial_hints.js index 25d9aa3a..428923d0 100644 --- a/src/js/game/hud/parts/tutorial_hints.js +++ b/src/js/game/hud/parts/tutorial_hints.js @@ -1,4 +1,3 @@ -import { cachebust } from "../../../core/cachebust"; import { InputReceiver } from "../../../core/input_receiver"; import { TrackedState } from "../../../core/tracked_state"; import { makeDiv } from "../../../core/utils"; @@ -6,9 +5,8 @@ import { KeyActionMapper, KEYMAPPINGS } from "../../key_action_mapper"; import { BaseHUDPart } from "../base_hud_part"; import { DynamicDomAttach } from "../dynamic_dom_attach"; import { T } from "../../../translations"; -import { globalConfig } from "../../../core/config"; -const tutorialVideos = [1, 2, 3, 4, 5, 6, 7, 9, 10, 11]; +const tutorialVideos = [2, 3, 4, 5, 6, 7, 9, 10, 11]; export class HUDPartTutorialHints extends BaseHUDPart { createElements(parent) { diff --git a/src/js/game/tutorial_goals.js b/src/js/game/tutorial_goals.js index 14b231f2..c7fa581b 100644 --- a/src/js/game/tutorial_goals.js +++ b/src/js/game/tutorial_goals.js @@ -35,7 +35,7 @@ export const tutorialGoals = [ // Circle { shape: "CuCuCuCu", // belts t1 - required: 20, + required: 40, reward: enumHubGoalRewards.reward_cutter_and_trash, }, diff --git a/translations/base-en.yaml b/translations/base-en.yaml index a1d95c03..b9d5c4eb 100644 --- a/translations/base-en.yaml +++ b/translations/base-en.yaml @@ -310,12 +310,21 @@ ingame: blueprintPlacer: cost: Cost + # Map markers waypoints: waypoints: Markers hub: HUB description: Left-click a marker to jump to it, right-click to delete it.

Press to create a marker from the current view, or right-click to create a marker at the selected location. creationSuccessNotification: Marker has been created. + # Interactive tutorial + interactiveTutorial: + title: Tutorial + hints: + 1_1_extractor: Place an extractor on top of a circle shape to extract it! + 1_2_conveyor: Connect the extractor with a conveyor belt to your hub! + 1_3_expand: This is NOT an idle game! Build more extractors and belts to finish the goal quicker. + # All shop upgrades shopUpgrades: belt: