Merge branch 'master' into right-click-doesnt-clear-cursor.
|
Before Width: | Height: | Size: 906 KiB After Width: | Height: | Size: 1.6 MiB |
BIN
artwork/itch.io/bg.png
Normal file
|
After Width: | Height: | Size: 3.1 MiB |
BIN
artwork/steam/announcement.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
3
artwork/steam/announcement.psd
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:de805473208e0901f1185485164a35fde59e4baf3000f30102d0f332842410a5
|
||||||
|
size 184895
|
||||||
BIN
artwork/steam/store_page_gif.gif
Normal file
|
After Width: | Height: | Size: 707 KiB |
@ -189,7 +189,7 @@ function serve({ standalone }) {
|
|||||||
gulp.watch("../res_built/atlas/*.json", ["imgres.atlas"]);
|
gulp.watch("../res_built/atlas/*.json", ["imgres.atlas"]);
|
||||||
|
|
||||||
// Watch the build folder and reload when anything changed
|
// 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) {
|
gulp.watch(extensions.map(ext => path.join(buildFolder, "**", "*." + ext))).on("change", function (e) {
|
||||||
return gulp.src(e.path).pipe(browserSync.reload({ stream: true }));
|
return gulp.src(e.path).pipe(browserSync.reload({ stream: true }));
|
||||||
});
|
});
|
||||||
@ -275,11 +275,7 @@ gulp.task(
|
|||||||
$.sequence("sounds.fullbuild", "translations.fullBuild", "js.standalone-beta")
|
$.sequence("sounds.fullbuild", "translations.fullBuild", "js.standalone-beta")
|
||||||
);
|
);
|
||||||
gulp.task("step.standalone-beta.mainbuild", cb =>
|
gulp.task("step.standalone-beta.mainbuild", cb =>
|
||||||
$.multiProcess(
|
$.multiProcess(["step.baseResources", "step.standalone-beta.code"], cb, false)
|
||||||
["utils.copyAdditionalBuildFiles", "step.baseResources", "step.standalone-beta.code"],
|
|
||||||
cb,
|
|
||||||
false
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
gulp.task(
|
gulp.task(
|
||||||
"step.standalone-beta.all",
|
"step.standalone-beta.all",
|
||||||
@ -293,11 +289,7 @@ gulp.task(
|
|||||||
$.sequence("sounds.fullbuild", "translations.fullBuild", "js.standalone-prod")
|
$.sequence("sounds.fullbuild", "translations.fullBuild", "js.standalone-prod")
|
||||||
);
|
);
|
||||||
gulp.task("step.standalone-prod.mainbuild", cb =>
|
gulp.task("step.standalone-prod.mainbuild", cb =>
|
||||||
$.multiProcess(
|
$.multiProcess(["step.baseResources", "step.standalone-prod.code"], cb, false)
|
||||||
["utils.copyAdditionalBuildFiles", "step.baseResources", "step.standalone-prod.code"],
|
|
||||||
cb,
|
|
||||||
false
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
gulp.task(
|
gulp.task(
|
||||||
"step.standalone-prod.all",
|
"step.standalone-prod.all",
|
||||||
|
|||||||
16
gulp/html.js
@ -96,12 +96,20 @@ function gulptasksHTML($, gulp, buildFolder, browserSync) {
|
|||||||
|
|
||||||
const initScript = document.createElement("script");
|
const initScript = document.createElement("script");
|
||||||
initScript.textContent = `
|
initScript.textContent = `
|
||||||
window.dataLayer = window.dataLayer || [];
|
window.dataLayer = window.dataLayer || [];
|
||||||
function gtag(){dataLayer.push(arguments);}
|
function gtag(){dataLayer.push(arguments);}
|
||||||
gtag('js', new Date());
|
gtag('js', new Date());
|
||||||
gtag('config', 'UA-165342524-1', { anonymize_ip: true });
|
gtag('config', 'UA-165342524-1', { anonymize_ip: true });
|
||||||
`;
|
`;
|
||||||
document.head.appendChild(initScript);
|
document.head.appendChild(initScript);
|
||||||
|
|
||||||
|
const abTestingScript = document.createElement("script");
|
||||||
|
abTestingScript.setAttribute(
|
||||||
|
"src",
|
||||||
|
"https://www.googleoptimize.com/optimize.js?id=OPT-M5NHCV7"
|
||||||
|
);
|
||||||
|
abTestingScript.setAttribute("async", "");
|
||||||
|
document.head.appendChild(abTestingScript);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do not need to preload in app or standalone
|
// Do not need to preload in app or standalone
|
||||||
|
|||||||
@ -5,7 +5,7 @@ const path = require("path");
|
|||||||
const nonImageResourcesGlobs = ["../res/**/*.woff2", "../res/*.ico", "../res/**/*.webm"];
|
const nonImageResourcesGlobs = ["../res/**/*.woff2", "../res/*.ico", "../res/**/*.webm"];
|
||||||
|
|
||||||
// Globs for ui resources
|
// 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) {
|
function gulptasksImageResources($, gulp, buildFolder) {
|
||||||
// Lossless options
|
// Lossless options
|
||||||
@ -17,6 +17,10 @@ function gulptasksImageResources($, gulp, buildFolder) {
|
|||||||
$.imagemin.optipng({
|
$.imagemin.optipng({
|
||||||
optimizationLevel: 3,
|
optimizationLevel: 3,
|
||||||
}),
|
}),
|
||||||
|
$.imageminGifsicle({
|
||||||
|
optimizationLevel: 3,
|
||||||
|
colors: 128,
|
||||||
|
}),
|
||||||
];
|
];
|
||||||
|
|
||||||
// Lossy options
|
// Lossy options
|
||||||
@ -36,6 +40,10 @@ function gulptasksImageResources($, gulp, buildFolder) {
|
|||||||
$.imagemin.optipng({
|
$.imagemin.optipng({
|
||||||
optimizationLevel: 3,
|
optimizationLevel: 3,
|
||||||
}),
|
}),
|
||||||
|
$.imageminGifsicle({
|
||||||
|
optimizationLevel: 3,
|
||||||
|
colors: 128,
|
||||||
|
}),
|
||||||
];
|
];
|
||||||
|
|
||||||
// Where the resources folder are
|
// Where the resources folder are
|
||||||
@ -124,6 +132,7 @@ function gulptasksImageResources($, gulp, buildFolder) {
|
|||||||
path.join(buildFolder, "res", "ui", "**", "*.png"),
|
path.join(buildFolder, "res", "ui", "**", "*.png"),
|
||||||
path.join(buildFolder, "res", "ui", "**", "*.jpg"),
|
path.join(buildFolder, "res", "ui", "**", "*.jpg"),
|
||||||
path.join(buildFolder, "res", "ui", "**", "*.svg"),
|
path.join(buildFolder, "res", "ui", "**", "*.svg"),
|
||||||
|
path.join(buildFolder, "res", "ui", "**", "*.gif"),
|
||||||
],
|
],
|
||||||
{ read: false }
|
{ read: false }
|
||||||
)
|
)
|
||||||
|
|||||||
@ -70,6 +70,7 @@
|
|||||||
"css-mqpacker": "^7.0.0",
|
"css-mqpacker": "^7.0.0",
|
||||||
"cssnano": "^4.1.10",
|
"cssnano": "^4.1.10",
|
||||||
"electron-packager": "^14.0.6",
|
"electron-packager": "^14.0.6",
|
||||||
|
"imagemin-gifsicle": "^7.0.0",
|
||||||
"faster.js": "^1.1.0",
|
"faster.js": "^1.1.0",
|
||||||
"glob": "^7.1.3",
|
"glob": "^7.1.3",
|
||||||
"gulp": "^3.9.1",
|
"gulp": "^3.9.1",
|
||||||
|
|||||||
@ -237,7 +237,7 @@ module.exports = ({
|
|||||||
pattern: /globalConfig\.beltSpeedItemsPerSecond/g,
|
pattern: /globalConfig\.beltSpeedItemsPerSecond/g,
|
||||||
replacement: () => "2.0",
|
replacement: () => "2.0",
|
||||||
},
|
},
|
||||||
{ pattern: /globalConfig\.itemSpacingOnBelts/g, replacement: () => "0.8" },
|
{ pattern: /globalConfig\.itemSpacingOnBelts/g, replacement: () => "0.63" },
|
||||||
{ pattern: /globalConfig\.debug/g, replacement: () => "''" },
|
{ pattern: /globalConfig\.debug/g, replacement: () => "''" },
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
|
|||||||
100
gulp/yarn.lock
@ -3412,6 +3412,15 @@ cross-spawn@^5.0.1:
|
|||||||
shebang-command "^1.2.0"
|
shebang-command "^1.2.0"
|
||||||
which "^1.2.9"
|
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:
|
cross-zip@^2.1.5:
|
||||||
version "2.1.6"
|
version "2.1.6"
|
||||||
resolved "https://registry.yarnpkg.com/cross-zip/-/cross-zip-2.1.6.tgz#344d3ba9488609942987d815bb84860cff3d9491"
|
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"
|
signal-exit "^3.0.0"
|
||||||
strip-eof "^1.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:
|
executable@^1.0.0:
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/executable/-/executable-1.1.0.tgz#877980e9112f3391066da37265de7ad8434ab4d9"
|
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:
|
dependencies:
|
||||||
pump "^3.0.0"
|
pump "^3.0.0"
|
||||||
|
|
||||||
get-stream@^5.1.0:
|
get-stream@^5.0.0, get-stream@^5.1.0:
|
||||||
version "5.1.0"
|
version "5.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.1.0.tgz#01203cdc92597f9b909067c3e656cc1f4d3c4dc9"
|
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.1.0.tgz#01203cdc92597f9b909067c3e656cc1f4d3c4dc9"
|
||||||
integrity sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==
|
integrity sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==
|
||||||
@ -5767,6 +5791,16 @@ gifsicle@^4.0.0:
|
|||||||
execa "^1.0.0"
|
execa "^1.0.0"
|
||||||
logalot "^2.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:
|
glob-all@^3.1.0:
|
||||||
version "3.1.0"
|
version "3.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/glob-all/-/glob-all-3.1.0.tgz#8913ddfb5ee1ac7812656241b03d5217c64b02ab"
|
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"
|
resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73"
|
||||||
integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=
|
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:
|
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"
|
version "0.4.24"
|
||||||
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
|
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"
|
gifsicle "^4.0.0"
|
||||||
is-gif "^3.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:
|
imagemin-jpegtran@^6.0.0:
|
||||||
version "6.0.0"
|
version "6.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/imagemin-jpegtran/-/imagemin-jpegtran-6.0.0.tgz#c8d3bcfb6ec9c561c20a987142854be70d90b04f"
|
resolved "https://registry.yarnpkg.com/imagemin-jpegtran/-/imagemin-jpegtran-6.0.0.tgz#c8d3bcfb6ec9c561c20a987142854be70d90b04f"
|
||||||
@ -8700,6 +8748,11 @@ merge-stream@^1.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
readable-stream "^2.0.1"
|
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:
|
merge2@^1.2.3:
|
||||||
version "1.3.0"
|
version "1.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.3.0.tgz#5b366ee83b2f1582c48f87e47cf1a9352103ca81"
|
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"
|
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022"
|
||||||
integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==
|
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"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
|
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
|
||||||
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
|
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
|
||||||
@ -9312,6 +9365,13 @@ npm-run-path@^2.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
path-key "^2.0.0"
|
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:
|
"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0, npmlog@^4.0.2:
|
||||||
version "4.1.2"
|
version "4.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
|
resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
|
||||||
@ -9533,6 +9593,13 @@ onetime@^2.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
mimic-fn "^1.0.0"
|
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:
|
open@^0.0.5:
|
||||||
version "0.0.5"
|
version "0.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/open/-/open-0.0.5.tgz#42c3e18ec95466b6bf0dc42f3a2945c3f0cad8fc"
|
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"
|
resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
|
||||||
integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=
|
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:
|
path-parse@^1.0.6:
|
||||||
version "1.0.6"
|
version "1.0.6"
|
||||||
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
|
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
|
||||||
@ -12038,11 +12110,23 @@ shebang-command@^1.2.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
shebang-regex "^1.0.0"
|
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:
|
shebang-regex@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
|
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
|
||||||
integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=
|
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:
|
shelljs@^0.6.0:
|
||||||
version "0.6.1"
|
version "0.6.1"
|
||||||
resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.6.1.tgz#ec6211bed1920442088fe0f70b2837232ed2c8a8"
|
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"
|
resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
|
||||||
integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=
|
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:
|
strip-indent@^1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2"
|
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:
|
dependencies:
|
||||||
isexe "^2.0.0"
|
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:
|
wide-align@^1.1.0:
|
||||||
version "1.1.3"
|
version "1.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457"
|
resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457"
|
||||||
|
|||||||
@ -12,7 +12,8 @@
|
|||||||
"lint": "npx eslint src/js",
|
"lint": "npx eslint src/js",
|
||||||
"prettier-all": "prettier --write src/**/*.* && prettier --write gulp/**/*.*",
|
"prettier-all": "prettier --write src/**/*.* && prettier --write gulp/**/*.*",
|
||||||
"publishOnItchWindows": "butler push tmp_standalone_files/shapez.io-standalone-win32-x64 tobspr/shapezio:windows --userversion-file version",
|
"publishOnItchWindows": "butler push tmp_standalone_files/shapez.io-standalone-win32-x64 tobspr/shapezio:windows --userversion-file version",
|
||||||
"publishOnItchLinux": "butler push tmp_standalone_files/shapez.io-standalone-linux-x64 tobspr/shapezio:linux-experimental --userversion-file version",
|
"publishOnItchLinux": "butler push tmp_standalone_files/shapez.io-standalone-linux-x64 tobspr/shapezio:linux --userversion-file version",
|
||||||
|
"publishOnItch": "yarn publishOnItchWindows && yarn publishOnItchLinux",
|
||||||
"publishOnSteam": "cd gulp/steampipe && ./upload.bat",
|
"publishOnSteam": "cd gulp/steampipe && ./upload.bat",
|
||||||
"publishStandalone": "yarn publishOnItch && yarn publishOnSteam",
|
"publishStandalone": "yarn publishOnItch && yarn publishOnSteam",
|
||||||
"publishWeb": "cd gulp && yarn main.deploy.prod",
|
"publishWeb": "cd gulp && yarn main.deploy.prod",
|
||||||
@ -41,6 +42,7 @@
|
|||||||
"howler": "^2.1.2",
|
"howler": "^2.1.2",
|
||||||
"html-loader": "^0.5.5",
|
"html-loader": "^0.5.5",
|
||||||
"ignore-loader": "^0.1.2",
|
"ignore-loader": "^0.1.2",
|
||||||
|
"logrocket": "^1.0.7",
|
||||||
"lz-string": "^1.4.4",
|
"lz-string": "^1.4.4",
|
||||||
"markdown-loader": "^4.0.0",
|
"markdown-loader": "^4.0.0",
|
||||||
"obfuscator-loader": "^1.1.2",
|
"obfuscator-loader": "^1.1.2",
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 695 B |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 1.1 KiB |
BIN
res/ui/interactive_tutorial.noinline/1_1_extractor.gif
Normal file
|
After Width: | Height: | Size: 120 KiB |
BIN
res/ui/interactive_tutorial.noinline/1_2_conveyor.gif
Normal file
|
After Width: | Height: | Size: 297 KiB |
BIN
res/ui/interactive_tutorial.noinline/1_3_expand.gif
Normal file
|
After Width: | Height: | Size: 993 KiB |
@ -5,7 +5,7 @@
|
|||||||
transform: translateX(-50%);
|
transform: translateX(-50%);
|
||||||
color: #333;
|
color: #333;
|
||||||
z-index: 9999;
|
z-index: 9999;
|
||||||
background: rgba(0, 10, 20, 0.5);
|
background: $ingameHudBg;
|
||||||
@include S(padding, 5px);
|
@include S(padding, 5px);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|||||||
@ -10,7 +10,7 @@
|
|||||||
@include S(width, 240px);
|
@include S(width, 240px);
|
||||||
@include S(grid-column-gap, 5px);
|
@include S(grid-column-gap, 5px);
|
||||||
|
|
||||||
background: rgba(#333438, 0.8);
|
background: $ingameHudBg;
|
||||||
grid-template-columns: 1fr auto;
|
grid-template-columns: 1fr auto;
|
||||||
grid-template-rows: auto 1fr;
|
grid-template-rows: auto 1fr;
|
||||||
|
|
||||||
@ -108,7 +108,8 @@
|
|||||||
.variant {
|
.variant {
|
||||||
grid-row: 2 / 3;
|
grid-row: 2 / 3;
|
||||||
@include S(border-radius, $globalBorderRadius);
|
@include S(border-radius, $globalBorderRadius);
|
||||||
background: rgba(0, 10, 20, 0.2);
|
background: rgba($ingameHudBg, 0.3);
|
||||||
|
opacity: 0.5;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
position: relative;
|
position: relative;
|
||||||
@ -117,7 +118,8 @@
|
|||||||
@include S(grid-gap, 10px);
|
@include S(grid-gap, 10px);
|
||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
background-color: rgba(74, 163, 223, 0.6);
|
opacity: 1;
|
||||||
|
background-color: rgba($colorBlueBright, 0.8);
|
||||||
}
|
}
|
||||||
|
|
||||||
$iconSize: 25px;
|
$iconSize: 25px;
|
||||||
|
|||||||
@ -41,8 +41,8 @@
|
|||||||
background: center center / 70% no-repeat;
|
background: center center / 70% no-repeat;
|
||||||
|
|
||||||
&:not(.unlocked) {
|
&:not(.unlocked) {
|
||||||
@include S(width, 30px);
|
@include S(width, 20px);
|
||||||
opacity: 0.8;
|
opacity: 0.15;
|
||||||
background-image: none !important;
|
background-image: none !important;
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
#ingame_HUD_DebugInfo {
|
#ingame_HUD_DebugInfo {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@include S(bottom, 5px);
|
@include S(bottom, 5px);
|
||||||
@include S(left, 5px);
|
@include S(right, 5px);
|
||||||
|
|
||||||
|
text-align: right;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
display: flex;
|
display: flex;
|
||||||
line-height: 15px;
|
line-height: 15px;
|
||||||
|
|||||||
@ -118,7 +118,7 @@
|
|||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
@include S(width, 350px);
|
@include S(width, 350px);
|
||||||
|
|
||||||
> strong {
|
strong {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,6 +139,14 @@
|
|||||||
background-color: rgb(250, 206, 206);
|
background-color: rgb(250, 206, 206);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ul.bucketList {
|
||||||
|
padding-left: 30px;
|
||||||
|
|
||||||
|
li {
|
||||||
|
display: list-item;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
> .buttons {
|
> .buttons {
|
||||||
|
|||||||
@ -76,7 +76,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
> button {
|
.buttonContainer button {
|
||||||
@include PlainText;
|
@include PlainText;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
border-color: rgba(0, 0, 0, 0.1);
|
border-color: rgba(0, 0, 0, 0.1);
|
||||||
@ -86,7 +86,7 @@
|
|||||||
@include S(margin-right, 3px);
|
@include S(margin-right, 3px);
|
||||||
@include IncreasedClickArea(0px);
|
@include IncreasedClickArea(0px);
|
||||||
@include ButtonText;
|
@include ButtonText;
|
||||||
@include S(min-height, 30px);
|
@include S(min-height, 40px);
|
||||||
transition: all 0.12s ease-in-out;
|
transition: all 0.12s ease-in-out;
|
||||||
transition-property: opacity, transform;
|
transition-property: opacity, transform;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
|
|||||||
50
src/css/ingame_hud/interactive_tutorial.scss
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -3,8 +3,7 @@
|
|||||||
@include S(top, 50px);
|
@include S(top, 50px);
|
||||||
left: 50%;
|
left: 50%;
|
||||||
transform: translateX(-50%);
|
transform: translateX(-50%);
|
||||||
background: rgba(lighten(#f77, 5), 0.95);
|
background: $ingameHudBg;
|
||||||
@include S(border-radius, $globalBorderRadius);
|
|
||||||
@include S(padding, 6px, 10px);
|
@include S(padding, 6px, 10px);
|
||||||
@include SuperSmallText;
|
@include SuperSmallText;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
|
|||||||
@ -1,7 +1,12 @@
|
|||||||
#ingame_HUD_TutorialHints {
|
#ingame_HUD_TutorialHints {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@include S(left, 10px);
|
@include S(left, 10px);
|
||||||
@include S(bottom, 50px);
|
@include S(bottom, 10px);
|
||||||
|
|
||||||
|
@include StyleBelowWidth(1430px) {
|
||||||
|
@include S(bottom, 50px);
|
||||||
|
}
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
background: rgba(50, 60, 70, 0);
|
background: rgba(50, 60, 70, 0);
|
||||||
@ -50,6 +55,7 @@
|
|||||||
|
|
||||||
button.toggleHint {
|
button.toggleHint {
|
||||||
@include PlainText;
|
@include PlainText;
|
||||||
|
@include IncreasedClickArea(0px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,7 +66,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.enlarged {
|
&.enlarged {
|
||||||
background: rgba(50, 60, 70, 0.9);
|
background: $ingameHudBg;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
bottom: 50%;
|
bottom: 50%;
|
||||||
transform: translate(-50%, 50%);
|
transform: translate(-50%, 50%);
|
||||||
@ -75,7 +81,7 @@
|
|||||||
bottom: -1000px;
|
bottom: -1000px;
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
|
|
||||||
background: rgba(50, 60, 70, 0.3);
|
background: rgba($ingameHudBg, 0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
#ingame_HUD_Watermark {
|
#ingame_HUD_Watermark {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background: uiResource("get_on_itch_io.svg") center center / contain no-repeat;
|
background: uiResource("get_on_steam.png") center center / contain no-repeat;
|
||||||
@include S(width, 110px);
|
@include S(width, 110px);
|
||||||
@include S(height, 40px);
|
@include S(height, 40px);
|
||||||
@include S(top, 10px);
|
@include S(top, 10px);
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
#ingame_HUD_Waypoints_Hint {
|
#ingame_HUD_Waypoints_Hint {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@include S(right, 10px);
|
@include S(right, 10px);
|
||||||
@include S(bottom, 100px);
|
@include S(bottom, 10px);
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|||||||
@ -49,6 +49,7 @@
|
|||||||
@import "ingame_hud/watermark";
|
@import "ingame_hud/watermark";
|
||||||
@import "ingame_hud/blueprint_placer";
|
@import "ingame_hud/blueprint_placer";
|
||||||
@import "ingame_hud/waypoints";
|
@import "ingame_hud/waypoints";
|
||||||
|
@import "ingame_hud/interactive_tutorial";
|
||||||
|
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
$elements:
|
$elements:
|
||||||
@ -69,6 +70,7 @@ ingame_HUD_Notifications,
|
|||||||
ingame_HUD_MassSelector,
|
ingame_HUD_MassSelector,
|
||||||
ingame_HUD_DebugInfo,
|
ingame_HUD_DebugInfo,
|
||||||
ingame_HUD_EntityDebugger,
|
ingame_HUD_EntityDebugger,
|
||||||
|
ingame_HUD_InteractiveTutorial,
|
||||||
ingame_HUD_TutorialHints,
|
ingame_HUD_TutorialHints,
|
||||||
ingame_HUD_buildings_toolbar,
|
ingame_HUD_buildings_toolbar,
|
||||||
ingame_HUD_BlueprintPlacer,
|
ingame_HUD_BlueprintPlacer,
|
||||||
@ -79,9 +81,9 @@ ingame_HUD_Watermark,
|
|||||||
ingame_HUD_BetaOverlay,
|
ingame_HUD_BetaOverlay,
|
||||||
|
|
||||||
// Dialogs
|
// Dialogs
|
||||||
ingame_HUD_UnlockNotification,
|
|
||||||
ingame_HUD_Shop,
|
ingame_HUD_Shop,
|
||||||
ingame_HUD_Statistics,
|
ingame_HUD_Statistics,
|
||||||
|
ingame_HUD_UnlockNotification,
|
||||||
ingame_HUD_SettingsMenu,
|
ingame_HUD_SettingsMenu,
|
||||||
ingame_HUD_ModalDialogs;
|
ingame_HUD_ModalDialogs;
|
||||||
|
|
||||||
|
|||||||
@ -60,28 +60,17 @@
|
|||||||
|
|
||||||
.mainWrapper {
|
.mainWrapper {
|
||||||
@include S(padding, 0, 10px);
|
@include S(padding, 0, 10px);
|
||||||
align-items: center;
|
align-items: start;
|
||||||
justify-items: center;
|
justify-items: center;
|
||||||
|
|
||||||
&.noDemo {
|
@include S(grid-column-gap, 10px);
|
||||||
display: flex;
|
display: grid;
|
||||||
flex-direction: column;
|
grid-template-columns: 1fr 1fr;
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.demo {
|
|
||||||
@include S(grid-column-gap, 10px);
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 1fr 1fr;
|
|
||||||
}
|
|
||||||
|
|
||||||
.standaloneBanner {
|
.standaloneBanner {
|
||||||
background: rgb(255, 234, 245);
|
background: rgb(255, 234, 245);
|
||||||
@include S(border-radius, $globalBorderRadius);
|
@include S(border-radius, $globalBorderRadius);
|
||||||
height: 100%;
|
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
@include S(width, 300px);
|
|
||||||
@include S(padding, 15px);
|
@include S(padding, 15px);
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -114,9 +103,9 @@
|
|||||||
|
|
||||||
.steamLink {
|
.steamLink {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@include S(height, 50px);
|
@include S(height, 40px);
|
||||||
|
|
||||||
background: uiResource("get_on_itch_io.svg") center center / contain no-repeat;
|
background: uiResource("get_on_steam.png") center center / contain no-repeat;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
display: block;
|
display: block;
|
||||||
text-indent: -999em;
|
text-indent: -999em;
|
||||||
@ -165,6 +154,44 @@
|
|||||||
border: #{D(2px)} solid rgba(0, 10, 20, 0.1);
|
border: #{D(2px)} solid rgba(0, 10, 20, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sideContainer {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
@include S(width, 300px);
|
||||||
|
|
||||||
|
.standaloneBanner {
|
||||||
|
flex-grow: 1;
|
||||||
|
@include S(margin-bottom, 10px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.contest {
|
||||||
|
flex-grow: 1;
|
||||||
|
background: rgb(32, 187, 166);
|
||||||
|
@include S(padding, 15px);
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
@include Heading;
|
||||||
|
color: #fff;
|
||||||
|
font-weight: bold;
|
||||||
|
text-transform: uppercase;
|
||||||
|
@include S(margin-bottom, 5px);
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
color: #fff;
|
||||||
|
@include Text;
|
||||||
|
strong {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
@include S(margin-bottom, 5px);
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
background: #fff;
|
||||||
|
color: #333538;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.mainContainer {
|
.mainContainer {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
@ -30,7 +30,7 @@
|
|||||||
width: 200px;
|
width: 200px;
|
||||||
height: 80px;
|
height: 80px;
|
||||||
min-height: 40px;
|
min-height: 40px;
|
||||||
background: uiResource("get_on_itch_io.svg") center center / contain no-repeat;
|
background: uiResource("get_on_steam.png") center center / contain no-repeat;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
display: block;
|
display: block;
|
||||||
text-indent: -999em;
|
text-indent: -999em;
|
||||||
|
|||||||
@ -34,8 +34,7 @@ $colorGreenBright: #66bb6a;
|
|||||||
$colorBlueBright: rgb(74, 163, 223);
|
$colorBlueBright: rgb(74, 163, 223);
|
||||||
$colorRedBright: #ef5072;
|
$colorRedBright: #ef5072;
|
||||||
$themeColor: #393747;
|
$themeColor: #393747;
|
||||||
$ingameHudBg: rgba($accentColorBright, 0.1);
|
$ingameHudBg: rgba(#333438, 0.9);
|
||||||
$ingameHudBorder: #{D(1.5px)} solid $accentColorDark;
|
|
||||||
|
|
||||||
$text3dColor: #f4ffff;
|
$text3dColor: #f4ffff;
|
||||||
|
|
||||||
|
|||||||
@ -40,9 +40,6 @@
|
|||||||
<meta http-equiv="Expires" content="0" />
|
<meta http-equiv="Expires" content="0" />
|
||||||
<link rel="shortcut icon" type="image/x-icon" href="favicon.ico" />
|
<link rel="shortcut icon" type="image/x-icon" href="favicon.ico" />
|
||||||
<link rel="canonical" href="https://shapez.io" />
|
<link rel="canonical" href="https://shapez.io" />
|
||||||
|
|
||||||
<!-- a/b testing -->
|
|
||||||
<script src="https://www.googleoptimize.com/optimize.js?id=OPT-M5NHCV7"></script>
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body oncontextmenu="return false" style="background: #393747;"></body>
|
<body oncontextmenu="return false" style="background: #393747;"></body>
|
||||||
|
|||||||
@ -121,29 +121,18 @@ export class Application {
|
|||||||
* Initializes all platform instances
|
* Initializes all platform instances
|
||||||
*/
|
*/
|
||||||
initPlatformDependentInstances() {
|
initPlatformDependentInstances() {
|
||||||
logger.log("Creating platform dependent instances");
|
logger.log("Creating platform dependent instances (standalone=", G_IS_STANDALONE, ")");
|
||||||
|
|
||||||
// Start with empty ad provider
|
|
||||||
this.adProvider = new NoAdProvider(this);
|
|
||||||
|
|
||||||
if (G_IS_STANDALONE) {
|
|
||||||
this.storage = new StorageImplElectron(this);
|
|
||||||
} else {
|
|
||||||
if (window.indexedDB) {
|
|
||||||
this.storage = new StorageImplBrowserIndexedDB(this);
|
|
||||||
} else {
|
|
||||||
this.storage = new StorageImplBrowser(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.sound = new SoundImplBrowser(this);
|
|
||||||
|
|
||||||
if (G_IS_STANDALONE) {
|
if (G_IS_STANDALONE) {
|
||||||
this.platformWrapper = new PlatformWrapperImplElectron(this);
|
this.platformWrapper = new PlatformWrapperImplElectron(this);
|
||||||
} else {
|
} else {
|
||||||
this.platformWrapper = new PlatformWrapperImplBrowser(this);
|
this.platformWrapper = new PlatformWrapperImplBrowser(this);
|
||||||
}
|
}
|
||||||
this.analytics = new GoogleAnalyticsImpl(this);
|
|
||||||
|
|
||||||
|
// Start with empty ad provider
|
||||||
|
this.adProvider = new NoAdProvider(this);
|
||||||
|
this.sound = new SoundImplBrowser(this);
|
||||||
|
this.analytics = new GoogleAnalyticsImpl(this);
|
||||||
this.gameAnalytics = new ShapezGameAnalytics(this);
|
this.gameAnalytics = new ShapezGameAnalytics(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,11 +256,15 @@ export class Application {
|
|||||||
onAppRenderableStateChanged(renderable) {
|
onAppRenderableStateChanged(renderable) {
|
||||||
logger.log("Application renderable:", renderable);
|
logger.log("Application renderable:", renderable);
|
||||||
window.focus();
|
window.focus();
|
||||||
|
const currentState = this.stateMgr.getCurrentState();
|
||||||
if (!renderable) {
|
if (!renderable) {
|
||||||
this.stateMgr.getCurrentState().onAppPause();
|
if (currentState) {
|
||||||
|
currentState.onAppPause();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Got resume
|
if (currentState) {
|
||||||
this.stateMgr.getCurrentState().onAppResume();
|
currentState.onAppResume();
|
||||||
|
}
|
||||||
this.checkResize();
|
this.checkResize();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -285,7 +278,10 @@ export class Application {
|
|||||||
if (!this.unloaded) {
|
if (!this.unloaded) {
|
||||||
logSection("UNLOAD HANDLER", "#f77");
|
logSection("UNLOAD HANDLER", "#f77");
|
||||||
this.unloaded = true;
|
this.unloaded = true;
|
||||||
this.stateMgr.getCurrentState().onBeforeExit();
|
const currentState = this.stateMgr.getCurrentState();
|
||||||
|
if (currentState) {
|
||||||
|
currentState.onBeforeExit();
|
||||||
|
}
|
||||||
this.deinitialize();
|
this.deinitialize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -295,8 +291,9 @@ export class Application {
|
|||||||
*/
|
*/
|
||||||
onBeforeUnload(event) {
|
onBeforeUnload(event) {
|
||||||
logSection("BEFORE UNLOAD HANDLER", "#f77");
|
logSection("BEFORE UNLOAD HANDLER", "#f77");
|
||||||
|
const currentState = this.stateMgr.getCurrentState();
|
||||||
|
|
||||||
if (!G_IS_DEV && this.stateMgr.getCurrentState().getHasUnloadConfirmation()) {
|
if (!G_IS_DEV && currentState && currentState.getHasUnloadConfirmation()) {
|
||||||
if (!G_IS_STANDALONE) {
|
if (!G_IS_STANDALONE) {
|
||||||
// Need to show a "Are you sure you want to exit"
|
// Need to show a "Are you sure you want to exit"
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
@ -346,7 +343,10 @@ export class Application {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.stateMgr.getCurrentState().onBackgroundTick(dt);
|
const currentState = this.stateMgr.getCurrentState();
|
||||||
|
if (currentState) {
|
||||||
|
currentState.onBackgroundTick(dt);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -366,7 +366,10 @@ export class Application {
|
|||||||
this.lastResizeCheck = time;
|
this.lastResizeCheck = time;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.stateMgr.getCurrentState().onRender(dt);
|
const currentState = this.stateMgr.getCurrentState();
|
||||||
|
if (currentState) {
|
||||||
|
currentState.onRender(dt);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -379,7 +382,10 @@ export class Application {
|
|||||||
if (this.screenWidth !== w || this.screenHeight !== h || forceUpdate) {
|
if (this.screenWidth !== w || this.screenHeight !== h || forceUpdate) {
|
||||||
this.screenWidth = w;
|
this.screenWidth = w;
|
||||||
this.screenHeight = h;
|
this.screenHeight = h;
|
||||||
this.stateMgr.getCurrentState().onResized(this.screenWidth, this.screenHeight);
|
const currentState = this.stateMgr.getCurrentState();
|
||||||
|
if (currentState) {
|
||||||
|
currentState.onResized(this.screenWidth, this.screenHeight);
|
||||||
|
}
|
||||||
|
|
||||||
const scale = this.getEffectiveUiScale();
|
const scale = this.getEffectiveUiScale();
|
||||||
waitNextFrame().then(() => document.documentElement.style.setProperty("--ui-scale", scale));
|
waitNextFrame().then(() => document.documentElement.style.setProperty("--ui-scale", scale));
|
||||||
|
|||||||
@ -1,4 +1,39 @@
|
|||||||
export const CHANGELOG = [
|
export const CHANGELOG = [
|
||||||
|
{
|
||||||
|
version: "1.1.8",
|
||||||
|
date: "07.06.2020",
|
||||||
|
entries: [
|
||||||
|
"You can now purchase the standalone on steam! <a href='https://steam.shapez.io' target='blank'>View steam page</a>",
|
||||||
|
"Added ability to create markers in the demo, but only two.",
|
||||||
|
"Contest #01 has ended! I'll now work through the entries, select the 5 I like most and present them to the community to vote for!",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
version: "1.1.7",
|
||||||
|
date: "04.06.2020",
|
||||||
|
entries: ["HOTFIX: Fix savegames not showing up on the standalone version"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
version: "1.1.6",
|
||||||
|
date: "04.06.2020",
|
||||||
|
entries: [
|
||||||
|
"The steam release will happen on the <strong>7th of June</strong> - Be sure to add it to your wishlist! <a href='https://steam.shapez.io' target='blank'>View on steam</a>",
|
||||||
|
"Fixed level complete dialog being blurred when the shop was opened before",
|
||||||
|
"Standalone: Increased icon visibility for windows builds",
|
||||||
|
"Web version: Fixed firefox not loading the game when browsing in private mode",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
version: "1.1.5",
|
||||||
|
date: "03.06.2020",
|
||||||
|
entries: ["Added weekly contests!"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
version: "1.1.4",
|
||||||
|
date: "01.06.2020",
|
||||||
|
entries: ["Add 'interactive' tutorial for the first level to improve onboarding experience"],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
version: "1.1.3",
|
version: "1.1.3",
|
||||||
date: "01.06.2020",
|
date: "01.06.2020",
|
||||||
|
|||||||
@ -10,7 +10,10 @@ import { AtlasDefinition, atlasFiles } from "./atlas_definitions";
|
|||||||
|
|
||||||
const logger = createLogger("background_loader");
|
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 = [
|
const essentialMainMenuSounds = [
|
||||||
SOUNDS.uiClick,
|
SOUNDS.uiClick,
|
||||||
SOUNDS.uiError,
|
SOUNDS.uiError,
|
||||||
@ -21,7 +24,7 @@ const essentialMainMenuSounds = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
const essentialBareGameAtlases = atlasFiles;
|
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 essentialBareGameSounds = [MUSIC.theme];
|
||||||
|
|
||||||
const additionalGameSprites = [];
|
const additionalGameSprites = [];
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import { GLOBAL_APP } from "./globals";
|
|||||||
|
|
||||||
const logger = createLogger("click_detector");
|
const logger = createLogger("click_detector");
|
||||||
|
|
||||||
export const MAX_MOVE_DISTANCE_PX = IS_MOBILE ? 20 : 40;
|
export const MAX_MOVE_DISTANCE_PX = IS_MOBILE ? 20 : 80;
|
||||||
|
|
||||||
// For debugging
|
// For debugging
|
||||||
const registerClickDetectors = G_IS_DEV && true;
|
const registerClickDetectors = G_IS_DEV && true;
|
||||||
@ -404,11 +404,11 @@ export class ClickDetector {
|
|||||||
if (this.clickDownPosition) {
|
if (this.clickDownPosition) {
|
||||||
const pos = /** @type {typeof ClickDetector} */ (this.constructor).extractPointerPosition(event);
|
const pos = /** @type {typeof ClickDetector} */ (this.constructor).extractPointerPosition(event);
|
||||||
const distance = pos.distance(this.clickDownPosition);
|
const distance = pos.distance(this.clickDownPosition);
|
||||||
if (distance <= this.maxDistance) {
|
if (!IS_MOBILE || distance <= this.maxDistance) {
|
||||||
dispatchClick = true;
|
dispatchClick = true;
|
||||||
dispatchClickPos = pos;
|
dispatchClickPos = pos;
|
||||||
} else {
|
} else {
|
||||||
// console.warn("[ClickDetector] Touch does not count as click: ms=", timeSinceStart, "-> tolerance:", tolerance, "(was", distance, ")");
|
console.warn("[ClickDetector] Touch does not count as click:", "(was", distance, ")");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -15,8 +15,7 @@ export const THIRDPARTY_URLS = {
|
|||||||
discord: "https://discord.gg/HN7EVzV",
|
discord: "https://discord.gg/HN7EVzV",
|
||||||
github: "https://github.com/tobspr/shapez.io",
|
github: "https://github.com/tobspr/shapez.io",
|
||||||
|
|
||||||
// standaloneStorePage: "https://steam.shapez.io",
|
standaloneStorePage: "https://store.steampowered.com/app/1318690/shapezio/",
|
||||||
standaloneStorePage: "https://tobspr.itch.io/shapez.io",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const globalConfig = {
|
export const globalConfig = {
|
||||||
@ -46,7 +45,7 @@ export const globalConfig = {
|
|||||||
// Belt speeds
|
// Belt speeds
|
||||||
// NOTICE: Update webpack.production.config too!
|
// NOTICE: Update webpack.production.config too!
|
||||||
beltSpeedItemsPerSecond: 2,
|
beltSpeedItemsPerSecond: 2,
|
||||||
itemSpacingOnBelts: 0.63,
|
itemSpacingOnBelts: 0.8,
|
||||||
minerSpeedItemsPerSecond: 0, // COMPUTED
|
minerSpeedItemsPerSecond: 0, // COMPUTED
|
||||||
|
|
||||||
undergroundBeltMaxTilesByTier: [5, 8],
|
undergroundBeltMaxTilesByTier: [5, 8],
|
||||||
@ -83,7 +82,7 @@ export const globalConfig = {
|
|||||||
|
|
||||||
debug: {
|
debug: {
|
||||||
/* dev:start */
|
/* dev:start */
|
||||||
// fastGameEnter: true,
|
fastGameEnter: true,
|
||||||
// noArtificialDelays: true,
|
// noArtificialDelays: true,
|
||||||
// disableSavegameWrite: true,
|
// disableSavegameWrite: true,
|
||||||
// showEntityBounds: true,
|
// showEntityBounds: true,
|
||||||
@ -95,7 +94,7 @@ export const globalConfig = {
|
|||||||
// rewardsInstant: true,
|
// rewardsInstant: true,
|
||||||
allBuildingsUnlocked: true,
|
allBuildingsUnlocked: true,
|
||||||
blueprintsNoCost: true,
|
blueprintsNoCost: true,
|
||||||
// upgradesNoCost: true,
|
upgradesNoCost: true,
|
||||||
// disableUnlockDialog: true,
|
// disableUnlockDialog: true,
|
||||||
// disableLogicTicks: true,
|
// disableLogicTicks: true,
|
||||||
// testClipping: true,
|
// testClipping: true,
|
||||||
@ -104,11 +103,12 @@ export const globalConfig = {
|
|||||||
// enableEntityInspector: true,
|
// enableEntityInspector: true,
|
||||||
// testAds: true,
|
// testAds: true,
|
||||||
// disableMapOverview: true,
|
// disableMapOverview: true,
|
||||||
disableTutorialHints: true,
|
// disableTutorialHints: true,
|
||||||
disableUpgradeNotification: true,
|
disableUpgradeNotification: true,
|
||||||
// instantBelts: true,
|
// instantBelts: true,
|
||||||
// instantProcessors: true,
|
// instantProcessors: true,
|
||||||
// instantMiners: true,
|
// instantMiners: true,
|
||||||
|
// resumeGameOnFastEnter: false,
|
||||||
|
|
||||||
// renderForTrailer: true,
|
// renderForTrailer: true,
|
||||||
/* dev:end */
|
/* dev:end */
|
||||||
|
|||||||
@ -94,14 +94,15 @@ export class HubGoals extends BasicSerializableObject {
|
|||||||
|
|
||||||
this.createNextGoal();
|
this.createNextGoal();
|
||||||
|
|
||||||
// Allow quickly switching goals in dev mode with key "C"
|
// Allow quickly switching goals in dev mode
|
||||||
if (G_IS_DEV) {
|
if (G_IS_DEV) {
|
||||||
this.root.gameState.inputReciever.keydown.add(key => {
|
if (G_IS_DEV) {
|
||||||
if (key.keyCode === 66) {
|
window.addEventListener("keydown", ev => {
|
||||||
// Key: b
|
if (ev.key === "b") {
|
||||||
this.onGoalCompleted();
|
this.onGoalCompleted();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -28,6 +28,7 @@ import { HUDWatermark } from "./parts/watermark";
|
|||||||
import { HUDModalDialogs } from "./parts/modal_dialogs";
|
import { HUDModalDialogs } from "./parts/modal_dialogs";
|
||||||
import { HUDPartTutorialHints } from "./parts/tutorial_hints";
|
import { HUDPartTutorialHints } from "./parts/tutorial_hints";
|
||||||
import { HUDWaypoints } from "./parts/waypoints";
|
import { HUDWaypoints } from "./parts/waypoints";
|
||||||
|
import { HUDInteractiveTutorial } from "./parts/interactive_tutorial";
|
||||||
|
|
||||||
/* dev:start */
|
/* dev:start */
|
||||||
import { TrailerMaker } from "./trailer_maker";
|
import { TrailerMaker } from "./trailer_maker";
|
||||||
@ -87,6 +88,7 @@ export class GameHUD {
|
|||||||
}
|
}
|
||||||
if (this.root.app.settings.getAllSettings().offerHints) {
|
if (this.root.app.settings.getAllSettings().offerHints) {
|
||||||
this.parts.tutorialHints = new HUDPartTutorialHints(this.root);
|
this.parts.tutorialHints = new HUDPartTutorialHints(this.root);
|
||||||
|
this.parts.interactiveTutorial = new HUDInteractiveTutorial(this.root);
|
||||||
}
|
}
|
||||||
|
|
||||||
const frag = document.createDocumentFragment();
|
const frag = document.createDocumentFragment();
|
||||||
|
|||||||
@ -5,9 +5,9 @@ import { enumNotificationType } from "./notifications";
|
|||||||
import { T } from "../../../translations";
|
import { T } from "../../../translations";
|
||||||
import { KEYMAPPINGS } from "../../key_action_mapper";
|
import { KEYMAPPINGS } from "../../key_action_mapper";
|
||||||
import { IS_DEMO } from "../../../core/config";
|
import { IS_DEMO } from "../../../core/config";
|
||||||
|
import { DynamicDomAttach } from "../dynamic_dom_attach";
|
||||||
|
|
||||||
export class HUDGameMenu extends BaseHUDPart {
|
export class HUDGameMenu extends BaseHUDPart {
|
||||||
initialize() {}
|
|
||||||
createElements(parent) {
|
createElements(parent) {
|
||||||
this.element = makeDiv(parent, "ingame_HUD_GameMenu");
|
this.element = makeDiv(parent, "ingame_HUD_GameMenu");
|
||||||
|
|
||||||
@ -22,12 +22,16 @@ export class HUDGameMenu extends BaseHUDPart {
|
|||||||
T.ingame.notifications.newUpgrade,
|
T.ingame.notifications.newUpgrade,
|
||||||
enumNotificationType.upgrade,
|
enumNotificationType.upgrade,
|
||||||
]),
|
]),
|
||||||
|
visible: () =>
|
||||||
|
!this.root.app.settings.getAllSettings().offerHints || this.root.hubGoals.level >= 3,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "stats",
|
id: "stats",
|
||||||
label: "Stats",
|
label: "Stats",
|
||||||
handler: () => this.root.hud.parts.statistics.show(),
|
handler: () => this.root.hud.parts.statistics.show(),
|
||||||
keybinding: KEYMAPPINGS.ingame.menuOpenStats,
|
keybinding: KEYMAPPINGS.ingame.menuOpenStats,
|
||||||
|
visible: () =>
|
||||||
|
!this.root.app.settings.getAllSettings().offerHints || this.root.hubGoals.level >= 3,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -36,14 +40,24 @@ export class HUDGameMenu extends BaseHUDPart {
|
|||||||
* button: HTMLElement,
|
* button: HTMLElement,
|
||||||
* badgeElement: HTMLElement,
|
* badgeElement: HTMLElement,
|
||||||
* lastRenderAmount: number,
|
* lastRenderAmount: number,
|
||||||
|
* condition?: function,
|
||||||
* notification: [string, enumNotificationType]
|
* notification: [string, enumNotificationType]
|
||||||
* }>} */
|
* }>} */
|
||||||
this.badgesToUpdate = [];
|
this.badgesToUpdate = [];
|
||||||
|
|
||||||
buttons.forEach(({ id, label, handler, keybinding, badge, notification }) => {
|
/** @type {Array<{
|
||||||
|
* button: HTMLElement,
|
||||||
|
* condition: function,
|
||||||
|
* domAttach: DynamicDomAttach
|
||||||
|
* }>} */
|
||||||
|
this.visibilityToUpdate = [];
|
||||||
|
|
||||||
|
this.buttonsElement = makeDiv(this.element, null, ["buttonContainer"]);
|
||||||
|
|
||||||
|
buttons.forEach(({ id, label, handler, keybinding, badge, notification, visible }) => {
|
||||||
const button = document.createElement("button");
|
const button = document.createElement("button");
|
||||||
button.setAttribute("data-button-id", id);
|
button.setAttribute("data-button-id", id);
|
||||||
this.element.appendChild(button);
|
this.buttonsElement.appendChild(button);
|
||||||
this.trackClicks(button, handler);
|
this.trackClicks(button, handler);
|
||||||
|
|
||||||
if (keybinding) {
|
if (keybinding) {
|
||||||
@ -52,6 +66,14 @@ export class HUDGameMenu extends BaseHUDPart {
|
|||||||
binding.appendLabelToElement(button);
|
binding.appendLabelToElement(button);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (visible) {
|
||||||
|
this.visibilityToUpdate.push({
|
||||||
|
button,
|
||||||
|
condition: visible,
|
||||||
|
domAttach: new DynamicDomAttach(this.root, button),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (badge) {
|
if (badge) {
|
||||||
const badgeElement = makeDiv(button, null, ["badge"]);
|
const badgeElement = makeDiv(button, null, ["badge"]);
|
||||||
this.badgesToUpdate.push({
|
this.badgesToUpdate.push({
|
||||||
@ -60,6 +82,7 @@ export class HUDGameMenu extends BaseHUDPart {
|
|||||||
button,
|
button,
|
||||||
badgeElement,
|
badgeElement,
|
||||||
notification,
|
notification,
|
||||||
|
condition: visible,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -78,27 +101,52 @@ export class HUDGameMenu extends BaseHUDPart {
|
|||||||
|
|
||||||
this.musicButton.classList.toggle("muted", this.root.app.settings.getAllSettings().musicMuted);
|
this.musicButton.classList.toggle("muted", this.root.app.settings.getAllSettings().musicMuted);
|
||||||
this.sfxButton.classList.toggle("muted", this.root.app.settings.getAllSettings().soundsMuted);
|
this.sfxButton.classList.toggle("muted", this.root.app.settings.getAllSettings().soundsMuted);
|
||||||
|
}
|
||||||
|
initialize() {
|
||||||
this.root.signals.gameSaved.add(this.onGameSaved, this);
|
this.root.signals.gameSaved.add(this.onGameSaved, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
update() {
|
update() {
|
||||||
let playSound = false;
|
let playSound = false;
|
||||||
let notifications = new Set();
|
let notifications = new Set();
|
||||||
|
|
||||||
|
// Update visibility of buttons
|
||||||
|
for (let i = 0; i < this.visibilityToUpdate.length; ++i) {
|
||||||
|
const { button, condition, domAttach } = this.visibilityToUpdate[i];
|
||||||
|
domAttach.update(condition());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for notifications and badges
|
||||||
for (let i = 0; i < this.badgesToUpdate.length; ++i) {
|
for (let i = 0; i < this.badgesToUpdate.length; ++i) {
|
||||||
const { badge, button, badgeElement, lastRenderAmount, notification } = this.badgesToUpdate[i];
|
const {
|
||||||
|
badge,
|
||||||
|
button,
|
||||||
|
badgeElement,
|
||||||
|
lastRenderAmount,
|
||||||
|
notification,
|
||||||
|
condition,
|
||||||
|
} = this.badgesToUpdate[i];
|
||||||
|
|
||||||
|
if (condition && !condition()) {
|
||||||
|
// Do not show notifications for invisible buttons
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the amount shown differs from the one shown last frame
|
||||||
const amount = badge();
|
const amount = badge();
|
||||||
if (lastRenderAmount !== amount) {
|
if (lastRenderAmount !== amount) {
|
||||||
if (amount > 0) {
|
if (amount > 0) {
|
||||||
badgeElement.innerText = amount;
|
badgeElement.innerText = amount;
|
||||||
}
|
}
|
||||||
// Check if the badge increased
|
// Check if the badge increased, if so play a notification
|
||||||
if (amount > lastRenderAmount) {
|
if (amount > lastRenderAmount) {
|
||||||
playSound = true;
|
playSound = true;
|
||||||
if (notification) {
|
if (notification) {
|
||||||
notifications.add(notification);
|
notifications.add(notification);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Rerender notifications
|
||||||
this.badgesToUpdate[i].lastRenderAmount = amount;
|
this.badgesToUpdate[i].lastRenderAmount = amount;
|
||||||
button.classList.toggle("hasBadge", amount > 0);
|
button.classList.toggle("hasBadge", amount > 0);
|
||||||
}
|
}
|
||||||
@ -107,6 +155,7 @@ export class HUDGameMenu extends BaseHUDPart {
|
|||||||
if (playSound) {
|
if (playSound) {
|
||||||
this.root.soundProxy.playUi(SOUNDS.badgeNotification);
|
this.root.soundProxy.playUi(SOUNDS.badgeNotification);
|
||||||
}
|
}
|
||||||
|
|
||||||
notifications.forEach(([notification, type]) => {
|
notifications.forEach(([notification, type]) => {
|
||||||
this.root.hud.signals.notification.dispatch(notification, type);
|
this.root.hud.signals.notification.dispatch(notification, type);
|
||||||
});
|
});
|
||||||
@ -118,13 +167,6 @@ export class HUDGameMenu extends BaseHUDPart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
startSave() {
|
startSave() {
|
||||||
// if (IS_DEMO) {
|
|
||||||
// this.root.hud.parts.dialogs.showFeatureRestrictionInfo(
|
|
||||||
// null,
|
|
||||||
// T.dialogs.saveNotPossibleInDemo.desc
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
this.root.gameState.doSave();
|
this.root.gameState.doSave();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
81
src/js/game/hud/parts/interactive_tutorial.js
Normal file
@ -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"],
|
||||||
|
`
|
||||||
|
<strong class="title">Tutorial</strong>
|
||||||
|
`
|
||||||
|
);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -23,10 +23,6 @@ export class HUDKeybindingOverlay extends BaseHUDPart {
|
|||||||
"ingame_HUD_KeybindingOverlay",
|
"ingame_HUD_KeybindingOverlay",
|
||||||
[],
|
[],
|
||||||
`
|
`
|
||||||
<div class="binding">
|
|
||||||
<code class="keybinding">${getKeycode(KEYMAPPINGS.navigation.createMarker)}</code>
|
|
||||||
<label>${T.ingame.keybindingsOverlay.createMarker}</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="binding">
|
<div class="binding">
|
||||||
<code class="keybinding leftMouse noPlacementOnly"></code><i class="noPlacementOnly"></i>
|
<code class="keybinding leftMouse noPlacementOnly"></code><i class="noPlacementOnly"></i>
|
||||||
@ -35,8 +31,15 @@ export class HUDKeybindingOverlay extends BaseHUDPart {
|
|||||||
<code class="keybinding">${getKeycode(KEYMAPPINGS.navigation.mapMoveDown)}</code>
|
<code class="keybinding">${getKeycode(KEYMAPPINGS.navigation.mapMoveDown)}</code>
|
||||||
<code class="keybinding">${getKeycode(KEYMAPPINGS.navigation.mapMoveRight)}</code>
|
<code class="keybinding">${getKeycode(KEYMAPPINGS.navigation.mapMoveRight)}</code>
|
||||||
<label>${T.ingame.keybindingsOverlay.moveMap}</label>
|
<label>${T.ingame.keybindingsOverlay.moveMap}</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="binding noPlacementOnly">
|
||||||
|
<code class="keybinding rightMouse"></code>
|
||||||
|
<label>${T.ingame.keybindingsOverlay.delete}</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="binding noPlacementOnly">
|
<div class="binding noPlacementOnly">
|
||||||
<code class="keybinding builtinKey">${getKeycode(
|
<code class="keybinding builtinKey">${getKeycode(
|
||||||
KEYMAPPINGS.massSelect.massSelectStart
|
KEYMAPPINGS.massSelect.massSelectStart
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
import { cachebust } from "../../../core/cachebust";
|
|
||||||
import { InputReceiver } from "../../../core/input_receiver";
|
import { InputReceiver } from "../../../core/input_receiver";
|
||||||
import { TrackedState } from "../../../core/tracked_state";
|
import { TrackedState } from "../../../core/tracked_state";
|
||||||
import { makeDiv } from "../../../core/utils";
|
import { makeDiv } from "../../../core/utils";
|
||||||
@ -6,9 +5,8 @@ import { KeyActionMapper, KEYMAPPINGS } from "../../key_action_mapper";
|
|||||||
import { BaseHUDPart } from "../base_hud_part";
|
import { BaseHUDPart } from "../base_hud_part";
|
||||||
import { DynamicDomAttach } from "../dynamic_dom_attach";
|
import { DynamicDomAttach } from "../dynamic_dom_attach";
|
||||||
import { T } from "../../../translations";
|
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 {
|
export class HUDPartTutorialHints extends BaseHUDPart {
|
||||||
createElements(parent) {
|
createElements(parent) {
|
||||||
@ -55,15 +53,6 @@ export class HUDPartTutorialHints extends BaseHUDPart {
|
|||||||
this.domAttach = new DynamicDomAttach(this.root, this.element);
|
this.domAttach = new DynamicDomAttach(this.root, this.element);
|
||||||
|
|
||||||
this.currentShownLevel = new TrackedState(this.updateVideoUrl, this);
|
this.currentShownLevel = new TrackedState(this.updateVideoUrl, this);
|
||||||
|
|
||||||
this.root.signals.postLoadHook.add(() => {
|
|
||||||
if (this.root.hubGoals.level === 1 && !(G_IS_DEV && globalConfig.debug.disableTutorialHints)) {
|
|
||||||
this.root.hud.parts.dialogs.showInfo(
|
|
||||||
T.dialogs.hintDescription.title,
|
|
||||||
T.dialogs.hintDescription.desc
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateVideoUrl(level) {
|
updateVideoUrl(level) {
|
||||||
|
|||||||
@ -28,7 +28,7 @@ export class HUDUnlockNotification extends BaseHUDPart {
|
|||||||
createElements(parent) {
|
createElements(parent) {
|
||||||
this.inputReciever = new InputReceiver("unlock-notification");
|
this.inputReciever = new InputReceiver("unlock-notification");
|
||||||
|
|
||||||
this.element = makeDiv(parent, "ingame_HUD_UnlockNotification", []);
|
this.element = makeDiv(parent, "ingame_HUD_UnlockNotification", ["noBlur"]);
|
||||||
|
|
||||||
const dialog = makeDiv(this.element, null, ["dialog"]);
|
const dialog = makeDiv(this.element, null, ["dialog"]);
|
||||||
|
|
||||||
|
|||||||
@ -13,7 +13,7 @@ export class HUDWatermark extends BaseHUDPart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onWatermarkClick() {
|
onWatermarkClick() {
|
||||||
this.root.app.analytics.trackUiClick("watermark_click");
|
this.root.app.analytics.trackUiClick("watermark_click_2");
|
||||||
this.root.app.platformWrapper.openExternalLink(THIRDPARTY_URLS.standaloneStorePage);
|
this.root.app.platformWrapper.openExternalLink(THIRDPARTY_URLS.standaloneStorePage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -133,11 +133,6 @@ export class HUDWaypoints extends BaseHUDPart {
|
|||||||
* @param {Vector=} worldPos Override the world pos, otherwise it is the camera position
|
* @param {Vector=} worldPos Override the world pos, otherwise it is the camera position
|
||||||
*/
|
*/
|
||||||
requestCreateMarker(worldPos = null) {
|
requestCreateMarker(worldPos = null) {
|
||||||
if (IS_DEMO) {
|
|
||||||
this.root.hud.parts.dialogs.showFeatureRestrictionInfo(T.demo.features.creatingMarkers);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const markerNameInput = new FormElementInput({
|
const markerNameInput = new FormElementInput({
|
||||||
id: "markerName",
|
id: "markerName",
|
||||||
label: null,
|
label: null,
|
||||||
@ -157,6 +152,11 @@ export class HUDWaypoints extends BaseHUDPart {
|
|||||||
const center = worldPos || this.root.camera.center;
|
const center = worldPos || this.root.camera.center;
|
||||||
|
|
||||||
dialog.buttonSignals.ok.add(() => {
|
dialog.buttonSignals.ok.add(() => {
|
||||||
|
if (IS_DEMO && this.waypoints.length > 2) {
|
||||||
|
this.root.hud.parts.dialogs.showFeatureRestrictionInfo("", T.dialogs.markerDemoLimit.desc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.waypoints.push({
|
this.waypoints.push({
|
||||||
label: markerNameInput.getValue(),
|
label: markerNameInput.getValue(),
|
||||||
center: { x: center.x, y: center.y },
|
center: { x: center.x, y: center.y },
|
||||||
|
|||||||
@ -35,7 +35,7 @@ export const tutorialGoals = [
|
|||||||
// Circle
|
// Circle
|
||||||
{
|
{
|
||||||
shape: "CuCuCuCu", // belts t1
|
shape: "CuCuCuCu", // belts t1
|
||||||
required: 20,
|
required: 40,
|
||||||
reward: enumHubGoalRewards.reward_cutter_and_trash,
|
reward: enumHubGoalRewards.reward_cutter_and_trash,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@ -18,6 +18,36 @@ if (window.coreThreadLoadedCb) {
|
|||||||
window.coreThreadLoadedCb();
|
window.coreThreadLoadedCb();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!G_IS_DEV && !G_IS_STANDALONE) {
|
||||||
|
const monthlyUsers = 300; // thousand
|
||||||
|
const logrocketLimit = 10; // thousand
|
||||||
|
const percentageOfUsers = logrocketLimit / monthlyUsers;
|
||||||
|
|
||||||
|
if (Math.random() <= percentageOfUsers) {
|
||||||
|
logger.log("Analyzing this session with logrocket");
|
||||||
|
const logrocket = require("logrocket");
|
||||||
|
logrocket.init("p1x9zh/shapezio");
|
||||||
|
|
||||||
|
try {
|
||||||
|
logrocket.getSessionURL(function (sessionURL) {
|
||||||
|
logger.log("Connected lockrocket to GA");
|
||||||
|
// @ts-ignore
|
||||||
|
try {
|
||||||
|
window.ga("send", {
|
||||||
|
hitType: "event",
|
||||||
|
eventCategory: "LogRocket",
|
||||||
|
eventAction: sessionURL,
|
||||||
|
});
|
||||||
|
} catch (ex) {
|
||||||
|
logger.warn("Logrocket connection to analytics failed:", ex);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (ex) {
|
||||||
|
logger.warn("Logrocket connection to analytics failed:", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
`%cshapez.io ️%c\n© 2020 Tobias Springer IT Solutions\nCommit %c${G_BUILD_COMMIT_HASH}%c on %c${new Date(
|
`%cshapez.io ️%c\n© 2020 Tobias Springer IT Solutions\nCommit %c${G_BUILD_COMMIT_HASH}%c on %c${new Date(
|
||||||
G_BUILD_TIME
|
G_BUILD_TIME
|
||||||
|
|||||||
@ -1,11 +1,13 @@
|
|||||||
import { Math_min } from "../../core/builtins";
|
import { Math_min } from "../../core/builtins";
|
||||||
import { globalConfig, IS_MOBILE, IS_DEBUG, IS_DEMO } from "../../core/config";
|
import { globalConfig, IS_DEMO, IS_MOBILE } from "../../core/config";
|
||||||
import { createLogger } from "../../core/logging";
|
import { createLogger } from "../../core/logging";
|
||||||
import { queryParamOptions } from "../../core/query_parameters";
|
import { queryParamOptions } from "../../core/query_parameters";
|
||||||
import { clamp } from "../../core/utils";
|
import { clamp } from "../../core/utils";
|
||||||
|
import { GamedistributionAdProvider } from "../ad_providers/gamedistribution";
|
||||||
import { NoAdProvider } from "../ad_providers/no_ad_provider";
|
import { NoAdProvider } from "../ad_providers/no_ad_provider";
|
||||||
import { PlatformWrapperInterface } from "../wrapper";
|
import { PlatformWrapperInterface } from "../wrapper";
|
||||||
import { GamedistributionAdProvider } from "../ad_providers/gamedistribution";
|
import { StorageImplBrowser } from "./storage";
|
||||||
|
import { StorageImplBrowserIndexedDB } from "./storage_indexed_db";
|
||||||
|
|
||||||
const logger = createLogger("platform/browser");
|
const logger = createLogger("platform/browser");
|
||||||
|
|
||||||
@ -72,7 +74,43 @@ export class PlatformWrapperImplBrowser extends PlatformWrapperInterface {
|
|||||||
|
|
||||||
logger.log("Embed provider:", this.embedProvider.id);
|
logger.log("Embed provider:", this.embedProvider.id);
|
||||||
|
|
||||||
return super.initialize().then(() => this.initializeAdProvider());
|
return this.detectStorageImplementation()
|
||||||
|
.then(() => this.initializeAdProvider())
|
||||||
|
.then(() => super.initialize());
|
||||||
|
}
|
||||||
|
|
||||||
|
detectStorageImplementation() {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
logger.log("Detecting storage");
|
||||||
|
|
||||||
|
if (!window.indexedDB) {
|
||||||
|
logger.log("Indexed DB not supported");
|
||||||
|
this.app.storage = new StorageImplBrowser(this.app);
|
||||||
|
resolve();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try accessing the indexedb
|
||||||
|
let request;
|
||||||
|
try {
|
||||||
|
request = window.indexedDB.open("indexeddb_feature_detection", 1);
|
||||||
|
} catch (ex) {
|
||||||
|
logger.warn("Error while opening indexed db:", ex);
|
||||||
|
resolve();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
request.onerror = err => {
|
||||||
|
logger.log("Indexed DB can *not* be accessed: ", err);
|
||||||
|
logger.log("Using fallback to local storage");
|
||||||
|
this.app.storage = new StorageImplBrowser(this.app);
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
|
request.onsuccess = () => {
|
||||||
|
logger.log("Indexed DB *can* be accessed");
|
||||||
|
this.app.storage = new StorageImplBrowserIndexedDB(this.app);
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getHasUnlimitedSavegames() {
|
getHasUnlimitedSavegames() {
|
||||||
@ -83,71 +121,6 @@ export class PlatformWrapperImplBrowser extends PlatformWrapperInterface {
|
|||||||
return this.embedProvider.showDemoBadge;
|
return this.embedProvider.showDemoBadge;
|
||||||
}
|
}
|
||||||
|
|
||||||
onSentryLoaded() {
|
|
||||||
logger.log("Initializing sentry");
|
|
||||||
window.Sentry.init({
|
|
||||||
dsn: "TODO SENTRY DSN",
|
|
||||||
release: G_APP_ENVIRONMENT + "-" + G_BUILD_VERSION + "@" + G_BUILD_COMMIT_HASH,
|
|
||||||
// Will cause a deprecation warning, but the demise of `ignoreErrors` is still under discussion.
|
|
||||||
// See: https://github.com/getsentry/raven-js/issues/73
|
|
||||||
ignoreErrors: [
|
|
||||||
// Random plugins/extensions
|
|
||||||
"top.GLOBALS",
|
|
||||||
// See: http://blog.errorception.com/2012/03/tale-of-unfindable-js-error.html
|
|
||||||
"originalCreateNotification",
|
|
||||||
"canvas.contentDocument",
|
|
||||||
"MyApp_RemoveAllHighlights",
|
|
||||||
"http://tt.epicplay.com",
|
|
||||||
"Can't find variable: ZiteReader",
|
|
||||||
"jigsaw is not defined",
|
|
||||||
"ComboSearch is not defined",
|
|
||||||
"http://loading.retry.widdit.com/",
|
|
||||||
"atomicFindClose",
|
|
||||||
// Facebook borked
|
|
||||||
"fb_xd_fragment",
|
|
||||||
// ISP "optimizing" proxy - `Cache-Control: no-transform` seems to reduce this. (thanks @acdha)
|
|
||||||
// See http://stackoverflow.com/questions/4113268/how-to-stop-javascript-injection-from-vodafone-proxy
|
|
||||||
"bmi_SafeAddOnload",
|
|
||||||
"EBCallBackMessageReceived",
|
|
||||||
// See http://toolbar.conduit.com/Developer/HtmlAndGadget/Methods/JSInjection.aspx
|
|
||||||
"conduitPage",
|
|
||||||
// Generic error code from errors outside the security sandbox
|
|
||||||
// You can delete this if using raven.js > 1.0, which ignores these automatically.
|
|
||||||
"Script error.",
|
|
||||||
|
|
||||||
// Errors from ads
|
|
||||||
"Cannot read property 'postMessage' of null",
|
|
||||||
|
|
||||||
// Firefox only
|
|
||||||
"AbortError: The operation was aborted.",
|
|
||||||
|
|
||||||
"<unknown>",
|
|
||||||
],
|
|
||||||
ignoreUrls: [
|
|
||||||
// Facebook flakiness
|
|
||||||
/graph\.facebook\.com/i,
|
|
||||||
// Facebook blocked
|
|
||||||
/connect\.facebook\.net\/en_US\/all\.js/i,
|
|
||||||
// Woopra flakiness
|
|
||||||
/eatdifferent\.com\.woopra-ns\.com/i,
|
|
||||||
/static\.woopra\.com\/js\/woopra\.js/i,
|
|
||||||
// Chrome extensions
|
|
||||||
/extensions\//i,
|
|
||||||
/^chrome:\/\//i,
|
|
||||||
// Other plugins
|
|
||||||
/127\.0\.0\.1:4001\/isrunning/i, // Cacaoweb
|
|
||||||
/webappstoolbarba\.texthelp\.com\//i,
|
|
||||||
/metrics\.itunes\.apple\.com\.edgesuite\.net\//i,
|
|
||||||
],
|
|
||||||
beforeSend(event, hint) {
|
|
||||||
if (window.anyModLoaded) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return event;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
getId() {
|
getId() {
|
||||||
return "browser@" + this.embedProvider.id;
|
return "browser@" + this.embedProvider.id;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,17 @@
|
|||||||
import { PlatformWrapperImplBrowser } from "../browser/wrapper";
|
import { PlatformWrapperImplBrowser } from "../browser/wrapper";
|
||||||
import { getIPCRenderer } from "../../core/utils";
|
import { getIPCRenderer } from "../../core/utils";
|
||||||
import { createLogger } from "../../core/logging";
|
import { createLogger } from "../../core/logging";
|
||||||
|
import { StorageImplElectron } from "./storage";
|
||||||
|
import { PlatformWrapperInterface } from "../wrapper";
|
||||||
|
|
||||||
const logger = createLogger("electron-wrapper");
|
const logger = createLogger("electron-wrapper");
|
||||||
|
|
||||||
export class PlatformWrapperImplElectron extends PlatformWrapperImplBrowser {
|
export class PlatformWrapperImplElectron extends PlatformWrapperImplBrowser {
|
||||||
|
initialize() {
|
||||||
|
this.app.storage = new StorageImplElectron(this);
|
||||||
|
return PlatformWrapperInterface.prototype.initialize.call(this);
|
||||||
|
}
|
||||||
|
|
||||||
getId() {
|
getId() {
|
||||||
return "electron";
|
return "electron";
|
||||||
}
|
}
|
||||||
@ -22,6 +29,14 @@ export class PlatformWrapperImplElectron extends PlatformWrapperImplBrowser {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getHasUnlimitedSavegames() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
getShowDemoBadges() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
performRestart() {
|
performRestart() {
|
||||||
logger.log(this, "Performing restart");
|
logger.log(this, "Performing restart");
|
||||||
window.location.reload(true);
|
window.location.reload(true);
|
||||||
|
|||||||
@ -24,14 +24,11 @@ export class MainMenuState extends GameState {
|
|||||||
|
|
||||||
<p>${T.demoBanners.intro}</p>
|
<p>${T.demoBanners.intro}</p>
|
||||||
|
|
||||||
<ul>
|
|
||||||
${T.demoBanners.advantages.map(advantage => `<li>${advantage}</li>`).join("")}
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<a href="#" class="steamLink" target="_blank">Get the shapez.io standalone!</a>
|
<a href="#" class="steamLink" target="_blank">Get the shapez.io standalone!</a>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
return `
|
return (
|
||||||
|
`
|
||||||
|
|
||||||
<button class="settingsButton"></button>
|
<button class="settingsButton"></button>
|
||||||
|
|
||||||
@ -54,18 +51,29 @@ export class MainMenuState extends GameState {
|
|||||||
|
|
||||||
<div class="logo">
|
<div class="logo">
|
||||||
<img src="${cachebust("res/logo.png")}" alt="shapez.io Logo">
|
<img src="${cachebust("res/logo.png")}" alt="shapez.io Logo">
|
||||||
${
|
|
||||||
IS_DEMO && this.app.platformWrapper.getShowDemoBadges()
|
|
||||||
? `<div class="demoBadge"></div>`
|
|
||||||
: ""
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="mainWrapper ${IS_DEMO ? "demo" : "noDemo"}">
|
<div class="mainWrapper ${IS_DEMO ? "demo" : "noDemo"}">
|
||||||
|
|
||||||
${IS_DEMO ? `<div class="standaloneBanner">${bannerHtml}</div>` : ""}
|
|
||||||
|
|
||||||
|
<div class="sideContainer">
|
||||||
|
${IS_DEMO ? `<div class="standaloneBanner">${bannerHtml}</div>` : ""}
|
||||||
|
|
||||||
|
<div class="contest">
|
||||||
|
<h3>${T.mainMenu.contests.contest_01_03062020.title}</h3>
|
||||||
|
` +
|
||||||
|
/*<p>${T.mainMenu.contests.contest_01_03062020.desc}</p>
|
||||||
|
<button class="styledButton participateContest">${
|
||||||
|
T.mainMenu.contests.showInfo
|
||||||
|
}</button>*/
|
||||||
|
|
||||||
|
`
|
||||||
|
<p>${T.mainMenu.contests.contestOver}</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="mainContainer">
|
<div class="mainContainer">
|
||||||
${
|
${
|
||||||
isSupportedBrowser()
|
isSupportedBrowser()
|
||||||
@ -104,7 +112,8 @@ export class MainMenuState extends GameState {
|
|||||||
<div class="author">Made by <a class="producerLink" target="_blank">Tobias Springer</a></div>
|
<div class="author">Made by <a class="producerLink" target="_blank">Tobias Springer</a></div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
`;
|
`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
requestImportSavegame() {
|
requestImportSavegame() {
|
||||||
@ -199,7 +208,7 @@ export class MainMenuState extends GameState {
|
|||||||
|
|
||||||
if (G_IS_DEV && globalConfig.debug.fastGameEnter) {
|
if (G_IS_DEV && globalConfig.debug.fastGameEnter) {
|
||||||
const games = this.app.savegameMgr.getSavegamesMetaData();
|
const games = this.app.savegameMgr.getSavegamesMetaData();
|
||||||
if (games.length > 0) {
|
if (games.length > 0 && globalConfig.debug.resumeGameOnFastEnter) {
|
||||||
this.resumeGame(games[0]);
|
this.resumeGame(games[0]);
|
||||||
} else {
|
} else {
|
||||||
this.onPlayButtonClicked();
|
this.onPlayButtonClicked();
|
||||||
@ -220,6 +229,11 @@ export class MainMenuState extends GameState {
|
|||||||
this.trackClicks(qs(".settingsButton"), this.onSettingsButtonClicked);
|
this.trackClicks(qs(".settingsButton"), this.onSettingsButtonClicked);
|
||||||
this.trackClicks(qs(".changelog"), this.onChangelogClicked);
|
this.trackClicks(qs(".changelog"), this.onChangelogClicked);
|
||||||
|
|
||||||
|
const contestButton = qs(".participateContest");
|
||||||
|
if (contestButton) {
|
||||||
|
this.trackClicks(contestButton, this.onContestClicked);
|
||||||
|
}
|
||||||
|
|
||||||
if (G_IS_STANDALONE) {
|
if (G_IS_STANDALONE) {
|
||||||
this.trackClicks(qs(".exitAppButton"), this.onExitAppButtonClicked);
|
this.trackClicks(qs(".exitAppButton"), this.onExitAppButtonClicked);
|
||||||
}
|
}
|
||||||
@ -254,7 +268,7 @@ export class MainMenuState extends GameState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onSteamLinkClicked() {
|
onSteamLinkClicked() {
|
||||||
this.app.analytics.trackUiClick("main_menu_steam_link");
|
this.app.analytics.trackUiClick("main_menu_steam_link_2");
|
||||||
this.app.platformWrapper.openExternalLink(THIRDPARTY_URLS.standaloneStorePage);
|
this.app.platformWrapper.openExternalLink(THIRDPARTY_URLS.standaloneStorePage);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -267,6 +281,15 @@ export class MainMenuState extends GameState {
|
|||||||
this.moveToState("ChangelogState");
|
this.moveToState("ChangelogState");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onContestClicked() {
|
||||||
|
this.app.analytics.trackUiClick("contest_click");
|
||||||
|
|
||||||
|
this.dialogs.showInfo(
|
||||||
|
T.mainMenu.contests.contest_01_03062020.title,
|
||||||
|
T.mainMenu.contests.contest_01_03062020.longDesc
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
renderSavegames() {
|
renderSavegames() {
|
||||||
const oldContainer = this.htmlElement.querySelector(".mainContainer .savegames");
|
const oldContainer = this.htmlElement.querySelector(".mainContainer .savegames");
|
||||||
if (oldContainer) {
|
if (oldContainer) {
|
||||||
@ -375,19 +398,6 @@ export class MainMenuState extends GameState {
|
|||||||
this.moveToState("SettingsState");
|
this.moveToState("SettingsState");
|
||||||
}
|
}
|
||||||
|
|
||||||
doStartNewGame() {
|
|
||||||
this.app.analytics.trackUiClick("startgame");
|
|
||||||
|
|
||||||
this.app.adProvider.showVideoAd().then(() => {
|
|
||||||
const savegame = this.app.savegameMgr.createNewSavegame();
|
|
||||||
|
|
||||||
this.moveToState("InGameState", {
|
|
||||||
savegame,
|
|
||||||
});
|
|
||||||
this.app.analytics.trackUiClick("startgame_adcomplete");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onPlayButtonClicked() {
|
onPlayButtonClicked() {
|
||||||
if (
|
if (
|
||||||
IS_DEMO &&
|
IS_DEMO &&
|
||||||
@ -399,17 +409,15 @@ export class MainMenuState extends GameState {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IS_DEMO) {
|
this.app.analytics.trackUiClick("startgame");
|
||||||
this.app.analytics.trackUiClick("startgame_pre_show");
|
this.app.adProvider.showVideoAd().then(() => {
|
||||||
const { ok } = this.dialogs.showWarning(
|
const savegame = this.app.savegameMgr.createNewSavegame();
|
||||||
T.dialogs.demoExplanation.title,
|
|
||||||
T.dialogs.demoExplanation.desc
|
|
||||||
);
|
|
||||||
ok.add(() => this.doStartNewGame());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.doStartNewGame();
|
this.moveToState("InGameState", {
|
||||||
|
savegame,
|
||||||
|
});
|
||||||
|
this.app.analytics.trackUiClick("startgame_adcomplete");
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onLeave() {
|
onLeave() {
|
||||||
|
|||||||
@ -13,11 +13,11 @@ export class MobileWarningState extends GameState {
|
|||||||
<img class="logo" src="${cachebust("res/logo.png")}" alt="shapez.io Logo">
|
<img class="logo" src="${cachebust("res/logo.png")}" alt="shapez.io Logo">
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
I'm sorry, but shapez.io is not yet available on mobile devices!
|
I'm sorry, but shapez.io is not available on mobile devices yet!
|
||||||
(There is also no estimate when this will change, but feel to make a contribution! It's
|
There is also no estimate when this will change, but feel to make a contribution! It's
|
||||||
<a href="https://github.com/tobspr/shapez.io" target="_blank">open source</a>!)</p>
|
<a href="https://github.com/tobspr/shapez.io" target="_blank">open source</a>!</p>
|
||||||
|
|
||||||
<p>If you want to play on your computer, you can also get the standalone on itch.io:</p>
|
<p>If you want to play on your computer, you can also get the standalone on steam:</p>
|
||||||
|
|
||||||
|
|
||||||
<a href="${
|
<a href="${
|
||||||
|
|||||||
@ -82,18 +82,14 @@ export class PreloadState extends GameState {
|
|||||||
.then(res => res.json())
|
.then(res => res.json())
|
||||||
.then(({ latest }) => {
|
.then(({ latest }) => {
|
||||||
if (latest !== G_BUILD_VERSION) {
|
if (latest !== G_BUILD_VERSION) {
|
||||||
const { ok, viewUpdate } = this.dialogs.showInfo(
|
const { ok } = this.dialogs.showInfo(
|
||||||
T.dialogs.newUpdate.title,
|
T.dialogs.newUpdate.title,
|
||||||
T.dialogs.newUpdate.desc,
|
T.dialogs.newUpdate.desc,
|
||||||
["ok:good", "viewUpdate:good"]
|
["ok:good"]
|
||||||
);
|
);
|
||||||
|
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
ok.add(resolve);
|
ok.add(resolve);
|
||||||
viewUpdate.add(() => {
|
|
||||||
window.open("https://tobspr.itch.io/shapezio", "_blank");
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,81 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>
|
|
||||||
shapez.io shape generator
|
|
||||||
</title>
|
|
||||||
|
|
||||||
<script async src="index.js"></script>
|
|
||||||
<style>
|
|
||||||
html,
|
|
||||||
body {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
body {
|
|
||||||
font-family: "Source Sans Pro", "Roboto", sans-serif;
|
|
||||||
background: #fafafa;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
#resultWrapper {
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
margin-top: 10px;
|
|
||||||
background: #fff;
|
|
||||||
padding: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#resultWrapper #result {
|
|
||||||
}
|
|
||||||
|
|
||||||
#code {
|
|
||||||
width: 600px;
|
|
||||||
font-family: monospace;
|
|
||||||
padding: 30px;
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
background: #fff;
|
|
||||||
font-size: 17px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#code:focus {
|
|
||||||
outline: none;
|
|
||||||
border-color: #39f;
|
|
||||||
}
|
|
||||||
|
|
||||||
#error {
|
|
||||||
height: 40px;
|
|
||||||
color: #f77;
|
|
||||||
margin-top: 10px;
|
|
||||||
display: flex;
|
|
||||||
text-align: left;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
#error:not(.hasError) {
|
|
||||||
color: rgb(71, 179, 71);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h2>Shape generator</h2>
|
|
||||||
<input
|
|
||||||
value="CuCuCuCu"
|
|
||||||
id="code"
|
|
||||||
placeholder="shape code"
|
|
||||||
onkeypress="debounce(generate)"
|
|
||||||
onkeydown="debounce(generate)"
|
|
||||||
onkeyup="debounce(generate)"
|
|
||||||
onchange="debounce(generate)"
|
|
||||||
/>
|
|
||||||
<div id="error">Error</div>
|
|
||||||
<br />
|
|
||||||
|
|
||||||
<div id="resultWrapper">
|
|
||||||
<canvas id="result" width="256" height="256"></canvas>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,301 +0,0 @@
|
|||||||
/*
|
|
||||||
* Lots of code here is copied 1:1 from actual game files
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** @enum {string} */
|
|
||||||
const enumSubShape = {
|
|
||||||
rect: "rect",
|
|
||||||
circle: "circle",
|
|
||||||
star: "star",
|
|
||||||
windmill: "windmill",
|
|
||||||
};
|
|
||||||
|
|
||||||
/** @enum {string} */
|
|
||||||
const enumSubShapeToShortcode = {
|
|
||||||
[enumSubShape.rect]: "R",
|
|
||||||
[enumSubShape.circle]: "C",
|
|
||||||
[enumSubShape.star]: "S",
|
|
||||||
[enumSubShape.windmill]: "W",
|
|
||||||
};
|
|
||||||
|
|
||||||
/** @enum {enumSubShape} */
|
|
||||||
const enumShortcodeToSubShape = {};
|
|
||||||
for (const key in enumSubShapeToShortcode) {
|
|
||||||
enumShortcodeToSubShape[enumSubShapeToShortcode[key]] = key;
|
|
||||||
}
|
|
||||||
|
|
||||||
const arrayQuadrantIndexToOffset = [
|
|
||||||
{ x: 1, y: -1 }, // tr
|
|
||||||
{ x: 1, y: 1 }, // br
|
|
||||||
{ x: -1, y: 1 }, // bl
|
|
||||||
{ x: -1, y: -1 }, // tl
|
|
||||||
];
|
|
||||||
|
|
||||||
// From colors.js
|
|
||||||
/** @enum {string} */
|
|
||||||
const enumColors = {
|
|
||||||
red: "red",
|
|
||||||
green: "green",
|
|
||||||
blue: "blue",
|
|
||||||
|
|
||||||
yellow: "yellow",
|
|
||||||
purple: "purple",
|
|
||||||
cyan: "cyan",
|
|
||||||
|
|
||||||
white: "white",
|
|
||||||
uncolored: "uncolored",
|
|
||||||
};
|
|
||||||
|
|
||||||
/** @enum {string} */
|
|
||||||
const enumColorToShortcode = {
|
|
||||||
[enumColors.red]: "r",
|
|
||||||
[enumColors.green]: "g",
|
|
||||||
[enumColors.blue]: "b",
|
|
||||||
|
|
||||||
[enumColors.yellow]: "y",
|
|
||||||
[enumColors.purple]: "p",
|
|
||||||
[enumColors.cyan]: "c",
|
|
||||||
|
|
||||||
[enumColors.white]: "w",
|
|
||||||
[enumColors.uncolored]: "u",
|
|
||||||
};
|
|
||||||
|
|
||||||
/** @enum {string} */
|
|
||||||
const enumColorsToHexCode = {
|
|
||||||
[enumColors.red]: "#ff666a",
|
|
||||||
[enumColors.green]: "#78ff66",
|
|
||||||
[enumColors.blue]: "#66a7ff",
|
|
||||||
|
|
||||||
// red + green
|
|
||||||
[enumColors.yellow]: "#fcf52a",
|
|
||||||
|
|
||||||
// red + blue
|
|
||||||
[enumColors.purple]: "#dd66ff",
|
|
||||||
|
|
||||||
// blue + green
|
|
||||||
[enumColors.cyan]: "#87fff5",
|
|
||||||
|
|
||||||
// blue + green + red
|
|
||||||
[enumColors.white]: "#ffffff",
|
|
||||||
|
|
||||||
[enumColors.uncolored]: "#aaaaaa",
|
|
||||||
};
|
|
||||||
|
|
||||||
/** @enum {enumColors} */
|
|
||||||
const enumShortcodeToColor = {};
|
|
||||||
for (const key in enumColorToShortcode) {
|
|
||||||
enumShortcodeToColor[enumColorToShortcode[key]] = key;
|
|
||||||
}
|
|
||||||
|
|
||||||
CanvasRenderingContext2D.prototype.beginCircle = function (x, y, r) {
|
|
||||||
if (r < 0.05) {
|
|
||||||
this.beginPath();
|
|
||||||
this.rect(x, y, 1, 1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.beginPath();
|
|
||||||
this.arc(x, y, r, 0, 2.0 * Math.PI);
|
|
||||||
};
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
function radians(degrees) {
|
|
||||||
return (degrees * Math.PI) / 180.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates the definition from the given short key
|
|
||||||
*/
|
|
||||||
function fromShortKey(key) {
|
|
||||||
const sourceLayers = key.split(":");
|
|
||||||
let layers = [];
|
|
||||||
for (let i = 0; i < sourceLayers.length; ++i) {
|
|
||||||
const text = sourceLayers[i];
|
|
||||||
if (text.length !== 8) {
|
|
||||||
throw new Error("Invalid layer: '" + text + "' -> must be 8 characters");
|
|
||||||
}
|
|
||||||
|
|
||||||
const quads = [null, null, null, null];
|
|
||||||
for (let quad = 0; quad < 4; ++quad) {
|
|
||||||
const shapeText = text[quad * 2 + 0];
|
|
||||||
const subShape = enumShortcodeToSubShape[shapeText];
|
|
||||||
const color = enumShortcodeToColor[text[quad * 2 + 1]];
|
|
||||||
if (subShape) {
|
|
||||||
if (!color) {
|
|
||||||
throw new Error("Invalid shape color key: " + key);
|
|
||||||
}
|
|
||||||
quads[quad] = {
|
|
||||||
subShape,
|
|
||||||
color,
|
|
||||||
};
|
|
||||||
} else if (shapeText !== "-") {
|
|
||||||
throw new Error("Invalid shape key: " + shapeText);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
layers.push(quads);
|
|
||||||
}
|
|
||||||
|
|
||||||
return layers;
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderShape(layers) {
|
|
||||||
const canvas = /** @type {HTMLCanvasElement} */ (document.getElementById("result"));
|
|
||||||
const context = canvas.getContext("2d");
|
|
||||||
|
|
||||||
context.save();
|
|
||||||
context.fillStyle = "#fff";
|
|
||||||
context.fillRect(0, 0, 1000, 1000);
|
|
||||||
|
|
||||||
const w = 256;
|
|
||||||
const h = 256;
|
|
||||||
const dpi = 1;
|
|
||||||
|
|
||||||
context.translate((w * dpi) / 2, (h * dpi) / 2);
|
|
||||||
context.scale((dpi * w) / 23, (dpi * h) / 23);
|
|
||||||
|
|
||||||
context.fillStyle = "#e9ecf7";
|
|
||||||
|
|
||||||
const quadrantSize = 10;
|
|
||||||
const quadrantHalfSize = quadrantSize / 2;
|
|
||||||
|
|
||||||
context.fillStyle = "rgba(40, 50, 65, 0.1)";
|
|
||||||
context.beginCircle(0, 0, quadrantSize * 1.15);
|
|
||||||
context.fill();
|
|
||||||
|
|
||||||
for (let layerIndex = 0; layerIndex < layers.length; ++layerIndex) {
|
|
||||||
const quadrants = layers[layerIndex];
|
|
||||||
|
|
||||||
const layerScale = Math.max(0.1, 0.9 - layerIndex * 0.22);
|
|
||||||
|
|
||||||
for (let quadrantIndex = 0; quadrantIndex < 4; ++quadrantIndex) {
|
|
||||||
if (!quadrants[quadrantIndex]) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const { subShape, color } = quadrants[quadrantIndex];
|
|
||||||
|
|
||||||
const quadrantPos = arrayQuadrantIndexToOffset[quadrantIndex];
|
|
||||||
const centerQuadrantX = quadrantPos.x * quadrantHalfSize;
|
|
||||||
const centerQuadrantY = quadrantPos.y * quadrantHalfSize;
|
|
||||||
|
|
||||||
const rotation = radians(quadrantIndex * 90);
|
|
||||||
|
|
||||||
context.translate(centerQuadrantX, centerQuadrantY);
|
|
||||||
context.rotate(rotation);
|
|
||||||
|
|
||||||
context.fillStyle = enumColorsToHexCode[color];
|
|
||||||
context.strokeStyle = "#555";
|
|
||||||
context.lineWidth = 1;
|
|
||||||
|
|
||||||
const insetPadding = 0.0;
|
|
||||||
|
|
||||||
switch (subShape) {
|
|
||||||
case enumSubShape.rect: {
|
|
||||||
context.beginPath();
|
|
||||||
const dims = quadrantSize * layerScale;
|
|
||||||
context.rect(
|
|
||||||
insetPadding + -quadrantHalfSize,
|
|
||||||
-insetPadding + quadrantHalfSize - dims,
|
|
||||||
dims,
|
|
||||||
dims
|
|
||||||
);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case enumSubShape.star: {
|
|
||||||
context.beginPath();
|
|
||||||
const dims = quadrantSize * layerScale;
|
|
||||||
|
|
||||||
let originX = insetPadding - quadrantHalfSize;
|
|
||||||
let originY = -insetPadding + quadrantHalfSize - dims;
|
|
||||||
|
|
||||||
const moveInwards = dims * 0.4;
|
|
||||||
context.moveTo(originX, originY + moveInwards);
|
|
||||||
context.lineTo(originX + dims, originY);
|
|
||||||
context.lineTo(originX + dims - moveInwards, originY + dims);
|
|
||||||
context.lineTo(originX, originY + dims);
|
|
||||||
context.closePath();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case enumSubShape.windmill: {
|
|
||||||
context.beginPath();
|
|
||||||
const dims = quadrantSize * layerScale;
|
|
||||||
|
|
||||||
let originX = insetPadding - quadrantHalfSize;
|
|
||||||
let originY = -insetPadding + quadrantHalfSize - dims;
|
|
||||||
const moveInwards = dims * 0.4;
|
|
||||||
context.moveTo(originX, originY + moveInwards);
|
|
||||||
context.lineTo(originX + dims, originY);
|
|
||||||
context.lineTo(originX + dims, originY + dims);
|
|
||||||
context.lineTo(originX, originY + dims);
|
|
||||||
context.closePath();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case enumSubShape.circle: {
|
|
||||||
context.beginPath();
|
|
||||||
context.moveTo(insetPadding + -quadrantHalfSize, -insetPadding + quadrantHalfSize);
|
|
||||||
context.arc(
|
|
||||||
insetPadding + -quadrantHalfSize,
|
|
||||||
-insetPadding + quadrantHalfSize,
|
|
||||||
quadrantSize * layerScale,
|
|
||||||
-Math.PI * 0.5,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
context.closePath();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default: {
|
|
||||||
assertAlways(false, "Unkown sub shape: " + subShape);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
context.fill();
|
|
||||||
context.stroke();
|
|
||||||
|
|
||||||
context.rotate(-rotation);
|
|
||||||
context.translate(-centerQuadrantX, -centerQuadrantY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
context.restore();
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
function showError(msg) {
|
|
||||||
const errorDiv = document.getElementById("error");
|
|
||||||
errorDiv.classList.toggle("hasError", !!msg);
|
|
||||||
if (msg) {
|
|
||||||
errorDiv.innerText = msg;
|
|
||||||
} else {
|
|
||||||
errorDiv.innerText = "Shape generated";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
window.generate = () => {
|
|
||||||
showError(null);
|
|
||||||
// @ts-ignore
|
|
||||||
const code = document.getElementById("code").value.trim();
|
|
||||||
|
|
||||||
let parsed = null;
|
|
||||||
try {
|
|
||||||
parsed = fromShortKey(code);
|
|
||||||
} catch (ex) {
|
|
||||||
showError(ex);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
renderShape(parsed);
|
|
||||||
};
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
window.debounce = fn => {
|
|
||||||
setTimeout(fn, 0);
|
|
||||||
};
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
window.addEventListener("load", window.generate);
|
|
||||||
@ -1,13 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "shape_generator",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"main": "index.js",
|
|
||||||
"license": "MIT",
|
|
||||||
"private": true,
|
|
||||||
"devDependencies": {
|
|
||||||
"http-server": "^0.12.3"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"serve": "http-server . -p 9000 -g --cors -o -c-1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,152 +0,0 @@
|
|||||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
|
||||||
# yarn lockfile v1
|
|
||||||
|
|
||||||
|
|
||||||
async@^2.6.2:
|
|
||||||
version "2.6.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff"
|
|
||||||
integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==
|
|
||||||
dependencies:
|
|
||||||
lodash "^4.17.14"
|
|
||||||
|
|
||||||
basic-auth@^1.0.3:
|
|
||||||
version "1.1.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-1.1.0.tgz#45221ee429f7ee1e5035be3f51533f1cdfd29884"
|
|
||||||
integrity sha1-RSIe5Cn37h5QNb4/UVM/HN/SmIQ=
|
|
||||||
|
|
||||||
colors@^1.4.0:
|
|
||||||
version "1.4.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78"
|
|
||||||
integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==
|
|
||||||
|
|
||||||
corser@^2.0.1:
|
|
||||||
version "2.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/corser/-/corser-2.0.1.tgz#8eda252ecaab5840dcd975ceb90d9370c819ff87"
|
|
||||||
integrity sha1-jtolLsqrWEDc2XXOuQ2TcMgZ/4c=
|
|
||||||
|
|
||||||
debug@^3.0.0, debug@^3.1.1:
|
|
||||||
version "3.2.6"
|
|
||||||
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
|
|
||||||
integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==
|
|
||||||
dependencies:
|
|
||||||
ms "^2.1.1"
|
|
||||||
|
|
||||||
ecstatic@^3.3.2:
|
|
||||||
version "3.3.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/ecstatic/-/ecstatic-3.3.2.tgz#6d1dd49814d00594682c652adb66076a69d46c48"
|
|
||||||
integrity sha512-fLf9l1hnwrHI2xn9mEDT7KIi22UDqA2jaCwyCbSUJh9a1V+LEUSL/JO/6TIz/QyuBURWUHrFL5Kg2TtO1bkkog==
|
|
||||||
dependencies:
|
|
||||||
he "^1.1.1"
|
|
||||||
mime "^1.6.0"
|
|
||||||
minimist "^1.1.0"
|
|
||||||
url-join "^2.0.5"
|
|
||||||
|
|
||||||
eventemitter3@^4.0.0:
|
|
||||||
version "4.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.0.tgz#d65176163887ee59f386d64c82610b696a4a74eb"
|
|
||||||
integrity sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg==
|
|
||||||
|
|
||||||
follow-redirects@^1.0.0:
|
|
||||||
version "1.11.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.11.0.tgz#afa14f08ba12a52963140fe43212658897bc0ecb"
|
|
||||||
integrity sha512-KZm0V+ll8PfBrKwMzdo5D13b1bur9Iq9Zd/RMmAoQQcl2PxxFml8cxXPaaPYVbV0RjNjq1CU7zIzAOqtUPudmA==
|
|
||||||
dependencies:
|
|
||||||
debug "^3.0.0"
|
|
||||||
|
|
||||||
he@^1.1.1:
|
|
||||||
version "1.2.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
|
|
||||||
integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
|
|
||||||
|
|
||||||
http-proxy@^1.18.0:
|
|
||||||
version "1.18.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.0.tgz#dbe55f63e75a347db7f3d99974f2692a314a6a3a"
|
|
||||||
integrity sha512-84I2iJM/n1d4Hdgc6y2+qY5mDaz2PUVjlg9znE9byl+q0uC3DeByqBGReQu5tpLK0TAqTIXScRUV+dg7+bUPpQ==
|
|
||||||
dependencies:
|
|
||||||
eventemitter3 "^4.0.0"
|
|
||||||
follow-redirects "^1.0.0"
|
|
||||||
requires-port "^1.0.0"
|
|
||||||
|
|
||||||
http-server@^0.12.3:
|
|
||||||
version "0.12.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/http-server/-/http-server-0.12.3.tgz#ba0471d0ecc425886616cb35c4faf279140a0d37"
|
|
||||||
integrity sha512-be0dKG6pni92bRjq0kvExtj/NrrAd28/8fCXkaI/4piTwQMSDSLMhWyW0NI1V+DBI3aa1HMlQu46/HjVLfmugA==
|
|
||||||
dependencies:
|
|
||||||
basic-auth "^1.0.3"
|
|
||||||
colors "^1.4.0"
|
|
||||||
corser "^2.0.1"
|
|
||||||
ecstatic "^3.3.2"
|
|
||||||
http-proxy "^1.18.0"
|
|
||||||
minimist "^1.2.5"
|
|
||||||
opener "^1.5.1"
|
|
||||||
portfinder "^1.0.25"
|
|
||||||
secure-compare "3.0.1"
|
|
||||||
union "~0.5.0"
|
|
||||||
|
|
||||||
lodash@^4.17.14:
|
|
||||||
version "4.17.15"
|
|
||||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
|
|
||||||
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
|
|
||||||
|
|
||||||
mime@^1.6.0:
|
|
||||||
version "1.6.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
|
|
||||||
integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
|
|
||||||
|
|
||||||
minimist@^1.1.0, minimist@^1.2.5:
|
|
||||||
version "1.2.5"
|
|
||||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
|
|
||||||
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
|
|
||||||
|
|
||||||
mkdirp@^0.5.1:
|
|
||||||
version "0.5.5"
|
|
||||||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
|
|
||||||
integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==
|
|
||||||
dependencies:
|
|
||||||
minimist "^1.2.5"
|
|
||||||
|
|
||||||
ms@^2.1.1:
|
|
||||||
version "2.1.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
|
||||||
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
|
||||||
|
|
||||||
opener@^1.5.1:
|
|
||||||
version "1.5.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.1.tgz#6d2f0e77f1a0af0032aca716c2c1fbb8e7e8abed"
|
|
||||||
integrity sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA==
|
|
||||||
|
|
||||||
portfinder@^1.0.25:
|
|
||||||
version "1.0.26"
|
|
||||||
resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.26.tgz#475658d56ca30bed72ac7f1378ed350bd1b64e70"
|
|
||||||
integrity sha512-Xi7mKxJHHMI3rIUrnm/jjUgwhbYMkp/XKEcZX3aG4BrumLpq3nmoQMX+ClYnDZnZ/New7IatC1no5RX0zo1vXQ==
|
|
||||||
dependencies:
|
|
||||||
async "^2.6.2"
|
|
||||||
debug "^3.1.1"
|
|
||||||
mkdirp "^0.5.1"
|
|
||||||
|
|
||||||
qs@^6.4.0:
|
|
||||||
version "6.9.4"
|
|
||||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.4.tgz#9090b290d1f91728d3c22e54843ca44aea5ab687"
|
|
||||||
integrity sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ==
|
|
||||||
|
|
||||||
requires-port@^1.0.0:
|
|
||||||
version "1.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
|
|
||||||
integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=
|
|
||||||
|
|
||||||
secure-compare@3.0.1:
|
|
||||||
version "3.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/secure-compare/-/secure-compare-3.0.1.tgz#f1a0329b308b221fae37b9974f3d578d0ca999e3"
|
|
||||||
integrity sha1-8aAymzCLIh+uN7mXTz1XjQypmeM=
|
|
||||||
|
|
||||||
union@~0.5.0:
|
|
||||||
version "0.5.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/union/-/union-0.5.0.tgz#b2c11be84f60538537b846edb9ba266ba0090075"
|
|
||||||
integrity sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==
|
|
||||||
dependencies:
|
|
||||||
qs "^6.4.0"
|
|
||||||
|
|
||||||
url-join@^2.0.5:
|
|
||||||
version "2.0.5"
|
|
||||||
resolved "https://registry.yarnpkg.com/url-join/-/url-join-2.0.5.tgz#5af22f18c052a000a48d7b82c5e9c2e2feeda728"
|
|
||||||
integrity sha1-WvIvGMBSoACkjXuCxenC4v7tpyg=
|
|
||||||
@ -64,15 +64,9 @@ global:
|
|||||||
|
|
||||||
demoBanners:
|
demoBanners:
|
||||||
# This is the "advertisement" shown in the main menu and other various places
|
# This is the "advertisement" shown in the main menu and other various places
|
||||||
title: Hey!
|
title: Demo Version
|
||||||
intro: >-
|
intro: >-
|
||||||
If you enjoy this game, please consider buying the full version!
|
Get the standalone to unlock all features!
|
||||||
advantages:
|
|
||||||
- Unlimited savegames
|
|
||||||
- Waypoints
|
|
||||||
- Dark mode & more
|
|
||||||
- >-
|
|
||||||
Allow me to further develop shapez.io ❤️
|
|
||||||
|
|
||||||
mainMenu:
|
mainMenu:
|
||||||
play: Play
|
play: Play
|
||||||
@ -88,6 +82,29 @@ mainMenu:
|
|||||||
savegameLevel: Level <x>
|
savegameLevel: Level <x>
|
||||||
savegameLevelUnknown: Unknown Level
|
savegameLevelUnknown: Unknown Level
|
||||||
|
|
||||||
|
contests:
|
||||||
|
contest_01_03062020:
|
||||||
|
title: "Contest #01"
|
||||||
|
desc: Win <strong>$25</strong> for the coolest base!
|
||||||
|
longDesc: >-
|
||||||
|
To give something back to you, I thought it would be cool to make weekly contests!
|
||||||
|
<br><br>
|
||||||
|
<strong>This weeks topic:</strong> Build the coolest base!
|
||||||
|
<br><br>
|
||||||
|
Here's the deal:<br>
|
||||||
|
<ul class="bucketList">
|
||||||
|
<li>Submit a screenshot of your base to <strong>contest@shapez.io</strong></li>
|
||||||
|
<li>Bonus points if you share it on social media!</li>
|
||||||
|
<li>I will choose 5 screenshots and propose it to the <strong>discord</strong> community to vote.</li>
|
||||||
|
<li>The winner gets <strong>$25</strong> (Paypal, Amazon Gift Card, whatever you prefer)</li>
|
||||||
|
<li>Deadline: 07.06.2020 12:00 AM CEST</li>
|
||||||
|
</ul>
|
||||||
|
<br>
|
||||||
|
I'm looking forward to seeing your awesome creations!
|
||||||
|
|
||||||
|
showInfo: View
|
||||||
|
contestOver: This contest has ended - Join the discord to get noticed about new contests!
|
||||||
|
|
||||||
dialogs:
|
dialogs:
|
||||||
buttons:
|
buttons:
|
||||||
ok: OK
|
ok: OK
|
||||||
@ -153,15 +170,11 @@ dialogs:
|
|||||||
|
|
||||||
leaveNotPossibleInDemo:
|
leaveNotPossibleInDemo:
|
||||||
title: Demo version
|
title: Demo version
|
||||||
desc: Your game was saved but you will not be able to restore it in the demo. Restoring your savegames is only possible in the full version. Are you sure?
|
desc: Your game has been saved, but you will not be able to restore it in the demo. Restoring your savegames is only possible in the full version. Are you sure?
|
||||||
|
|
||||||
newUpdate:
|
newUpdate:
|
||||||
title: Update available
|
title: Update available
|
||||||
desc: There is an update for this game available!
|
desc: There is an update for this game available, be sure to download it!
|
||||||
|
|
||||||
demoExplanation:
|
|
||||||
title: Notice from the Developer
|
|
||||||
desc: I am developing this game in my free time, and I hope you enjoy it! If you do, please consider to buy the standalone version!
|
|
||||||
|
|
||||||
oneSavegameLimit:
|
oneSavegameLimit:
|
||||||
title: Limited savegames
|
title: Limited savegames
|
||||||
@ -206,6 +219,9 @@ dialogs:
|
|||||||
title: New Marker
|
title: New Marker
|
||||||
desc: Give it a meaningful name
|
desc: Give it a meaningful name
|
||||||
|
|
||||||
|
markerDemoLimit:
|
||||||
|
desc: You can only create two custom markers in the demo. Get the standalone for unlimited markers!
|
||||||
|
|
||||||
ingame:
|
ingame:
|
||||||
# This is shown in the top left corner and displays useful keybindings in
|
# This is shown in the top left corner and displays useful keybindings in
|
||||||
# every situation
|
# every situation
|
||||||
@ -220,6 +236,7 @@ ingame:
|
|||||||
toggleHud: Toggle HUD
|
toggleHud: Toggle HUD
|
||||||
placeBuilding: Place building
|
placeBuilding: Place building
|
||||||
createMarker: Create Marker
|
createMarker: Create Marker
|
||||||
|
delete: Destroy
|
||||||
|
|
||||||
# Everything related to placing buildings (I.e. as soon as you selected a building
|
# Everything related to placing buildings (I.e. as soon as you selected a building
|
||||||
# from the toolbar)
|
# from the toolbar)
|
||||||
@ -313,12 +330,24 @@ ingame:
|
|||||||
blueprintPlacer:
|
blueprintPlacer:
|
||||||
cost: Cost
|
cost: Cost
|
||||||
|
|
||||||
|
# Map markers
|
||||||
waypoints:
|
waypoints:
|
||||||
waypoints: Markers
|
waypoints: Markers
|
||||||
hub: HUB
|
hub: HUB
|
||||||
description: Left-click a marker to jump to it, right-click to delete it.<br><br>Press <keybinding> to create a marker from the current view, or <strong>right-click</strong> to create a marker at the selected location.
|
description: Left-click a marker to jump to it, right-click to delete it.<br><br>Press <keybinding> to create a marker from the current view, or <strong>right-click</strong> to create a marker at the selected location.
|
||||||
creationSuccessNotification: Marker has been created.
|
creationSuccessNotification: Marker has been created.
|
||||||
|
|
||||||
|
# Interactive tutorial
|
||||||
|
interactiveTutorial:
|
||||||
|
title: Tutorial
|
||||||
|
hints:
|
||||||
|
1_1_extractor: Place an <strong>extractor</strong> on top of a <strong>circle shape</strong> to extract it!
|
||||||
|
1_2_conveyor: >-
|
||||||
|
Connect the extractor with a <strong>conveyor belt</strong> to your hub!<br><br>Tip: <strong>Click and drag</strong> the belt with your mouse!
|
||||||
|
|
||||||
|
1_3_expand: >-
|
||||||
|
This is <strong>NOT</strong> an idle game! Build more extractors and belts to finish the goal quicker.<br><br>Tip: Hold <strong>SHIFT</strong> to place multiple extractors, and use <strong>R</strong> to rotate them.
|
||||||
|
|
||||||
# All shop upgrades
|
# All shop upgrades
|
||||||
shopUpgrades:
|
shopUpgrades:
|
||||||
belt:
|
belt:
|
||||||
@ -574,7 +603,7 @@ settings:
|
|||||||
offerHints:
|
offerHints:
|
||||||
title: Hints & Tutorials
|
title: Hints & Tutorials
|
||||||
description: >-
|
description: >-
|
||||||
Whether to offer hints and tutorials while playing.
|
Whether to offer hints and tutorials while playing. Also hides certain UI elements onto a given level to make it easier to get into the game.
|
||||||
|
|
||||||
keybindings:
|
keybindings:
|
||||||
title: Keybindings
|
title: Keybindings
|
||||||
@ -649,6 +678,5 @@ demo:
|
|||||||
importingGames: Importing savegames
|
importingGames: Importing savegames
|
||||||
oneGameLimit: Limited to one savegame
|
oneGameLimit: Limited to one savegame
|
||||||
customizeKeybindings: Customizing Keybindings
|
customizeKeybindings: Customizing Keybindings
|
||||||
creatingMarkers: Create custom markers
|
|
||||||
|
|
||||||
settingNotAvailable: Not available in the demo.
|
settingNotAvailable: Not available in the demo.
|
||||||
|
|||||||
@ -26,6 +26,13 @@ global:
|
|||||||
# How big numbers are rendered, e.g. "10,000"
|
# How big numbers are rendered, e.g. "10,000"
|
||||||
thousandsDivider: "."
|
thousandsDivider: "."
|
||||||
|
|
||||||
|
# The suffix for large numbers, e.g. 1.3k, 400.2M, etc. cf wikipedia système international d'unité
|
||||||
|
suffix:
|
||||||
|
thousands: k
|
||||||
|
millions: M
|
||||||
|
billions: T
|
||||||
|
trillions: E
|
||||||
|
|
||||||
# Shown for infinitely big numbers
|
# Shown for infinitely big numbers
|
||||||
infinite: inf
|
infinite: inf
|
||||||
|
|
||||||
@ -152,10 +159,6 @@ dialogs:
|
|||||||
title: Mise-à-jour disponible
|
title: Mise-à-jour disponible
|
||||||
desc: Une mise-à-jour est disponible pour ce jeu!
|
desc: Une mise-à-jour est disponible pour ce jeu!
|
||||||
|
|
||||||
demoExplanation:
|
|
||||||
title: Note du développeur
|
|
||||||
desc: Je développe ce jeu pendant mon temps libre, et j'espère que vous l'appréciez! Si c'est le cas, merci de considérez l'achat de la version complète!
|
|
||||||
|
|
||||||
oneSavegameLimit:
|
oneSavegameLimit:
|
||||||
title: Sauvegardes limitées
|
title: Sauvegardes limitées
|
||||||
desc: Vous ne pouvez avoir qu'une seule sauvegarde en même temps dans la version démo. Merci de soit effacer l'actuelle ou de vous procurer la version complète!
|
desc: Vous ne pouvez avoir qu'une seule sauvegarde en même temps dans la version démo. Merci de soit effacer l'actuelle ou de vous procurer la version complète!
|
||||||
@ -213,6 +216,7 @@ ingame:
|
|||||||
toggleHud: Basculet l'ATH
|
toggleHud: Basculet l'ATH
|
||||||
placeBuilding: Placer un bâtiment
|
placeBuilding: Placer un bâtiment
|
||||||
createMarker: Créer une balise
|
createMarker: Créer une balise
|
||||||
|
delete: Supprimer
|
||||||
|
|
||||||
# Everything related to placing buildings (I.e. as soon as you selected a building
|
# Everything related to placing buildings (I.e. as soon as you selected a building
|
||||||
# from the toolbar)
|
# from the toolbar)
|
||||||
@ -278,7 +282,7 @@ ingame:
|
|||||||
description: Affiche tous les formes que votre usine entière produit, en incluant les formes intermédiaires.
|
description: Affiche tous les formes que votre usine entière produit, en incluant les formes intermédiaires.
|
||||||
delivered:
|
delivered:
|
||||||
title: Délivré
|
title: Délivré
|
||||||
description: Affiche les formes qui ont étés délivrées dans votres bâtiment central.
|
description: Affiche les formes qui ont été livrées dans votre noyau.
|
||||||
noShapesProduced: Aucune forme n'a été produite jusqu'à présent.
|
noShapesProduced: Aucune forme n'a été produite jusqu'à présent.
|
||||||
|
|
||||||
# Displays the shapes per minute, e.g. '523 / m'
|
# Displays the shapes per minute, e.g. '523 / m'
|
||||||
@ -306,12 +310,21 @@ ingame:
|
|||||||
blueprintPlacer:
|
blueprintPlacer:
|
||||||
cost: Coût
|
cost: Coût
|
||||||
|
|
||||||
|
# Map markers
|
||||||
waypoints:
|
waypoints:
|
||||||
waypoints: Balise
|
waypoints: Balise
|
||||||
hub: Noyau
|
hub: Noyau
|
||||||
description: Cliquez une balise pour vous y rendre, clic-droit pour l'effacer.<br><br>Appuyez sur <keybinding> pour créer une balise sur la vue actuelle, ou <strong>clic-droit</strong> pour en créer une sur l'endroit pointé.
|
description: Cliquez une balise pour vous y rendre, clic-droit pour l'effacer.<br><br>Appuyez sur <keybinding> pour créer une balise sur la vue actuelle, ou <strong>clic-droit</strong> pour en créer une sur l'endroit pointé.
|
||||||
creationSuccessNotification: La bailse a été créée.
|
creationSuccessNotification: La bailse a été créée.
|
||||||
|
|
||||||
|
# Interactive tutorial
|
||||||
|
interactiveTutorial:
|
||||||
|
title: Tutoriel
|
||||||
|
hints:
|
||||||
|
1_1_extractor: Placez un <strong>extracteur</strong> sur une <strong>forme en cercle</strong> pour l'extraire!
|
||||||
|
1_2_conveyor: Connectez l'extracteur avec un <strong>convoyeur</strong> vers votre noyau!
|
||||||
|
1_3_expand: Ceci n'est <strong>PAS</strong> un jeu incrémental et inactif! Construisez plus d'extracteurs et de convoyeurs pour atteindre plus votre votre but.
|
||||||
|
|
||||||
# All shop upgrades
|
# All shop upgrades
|
||||||
shopUpgrades:
|
shopUpgrades:
|
||||||
belt:
|
belt:
|
||||||
@ -440,7 +453,7 @@ storyRewards:
|
|||||||
|
|
||||||
reward_tunnel:
|
reward_tunnel:
|
||||||
title: Tunnel
|
title: Tunnel
|
||||||
desc: Le <strong>tunnel</strong> a été débloqué - Vous pouvez maintenant faire passer des formes vous les convoyeurs et les bâtimentts avec ça!
|
desc: Le <strong>tunnel</strong> a été débloqué - Vous pouvez maintenant faire passer des formes sous les convoyeurs et les bâtiments avec ça!
|
||||||
|
|
||||||
reward_rotater_ccw:
|
reward_rotater_ccw:
|
||||||
title: Pivoteur inversé
|
title: Pivoteur inversé
|
||||||
@ -448,7 +461,7 @@ storyRewards:
|
|||||||
|
|
||||||
reward_miner_chainable:
|
reward_miner_chainable:
|
||||||
title: Extracteur en série
|
title: Extracteur en série
|
||||||
desc: Vous avez débloqué <strong>l'extracteur en série</strong>! Il permet <strong>de transférer ses resources</strong> à d'autres extracteurs pour extraire les ressources plus efficacement!
|
desc: Vous avez débloqué <strong>l'extracteur en série</strong>! Il permet <strong>de transférer ses resources</strong> à d'autres extracteurs pour les extraire plus efficacement!
|
||||||
|
|
||||||
reward_underground_belt_tier_2:
|
reward_underground_belt_tier_2:
|
||||||
title: Tunnel échelon II
|
title: Tunnel échelon II
|
||||||
@ -481,7 +494,7 @@ storyRewards:
|
|||||||
|
|
||||||
reward_blueprints:
|
reward_blueprints:
|
||||||
title: Patrons
|
title: Patrons
|
||||||
desc: Vous pouvez maintenant <strong>copier et coller</strong> des perties de votre usines! Sélectionnez une zone (Appuyez sur CTRL, et sélectionnez avec votre souris), et appuyez sur 'C' pour la copier.<br><br>Coller n'est <strong>pas gratuit</strong>, vous devez produire <strong>des formes de patrons</strong> pour vous le payer! (Ceux qu'ont vient de vous donner).
|
desc: Vous pouvez maintenant <strong>copier et coller</strong> des parties de votre usines! Sélectionnez une zone (Appuyez sur CTRL, et sélectionnez avec votre souris), et appuyez sur 'C' pour la copier.<br><br>Coller n'est <strong>pas gratuit</strong>, vous devez produire <strong>des formes de patrons</strong> pour vous le payer! (Ceux que vous venez de livrer).
|
||||||
|
|
||||||
# Special reward, which is shown when there is no reward actually
|
# Special reward, which is shown when there is no reward actually
|
||||||
no_reward:
|
no_reward:
|
||||||
@ -511,6 +524,23 @@ settings:
|
|||||||
title: Taille de l'interface
|
title: Taille de l'interface
|
||||||
description: >-
|
description: >-
|
||||||
Change la taille de l'interface utilisateur. Cette interface se redimensionnera suivant la résolution de votre appareil, mais cette option contrôle le facteur de résolution.
|
Change la taille de l'interface utilisateur. Cette interface se redimensionnera suivant la résolution de votre appareil, mais cette option contrôle le facteur de résolution.
|
||||||
|
scales:
|
||||||
|
super_small: Très petite
|
||||||
|
small: Petite
|
||||||
|
regular: Normale
|
||||||
|
large: Largr
|
||||||
|
huge: Très large
|
||||||
|
|
||||||
|
scrollWheelSensitivity:
|
||||||
|
title: Sensibilité du zoom
|
||||||
|
description: >-
|
||||||
|
Change la sensibilité du zoom (AUssi bien de la roulette de la souris que du trackpad).
|
||||||
|
sensitivity:
|
||||||
|
super_slow: Super lent
|
||||||
|
slow: Lent
|
||||||
|
regular: Normal
|
||||||
|
fast: Rapide
|
||||||
|
super_fast: Super rapide
|
||||||
|
|
||||||
fullscreen:
|
fullscreen:
|
||||||
title: Plein écran
|
title: Plein écran
|
||||||
@ -557,6 +587,7 @@ keybindings:
|
|||||||
categoryLabels:
|
categoryLabels:
|
||||||
general: Application
|
general: Application
|
||||||
ingame: Jeu
|
ingame: Jeu
|
||||||
|
navigation: Navigation
|
||||||
placement: Placement
|
placement: Placement
|
||||||
massSelect: Suppression de masse
|
massSelect: Suppression de masse
|
||||||
buildings: Raccourcis bâtiment
|
buildings: Raccourcis bâtiment
|
||||||
@ -569,9 +600,11 @@ keybindings:
|
|||||||
mapMoveRight: Aller à droite
|
mapMoveRight: Aller à droite
|
||||||
mapMoveDown: Aller en bas
|
mapMoveDown: Aller en bas
|
||||||
mapMoveLeft: Aller à gauche
|
mapMoveLeft: Aller à gauche
|
||||||
|
centerMap: Centrer la carte
|
||||||
|
|
||||||
mapZoomIn: Zoom avant
|
mapZoomIn: Zoom avant
|
||||||
mapZoomOut: Zoom arrière
|
mapZoomOut: Zoom arrière
|
||||||
|
createMarker: Créer une balise
|
||||||
|
|
||||||
menuOpenShop: Améliorations
|
menuOpenShop: Améliorations
|
||||||
menuOpenStats: Statistiques
|
menuOpenStats: Statistiques
|
||||||
@ -621,5 +654,5 @@ demo:
|
|||||||
|
|
||||||
settingNotAvailable: Indisponible dans la démo.
|
settingNotAvailable: Indisponible dans la démo.
|
||||||
#
|
#
|
||||||
# French translation version v0.2 based on english v1.1.1 by Didier WEERTS 'The Corsaire'
|
# French translation version v0.3 based on english v1.1.4 by Didier WEERTS 'The Corsaire'
|
||||||
#
|
#
|
||||||
673
translations/base-pt-BR.yaml
Normal file
@ -0,0 +1,673 @@
|
|||||||
|
#
|
||||||
|
# GAME TRANSLATIONS
|
||||||
|
#
|
||||||
|
# Contributing:
|
||||||
|
#
|
||||||
|
# If you want to contribute, please make a pull request on this respository
|
||||||
|
# and I will have a look.
|
||||||
|
#
|
||||||
|
# Placeholders:
|
||||||
|
#
|
||||||
|
# Do *not* replace placeholders! Placeholders have a special syntax like
|
||||||
|
# `Hotkey: <key>`. They are encapsulated within angle brackets. The correct
|
||||||
|
# translation for this one in German for example would be: `Taste: <key>` (notice
|
||||||
|
# how the placeholder stayed '<key>' and was not replaced!)
|
||||||
|
#
|
||||||
|
# Adding a new language:
|
||||||
|
#
|
||||||
|
# If you want to add a new language, ask me in the discord and I will setup
|
||||||
|
# the basic structure so the game also detects it.
|
||||||
|
#
|
||||||
|
|
||||||
|
global:
|
||||||
|
loading: Carregando
|
||||||
|
error: Erro
|
||||||
|
|
||||||
|
# How big numbers are rendered, e.g. "10,000"
|
||||||
|
thousandsDivider: "."
|
||||||
|
|
||||||
|
# The suffix for large numbers, e.g. 1.3k, 400.2M, etc.
|
||||||
|
suffix:
|
||||||
|
thousands: K
|
||||||
|
millions: M
|
||||||
|
billions: B
|
||||||
|
trillions: T
|
||||||
|
|
||||||
|
# Shown for infinitely big numbers
|
||||||
|
infinite: inf
|
||||||
|
|
||||||
|
time:
|
||||||
|
# Used for formatting past time dates
|
||||||
|
oneSecondAgo: um segundo atrás
|
||||||
|
xSecondsAgo: <x> segundos atrás
|
||||||
|
oneMinuteAgo: um minuto atrás
|
||||||
|
xMinutesAgo: <x> minutos atrás
|
||||||
|
oneHourAgo: uma hora atrás
|
||||||
|
xHoursAgo: <x> horas atrás
|
||||||
|
oneDayAgo: um dia atrás
|
||||||
|
xDaysAgo: <x> dias atrás
|
||||||
|
|
||||||
|
# Short formats for times, e.g. '5h 23m'
|
||||||
|
secondsShort: <seconds>s
|
||||||
|
minutesAndSecondsShort: <minutes>m <seconds>s
|
||||||
|
hoursAndMinutesShort: <hours>h <minutes>s
|
||||||
|
|
||||||
|
xMinutes: <x> minutos
|
||||||
|
|
||||||
|
keys:
|
||||||
|
tab: TAB
|
||||||
|
control: CTRL
|
||||||
|
alt: ALT
|
||||||
|
escape: ESC
|
||||||
|
shift: SHIFT
|
||||||
|
space: ESPAÇO
|
||||||
|
|
||||||
|
demoBanners:
|
||||||
|
# This is the "advertisement" shown in the main menu and other various places
|
||||||
|
title: Versão Demo
|
||||||
|
intro: >-
|
||||||
|
Pegue a versão completa para desbloquear todas os recursos
|
||||||
|
|
||||||
|
mainMenu:
|
||||||
|
play: Jogar
|
||||||
|
changelog: Changelog
|
||||||
|
importSavegame: Importar
|
||||||
|
openSourceHint: Esse jogo tem código aberto!
|
||||||
|
discordLink: Discord oficial
|
||||||
|
|
||||||
|
# This is shown when using firefox and other browsers which are not supported.
|
||||||
|
browserWarning: >-
|
||||||
|
Desculpe, o jogo fica lento em seu navegador! Compre a versão completa ou baixe o Chrome para obter uma experiência completa.
|
||||||
|
|
||||||
|
savegameLevel: Level <x>
|
||||||
|
savegameLevelUnknown: Level desconhecido
|
||||||
|
|
||||||
|
contests:
|
||||||
|
contest_01_03062020:
|
||||||
|
title: "Concurso #01"
|
||||||
|
desc: Ganhe <strong> $ 25 </strong> pela melhor base!
|
||||||
|
longDesc: >-
|
||||||
|
Para retribuir, pensei que seria legal fazer concursos semanais!
|
||||||
|
<br><br>
|
||||||
|
<strong> Tópico dessa semana:</strong> Cronstua a base mais legal!
|
||||||
|
<br><br>
|
||||||
|
Here's the deal:<br>
|
||||||
|
<ul class="bucketList">
|
||||||
|
<li>Envie uma captura de tela da sua base para <strong>contest@shapez.io</strong></li>
|
||||||
|
<li>Pontos bônus se você o compartilhar nas mídias sociais!</li>
|
||||||
|
<li>Vou escolher 5 capturas de tela e propor à votação a comunidade <strong>discord</strong>.</li>
|
||||||
|
<li>o vencedor recebe <strong> $ 25 </strong> (Paypal, Amazon Gift Card, o que você preferir)</li>
|
||||||
|
<li>Até 07.06.2020 12:00 CEST</li>
|
||||||
|
</ul>
|
||||||
|
<br>
|
||||||
|
Estou ansioso para ver suas criações incríveis!
|
||||||
|
|
||||||
|
showInfo: Participate
|
||||||
|
|
||||||
|
dialogs:
|
||||||
|
buttons:
|
||||||
|
ok: OK
|
||||||
|
delete: Deletar
|
||||||
|
cancel: Cancelar
|
||||||
|
later: Voltar
|
||||||
|
restart: Reiniciar
|
||||||
|
reset: Reset
|
||||||
|
getStandalone: Obter versão completa
|
||||||
|
deleteGame: Eu sei o que eu faço
|
||||||
|
viewUpdate: Atualizações
|
||||||
|
showUpgrades: Mostrar atualizações
|
||||||
|
showKeybindings: Controles
|
||||||
|
|
||||||
|
importSavegameError:
|
||||||
|
title: Erro importante
|
||||||
|
text: >-
|
||||||
|
Falha ao carregar seu savegame:
|
||||||
|
|
||||||
|
importSavegameSuccess:
|
||||||
|
title: Sucesso
|
||||||
|
text: >-
|
||||||
|
Seu savegame foi importado.
|
||||||
|
|
||||||
|
gameLoadFailure:
|
||||||
|
title: Jogo esta quebrado
|
||||||
|
text: >-
|
||||||
|
Falha ao carregar seu savegame
|
||||||
|
|
||||||
|
confirmSavegameDelete:
|
||||||
|
title: Confirmar exclusão
|
||||||
|
text: >-
|
||||||
|
Tem certeza que quer excluir esse jogo?
|
||||||
|
|
||||||
|
savegameDeletionError:
|
||||||
|
title: Falha para deletar
|
||||||
|
text: >-
|
||||||
|
Falha ao deletar seu savegame:
|
||||||
|
|
||||||
|
restartRequired:
|
||||||
|
title: Reiniciar
|
||||||
|
text: >-
|
||||||
|
Voce precisa reiniciar o jogo para aplicar as mudanças.
|
||||||
|
|
||||||
|
editKeybinding:
|
||||||
|
title: Change Keybinding
|
||||||
|
desc: Press the key you want to assign, or escape to cancel.
|
||||||
|
|
||||||
|
resetKeybindingsConfirmation:
|
||||||
|
title: Resetar controles
|
||||||
|
desc: Essa opção deixa os controles no modo padrão.
|
||||||
|
|
||||||
|
keybindingsResetOk:
|
||||||
|
title: Resetar controles
|
||||||
|
desc: Os controles foram resetados para o modo padrão.
|
||||||
|
|
||||||
|
featureRestriction:
|
||||||
|
title: Versão Demo
|
||||||
|
desc: Você tentou acessar um recurso (<feature>) que não está disponível na demo. Considere obter a versão completa para a proceder!
|
||||||
|
|
||||||
|
saveNotPossibleInDemo:
|
||||||
|
desc: Seu jogo foi salvo, mas a restauração só é possível na versão completa. Considere obter a versão completa!
|
||||||
|
|
||||||
|
leaveNotPossibleInDemo:
|
||||||
|
title: Demo version
|
||||||
|
desc: Seu jogo foi salvo, mas você não poderá restaurá-lo na demo. Restaurar seus savegames só é possível na versão completa. Você tem certeza?
|
||||||
|
|
||||||
|
newUpdate:
|
||||||
|
title: Atualização disponível
|
||||||
|
desc: Uma atualização para esse jogo esta disponível!
|
||||||
|
|
||||||
|
oneSavegameLimit:
|
||||||
|
title: Save limitado
|
||||||
|
desc: Você pode ter apenas um savegame por vez na versão demo. Remova o existente ou obtenha a versão completa!
|
||||||
|
|
||||||
|
updateSummary:
|
||||||
|
title: Nova Atualização!
|
||||||
|
desc: >-
|
||||||
|
Aqui estão as alterações desde a última vez que você jogou:
|
||||||
|
|
||||||
|
hintDescription:
|
||||||
|
title: Tutorial
|
||||||
|
desc: >-
|
||||||
|
Sempre que precisar de ajuda ou estiver parado, confira o botão 'Mostrar dica' no canto inferior esquerdo e darei o meu melhor para ajudá-lo!
|
||||||
|
|
||||||
|
upgradesIntroduction:
|
||||||
|
title: Desbloquear updates
|
||||||
|
desc: >-
|
||||||
|
Todas as formas que você produz podem ser usadas para desbloquear atualizações - <strong> Não destrua suas antigas fábricas!!</strong>
|
||||||
|
O guia de atualizações pode ser encontrada no canto superior direito da tela.
|
||||||
|
|
||||||
|
massDeleteConfirm:
|
||||||
|
title: Deletar
|
||||||
|
desc: >-
|
||||||
|
Voce esta deletando vários itens (<count> para ser exato)! Voce quer continuar?
|
||||||
|
|
||||||
|
blueprintsNotUnlocked:
|
||||||
|
title: Não desbloqueado ainda
|
||||||
|
desc: >-
|
||||||
|
Os projetos ainda não foram desbloqueados! Complete mais níveis para desbloqueá-los.
|
||||||
|
|
||||||
|
keybindingsIntroduction:
|
||||||
|
title: Teclas úteis
|
||||||
|
desc: >-
|
||||||
|
Este jogo possui muitas combinações de teclas que facilitam a construção de grandes fábricas
|
||||||
|
Aqui estão alguns mas certifique-se de <strong> verificar as combinações de teclas </strong>!<br><br>
|
||||||
|
<code class='keybinding'>CTRL</code> + Drag: Selecione a área para copiar / delete.<br>
|
||||||
|
<code class='keybinding'>SHIFT</code>: Mantenha pressionado para colocar vários.<br>
|
||||||
|
<code class='keybinding'>ALT</code>: Inverter as posições.<br>
|
||||||
|
|
||||||
|
createMarker:
|
||||||
|
title: Nova Marcação
|
||||||
|
desc: De um nome
|
||||||
|
ingame:
|
||||||
|
# This is shown in the top left corner and displays useful keybindings in
|
||||||
|
# every situation
|
||||||
|
keybindingsOverlay:
|
||||||
|
moveMap: Mover
|
||||||
|
removeBuildings: Deletar
|
||||||
|
stopPlacement: Parar
|
||||||
|
rotateBuilding: Rotação
|
||||||
|
placeMultiple: Colocar vários
|
||||||
|
reverseOrientation: reverso
|
||||||
|
disableAutoOrientation: desligar orientações
|
||||||
|
toggleHud: Base
|
||||||
|
placeBuilding: Colocar construção
|
||||||
|
createMarker: Criar marcador
|
||||||
|
delete: Destruir
|
||||||
|
|
||||||
|
# Everything related to placing buildings (I.e. as soon as you selected a building
|
||||||
|
# from the toolbar)
|
||||||
|
buildingPlacement:
|
||||||
|
# Buildings can have different variants which are unlocked at later levels,
|
||||||
|
# and this is the hint shown when there are multiple variants available.
|
||||||
|
cycleBuildingVariants: Aperte <key> para variações.
|
||||||
|
|
||||||
|
# Shows the hotkey in the ui, e.g. "Hotkey: Q"
|
||||||
|
hotkeyLabel: >-
|
||||||
|
Hotkey: <key>
|
||||||
|
|
||||||
|
infoTexts:
|
||||||
|
speed: velocidade
|
||||||
|
range: distancia
|
||||||
|
storage: Estoque
|
||||||
|
oneItemPerSecond: 1 item / segundo
|
||||||
|
itemsPerSecond: <x> itens / s
|
||||||
|
itemsPerSecondDouble: (x2)
|
||||||
|
|
||||||
|
tiles: <x> tiles
|
||||||
|
|
||||||
|
# The notification when completing a level
|
||||||
|
levelCompleteNotification:
|
||||||
|
# <level> is replaced by the actual level, so this gets 'Level 03' for example.
|
||||||
|
levelTitle: Level <level>
|
||||||
|
completed: Completado
|
||||||
|
unlockText: Desbloqueado <reward>!
|
||||||
|
buttonNextLevel: Próximo Level
|
||||||
|
|
||||||
|
# Notifications on the lower right
|
||||||
|
notifications:
|
||||||
|
newUpgrade: Nova Atualização disponível!
|
||||||
|
gameSaved: Seu jogo foi Salvo.
|
||||||
|
|
||||||
|
# Mass select information, this is when you hold CTRL and then drag with your mouse
|
||||||
|
# to select multiple buildings
|
||||||
|
massSelect:
|
||||||
|
infoText: Aperte <keyCopy> para copiar, <keyDelete> para excluir e <keyCancel> para cancelar.
|
||||||
|
|
||||||
|
# The "Upgrades" window
|
||||||
|
shop:
|
||||||
|
title: Atualizações
|
||||||
|
buttonUnlock: Atualizações
|
||||||
|
|
||||||
|
# Gets replaced to e.g. "Tier IX"
|
||||||
|
tier: Nível <x>
|
||||||
|
|
||||||
|
# The roman number for each tier
|
||||||
|
tierLabels: [I, II, III, IV, V, VI, VII, VIII, IX, X]
|
||||||
|
|
||||||
|
maximumLevel: Level Máximo
|
||||||
|
|
||||||
|
# The "Statistics" window
|
||||||
|
statistics:
|
||||||
|
title: Estatísticas
|
||||||
|
dataSources:
|
||||||
|
stored:
|
||||||
|
title: Estoque
|
||||||
|
description: Exibindo a quantidade de formas armazenadas em seu edifício central.
|
||||||
|
produced:
|
||||||
|
title: Produção
|
||||||
|
description: Exibindo todas as formas que toda a sua fábrica produz, incluindo produtos intermediários..
|
||||||
|
delivered:
|
||||||
|
title: Entregue
|
||||||
|
description: Exibindo formas entregues ao seu edifício central..
|
||||||
|
noShapesProduced: Nenhuma forma foi produzida até o momento.
|
||||||
|
|
||||||
|
# Displays the shapes per minute, e.g. '523 / m'
|
||||||
|
shapesPerMinute: <formas> / m
|
||||||
|
|
||||||
|
# Settings menu, when you press "ESC"
|
||||||
|
settingsMenu:
|
||||||
|
playtime: Tempo de Jogo
|
||||||
|
|
||||||
|
buildingsPlaced: Construções
|
||||||
|
beltsPlaced: Belts
|
||||||
|
|
||||||
|
buttons:
|
||||||
|
continue: Continue
|
||||||
|
settings: Definições
|
||||||
|
menu: Voltar ao menu
|
||||||
|
|
||||||
|
# Bottom left tutorial hints
|
||||||
|
tutorialHints:
|
||||||
|
title: Precisa de ajuda?
|
||||||
|
showHint: Mostrar dica
|
||||||
|
hideHint: Fechar
|
||||||
|
|
||||||
|
# When placing a blueprint
|
||||||
|
blueprintPlacer:
|
||||||
|
cost: Custo
|
||||||
|
|
||||||
|
# Map markers
|
||||||
|
waypoints:
|
||||||
|
waypoints: Marcadores
|
||||||
|
hub: HUB
|
||||||
|
description: Clique com o botão esquerdo do mouse em um marcador para pular, clique com o botão direito do mouse para excluí-lo. <br> <br> Pressione <keybinding> para criar um marcador a partir da exibição atual ou <strong> clique com o botão direito do mouse </strong> para criar um marcador no local selecionado.
|
||||||
|
creationSuccessNotification: Marcador criado.
|
||||||
|
|
||||||
|
# Interactive tutorial
|
||||||
|
interactiveTutorial:
|
||||||
|
title: Tutorial
|
||||||
|
hints:
|
||||||
|
1_1_extractor: Coloque um <strong> extrator </strong> em cima de uma <strong> fonte de círculo </strong> para extraí-lo!
|
||||||
|
1_2_conveyor: >-
|
||||||
|
Conecte o extrator com uma <strong> esteira transportadora </strong> até a sua base! <br><br> Dica, <strong>clique e arraste</strong> a esteira com o mouse!
|
||||||
|
|
||||||
|
1_3_expand: >-
|
||||||
|
Este <strong> NÃO </strong> é um jogo inativo! Construa mais extratores e esteiras para concluir o objetivo mais rapidamente.<br><br>Dica, segure <strong> SHIFT </strong> para colocar vários extratores e use <strong> R </strong> para girá-los.
|
||||||
|
|
||||||
|
# All shop upgrades
|
||||||
|
shopUpgrades:
|
||||||
|
belt:
|
||||||
|
name: Esteiras, Distribuidores e Túneis
|
||||||
|
description: Velocidade +<gain>%
|
||||||
|
miner:
|
||||||
|
name: Extração
|
||||||
|
description: Velocidade +<gain>%
|
||||||
|
processors:
|
||||||
|
name: Cortar, Rotacionar e Empilhamento
|
||||||
|
description: Velocidade +<gain>%
|
||||||
|
painting:
|
||||||
|
name: Misturador e pintura
|
||||||
|
description: Velocidade +<gain>%
|
||||||
|
|
||||||
|
# Buildings and their name / description
|
||||||
|
buildings:
|
||||||
|
belt:
|
||||||
|
default:
|
||||||
|
name: &belt Conveyor Belt
|
||||||
|
description: Transporta itens, mantenha pressionado e arraste para colocar vários.
|
||||||
|
|
||||||
|
miner: # Internal name for the Extractor
|
||||||
|
default:
|
||||||
|
name: &miner Extractor
|
||||||
|
description: Coloque sobre uma forma ou cor para extraí-la.
|
||||||
|
|
||||||
|
chainable:
|
||||||
|
name: Extractor (Chain)
|
||||||
|
description: Coloque sobre uma forma ou cor para extraí-la. Pode ser acorrentado.
|
||||||
|
|
||||||
|
underground_belt: # Internal name for the Tunnel
|
||||||
|
default:
|
||||||
|
name: &underground_belt Tunnel
|
||||||
|
description: Permite transportar recursos sob construções.
|
||||||
|
|
||||||
|
tier2:
|
||||||
|
name: Tunnel Tier II
|
||||||
|
description: Permite transportar recursos sob construções.
|
||||||
|
|
||||||
|
splitter: # Internal name for the Balancer
|
||||||
|
default:
|
||||||
|
name: &splitter Balancer
|
||||||
|
description: Multifunctional - Distribui uniformemente todas as entradas em todas as saídas.
|
||||||
|
|
||||||
|
compact:
|
||||||
|
name: Merger (compact)
|
||||||
|
description: Mescla duas correias transportadoras em uma.
|
||||||
|
|
||||||
|
compact-inverse:
|
||||||
|
name: Merger (compact)
|
||||||
|
description: Mescla duas correias transportadoras em uma.
|
||||||
|
|
||||||
|
cutter:
|
||||||
|
default:
|
||||||
|
name: &cutter Cutter
|
||||||
|
description: Corta as formas de cima para baixo e produz as duas metades. <strong> Se você usar apenas uma parte, não se esqueça de destruir a outra parte, ou ela irá parar a produção! </strong>
|
||||||
|
quad:
|
||||||
|
name: Cutter (Quad)
|
||||||
|
description: Corta as formas em quatro partes. <strong> Se você usar apenas uma parte, não se esqueça de destruir as outras, ou ela irá parar a produção! </strong>
|
||||||
|
|
||||||
|
rotater:
|
||||||
|
default:
|
||||||
|
name: &rotater Rotate
|
||||||
|
description: Gira as formas no sentido horário em 90 graus.
|
||||||
|
ccw:
|
||||||
|
name: Rotate (CCW)
|
||||||
|
description: RGira as formas no sentido anti-horário em 90 graus.
|
||||||
|
|
||||||
|
stacker:
|
||||||
|
default:
|
||||||
|
name: &stacker Stacker
|
||||||
|
description: Empilha os dois itens. Se eles não puderem ser mesclados, o item certo será colocado acima do item esquerdo.
|
||||||
|
|
||||||
|
mixer:
|
||||||
|
default:
|
||||||
|
name: &mixer Color Mixer
|
||||||
|
description: Mistura duas cores usando mistura aditiva.
|
||||||
|
|
||||||
|
painter:
|
||||||
|
default:
|
||||||
|
name: &painter Painter
|
||||||
|
description: Colore a forma inteira na entrada esquerda com a cor da entrada direita.
|
||||||
|
double:
|
||||||
|
name: Painter (Double)
|
||||||
|
description: Colore as duas formas na entrada esquerda com a cor da entrada direita.
|
||||||
|
quad:
|
||||||
|
name: Painter (Quad)
|
||||||
|
description: Permite colorir cada quadrante da forma com uma cor diferente.
|
||||||
|
|
||||||
|
trash:
|
||||||
|
default:
|
||||||
|
name: &trash Lixo
|
||||||
|
description: Aceita qualquer item e os destrói. PARA SEMPRE
|
||||||
|
|
||||||
|
storage:
|
||||||
|
name: Estoque
|
||||||
|
description: Armazena itens em excesso, até uma determinada capacidade. Pode ser usado como uma porta de transbordamento.
|
||||||
|
|
||||||
|
storyRewards:
|
||||||
|
# Those are the rewards gained from completing the store
|
||||||
|
reward_cutter_and_trash:
|
||||||
|
title: Formas de corte
|
||||||
|
desc: Voce desbloqueou <strong>cutter</strong> - corte de formas pela metade de <strong>cima para baixo </strong> independentemente de sua orientação!<br><br> Certifique-se de se livrar do lixo, ou então <strong> ele irá parar a produção </strong> - Para esse propósito, eu lhe dei uma lixo, que destrói tudo o que você coloca nele
|
||||||
|
|
||||||
|
reward_rotater:
|
||||||
|
title: Rodando
|
||||||
|
desc: O <strong> rotator </strong> foi desbloqueado! Gira as formas no sentido horário em 90 graus
|
||||||
|
|
||||||
|
reward_painter:
|
||||||
|
title: Pintando
|
||||||
|
desc: >-
|
||||||
|
O <strong> pintor </strong> foi desbloqueado - Extraia algumas veias coloridas (como você faz com formas) e combine-as com uma forma no pintor para colori-las! <br> <br> PS: Se você é daltônico , Já estou trabalhando em uma solução!
|
||||||
|
|
||||||
|
reward_mixer:
|
||||||
|
title: Mistura de cores
|
||||||
|
desc: O <strong> misturador </strong> foi desbloqueado - combine duas cores usando <strong> mistura aditiva </strong> com esta construção!
|
||||||
|
|
||||||
|
reward_stacker:
|
||||||
|
title: Combinador
|
||||||
|
desc: Agora você pode combinar formas com o <strong> combinador </strong>! Ambas as entradas são combinadas e, se puderem ser colocadas próximas uma da outra, serão <strong> fundidas </strong>. Caso contrário, a entrada direita é <strong> empilhada em cima </strong> da entrada esquerda!
|
||||||
|
|
||||||
|
reward_splitter:
|
||||||
|
title: Divisor/fusão
|
||||||
|
desc: O balanceador multifuncional <strong> </strong> foi desbloqueado - ele pode ser usado para construir fábricas maiores dividindo e mesclando itens </strong>! <br> <br>
|
||||||
|
|
||||||
|
reward_tunnel:
|
||||||
|
title: Túnel
|
||||||
|
desc: O <strong> túnel </strong> foi desbloqueado - Agora você pode canalizar itens através de construções!
|
||||||
|
|
||||||
|
reward_rotater_ccw:
|
||||||
|
title: CCW Rotação
|
||||||
|
desc: Você desbloqueou uma variante do <strong> rotater </strong> - permite girar no sentido anti-horário! Para construí-lo, selecione o rotador e <strong> pressione 'T' para alternar suas variantes </strong>!
|
||||||
|
|
||||||
|
reward_miner_chainable:
|
||||||
|
title: Extrator de encadeamento
|
||||||
|
desc: Você desbloqueou o <strong> extrator de correntes </strong>! Ele pode <strong> encaminhar seus recursos </strong> para outros extratores, para que você possa extrair recursos com mais eficiência!
|
||||||
|
|
||||||
|
reward_underground_belt_tier_2:
|
||||||
|
title: Túnel Tier II
|
||||||
|
desc: Você desbloqueou uma nova variante do <strong> túnel </strong> - ele tem um <strong> maior alcance </strong>, e também pode misturar e combinar esses túneis agora!
|
||||||
|
|
||||||
|
reward_splitter_compact:
|
||||||
|
title: Balanceador compacto
|
||||||
|
desc: >-
|
||||||
|
Você desbloqueou uma variante compacta do <strong> balanceador </strong> - ele aceita duas entradas e as mescla em uma!
|
||||||
|
|
||||||
|
reward_cutter_quad:
|
||||||
|
title: Cortador quádruplo
|
||||||
|
desc: Você desbloqueou uma variante do <strong> cortador </strong> - permite cortar formas em <strong> quatro partes </strong> em vez de apenas duas!
|
||||||
|
|
||||||
|
reward_painter_double:
|
||||||
|
title: Pintura dupla
|
||||||
|
desc: Você desbloqueou uma variante do <strong> pintor </strong> - funciona como o pintor regular, mas processa <strong> duas formas ao mesmo tempo </strong>, consumindo apenas uma cor em vez de duas!
|
||||||
|
|
||||||
|
reward_painter_quad:
|
||||||
|
title: Pintura quádupla
|
||||||
|
desc: Você desbloqueou uma variante do <strong> pintor </strong> - permite pintar cada parte da forma individualmente!
|
||||||
|
|
||||||
|
reward_storage:
|
||||||
|
title: buffer de armazenamento
|
||||||
|
desc: Você desbloqueou uma variante do <strong> lixo </strong> - Permite armazenar itens até uma determinada capacidade!
|
||||||
|
|
||||||
|
reward_freeplay:
|
||||||
|
title: Modo Livre
|
||||||
|
desc: Você fez isso! Você desbloqueou o <strong> modo de jogo livre </strong>! Isso significa que as formas agora são geradas aleatoriamente! (Não se preocupe, mais conteúdo está planejado para o jogo completo!)
|
||||||
|
|
||||||
|
reward_blueprints:
|
||||||
|
title: Projetos
|
||||||
|
desc: Agora você pode <strong> copiar e colar </strong> partes de sua fábrica! Selecione uma área (mantenha pressionada a tecla CTRL e arraste com o mouse) e pressione 'C' para copiá-la. <br> <br> Colar <strong> não é de graça </strong>, é necessário produzir <strong> projetos e formas </strong> para pagar! (Aqueles que você acabou de entregar).
|
||||||
|
|
||||||
|
# Special reward, which is shown when there is no reward actually
|
||||||
|
no_reward:
|
||||||
|
title: Próximo level
|
||||||
|
desc: >-
|
||||||
|
Este nível não lhe deu nenhuma recompensa, mas em breve?! <br> <br> PS: Melhor não destruir sua fábrica existente - Você precisa de <strong> todas </strong> todas essas formas posteriormente mais tarde para <strong> desbloquear atualizações </strong>!
|
||||||
|
|
||||||
|
no_reward_freeplay:
|
||||||
|
title: Next level
|
||||||
|
desc: >-
|
||||||
|
Parabens, não se esqueça existe muita coisa planejada para essa versão.
|
||||||
|
|
||||||
|
settings:
|
||||||
|
title: opções
|
||||||
|
categories:
|
||||||
|
game: Jogo
|
||||||
|
app: Aplicação
|
||||||
|
|
||||||
|
versionBadges:
|
||||||
|
dev: Desenvolvedor
|
||||||
|
staging: Staging
|
||||||
|
prod: Produção
|
||||||
|
buildDate: Built <at-date>
|
||||||
|
|
||||||
|
labels:
|
||||||
|
uiScale:
|
||||||
|
title: Fonte
|
||||||
|
description: >-
|
||||||
|
Altera o tamanho da fonte do usuário. A interface ainda será dimensionada com base na resolução do dispositivo, mas essa configuração controla a quantidade de escala.
|
||||||
|
scales:
|
||||||
|
super_small: Super pequeno
|
||||||
|
small: Pequeno
|
||||||
|
regular: Normal
|
||||||
|
large: Grande
|
||||||
|
huge: Gigante
|
||||||
|
|
||||||
|
scrollWheelSensitivity:
|
||||||
|
title: Sensibilidade do zoom
|
||||||
|
description: >-
|
||||||
|
Altera a sensibilidade do zoom (scrol do mouse ou touchpad).
|
||||||
|
sensitivity:
|
||||||
|
super_slow: Super lento
|
||||||
|
slow: Lento
|
||||||
|
regular: Normal
|
||||||
|
fast: Rápido
|
||||||
|
super_fast: Super Rápido
|
||||||
|
|
||||||
|
fullscreen:
|
||||||
|
title: Tecla Cheia
|
||||||
|
description: >-
|
||||||
|
É recomendável jogar o jogo em tela cheia para obter a melhor experiência. Disponível apenas na versão completa.
|
||||||
|
|
||||||
|
soundsMuted:
|
||||||
|
title: Som
|
||||||
|
description: >-
|
||||||
|
Se ligado o jogo fica Mudo.
|
||||||
|
|
||||||
|
musicMuted:
|
||||||
|
title: Musica
|
||||||
|
description: >-
|
||||||
|
Se ligado a musica é desligada.
|
||||||
|
|
||||||
|
theme:
|
||||||
|
title: Tema
|
||||||
|
description: >-
|
||||||
|
Escolha o tema entre (Branco / Preto).
|
||||||
|
|
||||||
|
refreshRate:
|
||||||
|
title: Frequencia
|
||||||
|
description: >-
|
||||||
|
Se você possui um monitor de 144 hz, altere a taxa de atualização aqui para que o jogo seja simulado corretamente com taxas de atualização mais altas. Isso pode realmente diminuir o FPS se o computador estiver muito lento.
|
||||||
|
|
||||||
|
alwaysMultiplace:
|
||||||
|
title: Multiplicidade
|
||||||
|
description: >-
|
||||||
|
Se ativado, todos os edifícios permanecerão selecionados após o posicionamento até que você o cancele. Isso é equivalente a manter SHIFT permanentemente.
|
||||||
|
|
||||||
|
offerHints:
|
||||||
|
title: Dicas e tutoriais
|
||||||
|
description: >-
|
||||||
|
Se deve oferecer dicas e tutoriais enquanto estiver jogando.v.
|
||||||
|
|
||||||
|
keybindings:
|
||||||
|
title: Comandos
|
||||||
|
hint: >-
|
||||||
|
Tip: Certifique-se de usar CTRL, SHIFT e ALT! Eles permitem diferentes opções de veiculação.
|
||||||
|
|
||||||
|
resetKeybindings: Reset Keyinbindings
|
||||||
|
|
||||||
|
categoryLabels:
|
||||||
|
general: Geral
|
||||||
|
ingame: Jogo
|
||||||
|
navigation: Navegação
|
||||||
|
placement: Posicionamento
|
||||||
|
massSelect: Seleção
|
||||||
|
buildings: Construções
|
||||||
|
placementModifiers: Modificações
|
||||||
|
|
||||||
|
mappings:
|
||||||
|
confirm: Confirmar
|
||||||
|
back: Voltar
|
||||||
|
mapMoveUp: Mover para cima
|
||||||
|
mapMoveRight: Mover para direita
|
||||||
|
mapMoveDown: Mover para baixo
|
||||||
|
mapMoveLeft: Mover para a esquerda
|
||||||
|
centerMap: Centralizar
|
||||||
|
|
||||||
|
mapZoomIn: Aproximar
|
||||||
|
mapZoomOut: Distanciar
|
||||||
|
createMarker: Criar marcação
|
||||||
|
|
||||||
|
menuOpenShop: Atualizações
|
||||||
|
menuOpenStats: Estatísticas
|
||||||
|
|
||||||
|
toggleHud: Ocultar Menu
|
||||||
|
toggleFPSInfo: Mostar FPS
|
||||||
|
belt: *belt
|
||||||
|
splitter: *splitter
|
||||||
|
underground_belt: *underground_belt
|
||||||
|
miner: *miner
|
||||||
|
cutter: *cutter
|
||||||
|
rotater: *rotater
|
||||||
|
stacker: *stacker
|
||||||
|
mixer: *mixer
|
||||||
|
painter: *painter
|
||||||
|
trash: *trash
|
||||||
|
|
||||||
|
abortBuildingPlacement: Cancelar
|
||||||
|
rotateWhilePlacing: Rotacionar
|
||||||
|
rotateInverseModifier: >-
|
||||||
|
Modifier: Rotação instantanea
|
||||||
|
cycleBuildingVariants: Variações
|
||||||
|
confirmMassDelete: Confirmar exclusão em massa
|
||||||
|
cycleBuildings: Trocar de construção
|
||||||
|
|
||||||
|
massSelectStart: Segure e arraste para começar
|
||||||
|
massSelectSelectMultiple: Selecionar área
|
||||||
|
massSelectCopy: Copiar área
|
||||||
|
|
||||||
|
placementDisableAutoOrientation: Desligar orientações automaticas
|
||||||
|
placeMultiple: Permanecer no modo de produção
|
||||||
|
placeInverse: Inverter orientação de esteira
|
||||||
|
|
||||||
|
about:
|
||||||
|
title: Sobre o jogo
|
||||||
|
|
||||||
|
changelog:
|
||||||
|
title: Changelog
|
||||||
|
|
||||||
|
demo:
|
||||||
|
features:
|
||||||
|
restoringGames: Restaurando jogos salvos
|
||||||
|
importingGames: Carregando jogos salvos
|
||||||
|
oneGameLimit: Limitado para um savegamne
|
||||||
|
customizeKeybindings: Modificando Teclas
|
||||||
|
creatingMarkers: Criando marcações
|
||||||
|
|
||||||
|
settingNotAvailable: Não disponível na versão demo.
|
||||||
@ -5604,6 +5604,11 @@ logalot@^2.0.0, logalot@^2.1.0:
|
|||||||
figures "^1.3.5"
|
figures "^1.3.5"
|
||||||
squeak "^1.0.0"
|
squeak "^1.0.0"
|
||||||
|
|
||||||
|
logrocket@^1.0.7:
|
||||||
|
version "1.0.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/logrocket/-/logrocket-1.0.7.tgz#fe17dbdfc861481cd274fbda533d552de7800a3a"
|
||||||
|
integrity sha512-v6HWEQIsyG+3FkldB7vIAgHh7/qpsiz2Br4bLK5SHBvjqRrHs/Fp+Jr8oiA2GYq0UurAtCu51U8SWft5+OCKtg==
|
||||||
|
|
||||||
longest@^1.0.0:
|
longest@^1.0.0:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097"
|
resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097"
|
||||||
|
|||||||