javascript - 如何使两个 Canvas 元素发生碰撞

标签 javascript jquery html css canvas

我在 canvas 中有 2 个元素,我想让两个元素相互碰撞,当它们碰撞时其中一个元素应该反转它的速度,我没有得到使它们发生碰撞的逻辑,这是我的代码。

https://codepen.io/Thakur92411/pen/vjXJqq?editors=0011

<canvas id="canvas"></canvas>

这是我的javascript

    var can_width = document.querySelector("canvas").width = 500;
    var can_height = document.querySelector("canvas").height = 500;

var c = document.getElementById("canvas");
    ctx = c.getContext("2d");

    var x = 200;
    var dx = 6;

    var y = 300;
    var dy = 5;
    var radius = 30;

    var rx = 400;
    var ry = 200;

    function animate(){
    requestAnimationFrame(animate);

    ctx.clearRect(0,0,can_width,can_height);
    ctx.beginPath();
    ctx.strokeStyle="red";
    ctx.fillStyle="#FF0000";
    ctx.arc(x, y, radius, 0, 2 * Math.PI);
    ctx.fillRect(rx,ry,20,100);
    ctx.fill();
    ctx.stroke();

       if((can_height-y)-radius > x )
      {
        dx = + dx; 
      }

      if(x + radius > can_width || x - radius < 0 || can_width - ( can_width-rx )-radius < x )
      {
        dx = - dx; 
      }
      else if (y + radius > can_height || y - radius < 0 ){
        dy = - dy;
      }
    console.log(rx);
      x += dx;
      y += dy;
    }
    animate();

最佳答案

我写了一个简单的算法来检查圆是否与桨碰撞。并且还使桨可移动。详情请看下面的演示和评论...

var can_width = document.querySelector("canvas").width = 500;
var can_height = document.querySelector("canvas").height = 500;

var c = document.getElementById("canvas");
ctx = c.getContext("2d");

var x  = 200,
    dx = 6;

var y  = 300,
    dy = 5;

var radius = 30;

var rx = 400,
    ry = 200;

var paddleWidth  = 20,
    paddleHeight = 100;

var isCollided = false;

function animate() {
  requestAnimationFrame(animate);

  ctx.clearRect(0, 0, can_width, can_height);
  ctx.beginPath();
  ctx.strokeStyle = "red";
  ctx.fillStyle = "#FF0000";
  ctx.arc(x, y, radius, 0, 2 * Math.PI);
  ctx.fillRect(rx, ry, paddleWidth, paddleHeight);
  ctx.fill();
  ctx.stroke();

  //    x      y    inXRange    x       y
  // (xLeft, yTop)   atTop   (xRight, yTop)
  //                ---------
  //               |         |
  //     atLeft    |         |  atRight
  //     inYRange  |         |  inYRange
  //                ---------
  // (xLeft, yBot)   atBot   (xRight, yBot)
  //                inXRange

  // the coordinates of the paddle
  var xLeft  = rx,
      xRight = rx + paddleWidth,
      yTop   = ry,
      yBot   = ry + paddleHeight;

  // check if in specific range (see the figure above)
  var inXRange = x >= xLeft && x <= xRight,
      inYRange = y >= yTop && y <= yBot;

  // check if in specific area (see the figure above)
  var atTop   = y <= yTop,
      atBot   = y >= yBot,
      atLeft  = x <= xLeft,
      atRight = x >= xRight;

  // check if collides with 4 boundaries
  var outXLeft  = (x - radius) <= 0,
      outXRight = (x + radius) >= can_width,
      outYTop   = (y - radius) <= 0,
      outYBot   = (y + radius) >= can_height

  isCollided = false;
  
  // collides with any of boundaries
  if(outXLeft || outXRight || outYTop || outYBot) {
    // if collides with boundary...
    // left : set circle's x to radius
    // right: set circle's x to can_width-radius
    // or do nothing
    x  = outXLeft ? radius : outXRight ? (can_width - radius) : x;
    
    // if collides with boundary...
    // top: set circle's y to radius
    // bot: set circle's y to can_height-radius
    // or do nothing
    y  = outYTop  ? radius : outYBot   ? (can_height - radius) : y;
 
    // if collides with boundary...
    // right: set dx to negative
    // left : set dx to positive
    // or do nothing
    dx = outXRight ? -Math.abs(dx) : outXLeft ? Math.abs(dx) : dx;
    
    // if collides with boundary...
    // bot: set dy to negative
    // top: set dy to positive
    // or do nothing
    dy = outYBot   ? -Math.abs(dy) : outYTop  ? Math.abs(dy) : dy;
  }
  else {
    // if doesn't collide with any of boundaries, then...
    
    // if center point of the circle is at..., 
    // calculate the distance between center point and the paddle...
    
    // atLeft : xLeft - x
    // atRight: xRight - x
    // not both of them: doesn't matter, calculate the rY distance is enough
    var rX = Math.abs(atLeft ? xLeft - x : atRight ? x - xRight : 0);
    
    // atTop : yTop - y
    // atRight: yBot - y
    // not both of them: doesn't matter, calculate the rX distance is enough
    var rY = Math.abs(atTop  ? yTop - y : atBot   ? y - yBot : 0);

    // if both rX and rY are less than radius means the circle collides with the paddle
    if(rX <= radius && rY <= radius) {
      // if center point of the circle is at...
      
      // atLeft : set dx to negative
      // atRight: set dx to positive
      // or do nothing
      dx = atLeft ? -Math.abs(dx) : atRight  ? Math.abs(dx) : dx;
      
      // atTop: set dy to negative
      // atBot: set dy to positive
      // or do nothing
      dy = atTop  ? -Math.abs(dy) : atBot    ? Math.abs(dy) : dy;
    }
  }

  x += dx;
  y += dy;
}
animate();

// move the paddle vertically
c.addEventListener('mousemove', function(e){
  var maxHeight = can_height - paddleHeight;
  var _ry = e.clientY - paddleHeight/2;
  ry = _ry <= 0 ? 0 : (_ry >= maxHeight) ? maxHeight : _ry;
})
canvas {
  background: #ddd
}

body {
  margin: 0px;
}
<canvas id="canvas"></canvas>

关于javascript - 如何使两个 Canvas 元素发生碰撞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50062461/

相关文章:

javascript - HTML5 - html、前缀和元相关

javascript - 查看完成 Ajax 请求需要多长时间

javascript - 将值传递给函数参数 javascript 时遇到问题

javascript - 按下按钮时切换 cookie 和类

javascript - 如何阅读网页以获取其html内容

java - Java 中类似 Facebook 的通知实现

javascript - 使用 jQuery 换行函数

jquery - 使用 jQuery 将类添加到 DOM 对象数组的正确方法是什么?

html - 如何设置表格样式以鼓励某些单元格先垂直生长再水平生长

html - 友好的 URL 和 anchor