p5.collide2D icon indicating copy to clipboard operation
p5.collide2D copied to clipboard

Can you guys add some functionality?

Open Faeest opened this issue 1 year ago • 2 comments

don't be wrong, it's a pretty helpful plugin for my games. but, it's only detect the collision which only a bool, I have to smuggle some code so I know which direction the collision came in a rect to rect and circle to circle. so then I can use it on my platformer game. Can you guys add that?

Faeest avatar Jan 01 '24 23:01 Faeest

You can definitely do this. Here's an example GPT4 provided for circle2rect collision. Circle2circle should be easier. In this example collideRectCircle() is the exact same version as provided by the p5.collide2D library.

function setup() {
  createCanvas(400, 400);
  noCursor()
}

function draw() {
  background(220);

  if (collideRectCircle(mouseX, mouseY, 50, 50, 100, 100, 100)) {
    fill("red");
  } else {
    fill("white");
  }

  rect(mouseX, mouseY, 50, 50);
  circle(100, 100, 100);

  let pts = collisionPointsRectCircle(mouseX, mouseY, 50, 50, 100, 100, 100);

  if (pts) {
    for (let pt of pts) {
      fill('yellow')
      circle(pt.x, pt.y, 5);
    }
  }
}

function collideRectCircle(rx, ry, rw, rh, cx, cy, diameter) {
  //2d
  // temporary variables to set edges for testing
  var testX = cx;
  var testY = cy;

  // which edge is closest?
  if (cx < rx) {
    testX = rx; // left edge
  } else if (cx > rx + rw) {
    testX = rx + rw;
  } // right edge

  if (cy < ry) {
    testY = ry; // top edge
  } else if (cy > ry + rh) {
    testY = ry + rh;
  } // bottom edge

  // // get distance from closest edges
  var distance = this.dist(cx, cy, testX, testY);

  // if the distance is less than the radius, collision!
  if (distance <= diameter / 2) {
    return true;
  }
  return false;
}

function collisionPointsRectCircle(rx, ry, rw, rh, cx, cy, diameter) {
  let points = [];
  let radius = diameter / 2;
  let rectPoints = [
    { x: rx, y: ry },
    { x: rx + rw, y: ry },
    { x: rx, y: ry + rh },
    { x: rx + rw, y: ry + rh },
  ];

  // Check each corner of the rectangle
  for (let p of rectPoints) {
    if (dist(p.x, p.y, cx, cy) <= radius) {
      points.push(p);
    }
  }

  // Check middle points of each rectangle side
  let midPoints = [
    { x: rx + rw / 2, y: ry },
    { x: rx, y: ry + rh / 2 },
    { x: rx + rw / 2, y: ry + rh },
    { x: rx + rw, y: ry + rh / 2 },
  ];

  for (let p of midPoints) {
    let angle = Math.atan2(p.y - cy, p.x - cx);
    let circlePoint = {
      x: cx + radius * Math.cos(angle),
      y: cy + radius * Math.sin(angle),
    };

    if (
      circlePoint.x >= rx &&
      circlePoint.x <= rx + rw &&
      circlePoint.y >= ry &&
      circlePoint.y <= ry + rh
    ) {
      points.push(circlePoint);
    }
  }

  // Removing duplicate points
  points = points.filter(
    (point, index, self) =>
      index === self.findIndex((t) => t.x === point.x && t.y === point.y)
  );

  return points;
}

poisa avatar Jan 25 '24 16:01 poisa

Here's circle2circle as provided by GPT4:

function setup() {
  createCanvas(400, 400);
}

function draw() {
  background(240);
  let circle1 = { x: mouseX, y: mouseY, r: 40 };
  let circle2 = { x: 200, y: 200, r: 30 };

  let points = circleIntersection(circle1, circle2);
  fill("white");
  drawCircle(circle1);
  drawCircle(circle2);
  if (points) {
    drawPoints(points);
  }
}

function drawCircle(circle) {
  ellipse(circle.x, circle.y, circle.r * 2);
}

function drawPoints(points) {
  for (let p of points) {
    fill(255, 0, 0);
    ellipse(p.x, p.y, 10, 10);
  }
}

function circleIntersection(c1, c2) {
  let d = dist(c1.x, c1.y, c2.x, c2.y);

  if (d > c1.r + c2.r || d < abs(c1.r - c2.r) || (d === 0 && c1.r === c2.r)) {
    return null; // No intersection
  }

  let a = (c1.r * c1.r - c2.r * c2.r + d * d) / (2 * d);
  let h = sqrt(c1.r * c1.r - a * a);
  let p2 = {
    x: c1.x + (a * (c2.x - c1.x)) / d,
    y: c1.y + (a * (c2.y - c1.y)) / d,
  };

  return [
    {
      x: p2.x + (h * (c2.y - c1.y)) / d,
      y: p2.y - (h * (c2.x - c1.x)) / d,
    },
    {
      x: p2.x - (h * (c2.y - c1.y)) / d,
      y: p2.y + (h * (c2.x - c1.x)) / d,
    },
  ];
}

poisa avatar Jan 25 '24 16:01 poisa