Загрузка данных
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Квартира без выхода V2</title>
<style>
body { margin:0; overflow:hidden; background:black; font-family:monospace; }
#menu {
position:absolute; width:100%; height:100%;
display:flex; flex-direction:column;
justify-content:center; align-items:center;
background:black; color:white; z-index:10;
}
button { padding:12px; cursor:pointer; }
#hud {
position:absolute; top:10px; left:10px;
color:white; z-index:5;
}
#inv {
position:absolute; bottom:10px; left:10px;
color:white;
}
#vhs {
position:absolute; width:100%; height:100%;
pointer-events:none;
background: repeating-linear-gradient(0deg, rgba(255,255,255,0.03), rgba(0,0,0,0.03) 2px);
animation: noise .15s infinite;
mix-blend-mode:overlay;
}
@keyframes noise {
0%{transform:translate(0,0)}
50%{transform:translate(1px,-1px)}
100%{transform:translate(0,0)}
}
</style>
</head>
<body>
<div id="menu">
<h1>КВАРТИРА БЕЗ ВЫХОДА</h1>
<button onclick="start()">Start</button>
</div>
<div id="hud">
<button onclick="toggleLight()">Light</button>
</div>
<div id="inv">Inventory: []</div>
<div id="vhs"></div>
<script src="https://cdn.jsdelivr.net/npm/three@0.158.0/build/three.min.js"></script>
<script>
let scene,camera,renderer;
let light;
let objects=[];
let inventory=[];
let creature;
let speed=0.08;
let keys={};
let lightOn=true;
let doorLocked=true;
let endingTriggered=false;
function start(){
document.getElementById("menu").style.display="none";
init();
animate();
spawnCreature();
}
function init(){
scene=new THREE.Scene();
scene.fog=new THREE.Fog(0x000000,1,18);
camera=new THREE.PerspectiveCamera(75,innerWidth/innerHeight,0.1,1000);
camera.position.y=1.6;
renderer=new THREE.WebGLRenderer();
renderer.setSize(innerWidth,innerHeight);
document.body.appendChild(renderer.domElement);
// LIGHT
light=new THREE.PointLight(0xffffff,1,10);
light.position.set(0,3,0);
scene.add(light);
// FLOOR
let floor=new THREE.Mesh(
new THREE.BoxGeometry(20,0.1,20),
new THREE.MeshBasicMaterial({color:0x111111})
);
scene.add(floor);
// WALLS
function wall(x,z,rx,ry){
let w=new THREE.Mesh(
new THREE.BoxGeometry(10,3,0.2),
new THREE.MeshBasicMaterial({color:0x222222})
);
w.position.set(x,1.5,z);
w.rotation.y=ry||0;
scene.add(w);
}
wall(0,-10);
wall(0,10);
wall(-10,0,0,Math.PI/2);
wall(10,0,0,Math.PI/2);
// FURNITURE
spawnFurniture();
// KEY
let key=new THREE.Mesh(
new THREE.BoxGeometry(0.2,0.2,0.2),
new THREE.MeshBasicMaterial({color:0xffff00})
);
key.position.set(2,1,-2);
key.name="key";
scene.add(key);
objects.push(key);
// DOOR
let door=new THREE.Mesh(
new THREE.BoxGeometry(1,2,0.2),
new THREE.MeshBasicMaterial({color:0x552200})
);
door.position.set(0,1,-9);
door.name="door";
scene.add(door);
objects.push(door);
// CONTROLS
document.addEventListener("keydown",e=>keys[e.key]=true);
document.addEventListener("keyup",e=>keys[e.key]=false);
document.addEventListener("mousemove",(e)=>{
if(document.pointerLockElement){
camera.rotation.y -= e.movementX*0.002;
}
});
document.body.addEventListener("click",()=>document.body.requestPointerLock());
}
function spawnFurniture(){
for(let i=0;i<15;i++){
let obj=new THREE.Mesh(
new THREE.BoxGeometry(0.3,0.3,0.3),
new THREE.MeshBasicMaterial({color:0x444444})
);
obj.position.set((Math.random()-0.5)*10,0.3,(Math.random()-0.5)*10);
scene.add(obj);
}
}
function toggleLight(){
lightOn=!lightOn;
light.intensity=lightOn?1:0;
if(!lightOn && Math.random()<0.4) scare();
}
function spawnCreature(){
creature=new THREE.Mesh(
new THREE.BoxGeometry(0.6,2,0.6),
new THREE.MeshBasicMaterial({color:0xff0000})
);
creature.position.set(5,1,5);
scene.add(creature);
}
function updateCreature(){
let dir=new THREE.Vector3();
dir.subVectors(camera.position,creature.position);
dir.y=0;
dir.normalize();
creature.position.addScaledVector(dir,0.02);
if(creature.position.distanceTo(camera.position)<1.2){
gameOver();
}
}
function interact(){
let ray=new THREE.Raycaster();
ray.setFromCamera({x:0,y:0},camera);
let hits=ray.intersectObjects(objects);
if(hits.length>0){
let obj=hits[0].object;
if(obj.name==="key"){
inventory.push("key");
scene.remove(obj);
updateInv();
}
if(obj.name==="door"){
if(inventory.includes("key")){
doorLocked=false;
ending1();
}else{
scare();
}
}
}
}
function updateInv(){
document.getElementById("inv").innerText="Inventory: "+JSON.stringify(inventory);
}
function scare(){
let flash=document.createElement("div");
flash.style="position:absolute;top:0;left:0;width:100%;height:100%;background:white;z-index:99";
document.body.appendChild(flash);
setTimeout(()=>flash.remove(),100);
}
function gameOver(){
if(endingTriggered) return;
endingTriggered=true;
alert("YOU DIED");
location.reload();
}
function ending1(){
if(endingTriggered) return;
endingTriggered=true;
alert("You escaped... but something followed you.");
location.reload();
}
function animate(){
requestAnimationFrame(animate);
if(keys["w"]) camera.position.z -= speed;
if(keys["s"]) camera.position.z += speed;
if(keys["a"]) camera.position.x -= speed;
if(keys["d"]) camera.position.x += speed;
updateCreature();
renderer.render(scene,camera);
}
document.addEventListener("click",interact);
</script>
</body>
</html>