во время того как стреляю и вылетает пуля хочу чтоб был эффект с дула пистолета что стреляет реально


<html>
<head>
<meta charset="UTF-8">
<title>Кибершамыга: Простой 3D Шутер</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;
}
#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>
</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>

<!-- Полоса здоровья -->
<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;
const enemies = [];
const maxEnemies = 5;
const bullets = [];
const trees = []

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;
}


// 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 currentTime = new Date().getTime();
    const elapsedTime = Math.floor((currentTime - gameStartTime) / 1000);
    const minutes = Math.floor(elapsedTime / 60);
    const seconds = elapsedTime % 60;

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





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() {
const enemyTexture = new THREE.TextureLoader().load('https://i.postimg.cc/QC6j7xGC/photo-2024-05-28-17-49-00.jpg');
const enemyMaterial = new THREE.SpriteMaterial({ map: enemyTexture });
const enemy = new THREE.Sprite(enemyMaterial);
enemy.scale.set(2, 2, 1);
enemy.position.set(
(Math.random() - 0.5) * 100,
1,
(Math.random() - 0.5) * 100
);

const sword = createSword();
sword.position.set(0.5, 0, 0);
enemy.add(sword);

scene.add(enemy);
enemies.push(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);

return sword;
}

function shoot() {
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);
}

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); // Добавляем дерево в массив trees
}

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

// Добавляем пистолет от первого лица
const gunGeometry = new THREE.BoxGeometry(0.1, 0.1, 0.5);
const gunMaterial = new THREE.MeshBasicMaterial({ color: 0x333333 });
const gun = new THREE.Mesh(gunGeometry, gunMaterial);
gun.position.set(0.2, -0.2, -0.5);
camera.add(gun);

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.2, -0.3, -0.5);
camera.add(handle);
}

// Обработчики событий клавиатуры
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) {
switch (event.code) {
case 'KeyW':
moveForward = true;
break;
case 'KeyS':
moveBackward = true;
break;
case 'KeyA':
moveLeft = true;
break;
case 'KeyD':
moveRight = true;
break;
}
});

document.addEventListener('keyup', function(event) {
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 (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) {
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 * 400.0 * delta;
    if (moveLeft || moveRight) velocity.x -= direction.x * 400.0 * delta;

    // Перемещаем игрока на основе вычисленной скорости
    player.translateX(velocity.x * delta);
    player.translateZ(velocity.z * delta);

    // Создаем сферический коллайдер для игрока
    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];
        // Получаем ограничивающий прямоугольник (bounding box) дерева
        const treeBox = new THREE.Box3().setFromObject(tree);

        // Проверяем пересечение коллайдера игрока с коробкой дерева
        if (treeBox.intersectsSphere(playerCollider)) {
            collisionDetected = true;
            break;
        }
    }

    if (collisionDetected) {
        // Если произошло столкновение, возвращаем игрока на предыдущую позицию
        player.position.copy(prevPosition);
    }

    // Обновляем положение пуль
    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(); // Обновляем HUD

                // Спауним нового врага через 2 секунды
                setTimeout(createEnemy, 2000);
                break;
            }
        }

        // Если пуля улетела слишком далеко, удаляем ее
        if (bullet.position.length() > 200) {
            scene.remove(bullet);
            bullets.splice(i, 1);
        }
    }

    // Обновляем положение врагов и реализуем обход препятствий
    enemies.forEach(function(enemy) {
        // Сохраняем предыдущую позицию врага перед перемещением
        const prevEnemyPosition = enemy.position.clone();

        // Направление к игроку
        let enemyDirection = new THREE.Vector3();
        enemyDirection.subVectors(player.position, enemy.position);

        // Обнуляем компонент Y, чтобы враги не двигались вверх/вниз
        enemyDirection.y = 0;
        enemyDirection.normalize();

        // Объявляем вектор избежания препятствий
        let avoidDirection = new THREE.Vector3(0, 0, 0);
        let isObstacleDetected = false;

        // Создаем сферический коллайдер для врага
        const enemyCollider = new THREE.Sphere(enemy.position.clone(), 0.5);

        // Проверяем препятствия вокруг врага (деревья)
        trees.forEach(function(tree) {
            const treeBox = new THREE.Box3().setFromObject(tree);
            if (treeBox.intersectsSphere(enemyCollider)) {
                // Если враг уже внутри дерева, возвращаем его на предыдущую позицию
                enemy.position.copy(prevEnemyPosition);
            }

            // Проверяем расстояние до дерева
            const distance = enemy.position.distanceTo(tree.position);
            if (distance < 3) {
                // Вычисляем вектор отталкивания от дерева
                let f = new THREE.Vector3();
                f.subVectors(enemy.position, tree.position);
                f.y = 0; // Обнуляем компонент Y
                f.normalize();
                f.divideScalar(distance); // Чем ближе, тем сильнее отталкивание
                avoidDirection.add(f);
                isObstacleDetected = true;
            }
        });

        if (isObstacleDetected) {
            // Корректируем направление движения, избегая препятствий
            avoidDirection.normalize();
            enemyDirection.add(avoidDirection);
            enemyDirection.normalize();
        }

        // Перемещаем врага в новом направлении
        enemy.position.addScaledVector(enemyDirection, 0.05);

        // Поддерживаем постоянную высоту врага
        enemy.position.y = 1; // Установите желаемую высоту врага

        // Поворачиваем врага лицом к направлению движения
        const enemyLookAt = new THREE.Vector3().addVectors(enemy.position, enemyDirection);
        enemy.lookAt(enemyLookAt);

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

    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();

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

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

// Запускаем анимацию
animate();

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


// Функция для завершения игры
function endGame() {
// Очищаем сцену от врагов и пуль
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();
}

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

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

restartButton.addEventListener('click', function() {
const deathModal = document.getElementById('death-modal');
deathModal.style.display = 'none';

// Сбрасываем параметры игры и начинаем заново
startGame();
});

returnToMenuButton.addEventListener('click', function() {
const deathModal = document.getElementById('death-modal');
deathModal.style.display = 'none';

// Перезагружаем страницу
location.reload();
});


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

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

// Инициализация игры
initScene();
updateHealthBar();
updateHUD();

</script>
<div id="version">Версия 0.0.0.1</div>
</body>
</html>