summaryrefslogtreecommitdiff
path: root/serve/_carmod.js
diff options
context:
space:
mode:
authorpacan-bot <[email protected]>2026-07-11 02:46:59 +0000
committerpacan-bot <[email protected]>2026-07-11 02:46:59 +0000
commitae6d6689eec02b0328eb5e7b1f1f48c523268a8f (patch)
treecd4c79cd53ae8449a1cab8fb39f796b383509938 /serve/_carmod.js
parent499266fb5d1da142450280575702153740e14cfb (diff)
downloadplaneta-zhopa-ae6d6689eec02b0328eb5e7b1f1f48c523268a8f.tar.gz
planeta-zhopa-ae6d6689eec02b0328eb5e7b1f1f48c523268a8f.zip
машина: физика reVC (выбор дрон/машина) + фикс руля, скорости и фары
- руль: влево/вправо больше не перепутаны (инвертирован знак A/D) - скорость: БРОВЕНОСЕЦ 99->120 км/ч и вдвое живее разгон (engineAccel 16->34, maxVel 200->270); ЖОПЕРРАРИ 40->63 км/ч (engineAccel 18->32, maxVel 210->300, traction 1.15->1.30, меньше буксует на грунте) - фары: две area-light (RectAreaLight/LTC, как у роторов дрона) + светящиеся линзы, светят вперёд и чуть вниз на дорогу - в репозиторий добавлены исходники физики: serve/car_phys.js, serve/_carmod.js
Diffstat (limited to 'serve/_carmod.js')
-rw-r--r--serve/_carmod.js128
1 files changed, 128 insertions, 0 deletions
diff --git a/serve/_carmod.js b/serve/_carmod.js
new file mode 100644
index 0000000..da70fd3
--- /dev/null
+++ b/serve/_carmod.js
@@ -0,0 +1,128 @@
+/* ===== АВТО-РЕЖИМ: выбор транспорта + езда на ported reVC-физике (client) ===== */
+var carMode = false, carObj = null, carMesh = null, carGround = null, carAcc = 0, carPreset = 'brovenosec';
+var carMesh_wheels = [];
+var carHeadlights = [];
+var CAR_SPAWN = { x: 70, z: -40 };
+
+function buildCarMesh() {
+ var h = carObj.h;
+ var g = new THREE.Group();
+ var L = h.Dimension.y, Wd = h.Dimension.x, Ht = h.Dimension.z;
+ var body = new THREE.Mesh(new THREE.BoxGeometry(Wd, Ht * 0.6, L),
+ new THREE.MeshStandardMaterial({ color: 0xc81e3a, roughness: 0.45, metalness: 0.3 }));
+ body.position.y = Ht * 0.15; g.add(body);
+ var cab = new THREE.Mesh(new THREE.BoxGeometry(Wd * 0.86, Ht * 0.5, L * 0.5),
+ new THREE.MeshStandardMaterial({ color: 0x20242c, roughness: 0.3, metalness: 0.4 }));
+ cab.position.set(0, Ht * 0.55, -L * 0.05); g.add(cab);
+ var nose = new THREE.Mesh(new THREE.BoxGeometry(Wd * 0.5, Ht * 0.2, 0.3),
+ new THREE.MeshStandardMaterial({ color: 0xffd23a, emissive: 0x442200 }));
+ nose.position.set(0, Ht * 0.1, L * 0.5); g.add(nose); // жёлтый нос = вперёд (+Z)
+ // фары — area lights (LTC, как у дрона): светят вперёд (+Z) и чуть вниз на дорогу
+ var hlX = Wd * 0.34, hlY = Ht * 0.16, hlZ = L * 0.5 + 0.04;
+ var lensMat = new THREE.MeshStandardMaterial({ color: 0xfff6d8, emissive: 0xfff0b0, emissiveIntensity: 2.6, roughness: 0.25, metalness: 0.0 });
+ carHeadlights = [];
+ for (var hi = 0; hi < 2; hi++) {
+ var sx = hi === 0 ? -1 : 1;
+ var lens = new THREE.Mesh(new THREE.BoxGeometry(Wd * 0.26, Ht * 0.18, 0.10), lensMat);
+ lens.position.set(sx * hlX, hlY, hlZ); g.add(lens);
+ var hl = new THREE.RectAreaLight(0xfff2cc, 11.0, Wd * 0.55, Ht * 0.42);
+ hl.position.set(sx * hlX, hlY, hlZ + 0.06);
+ hl.rotation.set(Math.PI + 0.16, 0, 0); // локальный -Z -> +Z (вперёд), лёгкий наклон вниз
+ g.add(hl); carHeadlights.push(hl);
+ }
+ var wr = carObj.wheelRadius;
+ var wheelGeo = new THREE.CylinderGeometry(wr, wr, 0.3, 16);
+ var wheelMat = new THREE.MeshStandardMaterial({ color: 0x111214, roughness: 0.85 });
+ carMesh_wheels = [];
+ for (var i = 0; i < 4; i++) {
+ var w = new THREE.Mesh(wheelGeo, wheelMat);
+ var pb = carObj.m_wheelPosBody[i];
+ w.position.set(pb.x, pb.y, pb.z);
+ w.rotation.set(0, 0, Math.PI / 2); // ось колеса вдоль X
+ g.add(w); carMesh_wheels.push(w);
+ }
+ return g;
+}
+
+function spawnCar() {
+ var CP = window.PZCarPhys;
+ var hd = CP.makeHandling(CP.PRESETS[carPreset]);
+ carGround = CP.makeGround(groundH, WATER_Y, { patch: 1.5 });
+ var gy = groundH(CAR_SPAWN.x, CAR_SPAWN.z);
+ carObj = new CP.Car(hd, { x: CAR_SPAWN.x, y: gy + 2.0, z: CAR_SPAWN.z, heading: 0 });
+ carMesh = buildCarMesh();
+ scene.add(carMesh);
+ try { window.PZCAR = carObj; } catch(e){}
+}
+
+function readCarInput() {
+ var th = 0, st = 0;
+ if (keys['KeyW'] || keys['ArrowUp']) th += 1;
+ if (keys['KeyS'] || keys['ArrowDown']) th -= 1;
+ if (keys['KeyA'] || keys['ArrowLeft']) st += 1; // руль влево (исправлено: влево/вправо было перепутано)
+ if (keys['KeyD'] || keys['ArrowRight']) st -= 1; // руль вправо
+ return { throttle: th, steer: st, handbrake: !!keys['Space'], brakeHeld: (th < 0) };
+}
+
+var _cbR = new THREE.Vector3(), _cbU = new THREE.Vector3(), _cbF = new THREE.Vector3(), _cbM = new THREE.Matrix4();
+function carRespawn() {
+ var CP = window.PZCarPhys, gy = groundH(CAR_SPAWN.x, CAR_SPAWN.z);
+ carObj.pos = CP._v(CAR_SPAWN.x, gy + 2.0, CAR_SPAWN.z);
+ carObj.moveSpeed = CP._v(0, 0, 0); carObj.turnSpeed = CP._v(0, 0, 0);
+ carObj.setHeading(0);
+}
+function carStep(dt) {
+ if (!carObj) return;
+ if (keys['KeyR']) carRespawn();
+ var inp = readCarInput(); carAcc += dt; var n = 0;
+ while (carAcc >= 0.02 && n < 6) { carObj.step(inp, carGround); carAcc -= 0.02; n++; } // фиксированные 50 Гц
+ carMesh.position.set(carObj.pos.x, carObj.pos.y, carObj.pos.z);
+ _cbR.set(carObj.right.x, carObj.right.y, carObj.right.z);
+ _cbU.set(carObj.up.x, carObj.up.y, carObj.up.z);
+ _cbF.set(carObj.fwd.x, carObj.fwd.y, carObj.fwd.z);
+ _cbM.makeBasis(_cbR, _cbU, _cbF); carMesh.quaternion.setFromRotationMatrix(_cbM);
+ for (var i = 0; i < 4; i++) {
+ var w = carMesh_wheels[i]; if (!w) continue;
+ var pb = carObj.m_wheelPosBody[i]; w.position.set(pb.x, pb.y, pb.z);
+ var steer = (i < 2) ? carObj.m_fSteerAngle : 0; // FL,FR поворачиваются
+ w.rotation.set(0, -steer, Math.PI / 2);
+ }
+}
+
+var _carGoal = new THREE.Vector3(), _carLook = new THREE.Vector3();
+function carCamera() {
+ controls.enabled = false;
+ _cbF.set(carObj.fwd.x, 0, carObj.fwd.z); if (_cbF.lengthSq() < 1e-4) _cbF.set(0, 0, 1); _cbF.normalize();
+ _carGoal.set(carObj.pos.x, carObj.pos.y, carObj.pos.z).addScaledVector(_cbF, -12).addScaledVector(WUP, 5.5);
+ camera.position.lerp(_carGoal, 0.12);
+ _carLook.set(carObj.pos.x, carObj.pos.y + 1.3, carObj.pos.z);
+ _camLook.lerp(_carLook, 0.3); camera.lookAt(_camLook);
+}
+
+/* --- стартовый выбор транспорта --- */
+(function vehicleSelect() {
+ var ov = document.createElement('div');
+ ov.id = 'vsOverlay';
+ ov.style.cssText = 'position:fixed;inset:0;z-index:10050;display:flex;flex-direction:column;align-items:center;justify-content:center;background:rgba(4,6,12,.88);backdrop-filter:blur(4px);-webkit-backdrop-filter:blur(4px);font-family:system-ui,Segoe UI,Roboto,sans-serif;color:#eef3ff';
+ ov.innerHTML =
+ '<div style="font:800 30px system-ui;margin-bottom:6px;text-align:center;letter-spacing:1px">ПЛАНЕТА ЖОПА</div>' +
+ '<div style="opacity:.85;margin-bottom:24px">На чём поедешь?</div>' +
+ '<div style="display:flex;gap:18px;flex-wrap:wrap;justify-content:center">' +
+ '<button id="vsDrone" style="cursor:pointer;border:0;border-radius:16px;padding:24px 28px;min-width:190px;line-height:1.35;background:linear-gradient(180deg,#4aa3ff,#2166c8);color:#fff;font:800 20px system-ui;box-shadow:0 12px 40px rgba(0,0,0,.5)">🚁<br>ДРОН<br><span style="font:500 12px system-ui;opacity:.85">полёт · акро · WASD</span></button>' +
+ '<button id="vsCar" style="cursor:pointer;border:0;border-radius:16px;padding:24px 28px;min-width:190px;line-height:1.35;background:linear-gradient(180deg,#ff6a4a,#c8291e);color:#fff;font:800 20px system-ui;box-shadow:0 12px 40px rgba(0,0,0,.5)">🚗<br>МАШИНА<br><span style="font:500 12px system-ui;opacity:.85">физика reVC · газ/руль</span></button>' +
+ '</div>' +
+ '<div style="margin-top:22px;opacity:.6;font-size:12px">сменить транспорт — перезагрузка страницы</div>';
+ document.body.appendChild(ov);
+ ['pointerdown', 'touchstart', 'mousedown', 'keydown'].forEach(function (ev) { ov.addEventListener(ev, function (e) { e.stopPropagation(); }); });
+ document.getElementById('vsDrone').onclick = function () { carMode = false; ov.remove(); };
+ document.getElementById('vsCar').onclick = function () {
+ carMode = true;
+ try { spawnCar(); } catch (e) { console.error('spawnCar', e); }
+ try { if (typeof drone !== 'undefined' && drone) drone.visible = false; } catch (e) {}
+ try { sd.style.display = 'none'; } catch (e) {}
+ try { dp.style.display = 'none'; } catch (e) {}
+ var hp = document.getElementById('help');
+ if (hp) hp.innerHTML = '<b>🚗 МАШИНА (физика reVC):</b> <kbd>W</kbd> газ · <kbd>S</kbd> тормоз/задний · <kbd>A</kbd>/<kbd>D</kbd> руль · <kbd>Space</kbd> ручник · <kbd>R</kbd> сброс';
+ ov.remove();
+ };
+})();