<html>
<head>
<meta charset="UTF-8">
<title>Кибершамыга</title>
<style>
body { margin: 0; overflow: hidden; font-family: Arial, sans-serif; }
canvas { display: block; }
#menu {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.7);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
color: white;
}
#menu h1 {
font-size: 4em;
margin-bottom: 30px;
}
#playButton {
font-size: 1.5em;
padding: 10px 20px;
cursor: pointer;
}
#hud, #health-bar, #crosshair {
display: none;
}
#hud {
position: absolute;
top: 10px;
left: 10px;
color: white;
font-size: 18px;
}
#health-bar {
position: absolute;
bottom: 10px;
left: 10px;
width: 200px;
height: 20px;
background-color: red;
}
#health {
height: 100%;
background-color: green;
width: 100%;
text-align: center;
color: white;
font-weight: bold;
line-height: 20px;
}
#crosshair {
position: absolute;
top: 50%;
left: 50%;
width: 20px;
height: 20px;
background-color: transparent;
border: 2px solid red;
border-radius: 50%;
transform: translate(-50%, -50%);
pointer-events: none;
}
#death-modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.8); /* затемненный фон */
display: none; /* Скрыто по умолчанию */
justify-content: center;
align-items: center;
}

#death-modal-content {
background-color: #333;
padding: 40px;
border-radius: 10px;
text-align: center;
color: white;
}

#death-modal-content h2 {
margin-bottom: 30px;
}

#death-modal-content button {
font-size: 1.2em;
padding: 10px 30px;
margin: 10px;
cursor: pointer;
}
  #skins-modal {
       position: fixed;
       top: 0;
       left: 0;
       width: 100%;
       height: 100%;
       background-color: rgba(0, 0, 0, 0.8);
       display: none;
       justify-content: center;
       align-items: center;
   }
   #skins-modal-content {
       background-color: #333;
       padding: 40px;
       border-radius: 10px;
       text-align: center;
       color: white;
   }
   .skin-item {
    margin-bottom: 10px;
}
.skin-item span {
    margin-right: 10px;
}
#version {
position: fixed;
bottom: 10px;
right: 10px;
color: white;
font-size: 14px;
}
</style>
</head>
<body>
<!-- Меню -->
<div id="menu">
<h1>Кибершамыга</h1>
<button id="playButton">Играть</button>
<span id="previous-kills"> Kills record: <span id="kills-display">0</span></span>
<button id="skinsButton">Скины</button>
</div>
<div id="skins-modal">
    <div id="skins-modal-content">
        <h2>Выбор скинов</h2>
        <div id="skins-list">
            <!-- Здесь будут отображаться скины -->
        </div>
        <button id="closeSkinsButton">Закрыть</button>
    </div>
</div>
<div id="death-modal">
<div id="death-modal-content">
<h2>Вы погибли!</h2>
<button id="restartButton">Начать заново</button>
<button id="returnToMenuButton">Вернуться в меню</button>
</div>
</div>

<!-- HUD (Heads-Up Display) -->
<div id="hud">
    <div>Время: <span id="time">00:00</span></div>
    <div>Киллы: <span id="kills">0</span></div>
    <div>Патроны: <span id="ammo">10/∞</span></div>
</div>

<!-- Полоса здоровья -->
<div id="health-bar">
<div id="health">100%</div>
</div>

<!-- Прицел -->
<div id="crosshair"></div>

<!-- Подключаем библиотеку Three.js с CDN -->
<script src="https://cdn.jsdelivr.net/npm/three@0.148/build/three.min.js"></script>
<script>
let scene, camera, renderer, player;
let health = 100;
let bulletSpeed = 0.5;
let gameStartTime;
let kills = 0;
let killsRecord = 0;
let muzzleFlash; // Дульная вспышка
let muzzleFlashDuration = 0;
let muzzleFlashEndTime = 0;
let magazineSize = 10;        // Размер обоймы
let currentAmmo = magazineSize; // Текущее количество патронов
let isReloading = false;      // Флаг перезарядки
let canShoot = true;
let isGameActive = false; // Флаг состояния игры

let skins = {
    default: {
        name: "Стандартный",
        unlocked: true,
        model: null // Модель пистолета для этого скина
    },
    golden: {
        name: "Золотой",
        unlocked: false,
        model: null // Модель пистолета для этого скина
    }
};

let selectedSkin = 'default';


let reloadAnimationProgress = 0;
let isAnimatingReload = false;
const reloadAnimationDuration = 1.5; // Длительность анимации перезарядки
const CHUNK_SIZE = 100; // Размер каждого чанка
const chunks = {}; // Объект для хранения сгенерированных чанков

const enemies = [];
let enemySpeed = 0.05; // Начальная скорость врагов
let maxEnemies = 5;    // Начальное максимальное количество врагов
let lastDifficultyIncreaseTime; // Время последнего увеличения сложности
const bullets = [];
const trees = [];
  const skinsButton = document.getElementById('skinsButton');
   const skinsModal = document.getElementById('skins-modal');
   const closeSkinsButton = document.getElementById('closeSkinsButton');

   skinsButton.addEventListener('click', function(event) {
       event.stopPropagation();
       skinsModal.style.display = 'flex'; // Показываем меню скинов
   });

   closeSkinsButton.addEventListener('click', function(event) {
       event.stopPropagation();
       skinsModal.style.display = 'none'; // Скрываем меню скинов
   });

let gunGroup, gunBody, magazine;

function generateChunk(chunkX, chunkZ) {
    const chunkKey = `${chunkX}_${chunkZ}`;
    if (chunks[chunkKey]) {
        return; // Чанк уже сгенерирован
    }

    const chunk = new THREE.Group();

    // Генерируем землю для чанка
    const floorGeometry = new THREE.PlaneGeometry(CHUNK_SIZE, CHUNK_SIZE);
    const floorMaterial = new THREE.MeshBasicMaterial({ color: 0x228B22 });
    const floor = new THREE.Mesh(floorGeometry, floorMaterial);
    floor.rotation.x = -Math.PI / 2;
    floor.position.set(chunkX * CHUNK_SIZE + CHUNK_SIZE / 2, 0, chunkZ * CHUNK_SIZE + CHUNK_SIZE / 2);
    chunk.add(floor);

    // Генерируем деревья в чанке
    for (let i = 0; i < 10; i++) {
        const tree = createTree();
        tree.position.set(
            chunkX * CHUNK_SIZE + Math.random() * CHUNK_SIZE,
            0,
            chunkZ * CHUNK_SIZE + Math.random() * CHUNK_SIZE
        );
        chunk.add(tree);
        trees.push(tree);
    }

    // Генерируем врагов в чанке
    createEnemiesInChunk(chunkX, chunkZ, chunk);

    // Добавляем чанк в сцену и сохраняем его
    scene.add(chunk);
    chunks[chunkKey] = chunk;
}
function createEnemiesInChunk(chunkX, chunkZ, chunkGroup) {
    const numEnemies = 3; // Количество врагов в чанке

    for (let i = 0; i < numEnemies; i++) {
        const enemy = createEnemy();

        // Устанавливаем позицию врага внутри чанка
        enemy.position.set(
            chunkX * CHUNK_SIZE + Math.random() * CHUNK_SIZE,
            1,
            chunkZ * CHUNK_SIZE + Math.random() * CHUNK_SIZE
        );

        enemies.push(enemy);
        chunkGroup.add(enemy); // Добавляем врага в чанк
    }
}
function updateChunks() {
    const playerChunkX = Math.floor(player.position.x / CHUNK_SIZE);
    const playerChunkZ = Math.floor(player.position.z / CHUNK_SIZE);

    const renderDistance = 2; // Количество чанков вокруг игрока для генерации

    const neededChunks = {};

    for (let x = playerChunkX - renderDistance; x <= playerChunkX + renderDistance; x++) {
        for (let z = playerChunkZ - renderDistance; z <= playerChunkZ + renderDistance; z++) {
            const chunkKey = `${x}_${z}`; // Использование шаблонных строк
            generateChunk(x, z);
            neededChunks[chunkKey] = true;
        }
    }

    // Удаление дальних чанков
    for (let key in chunks) {
        if (!neededChunks[key]) {
            // Удаляем деревья из массива
            const chunk = chunks[key];
            chunk.traverse(function(child) {
                if (child.isMesh && child.geometry && child.geometry.type === "CylinderGeometry") {
                    // Предполагаем, что дерево имеет геометрию цилиндра (ствол)
                    const index = trees.indexOf(child);
                    if (index > -1) {
                        trees.splice(index, 1);
                    }
                }
                // Проверяем, является ли объект врагом
                if (child.userData.isEnemy) {
                    const index = enemies.indexOf(child);
                    if (index > -1) {
                        enemies.splice(index, 1);
                    }
                }
            });

            // Удаляем чанк из сцены и объекта
            scene.remove(chunk);
            delete chunks[key];
        }
    }
}

function updateGunSkin() {
    if (selectedSkin === 'golden') {
        gunBody.material.color.set(0xFFD700); // Золотой цвет
    } else {
        gunBody.material.color.set(0x333333); // Стандартный цвет
    }
}

function updateSkinsMenu() {
    const skinsList = document.getElementById('skins-list');
    skinsList.innerHTML = ''; // Очищаем список

    for (let key in skins) {
        let skin = skins[key];

        let skinDiv = document.createElement('div');
        skinDiv.className = 'skin-item';

        let skinName = document.createElement('span');
        skinName.textContent = skin.name;

        let selectButton = document.createElement('button');
        selectButton.textContent = 'Выбрать';
        selectButton.disabled = !skin.unlocked;
        selectButton.addEventListener('click', function () {
            selectedSkin = key;
            skinsModal.style.display = 'none';
            updateGunSkin();
        });

        if (!skin.unlocked) {
            let lockSpan = document.createElement('span');
            lockSpan.textContent = '🔒 Требуется 1000 киллов';
            skinDiv.appendChild(lockSpan);
        }

        skinDiv.appendChild(skinName);
        skinDiv.appendChild(selectButton);
        skinsList.appendChild(skinDiv);
    }
}

function saveSkins() {
    localStorage.setItem('skins', JSON.stringify({
        goldenUnlocked: skins.golden.unlocked
    }));
}

// Функция для загрузки информации о скинах из localStorage
function loadSkins() {
    let storedSkins = localStorage.getItem('skins');
    if (storedSkins) {
        let data = JSON.parse(storedSkins);
        skins.golden.unlocked = data.goldenUnlocked || false;
    }
}

// Вызываем loadSkins() после объявления переменных
loadSkins();


function getRandomSpawnPosition() {
    const playerChunkX = Math.floor(player.position.x / CHUNK_SIZE);
    const playerChunkZ = Math.floor(player.position.z / CHUNK_SIZE);

    const position = new THREE.Vector3(
        (playerChunkX + (Math.random() - 0.5)) * CHUNK_SIZE,
        1.6,
        (playerChunkZ + (Math.random() - 0.5)) * CHUNK_SIZE
    );

    return position;
}

function reload() {
    if (isReloading || currentAmmo === magazineSize) {
        return; // Уже выполняется перезарядка или обойма полная
    }

    isReloading = true;
    isAnimatingReload = true;
    reloadAnimationProgress = 0;
    updateHUD();
}

function showDeathModal() {
const deathModal = document.getElementById('death-modal');
deathModal.style.display = 'flex';
}

function saveProgress() {
    localStorage.setItem('killsRecord', killsRecord);
}



function loadProgress() {
const storedKillsRecord = localStorage.getItem('killsRecord');
if (storedKillsRecord) {
killsRecord = parseInt(storedKillsRecord, 10);
}
}

function updateMenu() {
    const killsDisplay = document.getElementById('kills-display');
    killsDisplay.textContent = killsRecord;

    // Обновляем список скинов
    updateSkinsMenu();
}


// Call this function when loading the page to show the previous kills
loadProgress();
updateMenu();


// Функция для обновления HUD
function updateHUD() {
    const timeElement = document.getElementById('time');
    const killsElement = document.getElementById('kills');
    const ammoElement = document.getElementById('ammo');

    const currentTime = new Date().getTime();
    const elapsedTime = Math.floor((currentTime - gameStartTime) / 1000);
    const minutes = Math.floor(elapsedTime / 60);
    const seconds = elapsedTime % 60;

    // Используем шаблонные строки (template literals) с обратными кавычками
    timeElement.textContent = `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
    killsElement.textContent = kills;

    // Обновляем отображение патронов
    ammoElement.textContent = isReloading ? 'Перезарядка...' : `${currentAmmo}/${String.fromCharCode(8734)}`; // ∞ символ
}






function updateHealthBar() {
const healthBar = document.getElementById('health');
healthBar.style.width = health + '%';
healthBar.textContent = health + '%';
}

function takeDamage(amount) {
health -= amount;
if (health <= 0) {
health = 0;
updateHealthBar();
endGame();
showDeathModal();
} else {
updateHealthBar();
}
}


function createTree() {
const trunkGeometry = new THREE.CylinderGeometry(0.2, 0.2, 2);
const trunkMaterial = new THREE.MeshBasicMaterial({ color: 0x8B4513 });
const trunk = new THREE.Mesh(trunkGeometry, trunkMaterial);

const leavesGeometry = new THREE.ConeGeometry(1, 2, 8);
const leavesMaterial = new THREE.MeshBasicMaterial({ color: 0x228B22 });
const leaves = new THREE.Mesh(leavesGeometry, leavesMaterial);
leaves.position.y = 2;

const tree = new THREE.Group();
tree.add(trunk);
tree.add(leaves);

return tree;
}

function createEnemy(position) {
    // Создаем объект врага для управления позицией
    const enemy = new THREE.Object3D();
    enemy.position.y = 1; // Установка высоты

    // Создаем визуальную модель врага (plane)
    const enemyTexture = new THREE.TextureLoader().load('https://i.postimg.cc/QC6j7xGC/photo-2024-05-28-17-49-00.jpg');
    const enemyMaterial = new THREE.MeshBasicMaterial({
        map: enemyTexture,
        transparent: true,
        side: THREE.DoubleSide
    });
    const enemyGeometry = new THREE.PlaneGeometry(2, 2);
    const enemyMesh = new THREE.Mesh(enemyGeometry, enemyMaterial);
    enemyMesh.userData.isEnemyMesh = true; // Помечаем для идентификации

    enemy.add(enemyMesh);

    // Создаем и добавляем меч к визуальной модели
    const sword = createSword();
    sword.position.set(0.5, -0.5, 0);
    sword.userData.initialRotation = sword.rotation.clone();
    sword.userData.isSword = true; // Помечаем меч
    enemyMesh.add(sword);

    // Устанавливаем позицию врага
    if (position) {
        enemy.position.copy(position);
    } else {
        // Если позиция не задана, спавним врага в случайной позиции
        let enemyPosition;
        do {
            enemyPosition = new THREE.Vector3(
                (Math.random() - 0.5) * 100,
                1,
                (Math.random() - 0.5) * 100
            );
        } while (enemyPosition.distanceTo(player.position) < 10);
        enemy.position.copy(enemyPosition);
    }

    // Помечаем врага для идентификации при удалении
    enemy.userData.isEnemy = true;

    enemies.push(enemy);
    scene.add(enemy);

    return enemy;
}


function createSword() {
    const bladeGeometry = new THREE.BoxGeometry(0.05, 1, 0.2);
    const bladeMaterial = new THREE.MeshBasicMaterial({ color: 0xffffff });
    const blade = new THREE.Mesh(bladeGeometry, bladeMaterial);
    blade.position.set(0, 0.5, 0);

    const hiltGeometry = new THREE.CylinderGeometry(0.05, 0.05, 0.3);
    const hiltMaterial = new THREE.MeshBasicMaterial({ color: 0x8B4513 });
    const hilt = new THREE.Mesh(hiltGeometry, hiltMaterial);
    hilt.position.set(0, -0.15, 0);

    const sword = new THREE.Group();
    sword.add(blade);
    sword.add(hilt);

    sword.rotation.order = 'YXZ'; // Устанавливаем порядок вращений, если необходимо

    return sword;
}

 function shoot() {
       if (isReloading || !canShoot) {
           return; // Нельзя стрелять во время перезарядки или если предыдущий выстрел еще не завершен
       }

       canShoot = false; // Блокируем возможность стрельбы до следующего кадра

       if (currentAmmo > 0) {
           // Уменьшаем количество патронов
           currentAmmo--;
           updateHUD();

           // Создаем и добавляем пулю
           const bulletGeometry = new THREE.SphereGeometry(0.1, 8, 8);
           const bulletMaterial = new THREE.MeshBasicMaterial({ color: 0xffff00 });
           const bullet = new THREE.Mesh(bulletGeometry, bulletMaterial);

           const cameraWorldPosition = new THREE.Vector3();
           camera.getWorldPosition(cameraWorldPosition);

           const cameraWorldDirection = new THREE.Vector3();
           camera.getWorldDirection(cameraWorldDirection);

           bullet.position.copy(cameraWorldPosition).add(cameraWorldDirection.multiplyScalar(1));

           bullet.userData.direction = cameraWorldDirection.clone();

           scene.add(bullet);
           bullets.push(bullet);

           // Показываем дульную вспышку
           muzzleFlash.visible = true;
           muzzleFlash.material.opacity = 1;
           const currentTime = performance.now() / 1000; // Время в секундах
           muzzleFlashEndTime = currentTime + 0.05; // Отображать вспышку в течение 0.05 секунд
       } else {
           // Патроны закончились, инициируем перезарядку
           reload();
       }

       // Разрешаем стрельбу снова в следующем кадре
       setTimeout(() => {
           canShoot = true;
       }, 0);
   }

function initScene() {
    // Создаем сцену, камеру и рендерер
    scene = new THREE.Scene();
    scene.background = new THREE.Color(0x87CEEB);

    camera = new THREE.PerspectiveCamera(
        75,
        window.innerWidth / window.innerHeight,
        0.1,
        1000
    );

    renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);

    // Добавляем плоскость (землю)
    const floorGeometry = new THREE.PlaneGeometry(200, 200);
    const floorMaterial = new THREE.MeshBasicMaterial({ color: 0x228B22 });
    const floor = new THREE.Mesh(floorGeometry, floorMaterial);
    floor.rotation.x = -Math.PI / 2;
    scene.add(floor);

    // Создаем несколько деревьев
    for (let i = 0; i < 20; i++) {
        const tree = createTree();
        tree.position.set(
            (Math.random() - 0.5) * 100,
            0,
            (Math.random() - 0.5) * 100
        );
        scene.add(tree);
        trees.push(tree);
    }

    // Создаем игрока
    player = new THREE.Object3D();
    player.position.set(0, 1.6, 0);
    scene.add(player);
    player.add(camera);

    // Создаем группу для пистолета
    gunGroup = new THREE.Group();

    // Создаем основную часть пистолета
    const gunGeometry = new THREE.BoxGeometry(0.1, 0.1, 0.5);
    const gunMaterial = new THREE.MeshBasicMaterial({ color: 0x333333 });

    // Инициализируем глобальную переменную gunBody
    gunBody = new THREE.Mesh(gunGeometry, gunMaterial);
    gunBody.position.set(0, 0, 0);
    gunGroup.add(gunBody);

    // Создаем рукоятку
    const handleGeometry = new THREE.BoxGeometry(0.05, 0.2, 0.1);
    const handleMaterial = new THREE.MeshBasicMaterial({ color: 0x111111 });
    const handle = new THREE.Mesh(handleGeometry, handleMaterial);
    handle.position.set(0, -0.15, -0.2);
    gunGroup.add(handle);

    // Создаем обойму
    const magazineGeometry = new THREE.BoxGeometry(0.04, 0.1, 0.1);
    const magazineMaterial = new THREE.MeshBasicMaterial({ color: 0x555555 });
    magazine = new THREE.Mesh(magazineGeometry, magazineMaterial);
    magazine.position.set(0, -0.25, -0.2);
    gunGroup.add(magazine);

    // Добавляем дульную вспышку
    const muzzleFlashGeometry = new THREE.ConeGeometry(0.1, 0.2, 4);
    const muzzleFlashMaterial = new THREE.MeshBasicMaterial({
        color: 0xffaa00,
        transparent: true, // Позволяет изменять прозрачность
    });
    muzzleFlash = new THREE.Mesh(muzzleFlashGeometry, muzzleFlashMaterial);
    muzzleFlash.position.set(0, 0, -0.25); // Позиционирование вспышки на конце дула
    muzzleFlash.rotation.x = Math.PI / 2; // Поворот вспышки вперед
    muzzleFlash.visible = false; // Скрываем вспышку по умолчанию
    gunBody.add(muzzleFlash);

    // Добавляем вызов функции для обновления скина пистолета
    updateGunSkin();

    // Добавляем группу пистолета к камере
    gunGroup.position.set(0.2, -0.2, -0.5);
    camera.add(gunGroup);
}

// Обработчики событий клавиатуры
let moveForward = false;
let moveBackward = false;
let moveLeft = false;
let moveRight = false;

const velocity = new THREE.Vector3();
const direction = new THREE.Vector3();

document.addEventListener('keydown', function(event) {
    if (!isGameActive) return; // Если игра не активна, игнорируем нажатия клавиш

    switch (event.code) {
        case 'KeyW':
            moveForward = true;
            break;
        case 'KeyS':
            moveBackward = true;
            break;
        case 'KeyA':
            moveLeft = true;
            break;
        case 'KeyD':
            moveRight = true;
            break;
        case 'KeyR':
            reload();
            break;
    }
});

document.addEventListener('keyup', function(event) {
    if (!isGameActive) return; // Если игра не активна, игнорируем отпускания клавиш

    switch (event.code) {
        case 'KeyW':
            moveForward = false;
            break;
        case 'KeyS':
            moveBackward = false;
            break;
        case 'KeyA':
            moveLeft = false;
            break;
        case 'KeyD':
            moveRight = false;
            break;
    }
});

// Стрельба по клику мыши
document.addEventListener('mousedown', function(event) {
    if (isGameActive && isLocked && event.button === 0) {
        shoot();
    }
});
// Управление камерой с помощью мыши
let isLocked = false;

const pointerLockChange = function () {
    isLocked = document.pointerLockElement === document.body;
};

document.addEventListener('pointerlockchange', pointerLockChange, false);

document.addEventListener('click', function () {
if (!isLocked) {
document.body.requestPointerLock();
}
}, false);

document.addEventListener('mousemove', function (event) {
    if (isLocked && isGameActive) {
        const movementX = event.movementX || event.mozMovementX || event.webkitMovementX || 0;
        const movementY = event.movementY || event.mozMovementY || event.webkitMovementY || 0;

        player.rotation.y -= movementX * 0.002;
        camera.rotation.x -= movementY * 0.002;
        camera.rotation.x = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, camera.rotation.x));
    }
}, false);

// Анимация
let prevTime = performance.now();
function animate() {
    requestAnimationFrame(animate);

    const time = performance.now();
    const delta = (time - prevTime) / 1000;

    // Сохраняем предыдущую позицию игрока перед перемещением
    const prevPosition = player.position.clone();

    // Обновляем скорость и направление движения игрока
    velocity.x -= velocity.x * 10.0 * delta;
    velocity.z -= velocity.z * 10.0 * delta;

    direction.z = Number(moveForward) - Number(moveBackward);
    direction.x = Number(moveLeft) - Number(moveRight);
    direction.normalize();

    if (moveForward || moveBackward) velocity.z -= direction.z * 150.0 * delta;
    if (moveLeft || moveRight) velocity.x -= direction.x * 150.0 * delta;

    // Перемещаем игрока
    player.translateX(velocity.x * delta);
    player.translateZ(velocity.z * delta);

    // Обновляем чанки в зависимости от позиции игрока
    updateChunks();

    // Обработка столкновений с деревьями
    const playerCollider = new THREE.Sphere(player.position.clone(), 0.5);
    let collisionDetected = false;

    for (let i = 0; i < trees.length; i++) {
        const tree = trees[i];
        const treeBox = new THREE.Box3().setFromObject(tree);
        if (treeBox.intersectsSphere(playerCollider)) {
            collisionDetected = true;
            break;
        }
    }

    if (collisionDetected) {
        player.position.copy(prevPosition);
    }

    // Обновляем положение пуль и проверяем столкновения
    if (isGameActive) {
        for (let i = bullets.length - 1; i >= 0; i--) {
            const bullet = bullets[i];
            bullet.position.add(bullet.userData.direction.clone().multiplyScalar(bulletSpeed));

            // Проверяем столкновение пули с врагом
            for (let j = enemies.length - 1; j >= 0; j--) {
                const enemy = enemies[j];
                if (bullet.position.distanceTo(enemy.position) < 1) {
                    // Удаляем врага и пулю
                    scene.remove(enemy);
                    enemies.splice(j, 1);

                    scene.remove(bullet);
                    bullets.splice(i, 1);

                    kills++;
                    updateHUD();

                    break; // Выходим из цикла врагов
                }
            }

            if (bullet.position.length() > 2000) {
                scene.remove(bullet);
                bullets.splice(i, 1);
            }
        }
    }

    // Обновляем положение врагов и обрабатываем их поведение
    if (isGameActive) {
        enemies.forEach(function(enemy) {
            const prevEnemyPosition = enemy.position.clone();

            // Вычисляем направление к игроку
            let enemyDirection = new THREE.Vector3();
            enemyDirection.subVectors(player.position.clone().setY(0), enemy.position.clone().setY(0));
            enemyDirection.normalize();

            // Перемещаем врага с учетом текущей скорости
            enemy.position.addScaledVector(enemyDirection, enemySpeed);
            enemy.position.y = 1; // Фиксируем высоту врага

            // Поворачиваем визуальную модель врага к камере
            enemy.traverse(function(child) {
                if (child.userData.isEnemyMesh) {
                    const enemyPositionWorld = new THREE.Vector3();
                    child.getWorldPosition(enemyPositionWorld);
                    const cameraPositionWorld = new THREE.Vector3();
                    camera.getWorldPosition(cameraPositionWorld);

                    const dx = cameraPositionWorld.x - enemyPositionWorld.x;
                    const dz = cameraPositionWorld.z - enemyPositionWorld.z;
                    const angle = Math.atan2(dx, dz);

                    child.rotation.set(0, angle, 0);
                }
            });

            // Проверка столкновения с игроком
            if (enemy.position.distanceTo(player.position) < 1) {
                takeDamage(10);
            }
        });
    }

    // Обновляем информацию на экране
    updateHUD();

    // Анимация дульной вспышки
    const currentTimeSec = time / 1000; // Время в секундах
    if (currentTimeSec >= muzzleFlashEndTime) {
        muzzleFlash.visible = false;
    } else {
        muzzleFlash.visible = true;
        // Вычисляем оставшееся время для эффекта затухания
        const remainingTime = muzzleFlashEndTime - currentTimeSec;
        muzzleFlash.material.opacity = remainingTime / 0.05;
    }

    // Анимация перезарядки
    if (isAnimatingReload) {
        reloadAnimationProgress += delta;

        const halfDuration = reloadAnimationDuration / 2;

        if (reloadAnimationProgress <= halfDuration) {
            // Первая половина анимации: обойма выходит вниз
            const t = reloadAnimationProgress / halfDuration;
            magazine.position.y = THREE.MathUtils.lerp(-0.25, -0.5, t);
        } else if (reloadAnimationProgress <= reloadAnimationDuration) {
            // Вторая половина анимации: обойма возвращается вверх
            const t = (reloadAnimationProgress - halfDuration) / halfDuration;
            magazine.position.y = THREE.MathUtils.lerp(-0.5, -0.25, t);
        } else {
            // Анимация завершена
            magazine.position.y = -0.25;
            isAnimatingReload = false;
            currentAmmo = magazineSize;
            isReloading = false;
            updateHUD();
        }
    }

    // Рендерим сцену
    renderer.render(scene, camera);
    prevTime = time;
}


// Функция для начала игры
function startGame() {
    const menu = document.getElementById('menu');
    menu.style.display = 'none';

    // Скрываем модальное окно, если оно было показано
    const deathModal = document.getElementById('death-modal');
    deathModal.style.display = 'none';

    // Показываем HUD, health-bar и crosshair
    document.getElementById('hud').style.display = 'block';
    document.getElementById('health-bar').style.display = 'block';
    document.getElementById('crosshair').style.display = 'block';

    // Сбрасываем счетчик убийств и здоровья
    kills = 0;
    health = 100;
    updateHealthBar();
    updateHUD();

    // Сбрасываем количество патронов и состояние перезарядки
    currentAmmo = magazineSize;
    isReloading = false;
    isAnimatingReload = false;
    reloadAnimationProgress = 0;
    updateHUD(); // Обновляем HUD

    // Сбрасываем позицию и поворот игрока и камеры
    player.position.copy(getRandomSpawnPosition());
    player.rotation.set(0, 0, 0);
    camera.rotation.set(0, 0, 0);

    // Сбрасываем скорость игрока
    velocity.x = 0;
    velocity.y = 0;
    velocity.z = 0;

    // Устанавливаем время начала игры
    gameStartTime = new Date().getTime();

    // Устанавливаем флаг активности игры
    isGameActive = true;

    // Инициализируем скорость врагов, максимальное количество и время последнего увеличения сложности
    enemySpeed = 0.05;       // Начальная скорость врагов
    maxEnemies = 5;          // Начальное максимальное количество врагов
    lastDifficultyIncreaseTime = gameStartTime; // Время последнего увеличения сложности

    // Создаем начальных врагов
    for (let i = 0; i < maxEnemies; i++) {
        createEnemy();
    }

    // Запрашиваем блокировку указателя мыши
    document.body.requestPointerLock();
}


// Функция для завершения игры
function endGame() {
    isGameActive = false; // Останавливаем обновление игры

    // Очищаем сцену от врагов и пуль
    enemies.forEach(enemy => scene.remove(enemy));
    enemies.length = 0;
    bullets.forEach(bullet => scene.remove(bullet));
    bullets.length = 0;

    // Освобождаем указатель мыши
    document.exitPointerLock();

    // Проверяем и обновляем рекорд
    if (kills > killsRecord) {
        killsRecord = kills;
        saveProgress();
    }

    // Разблокировка золотого пистолета при достижении 1000 киллов
    if (killsRecord >= 1000) {
        skins.golden.unlocked = true;
        saveSkins();
    }

    // Обновляем меню
    updateMenu();
}

const restartButton = document.getElementById('restartButton');
const returnToMenuButton = document.getElementById('returnToMenuButton');

restartButton.addEventListener('click', function(event) {
    event.stopPropagation();
    const deathModal = document.getElementById('death-modal');
    deathModal.style.display = 'none';
    
    // Сбрасываем параметры игры и начинаем заново
    startGame();
});

returnToMenuButton.addEventListener('click', function(event) {
    event.stopPropagation();
    const deathModal = document.getElementById('death-modal');
    deathModal.style.display = 'none';
    
    // Перезагружаем страницу
    location.reload();
});


// Обработчик кнопки "Играть"
const playButton = document.getElementById('playButton');
playButton.addEventListener('click', function(event) {
    event.stopPropagation();
    startGame();
});

// Изменение размера окна
window.addEventListener('resize', function() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}, false);

    // Инициализация игры
    loadProgress();
    loadSkins();
    initScene();       // Перенесено перед updateGunSkin()
    updateGunSkin();   // Теперь вызывается после initScene()
    updateMenu();
    updateHealthBar();
    updateHUD();
    
    // Запускаем анимацию один раз при загрузке страницы
    animate();
</script>
<div id="version">Версия 0.0.0.3</div>
</body>
</html>
при генерации чанков враги не двигаются и умирают а также подлагивает немного