Загрузка данных


<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <title>Reflex Trainer Pro</title>
    <style>
        :root {
            --bg-color: #121212;
            --surface-color: #1e1e1e;
            --primary-color: #00f3ff;
            --secondary-color: #bc13fe;
            --success-color: #00ff41;
            --danger-color: #ff0055;
            --text-color: #ffffff;
            --font-main: 'Segoe UI', Roboto, sans-serif;
        }

        * { box-sizing: border-box; margin: 0; padding: 0; user-select: none; -webkit-tap-highlight-color: transparent; }
        
        body {
            background-color: var(--bg-color);
            color: var(--text-color);
            font-family: var(--font-main);
            height: 100vh;
            overflow: hidden;
            display: flex;
            flex-direction: column;
        }

        /* --- ГЛОБАЛЬНЫЙ ПРИЦЕЛ --- */
        #global-crosshair {
            position: fixed;
            top: 0;
            left: 0;
            pointer-events: none;
            z-index: 9999;
            transform: translate(-50%, -50%);
            display: none;
        }

        .cross-dot { 
            width: 6px; height: 6px; 
            background: #00ff00; 
            border-radius: 50%; 
            box-shadow: 0 0 8px #00ff00, 0 0 20px #00ff00;
        }
        .cross-classic { 
            width: 24px; height: 24px; 
            border: 2px solid #00ff00; 
            border-radius: 50%; 
            box-shadow: 0 0 8px #00ff00;
        }
        .cross-sniper { 
            width: 40px; height: 2px; 
            background: #00ff00; 
            position: relative;
            box-shadow: 0 0 8px #00ff00;
        }
        .cross-sniper::after {
            content: ''; position: absolute; top: -19px; left: 19px; 
            width: 2px; height: 40px; background: #00ff00; box-shadow: 0 0 8px #00ff00;
        }

        /* Скрываем стандартный курсор в режиме прицеливания */
        .aiming-mode {
            cursor: none !important;
        }

        /* --- Экраны --- */
        .screen {
            position: absolute; top: 0; left: 0; width: 100%; height: 100%;
            display: none; flex-direction: column; align-items: center; justify-content: center;
            padding: 20px; opacity: 0; transition: opacity 0.3s ease; z-index: 1;
        }
        .screen.active { display: flex; opacity: 1; z-index: 10; }

        h1 { font-size: 2rem; color: var(--primary-color); text-shadow: 0 0 10px var(--primary-color); text-align: center; margin-bottom: 20px; }
        h2 { font-size: 1.2rem; color: #ccc; margin-bottom: 20px; text-align: center; }
        p { margin-bottom: 10px; }

        .btn {
            background: transparent; border: 2px solid var(--primary-color); color: var(--primary-color);
            padding: 12px 24px; font-size: 1rem; margin: 8px 0; cursor: pointer; border-radius: 5px;
            width: 100%; max-width: 300px; text-transform: uppercase; font-weight: bold;
            transition: all 0.2s; box-shadow: 0 0 5px var(--primary-color);
        }
        .btn:hover { background: var(--primary-color); color: #000; box-shadow: 0 0 20px var(--primary-color); }
        .btn-secondary { border-color: var(--secondary-color); color: var(--secondary-color); box-shadow: 0 0 5px var(--secondary-color); }
        .btn-secondary:hover { background: var(--secondary-color); color: white; box-shadow: 0 0 20px var(--secondary-color); }
        .btn-back { position: absolute; top: 20px; left: 20px; width: auto; padding: 8px 16px; font-size: 0.9rem; z-index: 100; }

        .settings-group { margin-bottom: 15px; width: 100%; max-width: 300px; text-align: center; }
        .settings-label { font-size: 0.9rem; color: #888; margin-bottom: 5px; display: block; }
        .options-row { display: flex; gap: 5px; justify-content: center; }
        .opt-btn {
            flex: 1; padding: 8px; border: 1px solid #444; background: #222; color: #aaa;
            cursor: pointer; font-size: 0.8rem; border-radius: 4px; transition: 0.2s;
        }
        .opt-btn.selected { 
            border-color: var(--primary-color); 
            color: var(--primary-color); 
            background: rgba(0, 243, 255, 0.1); 
            box-shadow: 0 0 5px var(--primary-color);
        }

        .hud { position: absolute; top: 20px; right: 20px; text-align: right; font-weight: bold; z-index: 50; pointer-events: none; }
        .record-display { font-size: 0.8rem; color: #888; margin-top: 5px; }

        #accuracy-area {
            width: 100%; max-width: 600px; height: 60vh;
            background-color: var(--surface-color); border: 2px solid #333; border-radius: 10px;
            position: relative; overflow: hidden; 
        }
        
        .target {
            background-color: var(--danger-color); border-radius: 50%; position: absolute;
            box-shadow: 0 0 10px var(--danger-color); transition: transform 0.1s;
            z-index: 10;
        }

        #reaction-zone {
            width: 100%; height: 100%; display: flex; flex-direction: column;
            align-items: center; justify-content: center; cursor: pointer;
            position: absolute; top: 0; left: 0; z-index: 5; transition: background 0.1s;
        }
        .react-waiting { background-color: var(--danger-color) !important; }
        .react-go { background-color: var(--success-color) !important; }
        #reaction-msg { font-size: 3rem; font-weight: bold; text-align: center; color: white; text-shadow: 0 2px 5px rgba(0,0,0,0.5); }
        #reaction-submsg { font-size: 1.2rem; margin-top: 10px; color: rgba(255,255,255,0.8); }

        #color-word { font-size: 3rem; font-weight: 900; margin: 40px 0; text-transform: uppercase; text-align: center; line-height: 1.2; }
        .color-controls { display: flex; gap: 20px; width: 100%; justify-content: center; }
        .btn-color { flex: 1; max-width: 150px; padding: 20px; border: none; border-radius: 8px; font-size: 1.1rem; font-weight: bold; color: white; cursor: pointer; }
        .btn-yes { background-color: var(--success-color); }
        .btn-no { background-color: var(--danger-color); }
        .btn-color:active { transform: scale(0.95); }

        #fail-modal {
            position: fixed; top: 0; left: 0; width: 100%; height: 100%;
            background: rgba(0,0,0,0.9); z-index: 200; display: none;
            flex-direction: column; align-items: center; justify-content: center;
            text-align: center; padding: 20px;
        }
        #fail-modal h2 { color: var(--danger-color); font-size: 2rem; text-shadow: 0 0 20px red; margin-bottom: 20px; }
        #fail-modal p { font-size: 1.5rem; color: white; margin-bottom: 30px; }
    </style>
</head>
<body>

    <!-- ГЛОБАЛЬНЫЙ ПРИЦЕЛ -->
    <div id="global-crosshair"><div class="cross-dot"></div></div>

    <!-- МЕНЮ -->
    <div id="menu" class="screen active">
        <h1>Reflex Trainer Pro</h1>
        
        <div class="settings-group">
            <span class="settings-label">Сложность</span>
            <div class="options-row" id="diff-settings">
                <button class="opt-btn selected" onclick="Game.setDifficulty('easy')">Легко</button>
                <button class="opt-btn" onclick="Game.setDifficulty('medium')">Норм</button>
                <button class="opt-btn" onclick="Game.setDifficulty('hard')">Хард</button>
            </div>
        </div>

        <div class="settings-group">
            <span class="settings-label">Прицел</span>
            <div class="options-row" id="crosshair-settings">
                <button class="opt-btn selected" onclick="Game.setCrosshair('dot')">Точка</button>
                <button class="opt-btn" onclick="Game.setCrosshair('classic')">Классика</button>
                <button class="opt-btn" onclick="Game.setCrosshair('sniper')">Снайпер</button>
            </div>
        </div>

        <div class="settings-group">
            <span class="settings-label">Время</span>
            <div class="options-row" id="time-settings">
                <button class="opt-btn selected" onclick="Game.setTime(30)">30с</button>
                <button class="opt-btn" onclick="Game.setTime(45)">45с</button>
                <button class="opt-btn" onclick="Game.setTime(60)">1м</button>
            </div>
        </div>

        <div style="height: 20px;"></div>

        <button class="btn" onclick="Game.startAccuracy()">Точность</button>
        <button class="btn" onclick="Game.startReaction()">Реакция</button>
        <button class="btn" onclick="Game.startColor()">Цвет</button>
        
        <div style="margin-top: 30px; text-align: center; color: #666; font-size: 0.9rem;">
            <p>Рекорды:</p>
            <div id="menu-records"></div>
        </div>
    </div>

    <!-- ИГРА 1: ТОЧНОСТЬ -->
    <div id="game-accuracy" class="screen">
        <button class="btn btn-secondary btn-back" onclick="Game.toMenu()">Меню</button>
        <div class="hud">
            <div>Время: <span id="acc-time">30</span></div>
            <div>Счет: <span id="acc-score">0</span></div>
            <div class="record-display">Рекорд: <span id="acc-rec">0</span></div>
        </div>
        <h2>Попадай по кругам!</h2>
        <div id="accuracy-area"></div>
    </div>

    <!-- ИГРА 2: РЕАКЦИЯ -->
    <div id="game-reaction" class="screen">
        <button class="btn btn-secondary btn-back" onclick="Game.toMenu()">Меню</button>
        <div id="reaction-zone" onmousedown="Game.handleReactionClick(event)" ontouchstart="Game.handleReactionClick(event)">
            <div id="reaction-msg">Нажми для старта</div>
            <div id="reaction-submsg"></div>
        </div>
        <div style="position: absolute; bottom: 20px; text-align: center; color: #888;">
            Рекорд: <span id="react-rec">---</span> мс
        </div>
    </div>

    <!-- ИГРА 3: ЦВЕТ -->
    <div id="game-color" class="screen">
        <button class="btn btn-secondary btn-back" onclick="Game.toMenu()">Меню</button>
        <div class="hud">
            <div>Время: <span id="col-time">60</span></div>
            <div>Счет: <span id="col-score">0</span></div>
            <div class="record-display">Рекорд: <span id="col-rec">0</span></div>
        </div>
        <h2>Цвет = слову?</h2>
        <div id="color-word">СЛОВО</div>
        <div class="color-controls">
            <button class="btn-color btn-yes" onclick="Game.checkColor(true)">ДА</button>
            <button class="btn-color btn-no" onclick="Game.checkColor(false)">НЕТ</button>
        </div>
    </div>

    <!-- ОКНО ПРОМАХА -->
    <div id="fail-modal">
        <h2>ТЫ ПРОМАЗАЛ!</h2>
        <p>А тебя размазали с калаша...</p>
        <button class="btn" onclick="Game.closeFailModal()">В меню</button>
    </div>

    <script>
        const Game = {
            config: {
                difficulty: 'easy',
                crosshair: 'dot',
                timeLimit: 30
            },
            sizes: {
                easy: { min: 60, max: 90 },
                medium: { min: 40, max: 60 },
                hard: { min: 20, max: 35 }
            },
            state: {
                accuracy: { score: 0, time: 0, timer: null, active: false },
                reaction: { step: 0, results: [], startTime: 0, timeout: null, state: 'idle' },
                color: { score: 0, time: 0, timer: null, active: false, isMatch: false }
            },
            records: { accuracy: 0, reaction: null, color: 0 },
            colorsList: [
                { name: 'КРАСНЫЙ', hex: '#ff0055' },
                { name: 'СИНИЙ', hex: '#00f3ff' },
                { name: 'ЗЕЛЕНЫЙ', hex: '#00ff41' },
                { name: 'ЖЕЛТЫЙ', hex: '#ffee00' }
            ],

            init() {
                this.loadRecords();
                this.updateMenuRecords();
                
                // === ВАШ КОД: Слежение прицела за мышью ===
                document.addEventListener('mousemove', (e) => {
                    const crosshair = document.getElementById('global-crosshair');
                    crosshair.style.left = e.clientX + 'px';
                    crosshair.style.top = e.clientY + 'px';
                });
                // ===========================================

                // Промах по полю
                document.getElementById('accuracy-area').addEventListener('mousedown', (e) => {
                    if(this.state.accuracy.active && e.target.id === 'accuracy-area') {
                        this.triggerFail();
                    }
                });
            },

            // === ВАШ КОД: Включение прицела ===
            showCrosshair(type) {
                const crosshair = document.getElementById('global-crosshair');
                crosshair.style.display = 'block';
                document.body.classList.add('aiming-mode');
                // Смена типа прицела
                const inner = crosshair.querySelector('div');
                inner.className = 'cross-' + (type || this.config.crosshair);
            },
            // =================================

            hideCrosshair() {
                document.getElementById('global-crosshair').style.display = 'none';
                document.body.classList.remove('aiming-mode');
            },

            setDifficulty(level) {
                this.config.difficulty = level;
                this.updateSettingsUI('diff-settings', level);
            },
            setCrosshair(type) {
                this.config.crosshair = type;
                this.updateSettingsUI('crosshair-settings', type);
                // Если прицел сейчас виден — обновляем его вид
                if(document.getElementById('global-crosshair').style.display === 'block') {
                    this.showCrosshair(type);
                }
            },
            setTime(sec) {
                this.config.timeLimit = sec;
                this.updateSettingsUI('time-settings', sec);
            },
            
            updateSettingsUI(parentId, value) {
                const buttons = document.getElementById(parentId).querySelectorAll('.opt-btn');
                buttons.forEach(btn => {
                    btn.classList.remove('selected');
                    const match = btn.getAttribute('onclick').match(/'([^']+)'/);
                    if (match && match[1] == value) btn.classList.add('selected');
                });
            },

            showScreen(id) {
                document.querySelectorAll('.screen').forEach(s => s.classList.remove('active'));
                document.getElementById(id).classList.add('active');
            },
            toMenu() {
                this.stopAll();
                this.updateMenuRecords();
                this.showScreen('menu');
            },
            stopAll() {
                clearInterval(this.state.accuracy.timer);
                clearInterval(this.state.color.timer);
                clearTimeout(this.state.reaction.timeout);
                this.state.accuracy.active = false;
                this.state.color.active = false;
                this.state.reaction.state = 'idle';
                this.hideCrosshair();
                document.getElementById('reaction-zone').className = '';
            },

            loadRecords() {
                const saved = localStorage.getItem('reflexGameRecordsPro');
                if (saved) this.records = JSON.parse(saved);
            },
            saveRecord(type, value) {
                let updated = false;
                if (type === 'accuracy' && value > this.records.accuracy) {
                    this.records.accuracy = value; updated = true;
                } else if (type === 'color' && value > this.records.color) {
                    this.records.color = value; updated = true;
                } else if (type === 'reaction') {
                    if (this.records.reaction === null || value < this.records.reaction) {
                        this.records.reaction = Math.round(value); updated = true;
                    }
                }
                if (updated) localStorage.setItem('reflexGameRecordsPro', JSON.stringify(this.records));
            },
            updateMenuRecords() {
                const r = this.records;
                document.getElementById('menu-records').innerHTML = `
                    Точность: ${r.accuracy} | Реакция: ${r.reaction ? r.reaction+'мс' : 'Нет'} | Цвет: ${r.color}
                `;
            },

            triggerFail() {
                this.state.accuracy.active = false;
                clearInterval(this.state.accuracy.timer);
                document.getElementById('fail-modal').style.display = 'flex';
            },
            closeFailModal() {
                document.getElementById('fail-modal').style.display = 'none';
                this.toMenu();
            },

            // === ИГРА 1: ТОЧНОСТЬ ===
            startAccuracy() {
                this.showScreen('game-accuracy');
                this.state.accuracy.score = 0;
                this.state.accuracy.time = this.config.timeLimit;
                this.state.accuracy.active = true;
                
                document.getElementById('acc-score').innerText = '0';
                document.getElementById('acc-time').innerText = this.config.timeLimit;
                document.getElementById('acc-rec').innerText = this.records.accuracy;
                document.getElementById('accuracy-area').innerHTML = '';

                // === ВАШ КОД: Включаем прицел при входе в игру ===
                this.showCrosshair(this.config.crosshair);
                // ================================================

                this.spawnTarget();

                this.state.accuracy.timer = setInterval(() => {
                    this.state.accuracy.time--;
                    document.getElementById('acc-time').innerText = this.state.accuracy.time;
                    if (this.state.accuracy.time <= 0) this.endAccuracy();
                }, 1000);
            },

            spawnTarget() {
                if (!this.state.accuracy.active) return;
                const area = document.getElementById('accuracy-area');
                const target = document.createElement('div');
                target.className = 'target';
                
                const range = this.sizes[this.config.difficulty];
                const size = Math.floor(Math.random() * (range.max - range.min + 1)) + range.min;
                target.style.width = size + 'px';
                target.style.height = size + 'px';
                
                const maxX = area.clientWidth - size;
                const maxY = area.clientHeight - size;
                target.style.left = (Math.random() * maxX) + 'px';
                target.style.top = (Math.random() * maxY) + 'px';

                const hitHandler = (e) => {
                    e.stopPropagation();
                    if(e.type === 'touchstart') e.preventDefault();
                    this.state.accuracy.score++;
                    document.getElementById('acc-score').innerText = this.state.accuracy.score;
                    target.remove();
                    this.spawnTarget();
                };
                target.onmousedown = hitHandler;
                target.ontouchstart = hitHandler;
                area.appendChild(target);
            },

            endAccuracy() {
                this.state.accuracy.active = false;
                clearInterval(this.state.accuracy.timer);
                this.saveRecord('accuracy', this.state.accuracy.score);
                alert(`Время вышло! Счет: ${this.state.accuracy.score}`);
                this.toMenu();
            },

            // === ИГРА 2: РЕАКЦИЯ ===
            startReaction() {
                this.showScreen('game-reaction');
                this.state.reaction.step = 0;
                this.state.reaction.results = [];
                this.state.reaction.state = 'idle';
                this.updateReactionUI();
            },
            updateReactionUI() {
                document.getElementById('react-rec').innerText = this.records.reaction || '---';
            },
            handleReactionClick(e) {
                if(e) e.preventDefault();
                const zone = document.getElementById('reaction-zone');
                const msg = document.getElementById('reaction-msg');
                const sub = document.getElementById('reaction-submsg');
                const st = this.state.reaction;

                if (st.state === 'idle' || st.state === 'result') {
                    if (st.step >= 5) { this.endReaction(); return; }
                    st.state = 'waiting';
                    zone.className = 'react-waiting';
                    msg.innerText = 'Жди...'; sub.innerText = '';
                    const delay = 2000 + Math.random() * 3000;
                    st.timeout = setTimeout(() => {
                        st.state = 'ready';
                        st.startTime = Date.now();
                        zone.className = 'react-go';
                        msg.innerText = 'ЖМИ!';
                    }, delay);
                    return;
                }
                if (st.state === 'waiting') {
                    clearTimeout(st.timeout);
                    st.state = 'result';
                    zone.className = '';
                    zone.style.backgroundColor = '#ffa500';
                    msg.innerText = 'Фальстарт!';
                    sub.innerText = 'Нажми, чтобы начать заново';
                    st.step = 0; st.results = [];
                    return;
                }
                if (st.state === 'ready') {
                    const time = Date.now() - st.startTime;
                    st.results.push(time);
                    st.step++;
                    st.state = 'result';
                    zone.className = '';
                    if(st.step < 5) {
                        msg.innerText = `${time} мс`;
                        sub.innerText = `Нажми для след. (${st.step}/5)`;
                    } else {
                        this.endReaction();
                    }
                }
            },
            endReaction() {
                const res = this.state.reaction.results;
                if(res.length === 0) return;
                const avg = Math.round(res.reduce((a,b)=>a+b,0) / res.length);
                this.saveRecord('reaction', avg);
                document.getElementById('reaction-msg').innerText = `ИТОГ: ${avg} мс`;
                document.getElementById('reaction-submsg').innerText = `Попытки: ${res.join(', ')}`;
                this.state.reaction.state = 'finished';
            },

            // === ИГРА 3: ЦВЕТ ===
            startColor() {
                this.showScreen('game-color');
                this.state.color.score = 0;
                this.state.color.time = this.config.timeLimit;
                this.state.color.active = true;
                document.getElementById('col-score').innerText = '0';
                document.getElementById('col-time').innerText = this.config.timeLimit;
                document.getElementById('col-rec').innerText = this.records.color;
                this.nextColorRound();
                this.state.color.timer = setInterval(() => {
                    this.state.color.time--;
                    document.getElementById('col-time').innerText = this.state.color.time;
                    if (this.state.color.time <= 0) this.endColor();
                }, 1000);
            },
            nextColorRound() {
                if (!this.state.color.active) return;
                const wordObj = this.colorsList[Math.floor(Math.random() * this.colorsList.length)];
                const shouldMatch = Math.random() > 0.5;
                let finalColorHex;
                if(shouldMatch) {
                    finalColorHex = wordObj.hex;
                } else {
                    const others = this.colorsList.filter(c => c.name !== wordObj.name);
                    finalColorHex = others[Math.floor(Math.random() * others.length)].hex;
                }
                this.state.color.isMatch = (wordObj.hex === finalColorHex);
                const el = document.getElementById('color-word');
                el.innerText = wordObj.name;
                el.style.color = finalColorHex;
            },
            checkColor(userSaidYes) {
                if (!this.state.color.active) return;
                if (userSaidYes === this.state.color.isMatch) {
                    this.state.color.score++;
                } else {
                    this.state.color.score = Math.max(0, this.state.color.score - 1);
                }
                document.getElementById('col-score').innerText = this.state.color.score;
                this.nextColorRound();
            },
            endColor() {
                this.state.color.active = false;
                clearInterval(this.state.color.timer);
                this.saveRecord('color', this.state.color.score);
                alert(`Время вышло! Счет: ${this.state.color.score}`);
                this.toMenu();
            }
        };

        window.onload = () => Game.init();
    </script>
</body>
</html>
//JAVA SCRIPT
document.addEventListener('mousemove', (e) => {
    const crosshair = document.getElementById('global-crosshair');
    crosshair.style.left = e.clientX + 'px';
    crosshair.style.top = e.clientY + 'px';
});
showCrosshair(type) 
{
    const crosshair = document.getElementById('global-crosshair');
    crosshair.style.display = 'block';
    document.body.classList.add('aiming-mode');
    const inner = crosshair.querySelector('div');
    inner.className = 'cross-' + (type || this.config.crosshair);
   
};
 this.showCrosshair(this.config.crosshair);