rinrin
rinrin

Reputation: 49

Collisions on JavaScript

I have the following JavaScript code. Using the WASD keys, I want to control its movement. What I want to do now is that the black square if it collides with the red square would stop. It shouldn't pass through the red square but I have little to no idea how to detect side collisions.

This is what I have tried so far. It is able to stop when the black square hits one of the edges. Now I want it to do the same but also with the red square on the other side for all sides of the red square.

function onkeydown(e) {
  if (e.keyCode == 68 && rectX + 30 < canvas.width) {
    rectX++;
  } else if (e.keyCode == 65 && rectX > 0) {
    rectX--;
  } else if (e.keyCode == 87 && rectY > 0) {
    rectY--;
  } else if (e.keyCode == 83 && rectY + 30 < canvas.height) {
    rectY++;
  }
  fillRect();
}

window.addEventListener("keydown", onkeydown);

Upvotes: 0

Views: 101

Answers (1)

Scriptkiddy1337
Scriptkiddy1337

Reputation: 791

If you don't write your coordinates not in different variables, you don't need to rebuild the me object everytime, but this is how i would do that:

var canvas;
var context;
var ctx;
var rectX = 10;
var rectY = 10;

var object = {
  height: 50,
  width: 50,
  x: 10,
  y: 10,
  //color: "#FF0000"        
}

var spd = 100;
window.onload = function() {
  canvas = document.getElementById("canvas1");
  context = canvas.getContext("2d");
  ctx = canvas.getContext("2d");
  canvas.width = 400;
  canvas.height = 400;
  fillRect();
}

function isIn(me, array) {
    for (var value of array) {
        if ((me.x + me.width > value.x && me.x < value.x + value.width) && (me.y + me.height > value.y && me.y < value.y + value.height)) {
            return true;
        }
    }
    return false;
}

var terrains = [];
var me = {
    height: 30,
    width: 30,
};

function fillRect() {
  context.beginPath();
  context.fillStyle = "#ffffff";
  context.fillRect(0, 0, canvas.width, canvas.height);
  context.beginPath();
  context.fillStyle = "black";
  context.fillRect(rectX, rectY, me.width, me.height);
  
  //obstacle
  var index =   terrains.push({
      x: 230,
      y: 100,
      width: object.width,
      height: object.height,
  }) - 1;
  ctx.beginPath();
  ctx.fillStyle = "red";
  ctx.fillRect(terrains[index].x, terrains[index].y, terrains[index].width, terrains[index].height);
}

function onkeydown(e) {
  if (e.keyCode == 68 && rectX + 30 < canvas.width) {
    rectX++;
    var newMe = (Object.assign({
        x: rectX,
        y: rectY,
    }, me));
    if (isIn(newMe, terrains)) {
        rectX--;
    }
  } else if (e.keyCode == 65 && rectX > 0) {
    rectX--;
    var newMe = (Object.assign({
        x: rectX,
        y: rectY,
    }, me));
    if (isIn(newMe, terrains)) {
        rectX++;
    }
  } else if (e.keyCode == 87 && rectY > 0) {
    rectY--;
    var newMe = (Object.assign({
        x: rectX,
        y: rectY,
    }, me));
    if (isIn(newMe, terrains)) {
        rectY++;
    }
  } else if (e.keyCode == 83 && rectY + 30 < canvas.height) {
    rectY++;
    var newMe = (Object.assign({
        x: rectX,
        y: rectY,
    }, me));
    if (isIn(newMe, terrains)) {
        rectY--;
    }
  }
  fillRect();
}

window.addEventListener("keydown", onkeydown);
<canvas id="canvas1" style="border: 1px solid black"></canvas>

in core:

/**
 * @params {{x: number, y: number, width: number, height: number}} me
 * @params {{x: number, y: number, width: number, height: number}[]} array
 * @returns boolean
 */
function isIn(me, array) {
    for (var value of array) {
        if (
            (me.x + me.width > value.x && // right
            me.x < value.x + value.width) && // left
            (me.y + me.height > value.y && // bottom
            me.y < value.y + value.height) // above
        ) {
            return true;
        }
    }
    return false;
}

Upvotes: 2

Related Questions