Вот код:
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>3D Шутер</title>
<style>
body { margin: 0; font-family: Arial, sans-serif; }
canvas { display: block; }
#ui {
position: absolute;
top: 20px;
left: 20px;
color: white;
font-size: 24px;
background: rgba(0, 0, 0, 0.7);
padding: 10px 20px;
border-radius: 10px;
}
#health-bar {
width: 200px;
height: 20px;
background: #555;
border-radius: 10px;
overflow: hidden;
margin-top: 10px;
}
#health-bar-fill {
height: 100%;
background: #ff0000;
width: 100%;
transition: width 0.3s;
}
#menu, #level-complete {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
text-align: center;
color: white;
background: rgba(0, 0, 0, 0.8);
padding: 20px;
border-radius: 10px;
}
button {
padding: 10px 20px;
font-size: 18px;
cursor: pointer;
margin-top: 10px;
}
</style>
</head>
<body>
<div id="menu">
<h1>3D Шутер</h1>
<button id="start-button">Начать игру</button>
</div>
<div id="level-complete" style="display: none;">
<h1>Уровень пройден!</h1>
<button id="next-level-button">Следующий уровень</button>
</div>
<div id="ui" style="display: none;">
<div>Здоровье: <span id="health">100</span></div>
<div>Счет: <span id="score">0</span></div>
<div>Уровень: <span id="level">1</span></div>
<div id="health-bar">
<div id="health-bar-fill"></div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r146/three.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/howler/2.2.3/howler.min.js"></script>
<script>
// Сцена
const scene = new THREE.Scene();
// Камера
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 5;
// Рендерер
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Освещение
const light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(1, 1, 1).normalize();
scene.add(light);
// Игрок (куб)
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshPhongMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
// Враги
const enemies = [];
const enemyGeometry = new THREE.SphereGeometry(0.5);
const enemyMaterial = new THREE.MeshPhongMaterial({ color: 0xff0000 });
// Пули
const bullets = [];
// Здоровье игрока
let playerHealth = 100;
const healthElement = document.getElementById('health');
const healthBarFill = document.getElementById('health-bar-fill');
// Счет
let score = 0;
const scoreElement = document.getElementById('score');
// Уровень
let currentLevel = 1;
const levelElement = document.getElementById('level');
// Звуки
const shootSound = new Howl({ src: ['https://assets.mixkit.co/sfx/preview/mixkit-laser-weapon-shot-1681.mp3'] });
const hitSound = new Howl({ src: ['https://assets.mixkit.co/sfx/preview/mixkit-arcade-game-explosion-2759.mp3'] });
const damageSound = new Howl({ src: ['https://assets.mixkit.co/sfx/preview/mixkit-player-losing-or-failing-2042.mp3'] });
// Управление камерой
const moveSpeed = 0.1;
const rotateSpeed = 0.01;
// Функция создания врагов
function createEnemies() {
enemies.length = 0; // Очищаем массив врагов
for (let i = 0; i < currentLevel * 3; i++) { // Увеличиваем количество врагов с уровнем
const enemy = new THREE.Mesh(enemyGeometry, enemyMaterial);
enemy.position.set(
(Math.random() - 0.5) * 10,
(Math.random() - 0.5) * 10,
(Math.random() - 0.5) * 10
);
scene.add(enemy);
enemies.push(enemy);
}
}
// Функция сброса игры
function resetGame() {
playerHealth = 100;
healthElement.textContent = playerHealth;
healthBarFill.style.width = '100%';
score = 0;
scoreElement.textContent = score;
currentLevel = 1;
levelElement.textContent = currentLevel;
createEnemies();
}
// Старт игры
document.getElementById('start-button').addEventListener('click', () => {
document.getElementById('menu').style.display = 'none';
document.getElementById('ui').style.display = 'block';
resetGame();
animate();
});
// Переход на следующий уровень
document.getElementById('next-level-button').addEventListener('click', () => {
document.getElementById('level-complete').style.display = 'none';
document.getElementById('ui').style.display = 'block';
currentLevel++;
levelElement.textContent = currentLevel;
createEnemies();
animate();
});
// Стрельба
document.addEventListener('mousedown', () => {
const bulletGeometry = new THREE.SphereGeometry(0.1);
const bulletMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000 });
const bullet = new THREE.Mesh(bulletGeometry, bulletMaterial);
bullet.position.copy(camera.position);
bullet.quaternion.copy(camera.quaternion);
scene.add(bullet);
bullets.push(bullet);
// Звук выстрела
shootSound.play();
const bulletSpeed = 0.2;
const animateBullet = () => {
bullet.translateZ(-bulletSpeed);
if (bullet.position.distanceTo(camera.position) > 10) {
scene.remove(bullet);
bullets.splice(bullets.indexOf(bullet), 1);
} else {
requestAnimationFrame(animateBullet);
}
};
animateBullet();
});
// Проверка коллизий
function checkCollisions() {
// Коллизии пуль с врагами
bullets.forEach((bullet, bulletIndex) => {
enemies.forEach((enemy, enemyIndex) => {
if (bullet.position.distanceTo(enemy.position) < 0.6) {
scene.remove(bullet);
scene.remove(enemy);
bullets.splice(bulletIndex, 1);
enemies.splice(enemyIndex, 1);
// Звук попадания
hitSound.play();
// Увеличение счета
score += 10;
scoreElement.textContent = score;
// Проверка завершения уровня
if (enemies.length === 0) {
document.getElementById('level-complete').style.display = 'block';
document.getElementById('ui').style.display = 'none';
}
}
});
});
// Коллизии игрока с врагами
enemies.forEach((enemy) => {
if (cube.position.distanceTo(enemy.position) < 1) {
playerHealth -= 10;
healthElement.textContent = playerHealth;
healthBarFill.style.width = `${playerHealth}%`;
// Звук потери здоровья
damageSound.play();
if (playerHealth <= 0) {
alert('Игра окончена! Ваш счет: ' + score);
resetGame();
document.getElementById('menu').style.display = 'block';
document.getElementById('ui').style.display = 'none';
}
}
});
}
// Анимация
const animate = () => {
requestAnimationFrame(animate);
// Движение врагов
enemies.forEach(enemy => {
enemy.position.x += (Math.random() - 0.5) * 0.05 * currentLevel; // Увеличиваем скорость с уровнем
enemy.position.y += (Math.random() - 0.5) * 0.05 * currentLevel;
enemy.position.z += (Math.random() - 0.5) * 0.05 * currentLevel;
});
// Проверка коллизий
checkCollisions();
// Вращение куба
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
};
</script>
</body>
</html>