diff --git a/img/github.svg b/img/github.svg
deleted file mode 100644
index e575fa3..0000000
--- a/img/github.svg
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/img/sprite.svg b/img/sprite.svg
new file mode 100644
index 0000000..47bb3be
--- /dev/null
+++ b/img/sprite.svg
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/img/twitch.svg b/img/twitch.svg
deleted file mode 100644
index 28e4aab..0000000
--- a/img/twitch.svg
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/index.html b/index.html
index e6a6b5f..a92e3cb 100644
--- a/index.html
+++ b/index.html
@@ -13,25 +13,42 @@
Введите имя канала для игры
-
Автоперезапуск после поражения
+
+
+ Скрывать игру после поражения
+
+ ?
+
+
+
С включенной галочкой игра скроется после одной партии.
+
+ В OBS для этого источника нужно включить «Отключать источник, когда он не виден»
+
+
Чтобы запустить игру заново, скройте и снова покажите источник.
+
Можно автоматизировать через Streamer.bot.
+
+
+
+ ОТКРЫТЬ В БРАУЗЕРЕ
+ СКОПИРОВАТЬ ССЫЛКУ
- СКОПИРОВАТЬ ССЫЛКУ
- Вставь ссылку в OBS как источник браузера
- Желательно высоту побольше
+ Открой ссылку в браузере
+ Или вставь ссылку в OBS как источник браузера
+ Желательно высоту побольше
diff --git a/js/game.js b/js/game.js
index 8799ce0..90df9b0 100644
--- a/js/game.js
+++ b/js/game.js
@@ -25,7 +25,7 @@ let playerStats = {};
const params = new URLSearchParams(location.search);
const settings = {
- autoRestart: params.get("autoRestart") !== "0",
+ singlePlay: params.get("singlePlay") === "1",
};
function initKeyboardBridge() {
@@ -183,7 +183,7 @@ function gameOver() {
document.getElementById("ui-overlay").classList.add("hidden");
document.getElementById("input-chat").classList.add("hidden");
gameLoopStarted = false;
- if (settings.autoRestart) {
+ if (!settings.singlePlay) {
recalc();
runIntro();
} else {
diff --git a/js/index.js b/js/index.js
index 3ee9a64..b8dc084 100644
--- a/js/index.js
+++ b/js/index.js
@@ -1,19 +1,43 @@
const input = document.getElementById("channel-input");
const copyBtn = document.getElementById("copy-btn");
+const openBtn = document.getElementById("open-btn");
const linkEl = document.getElementById("game-link");
-const autoRestartEl = document.getElementById("opt-auto-restart");
+const singlePlayEl = document.getElementById("opt-single-play");
+
+function buildUrl() {
+ const name = input.value.trim().toLowerCase() || "Ku6ep_XBOCTuK";
+ const single = singlePlayEl.checked ? "1" : "0";
+ return `${location.origin}${location.pathname.replace(/\/[^/]*$/, "/")}game?channel=${encodeURIComponent(name)}&singlePlay=${single}`;
+}
+
+function updateLink() {
+ linkEl.textContent = buildUrl();
+ linkEl.className = "";
+}
function copyLink() {
- const name = input.value.trim().toLowerCase() || "Ku6ep_XBOCTuK";
- const autoRestart = autoRestartEl.checked ? "1" : "0";
- const url = `${location.origin}${location.pathname.replace(/\/[^/]*$/, "/")}game.html?channel=${encodeURIComponent(name)}&autoRestart=${autoRestart}`;
- navigator.clipboard.writeText(url).then(() => {
+ navigator.clipboard.writeText(buildUrl()).then(() => {
linkEl.textContent = "СКОПИРОВАНО!";
linkEl.className = "copied";
+ setTimeout(updateLink, 1500);
});
}
-copyBtn.addEventListener("click", copyLink);
+function openLink() {
+ window.open(buildUrl(), "_blank");
+}
+
+input.addEventListener("input", updateLink);
+singlePlayEl.addEventListener("change", updateLink);
input.addEventListener("keydown", (e) => {
if (e.key === "Enter") copyLink();
});
+
+copyBtn.addEventListener("click", copyLink);
+openBtn.addEventListener("click", openLink);
+
+updateLink();
+
+document.querySelector(".hint-toggle").addEventListener("click", () => {
+ document.querySelector(".settings-hints").classList.toggle("hidden");
+});
diff --git a/serve.json b/serve.json
index 20c6bac..3603c13 100644
--- a/serve.json
+++ b/serve.json
@@ -1,6 +1,7 @@
{
- "cleanUrls": true,
+ "cleanUrls": false,
"rewrites": [
- { "source": "/game", "destination": "/game.html" }
+ { "source": "/game", "destination": "/game.html" },
+ { "source": "/", "destination": "/index.html" }
]
-}
\ No newline at end of file
+}
diff --git a/style.css b/style.css
index 17d3501..0cd90ce 100644
--- a/style.css
+++ b/style.css
@@ -65,6 +65,12 @@ body {
text-shadow: 0 0 8px #00ff41;
letter-spacing: 1px;
}
+.ui-text:nth-child(2) {
+ text-align: center;
+}
+.ui-text:nth-child(3) {
+ text-align: right;
+}
#input-display {
position: absolute;
bottom: 0;
@@ -283,6 +289,10 @@ body {
gap: 10px;
margin-bottom: 12px;
}
+.settings-row {
+ display: flex;
+ align-items: center;
+}
.settings-label {
color: #00cc33;
font-size: 28px;
@@ -296,6 +306,39 @@ body {
.settings-label:hover {
opacity: 1;
}
+.hint-toggle {
+ background: transparent;
+ border: 2px solid #00aa33;
+ color: #00aa33;
+ font-size: 18px;
+ width: 36px;
+ height: 36px;
+ border-radius: 50%;
+ cursor: pointer;
+ text-shadow: 0 0 6px #00aa33;
+ transition: all 0.15s;
+ margin-left: 8px;
+}
+.hint-toggle:hover {
+ border-color: #00ff41;
+ color: #00ff41;
+ text-shadow: 0 0 10px #00ff41;
+}
+.settings-hints {
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+ align-items: center;
+ margin-top: 12px;
+}
+.settings-hint {
+ color: #00aa33;
+ font-size: 18px;
+ text-shadow: none;
+ line-height: 1.5;
+ max-width: 500px;
+ text-align: center;
+}
.settings-label input[type="checkbox"] {
width: 28px;
height: 28px;
@@ -303,7 +346,12 @@ body {
cursor: pointer;
margin-right: 12px;
}
-#channel-form button {
+.btn-row {
+ display: flex;
+ flex-direction: column;
+ gap: 12px;
+}
+.btn-primary {
background: transparent;
border: 2px solid #00ff41;
color: #00ff41;
@@ -315,7 +363,7 @@ body {
transition: all 0.15s;
min-width: 260px;
}
-#channel-form button:hover {
+.btn-primary:hover {
background: rgba(0, 255, 65, 0.1);
box-shadow: 0 0 30px rgba(0, 255, 65, 0.4);
}
@@ -340,7 +388,9 @@ body {
}
.links-row {
display: flex;
- gap: 40px;
+ flex-wrap: wrap;
+ justify-content: center;
+ gap: 20px 40px;
margin-top: 16px;
}
.page-link {
@@ -357,8 +407,8 @@ body {
.link-icon {
width: 24px;
height: 24px;
+ fill: currentColor;
flex-shrink: 0;
- color: #00ff41;
}
.page-link:hover {
opacity: 1;