diff options
| author | pacan-bot <[email protected]> | 2026-07-11 02:46:59 +0000 |
|---|---|---|
| committer | pacan-bot <[email protected]> | 2026-07-11 02:46:59 +0000 |
| commit | ae6d6689eec02b0328eb5e7b1f1f48c523268a8f (patch) | |
| tree | cd4c79cd53ae8449a1cab8fb39f796b383509938 /serve/_carmod.js | |
| parent | 499266fb5d1da142450280575702153740e14cfb (diff) | |
| download | planeta-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.js | 128 |
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(); + }; +})(); |
