Search code examples
javascriptfunctioncollision

Keep getting TypeError when using collision function


enter image description here

I keep getting this error when using points[i+2], it doesn't return an error, but doesn't work as supposed to either when using points[i+1] (line 60). I can't seem to figure out why this error is happening. I looked in the console and don't know what undefined should be.

var canvas = document.getElementById('canvas');
canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;
var ctx = canvas.getContext('2d');

var GLOBAL = {};

var point1 = [300, 300];
var point2 = [245, 55];
var point3 = [23, 143];
var point4 = [40, 200];

/*
 * y = mx + b
 * b = y - mx
 * m = y - b/x
 * x = y - b/m
 */
function lineSide(a, b, c) {
  var m = (b[1] - a[1]) / (b[0] - a[0]);
  var b = a[1] - (m * a[0]);

  var result = function(x, y) {
    if (y < m * x + b) return 0;
    else if (y > m * x + b) return 1;
    else if (y == m * x + b) return 2;
    //TODO implement error handling
  }(c[0], c[1]);

  switch (result) {
    case 0:
      return 'lt';
      break;
    case 1:
      return 'gt';
      break;
    case 2:
      return 'eq';
      break;
    default:
      return 'asdf';
      break;
  }
}

function inBounds(p, points) {
  var bcheck = [],
    pcheck = [];
  for (var i = 0; i < points.length; i++) {
    var pointa, pointb;
    if (i + 1 >= points.length) {
      pointa = points[i];
      pointb = points[0];
      bcheck.push(lineSide(pointa, pointb, points[1]));
    } else {
      pointa = points[i];
      pointb = points[i + 1];
      console.log(i + 2);
      console.log(points[i + 2]);
      bcheck.push(lineSide(pointa, pointb, points[i + 2])); // <-- THE PROBLEM AREA.
    }
  }
  // console.log(bcheck);

  for (var i = 0; i < points.length; i++) {
    var pointa, pointb;
    if (i + 1 >= points.length) {
      pointa = points[i];
      pointb = points[0];
      pcheck.push(lineSide(pointa, pointb, p));
    } else {
      pointa = points[i];
      pointb = points[i + 1];
      pcheck.push(lineSide(pointa, pointb, p));
    }
  }

  console.log(pcheck)
  for (var i in bcheck) {
    if (bcheck[i] != pcheck[i]) return false;
  }

  return true;
}

canvas.onmousemove = function(e) {
  GLOBAL.mouseX = e.clientX;
  GLOBAL.mouseY = e.clientY;
}

function render() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  if (inBounds([GLOBAL.mouseX, GLOBAL.mouseY], [point1, point2, point3, point4])) {
    ctx.fillStyle = 'red';
  } else {
    ctx.fillStyle = 'black';
  }

  ctx.beginPath();
  ctx.moveTo(point1[0], point1[1]);
  ctx.lineTo(point2[0], point2[1]);
  ctx.lineTo(point3[0], point3[1]);
  ctx.lineTo(point4[0], point4[1]);
  ctx.closePath();
  ctx.fill();

  window.requestAnimationFrame(render);
}

render();

Solution

  • The loop inside inBounds() needs to be adjusted.

    Either line 60 needs to only add by one:

    bcheck.push(lineSide(pointa, pointb, points[i + 1])); // <-- THE PROBLEM AREA.
    

    Or the if block on line 51 needs to add by two:

    if (i + 2 >= points.length) {
    

    I'm not entirely sure what you're trying to accomplish with the loop, so adjust as necessary.

    jsFiddle of option #2.

    The shape highlighting seems to break when the cursor exits through the bottom border. That's because the onmousemove event is only on the canvas element. You can change that event to be on the entire document, or add an onmouseleave event to the canvas element.

    canvas.onmouseleave = function(e) {
        GLOBAL.mouseX = undefined;
        GLOBAL.mouseY = undefined;
    };