Обновить doom.html
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>DOOM ETERNAL: Web 3D (Real Textures)</title>
|
<title>DOOM ETERNAL: Web 3D (Fixed)</title>
|
||||||
<style>
|
<style>
|
||||||
body { margin: 0; overflow: hidden; background: #000; font-family: 'Impact', 'Arial Black', sans-serif; user-select: none; }
|
body { margin: 0; overflow: hidden; background: #000; font-family: 'Impact', 'Arial Black', sans-serif; user-select: none; }
|
||||||
#game-container { position: relative; width: 100vw; height: 100vh; }
|
#game-container { position: relative; width: 100vw; height: 100vh; }
|
||||||
@@ -19,12 +19,12 @@
|
|||||||
#crosshair::after { top: 0; left: 11px; width: 2px; height: 24px; }
|
#crosshair::after { top: 0; left: 11px; width: 2px; height: 24px; }
|
||||||
|
|
||||||
#blocker {
|
#blocker {
|
||||||
position: absolute; width: 100%; height: 100%; background: rgba(0,0,0,0.9);
|
position: absolute; width: 100%; height: 100%; background: rgba(0,0,0,0.85);
|
||||||
display: flex; flex-direction: column; align-items: center; justify-content: center;
|
display: flex; flex-direction: column; align-items: center; justify-content: center;
|
||||||
z-index: 20; color: #fff; cursor: pointer;
|
z-index: 20; color: #fff; cursor: pointer;
|
||||||
}
|
}
|
||||||
#instructions { font-size: 42px; text-transform: uppercase; letter-spacing: 6px; color: #ff3333; text-shadow: 0 0 20px #ff0000; text-align: center; }
|
#instructions { font-size: 42px; text-transform: uppercase; letter-spacing: 6px; color: #ff3333; text-shadow: 0 0 20px #ff0000; text-align: center; }
|
||||||
#sub-instructions { font-size: 16px; color: #888; margin-top: 20px; font-family: monospace; letter-spacing: 1px; }
|
#sub-instructions { font-size: 16px; color: #ccc; margin-top: 20px; font-family: monospace; letter-spacing: 1px; }
|
||||||
#loading { font-size: 18px; color: #ffaa00; margin-top: 30px; display: none; }
|
#loading { font-size: 18px; color: #ffaa00; margin-top: 30px; display: none; }
|
||||||
|
|
||||||
#hud {
|
#hud {
|
||||||
@@ -34,7 +34,7 @@
|
|||||||
align-items: center; padding: 0 50px; box-sizing: border-box; pointer-events: none; z-index: 10;
|
align-items: center; padding: 0 50px; box-sizing: border-box; pointer-events: none; z-index: 10;
|
||||||
}
|
}
|
||||||
.stat-box { text-align: center; color: #fff; position: relative; }
|
.stat-box { text-align: center; color: #fff; position: relative; }
|
||||||
.stat-label { font-size: 14px; color: #666; letter-spacing: 3px; text-transform: uppercase; font-family: monospace; }
|
.stat-label { font-size: 14px; color: #888; letter-spacing: 3px; text-transform: uppercase; font-family: monospace; }
|
||||||
.stat-value { font-size: 56px; line-height: 56px; text-shadow: 0 0 15px currentColor; font-family: 'Impact', sans-serif; }
|
.stat-value { font-size: 56px; line-height: 56px; text-shadow: 0 0 15px currentColor; font-family: 'Impact', sans-serif; }
|
||||||
.health { color: #00ff00; }
|
.health { color: #00ff00; }
|
||||||
.armor { color: #00bfff; }
|
.armor { color: #00bfff; }
|
||||||
@@ -108,7 +108,7 @@
|
|||||||
let pickups = [];
|
let pickups = [];
|
||||||
let weaponGroup, pumpGroup;
|
let weaponGroup, pumpGroup;
|
||||||
let isPumping = false;
|
let isPumping = false;
|
||||||
let muzzleLight;
|
let muzzleLight, playerLight;
|
||||||
let audioCtx;
|
let audioCtx;
|
||||||
|
|
||||||
const mapLayout = [
|
const mapLayout = [
|
||||||
@@ -133,6 +133,7 @@
|
|||||||
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
|
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
|
||||||
];
|
];
|
||||||
const CELL_SIZE = 4;
|
const CELL_SIZE = 4;
|
||||||
|
const PLAYER_RADIUS = 0.6; // Радиус игрока для коллизий
|
||||||
|
|
||||||
const uiHealth = document.getElementById('health-val');
|
const uiHealth = document.getElementById('health-val');
|
||||||
const uiArmor = document.getElementById('armor-val');
|
const uiArmor = document.getElementById('armor-val');
|
||||||
@@ -213,14 +214,31 @@
|
|||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
scene = new THREE.Scene();
|
scene = new THREE.Scene();
|
||||||
scene.background = new THREE.Color(0x050000);
|
scene.background = new THREE.Color(0x1a0a0a); // Светлее фон
|
||||||
scene.fog = new THREE.FogExp2(0x1a0505, 0.04);
|
|
||||||
|
// УМЕНЬШЕНА плотность тумана и сделан светлее для лучшей видимости
|
||||||
|
scene.fog = new THREE.FogExp2(0x2a0a0a, 0.02);
|
||||||
|
|
||||||
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 100);
|
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 100);
|
||||||
|
|
||||||
const ambientLight = new THREE.AmbientLight(0x220505, 0.6);
|
// --- УЛУЧШЕННОЕ ОСВЕЩЕНИЕ ---
|
||||||
|
// 1. Яркий общий теплый свет
|
||||||
|
const ambientLight = new THREE.AmbientLight(0xffaaaa, 1.0);
|
||||||
scene.add(ambientLight);
|
scene.add(ambientLight);
|
||||||
|
|
||||||
|
// 2. Направленный свет сверху (имитация адского светила)
|
||||||
|
const dirLight = new THREE.DirectionalLight(0xffccaa, 1.2);
|
||||||
|
dirLight.position.set(30, 50, 30);
|
||||||
|
dirLight.castShadow = true;
|
||||||
|
dirLight.shadow.mapSize.width = 1024;
|
||||||
|
dirLight.shadow.mapSize.height = 1024;
|
||||||
|
scene.add(dirLight);
|
||||||
|
|
||||||
|
// 3. Свет от игрока (всегда освещает пространство перед ним)
|
||||||
|
playerLight = new THREE.PointLight(0xffaa55, 1.5, 18);
|
||||||
|
playerLight.position.set(0, 0, -1);
|
||||||
|
camera.add(playerLight);
|
||||||
|
|
||||||
muzzleLight = new THREE.PointLight(0xffaa00, 0, 15);
|
muzzleLight = new THREE.PointLight(0xffaa00, 0, 15);
|
||||||
muzzleLight.castShadow = true;
|
muzzleLight.castShadow = true;
|
||||||
scene.add(muzzleLight);
|
scene.add(muzzleLight);
|
||||||
@@ -229,7 +247,6 @@
|
|||||||
loadingText.style.display = 'block';
|
loadingText.style.display = 'block';
|
||||||
const textureLoader = new THREE.TextureLoader();
|
const textureLoader = new THREE.TextureLoader();
|
||||||
|
|
||||||
// Используем надежные URL с официального репозитория Three.js (CORS-friendly)
|
|
||||||
const wallUrl = 'https://threejs.org/examples/textures/brick_diffuse.jpg';
|
const wallUrl = 'https://threejs.org/examples/textures/brick_diffuse.jpg';
|
||||||
const floorUrl = 'https://threejs.org/examples/textures/metal.jpg';
|
const floorUrl = 'https://threejs.org/examples/textures/metal.jpg';
|
||||||
|
|
||||||
@@ -241,23 +258,22 @@
|
|||||||
floorTexture.wrapS = floorTexture.wrapT = THREE.RepeatWrapping;
|
floorTexture.wrapS = floorTexture.wrapT = THREE.RepeatWrapping;
|
||||||
floorTexture.repeat.set(10, 10);
|
floorTexture.repeat.set(10, 10);
|
||||||
|
|
||||||
// Генерация уровня
|
// Материалы сделаны светлее (запасной цвет), чтобы даже без текстур было видно
|
||||||
const wallGeo = new THREE.BoxGeometry(CELL_SIZE, CELL_SIZE * 1.5, CELL_SIZE);
|
|
||||||
const wallMat = new THREE.MeshStandardMaterial({
|
const wallMat = new THREE.MeshStandardMaterial({
|
||||||
map: wallTexture,
|
map: wallTexture,
|
||||||
color: 0x884444, // Запасной цвет, если текстура не загрузится
|
color: 0x996666, // Светло-красный запасной цвет
|
||||||
|
roughness: 0.9,
|
||||||
|
metalness: 0.1
|
||||||
|
});
|
||||||
|
|
||||||
|
const floorMat = new THREE.MeshStandardMaterial({
|
||||||
|
map: floorTexture,
|
||||||
|
color: 0x777777, // Светло-серый запасной цвет
|
||||||
roughness: 0.8,
|
roughness: 0.8,
|
||||||
metalness: 0.2
|
metalness: 0.2
|
||||||
});
|
});
|
||||||
|
|
||||||
const floorGeo = new THREE.PlaneGeometry(mapLayout[0].length * CELL_SIZE, mapLayout.length * CELL_SIZE);
|
const floorGeo = new THREE.PlaneGeometry(mapLayout[0].length * CELL_SIZE, mapLayout.length * CELL_SIZE);
|
||||||
const floorMat = new THREE.MeshStandardMaterial({
|
|
||||||
map: floorTexture,
|
|
||||||
color: 0x555555, // Запасной цвет
|
|
||||||
roughness: 0.7,
|
|
||||||
metalness: 0.5
|
|
||||||
});
|
|
||||||
|
|
||||||
const floor = new THREE.Mesh(floorGeo, floorMat);
|
const floor = new THREE.Mesh(floorGeo, floorMat);
|
||||||
floor.rotation.x = -Math.PI / 2;
|
floor.rotation.x = -Math.PI / 2;
|
||||||
floor.position.set((mapLayout[0].length * CELL_SIZE)/2 - CELL_SIZE/2, 0, (mapLayout.length * CELL_SIZE)/2 - CELL_SIZE/2);
|
floor.position.set((mapLayout[0].length * CELL_SIZE)/2 - CELL_SIZE/2, 0, (mapLayout.length * CELL_SIZE)/2 - CELL_SIZE/2);
|
||||||
@@ -265,7 +281,7 @@
|
|||||||
scene.add(floor);
|
scene.add(floor);
|
||||||
|
|
||||||
const ceilGeo = new THREE.PlaneGeometry(mapLayout[0].length * CELL_SIZE, mapLayout.length * CELL_SIZE);
|
const ceilGeo = new THREE.PlaneGeometry(mapLayout[0].length * CELL_SIZE, mapLayout.length * CELL_SIZE);
|
||||||
const ceilMat = new THREE.MeshStandardMaterial({ color: 0x110505, roughness: 1 });
|
const ceilMat = new THREE.MeshStandardMaterial({ color: 0x221111, roughness: 1 });
|
||||||
const ceil = new THREE.Mesh(ceilGeo, ceilMat);
|
const ceil = new THREE.Mesh(ceilGeo, ceilMat);
|
||||||
ceil.rotation.x = Math.PI / 2;
|
ceil.rotation.x = Math.PI / 2;
|
||||||
ceil.position.set((mapLayout[0].length * CELL_SIZE)/2 - CELL_SIZE/2, CELL_SIZE * 1.5, (mapLayout.length * CELL_SIZE)/2 - CELL_SIZE/2);
|
ceil.position.set((mapLayout[0].length * CELL_SIZE)/2 - CELL_SIZE/2, CELL_SIZE * 1.5, (mapLayout.length * CELL_SIZE)/2 - CELL_SIZE/2);
|
||||||
@@ -278,17 +294,19 @@
|
|||||||
const posZ = z * CELL_SIZE;
|
const posZ = z * CELL_SIZE;
|
||||||
|
|
||||||
if (type === 1) {
|
if (type === 1) {
|
||||||
|
const wallGeo = new THREE.BoxGeometry(CELL_SIZE, CELL_SIZE * 1.5, CELL_SIZE);
|
||||||
const wall = new THREE.Mesh(wallGeo, wallMat);
|
const wall = new THREE.Mesh(wallGeo, wallMat);
|
||||||
wall.position.set(posX, CELL_SIZE * 0.75, posZ);
|
wall.position.set(posX, CELL_SIZE * 0.75, posZ);
|
||||||
wall.castShadow = true;
|
wall.castShadow = true;
|
||||||
wall.receiveShadow = true;
|
wall.receiveShadow = true;
|
||||||
scene.add(wall);
|
scene.add(wall);
|
||||||
} else if (type === 9) {
|
} else if (type === 9) {
|
||||||
camera.position.set(posX, 1.6, posZ);
|
// Спавн игрока строго в центре клетки
|
||||||
|
camera.position.set(posX + CELL_SIZE/2, 1.6, posZ + CELL_SIZE/2);
|
||||||
} else if (type === 2) {
|
} else if (type === 2) {
|
||||||
spawnEnemy(posX, posZ);
|
spawnEnemy(posX + CELL_SIZE/2, posZ + CELL_SIZE/2);
|
||||||
} else if (type === 3) {
|
} else if (type === 3) {
|
||||||
spawnPickup(posX, posZ);
|
spawnPickup(posX + CELL_SIZE/2, posZ + CELL_SIZE/2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -296,7 +314,7 @@
|
|||||||
// Оружие
|
// Оружие
|
||||||
weaponGroup = new THREE.Group();
|
weaponGroup = new THREE.Group();
|
||||||
const bodyGeo = new THREE.BoxGeometry(0.12, 0.15, 0.7);
|
const bodyGeo = new THREE.BoxGeometry(0.12, 0.15, 0.7);
|
||||||
const bodyMat = new THREE.MeshStandardMaterial({ color: 0x222222, metalness: 0.8, roughness: 0.4 });
|
const bodyMat = new THREE.MeshStandardMaterial({ color: 0x333333, metalness: 0.8, roughness: 0.4 });
|
||||||
const body = new THREE.Mesh(bodyGeo, bodyMat);
|
const body = new THREE.Mesh(bodyGeo, bodyMat);
|
||||||
|
|
||||||
const barrelGeo = new THREE.CylinderGeometry(0.035, 0.035, 0.6, 8);
|
const barrelGeo = new THREE.CylinderGeometry(0.035, 0.035, 0.6, 8);
|
||||||
@@ -308,7 +326,7 @@
|
|||||||
|
|
||||||
pumpGroup = new THREE.Group();
|
pumpGroup = new THREE.Group();
|
||||||
const pumpGeo = new THREE.BoxGeometry(0.14, 0.12, 0.25);
|
const pumpGeo = new THREE.BoxGeometry(0.14, 0.12, 0.25);
|
||||||
const pumpMat = new THREE.MeshStandardMaterial({ color: 0x4a3c31, roughness: 0.9 });
|
const pumpMat = new THREE.MeshStandardMaterial({ color: 0x5c4a3d, roughness: 0.9 });
|
||||||
const pump = new THREE.Mesh(pumpGeo, pumpMat);
|
const pump = new THREE.Mesh(pumpGeo, pumpMat);
|
||||||
pump.position.z = 0.15;
|
pump.position.z = 0.15;
|
||||||
pumpGroup.add(pump);
|
pumpGroup.add(pump);
|
||||||
@@ -322,7 +340,6 @@
|
|||||||
// --- УПРАВЛЕНИЕ ---
|
// --- УПРАВЛЕНИЕ ---
|
||||||
controls = new PointerLockControls(camera, document.body);
|
controls = new PointerLockControls(camera, document.body);
|
||||||
|
|
||||||
// Надежный обработчик клика для запуска
|
|
||||||
blocker.addEventListener('click', function() {
|
blocker.addEventListener('click', function() {
|
||||||
initAudio();
|
initAudio();
|
||||||
controls.lock();
|
controls.lock();
|
||||||
@@ -352,10 +369,35 @@
|
|||||||
window.addEventListener('resize', onWindowResize);
|
window.addEventListener('resize', onWindowResize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- ИСПРАВЛЕННАЯ КОЛЛИЗИЯ ---
|
||||||
|
function checkWallCollision(x, z) {
|
||||||
|
// Проверяем 4 угла вокруг игрока (квадрат коллизии)
|
||||||
|
const checks = [
|
||||||
|
{ x: x - PLAYER_RADIUS, z: z - PLAYER_RADIUS },
|
||||||
|
{ x: x + PLAYER_RADIUS, z: z - PLAYER_RADIUS },
|
||||||
|
{ x: x - PLAYER_RADIUS, z: z + PLAYER_RADIUS },
|
||||||
|
{ x: x + PLAYER_RADIUS, z: z + PLAYER_RADIUS }
|
||||||
|
];
|
||||||
|
|
||||||
|
for (let p of checks) {
|
||||||
|
const gridX = Math.floor(p.x / CELL_SIZE);
|
||||||
|
const gridZ = Math.floor(p.z / CELL_SIZE);
|
||||||
|
|
||||||
|
// Если вышли за пределы карты или попали в стену (1)
|
||||||
|
if (gridZ < 0 || gridZ >= mapLayout.length || gridX < 0 || gridX >= mapLayout[0].length) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (mapLayout[gridZ][gridX] === 1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
function spawnEnemy(x, z) {
|
function spawnEnemy(x, z) {
|
||||||
const group = new THREE.Group();
|
const group = new THREE.Group();
|
||||||
const bodyGeo = new THREE.IcosahedronGeometry(0.7, 1);
|
const bodyGeo = new THREE.IcosahedronGeometry(0.7, 1);
|
||||||
const bodyMat = new THREE.MeshStandardMaterial({ color: 0x880000, roughness: 0.3, metalness: 0.6, emissive: 0x220000 });
|
const bodyMat = new THREE.MeshStandardMaterial({ color: 0xaa0000, roughness: 0.3, metalness: 0.6, emissive: 0x330000 });
|
||||||
const body = new THREE.Mesh(bodyGeo, bodyMat);
|
const body = new THREE.Mesh(bodyGeo, bodyMat);
|
||||||
|
|
||||||
const eyeGeo = new THREE.SphereGeometry(0.25, 16, 16);
|
const eyeGeo = new THREE.SphereGeometry(0.25, 16, 16);
|
||||||
@@ -363,7 +405,7 @@
|
|||||||
const eye = new THREE.Mesh(eyeGeo, eyeMat);
|
const eye = new THREE.Mesh(eyeGeo, eyeMat);
|
||||||
eye.position.set(0, 0.2, 0.6);
|
eye.position.set(0, 0.2, 0.6);
|
||||||
|
|
||||||
const light = new THREE.PointLight(0xff0000, 1, 5);
|
const light = new THREE.PointLight(0xff0000, 1.5, 6);
|
||||||
light.position.y = 0.5;
|
light.position.y = 0.5;
|
||||||
|
|
||||||
group.add(body, eye, light);
|
group.add(body, eye, light);
|
||||||
@@ -376,10 +418,10 @@
|
|||||||
|
|
||||||
function spawnPickup(x, z, isDrop = false) {
|
function spawnPickup(x, z, isDrop = false) {
|
||||||
const geo = new THREE.BoxGeometry(0.6, 0.4, 0.4);
|
const geo = new THREE.BoxGeometry(0.6, 0.4, 0.4);
|
||||||
const mat = new THREE.MeshStandardMaterial({ color: 0xffcc00, emissive: 0xaa6600, emissiveIntensity: 0.5, metalness: 0.8 });
|
const mat = new THREE.MeshStandardMaterial({ color: 0xffcc00, emissive: 0xaa6600, emissiveIntensity: 0.8, metalness: 0.8 });
|
||||||
const mesh = new THREE.Mesh(geo, mat);
|
const mesh = new THREE.Mesh(geo, mat);
|
||||||
mesh.position.set(x, isDrop ? 0.5 : 1, z);
|
mesh.position.set(x, isDrop ? 0.5 : 1, z);
|
||||||
const light = new THREE.PointLight(0xffcc00, 0.5, 3);
|
const light = new THREE.PointLight(0xffcc00, 1.0, 4);
|
||||||
mesh.add(light);
|
mesh.add(light);
|
||||||
scene.add(mesh);
|
scene.add(mesh);
|
||||||
pickups.push({ mesh, isDrop, bobOffset: Math.random() * Math.PI });
|
pickups.push({ mesh, isDrop, bobOffset: Math.random() * Math.PI });
|
||||||
@@ -445,7 +487,8 @@
|
|||||||
|
|
||||||
setTimeout(() => { pumpGroup.position.z = 0; }, 300);
|
setTimeout(() => { pumpGroup.position.z = 0; }, 300);
|
||||||
|
|
||||||
muzzleLight.intensity = 8;
|
muzzleLight.position.copy(camera.position).add(camera.getWorldDirection(new THREE.Vector3()).multiplyScalar(1));
|
||||||
|
muzzleLight.intensity = 10;
|
||||||
setTimeout(() => { muzzleLight.intensity = 0; }, 60);
|
setTimeout(() => { muzzleLight.intensity = 0; }, 60);
|
||||||
|
|
||||||
const raycaster = new THREE.Raycaster();
|
const raycaster = new THREE.Raycaster();
|
||||||
@@ -485,7 +528,7 @@
|
|||||||
}
|
}
|
||||||
if(emptySpots.length > 0) {
|
if(emptySpots.length > 0) {
|
||||||
const spot = emptySpots[Math.floor(Math.random() * emptySpots.length)];
|
const spot = emptySpots[Math.floor(Math.random() * emptySpots.length)];
|
||||||
spawnEnemy(spot.x * CELL_SIZE, spot.z * CELL_SIZE);
|
spawnEnemy(spot.x * CELL_SIZE + CELL_SIZE/2, spot.z * CELL_SIZE + CELL_SIZE/2);
|
||||||
}
|
}
|
||||||
}, 2000);
|
}, 2000);
|
||||||
}
|
}
|
||||||
@@ -493,15 +536,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkWallCollision(newX, newZ) {
|
|
||||||
const gridX = Math.round(newX / CELL_SIZE);
|
|
||||||
const gridZ = Math.round(newZ / CELL_SIZE);
|
|
||||||
if (gridZ >= 0 && gridZ < mapLayout.length && gridX >= 0 && gridX < mapLayout[0].length) {
|
|
||||||
return mapLayout[gridZ][gridX] === 1;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function onWindowResize() {
|
function onWindowResize() {
|
||||||
camera.aspect = window.innerWidth / window.innerHeight;
|
camera.aspect = window.innerWidth / window.innerHeight;
|
||||||
camera.updateProjectionMatrix();
|
camera.updateProjectionMatrix();
|
||||||
@@ -516,22 +550,34 @@
|
|||||||
prevTime = time;
|
prevTime = time;
|
||||||
|
|
||||||
if (controls.isLocked) {
|
if (controls.isLocked) {
|
||||||
velocity.x -= velocity.x * 12.0 * delta;
|
// Физика движения
|
||||||
velocity.z -= velocity.z * 12.0 * delta;
|
velocity.x -= velocity.x * 10.0 * delta;
|
||||||
|
velocity.z -= velocity.z * 10.0 * delta;
|
||||||
|
|
||||||
direction.z = Number(moveForward) - Number(moveBackward);
|
direction.z = Number(moveForward) - Number(moveBackward);
|
||||||
direction.x = Number(moveRight) - Number(moveLeft);
|
direction.x = Number(moveRight) - Number(moveLeft);
|
||||||
direction.normalize();
|
direction.normalize();
|
||||||
|
|
||||||
if (moveForward || moveBackward) velocity.z -= direction.z * 80.0 * delta;
|
if (moveForward || moveBackward) velocity.z -= direction.z * 100.0 * delta;
|
||||||
if (moveLeft || moveRight) velocity.x -= direction.x * 80.0 * delta;
|
if (moveLeft || moveRight) velocity.x -= direction.x * 100.0 * delta;
|
||||||
|
|
||||||
const nextX = camera.position.x - velocity.x * delta;
|
const nextX = camera.position.x - velocity.x * delta;
|
||||||
const nextZ = camera.position.z - velocity.z * delta;
|
const nextZ = camera.position.z - velocity.z * delta;
|
||||||
|
|
||||||
if (!checkWallCollision(nextX, camera.position.z)) camera.position.x = nextX;
|
// ИСПРАВЛЕННОЕ СКОЛЬЖЕНИЕ ВДОЛЬ СТЕН: проверяем оси независимо
|
||||||
if (!checkWallCollision(camera.position.x, nextZ)) camera.position.z = nextZ;
|
if (!checkWallCollision(nextX, camera.position.z)) {
|
||||||
|
camera.position.x = nextX;
|
||||||
|
} else {
|
||||||
|
velocity.x = 0; // Гасим инерцию при ударе о стену
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!checkWallCollision(camera.position.x, nextZ)) {
|
||||||
|
camera.position.z = nextZ;
|
||||||
|
} else {
|
||||||
|
velocity.z = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Анимация оружия
|
||||||
weaponGroup.position.z = THREE.MathUtils.lerp(weaponGroup.position.z, -0.6, delta * 12);
|
weaponGroup.position.z = THREE.MathUtils.lerp(weaponGroup.position.z, -0.6, delta * 12);
|
||||||
weaponGroup.rotation.x = THREE.MathUtils.lerp(weaponGroup.rotation.x, 0, delta * 12);
|
weaponGroup.rotation.x = THREE.MathUtils.lerp(weaponGroup.rotation.x, 0, delta * 12);
|
||||||
|
|
||||||
@@ -541,6 +587,7 @@
|
|||||||
weaponGroup.position.x = 0.35 + Math.cos(bobSpeed * 0.5) * 0.01;
|
weaponGroup.position.x = 0.35 + Math.cos(bobSpeed * 0.5) * 0.01;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Логика врагов
|
||||||
enemies.forEach(enemy => {
|
enemies.forEach(enemy => {
|
||||||
const dist = enemy.position.distanceTo(camera.position);
|
const dist = enemy.position.distanceTo(camera.position);
|
||||||
const dirToPlayer = new THREE.Vector3().subVectors(camera.position, enemy.position).normalize();
|
const dirToPlayer = new THREE.Vector3().subVectors(camera.position, enemy.position).normalize();
|
||||||
@@ -584,6 +631,7 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Подбор предметов
|
||||||
for (let i = pickups.length - 1; i >= 0; i--) {
|
for (let i = pickups.length - 1; i >= 0; i--) {
|
||||||
const p = pickups[i];
|
const p = pickups[i];
|
||||||
p.mesh.rotation.y += delta * 2;
|
p.mesh.rotation.y += delta * 2;
|
||||||
@@ -598,6 +646,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Частицы
|
||||||
for (let i = particles.length - 1; i >= 0; i--) {
|
for (let i = particles.length - 1; i >= 0; i--) {
|
||||||
const p = particles[i];
|
const p = particles[i];
|
||||||
p.life -= delta * 1.5;
|
p.life -= delta * 1.5;
|
||||||
|
|||||||
Reference in New Issue
Block a user