// Loop cập nhật toàn bộ trò chơi function animate() { if (!isGameRunning) return; requestAnimationFrame(animate); // SỬA LỖI ĐIỀU KHIỂN: Xoay vector di chuyển dựa trên góc camera // Đảm bảo hướng lên (joystick) luôn là hướng camera nhìn tới const moveInputX = moveInput.x; const moveInputZ = moveInput.z; // Đảo dấu nếu cần cho đúng hướng Forward const cos = Math.cos(cameraAngleY); const sin = Math.sin(cameraAngleY); // Công thức chuẩn để xoay vector 2D theo góc Camera const moveX = (moveInputX * cos + moveInputZ * sin); const moveZ = (-moveInputX * sin + moveInputZ * cos); const speedCoeff = 0.35; playerVel.x = moveX * speedCoeff; playerVel.z = moveZ * speedCoeff; // Xoay nhân vật hướng về nơi đang đi if (Math.abs(moveX) > 0.1 || Math.abs(moveZ) > 0.1) { const targetAngle = Math.atan2(moveX, moveZ); p3d_player.rotation.y = targetAngle; } function setupCameraControls(element) { element.addEventListener('touchstart', (e) => { if (e.touches.length === 1) { isDraggingCam = true; prevTouchX = e.touches[0].clientX; } }, { passive: true }); element.addEventListener('touchmove', (e) => { if (isDraggingCam) { const deltaX = e.touches[0].clientX - prevTouchX; cameraAngleY += deltaX * 0.01; // Đổi dấu để xoay mượt theo ngón tay prevTouchX = e.touches[0].clientX; } }, { passive: true });