🎮ArcadeLab

NEBULA CALC + СЕКРЕТ | SubVS

by SparkHawk26
687 lines29.5 KB
▶ Play
<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no, viewport-fit=cover">
    <title>NEBULA CALC + СЕКРЕТ | SubVS</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            user-select: none;
        }

        body {
            min-height: 100vh;
            background: radial-gradient(circle at 30% 10%, #0c0a1a, #020105);
            display: flex;
            justify-content: center;
            align-items: center;
            font-family: 'Segoe UI', 'Poppins', 'Courier New', monospace;
            padding: 20px;
            transition: all 0.3s;
        }

        /* секретный режим (игра вместо калькулятора) */
        body.game-mode .calculator-wrapper {
            display: none;
        }
        body.game-mode .game-container {
            display: block;
        }

        .game-container {
            display: none;
            width: 100%;
            max-width: 1000px;
            margin: 0 auto;
            background: #0c0820;
            border-radius: 56px;
            padding: 20px;
            box-shadow: 0 25px 45px rgba(0,0,0,0.8), inset 0 1px 1px rgba(156,80,255,0.2);
            border: 1px solid #7f4ef0;
        }

        /* Главный калькулятор в черно-фиолетовом стиле */
        .calculator-wrapper {
            width: 100%;
            max-width: 450px;
            margin: 0 auto;
        }
        .calculator {
            background: linear-gradient(145deg, #1e1a2f, #0f0b1a);
            border-radius: 56px;
            padding: 24px 20px 30px 20px;
            box-shadow: 0 25px 45px rgba(0, 0, 0, 0.6), inset 0 1px 1px rgba(255, 255, 255, 0.08);
            border: 1px solid rgba(156, 80, 255, 0.35);
            transition: 0.2s;
        }

        .screen {
            background: #07050e;
            padding: 25px 20px;
            border-radius: 48px;
            margin-bottom: 30px;
            box-shadow: inset 0 5px 12px rgba(0, 0, 0, 0.6), 0 2px 3px rgba(156, 80, 255, 0.2);
            border: 1px solid #3c2a6e;
        }

        .previous-operand {
            min-height: 32px;
            font-size: 1.2rem;
            color: #b58eff;
            text-align: right;
            word-wrap: break-word;
            letter-spacing: 1px;
            font-family: monospace;
            opacity: 0.85;
        }

        .current-operand {
            font-size: 3rem;
            font-weight: 700;
            color: #f0e6ff;
            text-align: right;
            word-wrap: break-word;
            word-break: break-all;
            text-shadow: 0 0 6px #9b4dff;
            font-family: 'Segoe UI', monospace;
        }

        .buttons {
            display: grid;
            grid-template-columns: repeat(4, 1fr);
            gap: 14px;
        }

        button {
            background: #15102a;
            border: none;
            padding: 18px 0;
            font-size: 1.6rem;
            font-weight: bold;
            border-radius: 48px;
            color: #e2d6ff;
            cursor: pointer;
            transition: 0.08s linear;
            box-shadow: 0 6px 0 #0a0720;
            font-family: monospace;
            border: 1px solid rgba(128, 90, 240, 0.4);
        }

        button:active {
            transform: translateY(3px);
            box-shadow: 0 2px 0 #0a0720;
        }

        .operator {
            background: #2a1a55;
            color: #dbbaff;
            text-shadow: 0 0 3px #b77eff;
            font-size: 1.9rem;
        }

        .equals {
            background: #9b4dff;
            color: #1a0f2e;
            text-shadow: 0 1px 1px white;
            box-shadow: 0 6px 0 #5c2ab3;
        }

        .clear, .delete {
            background: #3d1f5e;
        }
        .delete {
            background: #5a2a82;
        }

        .style-badge {
            text-align: center;
            margin-top: 20px;
            font-size: 0.7rem;
            color: #8a6fcf;
            font-weight: bold;
        }

        /* Игровой интерфейс внутри секретного меню */
        .game-header {
            display: flex;
            justify-content: space-between;
            background: #180e2e;
            padding: 12px 20px;
            border-radius: 60px;
            margin-bottom: 18px;
            color: #f2dd9f;
            font-weight: bold;
            flex-wrap: wrap;
            gap: 10px;
        }
        .game-canvas-box {
            background: #00000066;
            border-radius: 32px;
            padding: 8px;
            border: 2px solid #9b4dff;
        }
        canvas {
            display: block;
            margin: 0 auto;
            border-radius: 24px;
            width: 100%;
            height: auto;
            background: #0d0a1a;
            cursor: pointer;
        }
        .secret-controls {
            display: flex;
            justify-content: center;
            gap: 20px;
            margin-top: 20px;
        }
        .sec-btn {
            background: #2d1f53;
            padding: 10px 20px;
            font-size: 1.4rem;
            box-shadow: 0 4px 0 #0e0820;
        }
        .back-btn {
            background: #671b5e;
            color: #ffe5b4;
        }
        .cheat-msg {
            text-align: center;
            margin-top: 12px;
            color: #ffdc97;
            background: #00000088;
            padding: 6px;
            border-radius: 60px;
            font-size: 0.8rem;
        }
        @media (max-width: 560px) {
            .buttons { gap: 8px; }
            button { padding: 12px 0; font-size: 1.3rem; }
            .game-header { font-size: 0.9rem; }
        }
    </style>
</head>
<body>
    <!-- Обычный калькулятор (черно-фиолетовый) -->
    <div class="calculator-wrapper">
        <div class="calculator">
            <div class="screen">
                <div class="previous-operand" id="previousOperand"></div>
                <div class="current-operand" id="currentOperand">0</div>
            </div>
            <div class="buttons">
                <button class="clear" data-action="clear">C</button>
                <button class="delete" data-action="delete">⌫</button>
                <button class="operator" data-operator="%">%</button>
                <button class="operator" data-operator="/">÷</button>
                <button data-number="7">7</button>
                <button data-number="8">8</button>
                <button data-number="9">9</button>
                <button class="operator" data-operator="*">×</button>
                <button data-number="4">4</button>
                <button data-number="5">5</button>
                <button data-number="6">6</button>
                <button class="operator" data-operator="-">−</button>
                <button data-number="1">1</button>
                <button data-number="2">2</button>
                <button data-number="3">3</button>
                <button class="operator" data-operator="+">+</button>
                <button data-number="0">0</button>
                <button data-number=".">.</button>
                <button class="equals" data-equals id="equalsBtn">=</button>
            </div>
            <div class="style-badge">✦ VIOLET PHANTOM | введи код: 25 84 25 ✦</div>
        </div>
    </div>

    <!-- СЕКРЕТНЫЙ КОНТЕЙНЕР: игра SubVS (наш Subway Surfers стиль) -->
    <div class="game-container" id="secretGameContainer">
        <div class="game-header">
            <span>🌀 SUBVS: SURF & HAMSTERS 🐹</span>
            <span>🏆 ОЧКИ: <span id="gameScore">0</span></span>
            <span>🐹 ХОМЯКИ: <span id="gameCoins">0</span></span>
            <span>⚡ РЕКОРД: <span id="gameBest">0</span></span>
        </div>
        <div class="game-canvas-box">
            <canvas id="subCanvas" width="800" height="500" style="width:100%; height:auto; max-width:800px; aspect-ratio:800/500"></canvas>
        </div>
        <div class="secret-controls">
            <button class="sec-btn" id="gameLeftBtn">◀ ЛЕВО</button>
            <button class="sec-btn" id="gameRightBtn">ПРАВО ▶</button>
            <button class="sec-btn back-btn" id="exitGameBtn">🔮 ВЫЙТИ ИЗ СЕКРЕТА</button>
        </div>
        <div class="cheat-msg">✨ ЧИТ-МЕНЮ АКТИВИРОВАНО! Беги, собирай крутящихся хомяков ✨</div>
    </div>

    <script>
        // ---------- КАЛЬКУЛЯТОР С ФУНКЦИЕЙ ПАРОЛЯ ----------
        (function() {
            // Элементы калькулятора
            const previousOperandEl = document.getElementById('previousOperand');
            const currentOperandEl = document.getElementById('currentOperand');

            let currentOperand = "0";
            let previousOperand = "";
            let operation = null;
            let shouldResetScreen = false;

            // Секретная комбинация: "25", "84", "25"
            let secretBuffer = [];
            const SECRET_CODE = ["25", "84", "25"];
            
            function formatNumber(number) {
                const str = number.toString();
                const parts = str.split('.');
                parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, " ");
                return parts.join('.');
            }

            function updateDisplay() {
                currentOperandEl.innerText = formatNumber(currentOperand);
                if (operation != null && previousOperand !== "") {
                    previousOperandEl.innerText = `${formatNumber(previousOperand)} ${getOperatorSymbol(operation)}`;
                } else {
                    previousOperandEl.innerText = previousOperand ? formatNumber(previousOperand) : "";
                }
            }

            function getOperatorSymbol(op) {
                switch(op) {
                    case '+': return '+'; case '-': return '−'; case '*': return '×';
                    case '/': return '÷'; case '%': return '%'; default: return '';
                }
            }

            function appendNumber(number) {
                if (shouldResetScreen) {
                    currentOperand = "";
                    shouldResetScreen = false;
                }
                if (number === '.' && currentOperand.includes('.')) return;
                if (currentOperand === "0" && number !== '.') currentOperand = number;
                else currentOperand += number;
                updateDisplay();
                // ПРОВЕРКА СЕКРЕТНОЙ КОМБИНАЦИИ НА ЛЕТУ (цифры, но мы проверяем именно ввод целых чисел)
                // Проверяем последнее введенное "число" — пользователь вводит последовательно цифры.
                // Чтобы активировать игру при вводе 25 84 25 (подряд как числа), будем отслеживать числа через точку? 
                // Лучше: мониторить текущий ввод после нажатия оператора/равно? но проще всего сделать: если пользователь нажал "=" и результат равен секретному, но у нас проще ловить последовательность чисел прямо при вводе цифр.
                // Имитируем ввод через пробел: пароль вводится набором цифр с последующим нажатием "=" или просто подряд? 
                // Сделаем детектор: каждый раз когда текущий операнд совпадает с очередным ожидаемым числом (по целому числу) и после него нажат оператор или равно — но проще сделать так:
                // Будем детектить ПОЛНОЕ совпадение экрана при нажатии "=" если строка экрана равна "258425"? Но юзер хочет именно "двадцать пять восемьдесят четыре двадцать пять". 
                // Лучший способ: слушать кнопку равно и сравнивать текущий операнд с числом 258425? Нет. Нам нужно три отдельных числа.
                // Реализуем отложенную проверку по мере набора: когда пользователь ввел число и нажал какую-либо операцию (+, -, ×...), мы кладём число в буфер.
                // но проще ловить прямо по вводу: при каждом изменении currentOperand (целое число) проверяем, является ли оно частью кода.
            }

            // Функция проверки секретного кода (вызываем когда число "завершено" — либо после оператора, либо равно)
            function checkSecretSequence(value) {
                if (!value) return false;
                // убираем пробелы форматирования, оставляем только цифры
                let cleanVal = value.toString().replace(/\s/g, '');
                if (cleanVal === SECRET_CODE[secretBuffer.length]) {
                    secretBuffer.push(cleanVal);
                    if (secretBuffer.length === SECRET_CODE.length) {
                        // секрет активирован!
                        activateSecretGame();
                        secretBuffer = [];
                        return true;
                    }
                } else {
                    // сброс буфера при несовпадении, но с проверкой заново: может начаться новая последовательность
                    let newBuf = [];
                    let total = secretBuffer.join('') + cleanVal;
                    // ищем суффикс, который может быть началом кода
                    for (let i = 0; i < SECRET_CODE.length; i++) {
                        if (cleanVal === SECRET_CODE[i]) {
                            newBuf = [cleanVal];
                            break;
                        }
                    }
                    if (newBuf.length === 0) secretBuffer = [];
                    else secretBuffer = newBuf;
                }
                return false;
            }

            function activateSecretGame() {
                // Показать игровой контейнер, скрыть калькулятор
                document.body.classList.add('game-mode');
                // Запустить игру, если ещё не запущена
                if (typeof initGame === 'function') {
                    initGame();
                }
            }

            // Перехватываем действия для отслеживания "чисел" (операндов)
            function commitCurrentNumber() {
                if (currentOperand && currentOperand !== "") {
                    let numRaw = currentOperand.replace(/\s/g, '');
                    if (!isNaN(parseFloat(numRaw))) {
                        checkSecretSequence(numRaw);
                    }
                }
            }

            // Доработаем вычисления и операции чтобы проверять код при фиксации числа
            const origChooseOperation = null;
            function customChooseOperation(op) {
                if (currentOperand === "" && previousOperand === "") return;
                if (previousOperand !== "" && !shouldResetScreen) customCompute();
                commitCurrentNumber();   // проверяем текущее число перед операцией
                if (currentOperand === "") return;
                operation = op;
                previousOperand = currentOperand;
                currentOperand = "";
                shouldResetScreen = false;
                updateDisplay();
            }

            function customCompute() {
                if (operation === null || previousOperand === "" || currentOperand === "") return;
                let result;
                const prev = parseFloat(previousOperand.replace(/\s/g, ''));
                const cur = parseFloat(currentOperand.replace(/\s/g, ''));
                if (isNaN(prev) || isNaN(cur)) return;
                switch(operation) {
                    case '+': result = prev + cur; break;
                    case '-': result = prev - cur; break;
                    case '*': result = prev * cur; break;
                    case '/': result = cur === 0 ? "Ошибка" : prev / cur; break;
                    case '%': result = prev % cur; break;
                    default: return;
                }
                if (result === "Ошибка") {
                    currentOperand = "∞";
                    previousOperand = "";
                    operation = null;
                    shouldResetScreen = true;
                    updateDisplay();
                    return;
                }
                result = parseFloat(result.toFixed(8));
                currentOperand = result.toString();
                operation = null;
                previousOperand = "";
                shouldResetScreen = true;
                updateDisplay();
                // после вычисления тоже проверяем результат на совпадение с кодом? 
                // но по заданию достаточно при вводе чисел. Однако для надёжности проверим и результат
                if (currentOperand && currentOperand !== "∞") {
                    let resClean = currentOperand.replace(/\s/g, '');
                    if (!isNaN(parseFloat(resClean))) checkSecretSequence(resClean);
                }
            }

            function customClear() {
                currentOperand = "0";
                previousOperand = "";
                operation = null;
                shouldResetScreen = false;
                updateDisplay();
            }
            function customDelete() {
                if (shouldResetScreen) return;
                if (currentOperand.length === 1 || (currentOperand === "0")) {
                    currentOperand = "0";
                } else {
                    currentOperand = currentOperand.slice(0, -1);
                }
                updateDisplay();
            }
            function appendNumberHandler(num) {
                if (shouldResetScreen) {
                    currentOperand = "";
                    shouldResetScreen = false;
                }
                if (num === '.' && currentOperand.includes('.')) return;
                if (currentOperand === "0" && num !== '.') currentOperand = num;
                else currentOperand += num;
                updateDisplay();
            }

            // Переопределяем кнопки
            document.querySelectorAll('[data-number]').forEach(btn => {
                btn.addEventListener('click', () => {
                    appendNumberHandler(btn.getAttribute('data-number'));
                });
            });
            document.querySelectorAll('[data-operator]').forEach(btn => {
                btn.addEventListener('click', () => {
                    customChooseOperation(btn.getAttribute('data-operator'));
                });
            });
            document.querySelector('[data-action="clear"]').addEventListener('click', customClear);
            document.querySelector('[data-action="delete"]').addEventListener('click', customDelete);
            document.getElementById('equalsBtn').addEventListener('click', () => {
                commitCurrentNumber(); 
                customCompute();
            });

            // Дополнительно отслеживаем каждый клик для скрытой инициализации буфера
            updateDisplay();
            window.activateSecretGame = activateSecretGame;
        })();

        // ---------- ИГРА SUBVS (стиль subway surfers, но с 3D-эффектом? максимально похоже на 2.5D с хомяками) ----------
        let gameRunning = true;
        let score = 0;
        let coinsCollected = 0;
        let bestScore = localStorage.getItem('subvsBest') ? parseInt(localStorage.getItem('subvsBest')) : 0;
        let playerLane = 1; // 0,1,2
        let trains = [];
        let hamsters = [];
        let frame = 0;
        let currentSpeed = 4.5;
        let animationId = null;

        const LANES = 3;
        const LANE_WIDTH = 110;
        const BASE_X = 180;
        const PLAYER_W = 38;
        const PLAYER_H = 48;
        const TRAIN_W = 50;
        const TRAIN_H = 60;
        const HAMSTER_SIZE = 34;

        let canvas = null, ctx = null;
        let gameActive = true;

        function updateUI() {
            document.getElementById('gameScore').innerText = Math.floor(score);
            document.getElementById('gameCoins').innerText = coinsCollected;
            document.getElementById('gameBest').innerText = bestScore;
        }

        function spawnTrain() {
            let lane = Math.floor(Math.random() * LANES);
            trains.push({ lane: lane, y: -TRAIN_H - Math.random() * 40 });
        }
        function spawnHamster() {
            let lane = Math.floor(Math.random() * LANES);
            hamsters.push({ lane: lane, y: -HAMSTER_SIZE - Math.random() * 70, rot: Math.random() * Math.PI * 2 });
        }

        function updateGame() {
            if (!gameActive) return;
            currentSpeed = 4.2 + Math.floor(score / 450) * 0.6;
            if (currentSpeed > 11.5) currentSpeed = 11.5;

            for (let t of trains) t.y += currentSpeed;
            trains = trains.filter(t => t.y < canvas.height + 120);
            for (let h of hamsters) {
                h.y += currentSpeed;
                h.rot = (h.rot + 0.12) % (Math.PI * 2);
            }
            hamsters = hamsters.filter(h => h.y < canvas.height + 100);

            let spawnRateTrains = Math.max(20, 48 - Math.floor(score / 140));
            let spawnRateHam = Math.max(14, 32 - Math.floor(score / 110));
            if (frame % spawnRateTrains === 0) spawnTrain();
            if (frame % spawnRateHam === 0) spawnHamster();

            const playerX = BASE_X + playerLane * LANE_WIDTH + (LANE_WIDTH/2) - PLAYER_W/2;
            const playerRect = { x: playerX, y: canvas.height - PLAYER_H - 20, w: PLAYER_W, h: PLAYER_H };
            // столкновение с поездами
            for (let i=0; i<trains.length; i++) {
                const t = trains[i];
                const trainX = BASE_X + t.lane * LANE_WIDTH + (LANE_WIDTH/2) - TRAIN_W/2;
                if (playerRect.x < trainX + TRAIN_W && playerRect.x + PLAYER_W > trainX &&
                    playerRect.y < t.y + TRAIN_H && playerRect.y + PLAYER_H > t.y) {
                    gameActive = false;
                    if (Math.floor(score) > bestScore) {
                        bestScore = Math.floor(score);
                        localStorage.setItem('subvsBest', bestScore);
                    }
                    updateUI();
                    return;
                }
            }
            // сбор хомяков
            for (let i=0; i<hamsters.length; i++) {
                const h = hamsters[i];
                const hamX = BASE_X + h.lane * LANE_WIDTH + (LANE_WIDTH/2) - HAMSTER_SIZE/2;
                if (playerRect.x < hamX + HAMSTER_SIZE && playerRect.x + PLAYER_W > hamX &&
                    playerRect.y < h.y + HAMSTER_SIZE && playerRect.y + PLAYER_H > h.y) {
                    coinsCollected++;
                    hamsters.splice(i,1);
                    i--;
                    updateUI();
                }
            }
            score += 0.27;
            updateUI();
            frame++;
        }

        function draw() {
            if (!ctx) return;
            ctx.clearRect(0,0,canvas.width,canvas.height);
            ctx.fillStyle = "#16122b";
            ctx.fillRect(0,0,canvas.width,canvas.height);
            // рельсы
            for(let i=0;i<=LANES;i++){
                let railX = BASE_X + i*LANE_WIDTH - 6;
                ctx.beginPath();
                ctx.strokeStyle = "#b886ff";
                ctx.lineWidth = 3;
                for(let s=0;s<canvas.height+30;s+=35){
                    ctx.beginPath();
                    ctx.moveTo(railX,s);
                    ctx.lineTo(railX+10,s+18);
                    ctx.stroke();
                }
            }
            // поезда 3D-подобные
            for(let t of trains){
                let x = BASE_X + t.lane*LANE_WIDTH + (LANE_WIDTH/2) - TRAIN_W/2;
                ctx.fillStyle = "#482d6b";
                ctx.shadowBlur = 6;
                ctx.fillRect(x,t.y, TRAIN_W, TRAIN_H);
                ctx.fillStyle = "#aa86db";
                ctx.fillRect(x+8,t.y+12, TRAIN_W-16,12);
                ctx.fillStyle = "#ffcf70";
                ctx.beginPath();
                ctx.arc(x+TRAIN_W/2, t.y+14, 8,0,Math.PI*2);
                ctx.fill();
            }
            // хомяки крутящиеся
            for(let h of hamsters){
                let x = BASE_X + h.lane*LANE_WIDTH + (LANE_WIDTH/2) - HAMSTER_SIZE/2;
                ctx.save();
                ctx.translate(x+HAMSTER_SIZE/2, h.y+HAMSTER_SIZE/2);
                ctx.rotate(h.rot);
                ctx.fillStyle = "#bc8a5a";
                ctx.beginPath();
                ctx.ellipse(0,0, HAMSTER_SIZE/2.2, HAMSTER_SIZE/2.2,0,0,Math.PI*2);
                ctx.fill();
                ctx.fillStyle = "#5d3a1a";
                ctx.beginPath();
                ctx.ellipse(-6,-5,4,5,0,0,Math.PI*2);
                ctx.ellipse(6,-5,4,5,0,0,Math.PI*2);
                ctx.fill();
                ctx.fillStyle = "white";
                ctx.beginPath();
                ctx.arc(-5,-7,1.8,0,Math.PI*2);
                ctx.arc(5,-7,1.8,0,Math.PI*2);
                ctx.fill();
                ctx.fillStyle = "#ff9966";
                ctx.font = `${Math.floor(HAMSTER_SIZE/1.6)}px monospace`;
                ctx.fillText("🐹", -8,-6);
                ctx.restore();
            }
            // игрок
            let plX = BASE_X + playerLane*LANE_WIDTH + (LANE_WIDTH/2) - PLAYER_W/2;
            let plY = canvas.height - PLAYER_H - 20;
            ctx.fillStyle = "#a55ef0";
            ctx.fillRect(plX,plY, PLAYER_W, PLAYER_H);
            ctx.fillStyle = "#ffb86b";
            ctx.beginPath();
            ctx.ellipse(plX+PLAYER_W/2, plY-5, 14,10,0,0,Math.PI*2);
            ctx.fill();
            ctx.fillStyle = "white";
            ctx.fillRect(plX+10,plY+12,6,8);
            ctx.fillRect(plX+PLAYER_W-16,plY+12,6,8);
            ctx.fillStyle = "#d43f1f";
            ctx.fillRect(plX-4,plY+PLAYER_H-6, PLAYER_W+8, 6);
            if(!gameActive){
                ctx.font = "bold 26monospace";
                ctx.fillStyle = "#ffdbb5";
                ctx.fillText("💀 GAME OVER", canvas.width/2-110, canvas.height/2);
            }
        }

        function gameLoop() {
            if(!canvas || !ctx) return;
            if(gameActive) updateGame();
            draw();
            animationId = requestAnimationFrame(gameLoop);
        }

        function resetGameSession() {
            gameActive = true;
            score = 0;
            coinsCollected = 0;
            trains = [];
            hamsters = [];
            playerLane = 1;
            frame = 0;
            currentSpeed = 4.5;
            updateUI();
        }

        function initGame() {
            canvas = document.getElementById('subCanvas');
            if(!canvas) return;
            ctx = canvas.getContext('2d');
            resetGameSession();
            if(animationId) cancelAnimationFrame(animationId);
            gameLoop();
            // управление
            document.getElementById('gameLeftBtn').onclick = () => { if(gameActive && playerLane>0) playerLane--; };
            document.getElementById('gameRightBtn').onclick = () => { if(gameActive && playerLane<LANES-1) playerLane++; };
            document.getElementById('exitGameBtn').onclick = () => {
                document.body.classList.remove('game-mode');
                if(animationId) cancelAnimationFrame(animationId);
                gameActive = false;
            };
            window.addEventListener('keydown', (e) => {
                if(document.body.classList.contains('game-mode')){
                    if(e.key === 'ArrowLeft') { if(gameActive && playerLane>0) playerLane--; e.preventDefault();}
                    if(e.key === 'ArrowRight') { if(gameActive && playerLane<LANES-1) playerLane++; e.preventDefault();}
                }
            });
        }

        window.initGame = initGame;
        // показ секретной игры и инициализация
        const origActivate = window.activateSecretGame;
        window.activateSecretGame = function() {
            if(origActivate) origActivate();
            setTimeout(() => { if(document.body.classList.contains('game-mode')) initGame(); }, 50);
        };
    </script>
</body>
</html>

Game Source: NEBULA CALC + СЕКРЕТ | SubVS

Creator: SparkHawk26

Libraries: none

Complexity: complex (687 lines, 29.5 KB)

The full source code is displayed above on this page.

Remix Instructions

To remix this game, copy the source code above and modify it. Add a ARCADELAB header at the top with "remix_of: nebula-calc-subvs-sparkhawk26" to link back to the original. Then publish at arcadelab.ai/publish.