fix(studio): бластер от 3-го лица стреляет в точку клика, а не в центр камеры
При свободном курсоре (нет pointer-lock, 3-е лицо) выстрел шёл из getForwardRay (фокус камеры). Теперь onDown берёт координаты клика → setAimScreenPoint → луч через точку клика; onMove обновляет _holdAim для авто-огня при удержании. При pointer-lock (1-е лицо, курсор в центре) — прежнее поведение (центр). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
e4fdd91b12
commit
931d53b4d9
@ -90,6 +90,18 @@ export class WeaponSystem {
|
||||
if (e.button !== 0) return;
|
||||
// Если UI-режим курсора — не стреляем (мышь работает по GUI)
|
||||
if (this.scene3d?.player?.isUiCursorMode?.()) return;
|
||||
// Если курсор СВОБОДЕН (нет pointer-lock — обычно 3-е лицо) — стреляем
|
||||
// ТУДА, КУДА КЛИКНУЛИ, а не в центр камеры. При pointer-lock курсор в
|
||||
// центре экрана → используем прицел камеры (aim не задаём).
|
||||
if (document.pointerLockElement !== canvas) {
|
||||
const rect = canvas.getBoundingClientRect();
|
||||
const cx = (e.clientX != null ? e.clientX : 0) - rect.left;
|
||||
const cy = (e.clientY != null ? e.clientY : 0) - rect.top;
|
||||
if (cx >= 0 && cy >= 0 && cx <= rect.width && cy <= rect.height) {
|
||||
this.setAimScreenPoint(cx * (canvas.width / rect.width),
|
||||
cy * (canvas.height / rect.height));
|
||||
}
|
||||
}
|
||||
this._mouseDown = true;
|
||||
this._tryFire();
|
||||
};
|
||||
@ -97,14 +109,28 @@ export class WeaponSystem {
|
||||
if (e.button !== 0) return;
|
||||
this._mouseDown = false;
|
||||
};
|
||||
// При свободном курсоре (3-е лицо) запоминаем позицию мыши — чтобы
|
||||
// авто-огонь при удержании ЛКМ продолжал стрелять в точку курсора.
|
||||
const onMove = (e) => {
|
||||
if (!this._mouseDown) return;
|
||||
if (document.pointerLockElement === canvas) return;
|
||||
const rect = canvas.getBoundingClientRect();
|
||||
const cx = (e.clientX != null ? e.clientX : 0) - rect.left;
|
||||
const cy = (e.clientY != null ? e.clientY : 0) - rect.top;
|
||||
if (cx >= 0 && cy >= 0 && cx <= rect.width && cy <= rect.height) {
|
||||
this._holdAim = { x: cx * (canvas.width / rect.width), y: cy * (canvas.height / rect.height) };
|
||||
}
|
||||
};
|
||||
const onKey = (e) => {
|
||||
if (e.code === 'KeyR') this.reload();
|
||||
};
|
||||
canvas.addEventListener('mousedown', onDown);
|
||||
window.addEventListener('mouseup', onUp);
|
||||
window.addEventListener('mousemove', onMove);
|
||||
window.addEventListener('keydown', onKey);
|
||||
this._listeners.push({ target: canvas, type: 'mousedown', fn: onDown });
|
||||
this._listeners.push({ target: window, type: 'mouseup', fn: onUp });
|
||||
this._listeners.push({ target: window, type: 'mousemove', fn: onMove });
|
||||
this._listeners.push({ target: window, type: 'keydown', fn: onKey });
|
||||
|
||||
// Регистрируем перед-кадровый хук для авто-стрельбы (если auto=true)
|
||||
@ -583,7 +609,12 @@ export class WeaponSystem {
|
||||
// (для tap-to-shoot на мобиле). Точка применяется один раз.
|
||||
let hit = null;
|
||||
let ray;
|
||||
const aim = this._aimScreenPoint;
|
||||
// aim: разовый клик (_aimScreenPoint) или удержание по курсору (_holdAim,
|
||||
// только когда курсор свободен — нет pointer-lock).
|
||||
let aim = this._aimScreenPoint;
|
||||
if (!aim && this._holdAim && document.pointerLockElement !== this.scene3d?.canvas) {
|
||||
aim = this._holdAim;
|
||||
}
|
||||
try {
|
||||
if (aim) {
|
||||
ray = this.scene.createPickingRay(aim.x, aim.y, null, camera);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user