javascript - 侧面发生碰撞时向上滑行

标签 javascript canvas geometry

我很抱歉这个粗鲁的标题,我不知道如何正确地标题这个问题,但我想做的是: 考虑到圆圈正在朝那个方向移动,其中红 Angular 是 Canvas ,下面的obj是圆圈。

circle moving to that direction

现在当圆圈到达侧面时。

enter image description here

我当前的实现是,当发生碰撞时,它将停止移动,因为在我的 update 函数中,它无论如何都会阻止移动。这困扰了我对如何实现这一点的思考,我想做的是圆圈将继续向上移动,同时防止 X 发生任何移动,直到它到达顶 Angular 。

corners 变量,其中 cW 是 Canvas 宽度cH 是高度

var corners = [
    // top left
    { x: 0, y: 0 },
    // top right
    { x: cW, y: 0 },
    // bottom right
    { x: cW, y: cH },
    // bottom left
    { x: 0, y: cH }
];

我的碰撞检测函数,其中 obj 参数是我使用 X、Y 和半径 创建的圆形对象。

var outOfBounds = function (obj) {
    var returnValue = false,
        circX = obj.get("X"),
        circY = obj.get("Y"),
        circR = obj.get("radius");

        // check 4 corners of the canvas
        for (var i = 0; i < corners.length; i++) {
            var start = corners[i],
                end = i == corners.length - 1 ? corners[0] : corners[i + 1],
                // Calculate the euclidean distance between start and end points
                distStartToEnd = Math.sqrt(
                      Math.pow(end.x - start.x, 2)
                    + Math.pow(end.y - start.y, 2)
                ),
                // compute the direction vector d from start to end
                d = [
                    (end.x - start.x) / distStartToEnd,
                    (end.y - start.y) / distStartToEnd
                ],
                // compute the value t of the closest point to the circle center (cx, cy)
                t =   (d[0] * (circX - start.x)) 
                    + (d[1] * (circY - start.y)),
                e = {
                    coords: {
                        x : 0,
                        y : 0
                    }
                },
                distCircToE;

            // compute the coordinates of the point e on line and closest to c
            e.coords.x = (t * d[0]) + start.x;
            e.coords.y = (t * d[1]) + start.y;

            // calculate the euclidean distance between circle and e
            distCircToE = Math.sqrt(
                  Math.pow(e.coords.x - circX, 2)
                + Math.pow(e.coords.y - circY, 2)
            );

            // check line intersects the circle
            if (distCircToE < circR) {
                returnValue = true;
                break;
            }
        }

    return returnValue;
}

以及我处理移动的更新函数

var update = function () {
    var time = (new Date()).getTime() - startTime;
    // Loop through each sections
    jQuery.each(sections, function () {
        var self = this,
            X = self.get("X"),
            Y = self.get("Y"),
            r = self.get("radius"),
            a = self.get("angle"),
            aX = X + parseInt((5 * Math.cos(a * Math.PI / 180)) * time) / 1000,
            aY = Y + parseInt((5 * Math.sin(a * Math.PI / 180)) * time) / 1000;

        // Prevent any of the circles from getting out of canvas
        if (!outOfBounds(self)) {
            self.set("X", aX);
            self.set("Y", aY);
        }
    });
}

预先感谢您提供的任何帮助。

最佳答案

当球碰撞时,将其放回界内并改变 Angular 。

var can = document.getElementById("can");
var ctx = can.getContext('2d');
var cW = can.width;
var cH = can.height;

var sections = [{
  X: 100,
  Y: 100,
  radius: 20,
  angle: 180,
  startTime: (new Date()).getTime()
}];





var corners = [
  // top left
  {
    x: 0,
    y: 0
  },
  // top right
  {
    x: cW,
    y: 0
  },
  // bottom right
  {
    x: cW,
    y: cH
  },
  // bottom left
  {
    x: 0,
    y: cH
  }
];

var outOfBounds = function(obj) {
  var returnValue = false,
    circX = obj.X;
    circY = obj.Y;
    circR = obj.radius;

  // check 4 corners of the canvas
  for (var i = 0; i < corners.length; i++) {
    var start = corners[i],
      end = i == corners.length - 1 ? corners[0] : corners[i + 1],
      // Calculate the euclidean distance between start and end points
      distStartToEnd = Math.sqrt(
        Math.pow(end.x - start.x, 2) + Math.pow(end.y - start.y, 2)
      ),
      // compute the direction vector d from start to end
      d = [
        (end.x - start.x) / distStartToEnd, (end.y - start.y) / distStartToEnd
      ],
      // compute the value t of the closest point to the circle center (cx, cy)
      t = (d[0] * (circX - start.x)) + (d[1] * (circY - start.y)),
      e = {
        coords: {
          x: 0,
          y: 0
        }
      },
      distCircToE;

    // compute the coordinates of the point e on line and closest to c
    e.coords.x = (t * d[0]) + start.x;
    e.coords.y = (t * d[1]) + start.y;

    // calculate the euclidean distance between circle and e
    distCircToE = Math.sqrt(
      Math.pow(e.coords.x - circX, 2) + Math.pow(e.coords.y - circY, 2)
    );

    // check line intersects the circle
    if (distCircToE < circR) {
      returnValue = true;
      break;
    }
  }

  return returnValue;
};


var update = function() {
  // Loop through each sections
  
  var len = sections.length;
  
  for (var i = 0; i < len; i++) {
    var obj = sections[i];
    var X = obj.X;
    var Y = obj.Y;
    var r = obj.radius;
    var a = obj.angle;
    var time = (new Date()).getTime() - obj.startTime
    var aX = X + parseInt((5 * Math.cos(a * Math.PI / 180)) * time) / 1000;
    var aY = Y + parseInt((5 * Math.sin(a * Math.PI / 180)) * time) / 1000;

    // Prevent any of the circles from getting out of canvas
    if (!outOfBounds(obj)) {
      obj.X = aX;
      obj.Y = aY;
    } else {
      // CHANGE DIRECTION HERE
      obj.angle += 90;
      obj.angle %= 360;
      obj.startTime = (new Date()).getTime();
      // MAKE OBJECT STAY IN BOUNDS
      if (obj.X + obj.radius > cW) {
        obj.X = cW-obj.radius-1;
      } else if (obj.X - obj.radius < 0) {
        obj.X = obj.radius+1;
      }
      if (obj.Y + obj.radius > cH) {
        obj.Y = cH-obj.radius-1;
      } else if (obj.Y - obj.radius < 0) {
        obj.Y = obj.radius+1;
      }
    }
  }
};

function ani() {
  ctx.clearRect(0,0,cW,cH);
  update();
  var len = sections.length;
  for (var i = 0; i < len; i++) {
    var obj = sections[i];
    ctx.beginPath();
    ctx.fillStyle = "#000000";
    ctx.arc(obj.X, obj.Y, obj.radius, 0, Math.PI * 2);
    ctx.fill();
  }
  requestAnimationFrame(ani);
}

var startTime = (new Date()).getTime();

ani();
<canvas id="can" width="300" height="250" style="border:2px solid red"></canvas>

关于javascript - 侧面发生碰撞时向上滑行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32073219/

相关文章:

javascript - 使用多个 View 注册一个 Backbone 模型

javascript - 在 Javascript 中递增 < 1

javascript - 需要滑出按钮才能单独工作。当单击一个按钮时,两者都会执行任务。

javascript - 将对象置于 Canvas 中居中

javascript - document.createElement() 以不同方式创建元素?

math - 在一点处分割三次贝塞尔曲线

image - 如何在 Titanium 中以圆形裁剪图像?

php - GMT 时间格式转整数格式

javascript - Canvas 游戏 : My food disappears

c++ - 在 opengl 中将立方体转换为球体