You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在p5.js WEBGL中实现相机围绕目标点旋转?

解决p5.js WEBGL中第三人称相机围绕目标旋转的问题

要实现相机围绕玩家(立方体)旋转,核心是通过极坐标转换计算相机位置,而非直接旋转玩家模型。以下是修正后的完整方案:

关键调整点

  • 添加相机旋转角度与距离变量,控制相机的相对位置
  • 使用鼠标拖动事件控制旋转,限制垂直旋转范围避免异常视角
  • 基于相机视角调整玩家移动方向(不再沿世界坐标轴移动)
  • 修复重力逻辑的错误,确保玩家正常落地

修正后的完整代码

let x = 0;
let y = 1;
let z = 0;
let dy = 0; // 垂直速度(用于跳跃和重力)
let speed = 2;
let cam;
let jumpHeight = 0.5;
let grav = 0.02;

// 相机旋转与距离参数
let camYaw = 0; // 水平旋转角(绕Y轴)
let camPitch = -0.3; // 垂直旋转角(绕X轴),初始值让相机稍微俯视玩家
let camDistance = 250; // 相机到玩家的固定距离

function setup() {
  createCanvas(windowWidth, windowHeight, WEBGL);
  background(100);
  debugMode();
  cam = createCamera();
}

function draw() {
  background(100);
  controller();
  gravity();

  // 通过极坐标计算相机相对于玩家的位置
  let camX = x + camDistance * sin(camYaw) * cos(camPitch);
  let camY = y + camDistance * sin(camPitch);
  let camZ = z + camDistance * cos(camYaw) * cos(camPitch);
  
  // 设置相机位置并始终看向玩家
  cam.setPosition(camX, camY, camZ);
  cam.lookAt(x, y, z);

  // 绘制玩家立方体
  push();
  translate(x, y, z);
  box(20);
  pop();
}

function controller() {
  let moveSpeed = speed;
  // 获取相机旋转矩阵,提取前向和右向向量(用于基于视角的移动)
  let camMatrix = cam.getMatrix();
  let forward = createVector(-camMatrix[8], -camMatrix[9], -camMatrix[10]).normalize();
  let right = createVector(camMatrix[0], camMatrix[1], camMatrix[2]).normalize();

  // W/S:沿相机前向/后向移动
  if (keyIsDown(87)) {
    x += forward.x * moveSpeed;
    z += forward.z * moveSpeed;
  }
  if (keyIsDown(83)) {
    x -= forward.x * moveSpeed;
    z -= forward.z * moveSpeed;
  }
  // A/D:沿相机左向/右向移动
  if (keyIsDown(65)) {
    x -= right.x * moveSpeed;
    z -= right.z * moveSpeed;
  }
  if (keyIsDown(68)) {
    x += right.x * moveSpeed;
    z += right.z * moveSpeed;
  }
}

function keyPressed() {
  // 空格跳跃,仅当玩家在地面时生效
  if (keyCode == 32 && y <= 0.1) {
    dy = -jumpHeight;
  }
}

function gravity() {
  y += dy;
  dy += grav; // 持续施加重力加速度
  // 落地检测,重置位置与垂直速度
  if (y <= 0) {
    y = 0;
    dy = 0;
  }
}

function mouseDragged() {
  // 根据鼠标位移更新相机旋转角度
  camYaw += mouseX - pmouseX;
  camPitch += mouseY - pmouseY;
  
  // 限制垂直旋转范围,避免相机翻转到异常角度
  camPitch = constrain(camPitch, -PI/2 + 0.1, PI/2 - 0.1);
}

核心代码解释

  1. 相机位置计算:
    利用三角函数将极坐标(角度+距离)转换为笛卡尔坐标,确保相机始终围绕玩家旋转,同时保持固定距离。camYaw控制水平旋转,camPitch控制垂直旋转。

  2. 基于视角的移动:
    通过cam.getMatrix()获取相机的旋转矩阵,从中提取前向和右向向量,让玩家的WASD移动始终跟随相机视角方向,符合第三人称控制器的常规逻辑。

  3. 鼠标旋转控制:
    使用mouseDragged事件捕捉鼠标位移,实时更新旋转角度,并通过constrain限制垂直旋转范围,防止相机过度上下翻转导致视角异常。

  4. 重力修复:
    修正原代码中错误的落地逻辑,当玩家接触地面时重置垂直位置和速度,确保跳跃和重力表现正常。

内容的提问来源于stack exchange,提问作者CoderGuy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 18:00:55