与正方形碰撞后如何保持圆周速度?

我正在开发一个游戏,其中玩家是一个圆圈,瓷砖是正方形。用户用键盘移动头像(圆圈),不能与瓷砖(方块)发生碰撞。

另外,我希望圆圈在碰到角落时沿着正方形滑动,这样如果玩家继续按下键向同一方向移动,他们将沿着正方形滑动而不是卡在上面。

我已经开发了我在这里面临的问题的完整再现:

let canvas = document.querySelector("canvas");
let ctx = canvas.getContext("2d");

class Vec2 {
  constructor(x, y) {
    this.x = x || 0;
    this.y = y || 0;
  }

  distance(v) {
    let x = v.x - this.x;
    let y = v.y - this.y;

    return Math.sqrt(x * x + y * y);
  }

  magnitude() { 
    return Math.sqrt(this.x * this.x + this.y * this.y);
  }

  dot(v) { 
    return this.x * v.x + this.y * v.y;
  }

  normalize() {
    let magnitude = this.magnitude();
    
    return new Vec2(this.x / magnitude, this.y / magnitude);
  }
  
  multiply(val) {
    return typeof val === "number" ? new Vec2(this.x * val, this.y * val) : new Vec2(this.x * val.x, this.y * val.y);
  }

  subtract(val) {
    return typeof val === "number" ? new Vec2(this.x - val, this.y - val) : new Vec2(this.x - val.x, this.y - val.y);
  }

  add(val) {
    return typeof val === "number" ? new Vec2(this.x + val, this.y + val) : new Vec2(this.x + val.x, this.y + val.y);
  }
}

function clamp(value, min, max) {
  return Math.min(Math.max(value, min), max);
}

function drawCircle(xCenter, yCenter, radius) {
  ctx.beginPath();
  ctx.arc(xCenter, yCenter, radius, 0, 2 * Math.PI);
  ctx.fill();
}

function drawSquare(x, y, w, h) {
  ctx.beginPath();
  ctx.rect(x, y, w, h);
  ctx.stroke();
}

function circleRectangleCollision(cX, cY, cR, rX, rY, rW, rH) {
  let x = clamp(cX, rX, rX + rW);
  let y = clamp(cY, rY, rY + rH);

  let cPos = new Vec2(cX, cY);

  return cPos.distance(new Vec2(x, y)) < cR;
}

function getCircleRectangleDisplacement(rX, rY, rW, rH, cX, cY, cR, cVel) {
  let circle = new Vec2(cX, cY);

  let nearestX = Math.max(rX, Math.min(cX, rX + rW));
  let nearestY = Math.max(rY, Math.min(cY, rY + rH));    
  let dist = new Vec2(cX - nearestX, cY - nearestY);

  let tangentVel = dist.normalize().dot(cVel);

  // The original answer had `cVel.subtract(tangentVel * 2);` here
  // but that was giving me issues as well
  return cVel.add(tangentVel);
}

let circlePos = new Vec2(150, 80);
let squarePos = new Vec2(240, 110);

let circleR = 50;

let squareW = 100;
let squareH = 100;

let circleVel = new Vec2(5, 0);

draw = () => {
  ctx.fillStyle = "#b2c7ef";
  ctx.fillRect(0, 0, 800, 800); 

  ctx.fillStyle = "#ffffff";

  drawCircle(circlePos.x, circlePos.y, circleR);
  drawSquare(squarePos.x, squarePos.y, squareW, squareH);
}

update = () => {
  draw();

  if (circleRectangleCollision(circlePos.x, circlePos.y, circleR, squarePos.x, squarePos.y, squareW, squareH)) {
    circleVel = getCircleRectangleDisplacement(squarePos.x, squarePos.y, squareW, squareH, circlePos.x, circlePos.y, circleR, circleVel);
  }

  circlePos = circlePos.add(circleVel);
}

setInterval(update, 30);
canvas { display: flex; margin: 0 auto; }
<canvas></canvas>
以上是与正方形碰撞后如何保持圆周速度?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>