0

I want to create a function that make collision detection with two objects in canvas using JavaScript. I have coin objects and piggy bank objects. I am trying to create a function that when the coin touches the piggy bank, the coin object will disappear. Can anyone help me to explain the algorithm of the collision detection please?

<!DOCTYPE html>
<html lang="en">
<head>
    <script src="https://unpkg.com/[email protected]/konva.min.js"></script>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        body{
            margin:0;
            padding: 0;
            overflow: hidden;
            background-color: lightyellow; 
        }
        .konvajs-content{
            background-color: aliceblue;
            margin: 5%;
            border: solid 5px gray;
        }
        #stage-parent{
            width: 100%;
        }
     
    </style>
</head>
<body>
    <div id="stage-parent">
    <div id="container"></div>
</div>
<script>
 var stageWidth =  1200;
 var stageHeight = 1200;

    var stage = new Konva.Stage({
        width: stageWidth,
        height: stageHeight,
        container: 'container'
    });

    var layer = new Konva.Layer();
    stage.add(layer);

    //1yen
    var ichiYenImg = new Konva.Image({
        x:20,
        y:20,
        width:100,
        height: 100,
        draggable: true
            }); 
    layer.add(ichiYenImg);

    //5yen
    var goYenImg = new Konva.Image({
        x:200,
        y:20,
        width:100,
        height: 100,
        draggable: true
    });
layer.add(goYenImg);

    //10yen
    var jyuYenImg = new Konva.Image({
        x:200,
        y:50,
        width:100,
        height: 100,
        draggable: true
    });
layer.add(jyuYenImg);

    //50yen
    var gojyuYenImg = new Konva.Image({
        x:20,
        y:50,
        width:100,
        height: 100,
        draggable: true
    });
layer.add(gojyuYenImg);

    //500yen
    var gohyakuYenImg = new Konva.Image({
        x:100,
        y:20,
        width:100,
        height: 100,
        draggable: true
    });
layer.add(gohyakuYenImg);

    //100yen
    var hyakuYenImg = new Konva.Image({
        x:100,
        y:50,
        width:100,
        height: 100,
        draggable: true
    });
layer.add(hyakuYenImg);

  //piggy bank 1yen
  var ichiYenpiggyImg = new Konva.Image({
        x:100,
        y:500,
        width:100,
        height: 100,
        draggable: false
    });
layer.add(ichiYenpiggyImg);

//piggy bank 5yen
var goYenpiggyImg = new Konva.Image({
        x:450,
        y:500,
        width:100,
        height: 100,
        draggable: false
    });
layer.add(goYenpiggyImg);

//piggy bank 10yen
var jyuYenpiggyImg = new Konva.Image({
        x:800,
        y:500,
        width:100,
        height: 100,
        draggable: false
    });
layer.add(jyuYenpiggyImg);

//piggy bank 50yen
var gojyuYenpiggyImg = new Konva.Image({
        x:100,
        y:650,
        width:100,
        height: 100,
        draggable: false
    });
layer.add(gojyuYenpiggyImg);

//piggy bank 100yen
var hyakuYenpiggyImg = new Konva.Image({
        x:450,
        y:650,
        width:100,
        height: 100,
        draggable: false
    });
layer.add(hyakuYenpiggyImg);

//piggy bank 500yen
var gohyakuYenpiggyImg = new Konva.Image({
        x:800,
        y:650,
        width:100,
        height: 100,
        draggable: false
    });
layer.add(gohyakuYenpiggyImg);

//1yen
var imageObj1 = new Image();
imageObj1.onload = function(){
    ichiYenImg.image(imageObj1);
    layer.draw();
};
var sourceImg1 = "https://illustrain.com/img/work/2016/illustrain09-okane5.png";
drawImage(sourceImg1, ichiYenImg);
//5yen

var sourceImg2 = "https://illustrain.com/img/work/2016/illustrain09-okane7.png";
drawImage(sourceImg2, goYenImg);
//10yen

var sourceImg3 = "https://illustrain.com/img/work/2016/illustrain09-okane6.png";
drawImage(sourceImg3, jyuYenImg);
//50yen

var sourceImg4 = "https://illustrain.com/img/work/2016/illustrain02-money04.png";
drawImage(sourceImg4, gojyuYenImg);
//100yen

var sourceImg5 = "https://illustrain.com/img/work/2016/illustrain09-okane8.png";
drawImage(sourceImg5, hyakuYenImg);

//500yen
var sourceImg6 = "https://illustrain.com/img/work/2016/illustrain02-money06.png";
drawImage(sourceImg6, gohyakuYenImg);
//piggy1yen

var sourceImg7 = "https://user-images.githubusercontent.com/31402838/63416628-a322b080-c3b4-11e9-96e8-e709ace70ec1.png";
drawImage(sourceImg7, ichiYenpiggyImg);

//piggy5yen

var sourceImg8 = "https://user-images.githubusercontent.com/31402838/63416629-a322b080-c3b4-11e9-94a8-eb6c008d4584.png";
drawImage(sourceImg8, goYenpiggyImg);

//piggy10yen

var sourceImg9 = "https://user-images.githubusercontent.com/31402838/63416630-a322b080-c3b4-11e9-95ef-a04228fc3c0d.png";
drawImage(sourceImg9, jyuYenpiggyImg);
//piggy50yen
var sourceImg10 = "https://user-images.githubusercontent.com/31402838/63416631-a322b080-c3b4-11e9-9e99-43061e2eaf2c.png";
drawImage(sourceImg10, gojyuYenpiggyImg);

//piggy100yen
var sourceImg11 = "https://user-images.githubusercontent.com/31402838/63416626-a322b080-c3b4-11e9-9ff6-00b3babf3fe9.png";
drawImage(sourceImg11, hyakuYenpiggyImg);

//piggy500yen
var sourceImg12 = "https://user-images.githubusercontent.com/31402838/63416627-a322b080-c3b4-11e9-86c4-4edf13a57063.png";
drawImage(sourceImg12, gohyakuYenpiggyImg);

// This will draw the image on the canvas.
function drawImage(source, konvaImage) {
    var image = new Image();
    image.src = source;
    image.onload = function() {
        konvaImage.image(image);
        layer.draw();
    }
}

//use event delegation to update pointer style
layer.on('mouseover', function(evt){
    var shape = evt.target;
    document.body.style.cursor = 'pointer';
    shape.strokeEnabled(false);
    layer.draw();
});

layer.on('mouseout', function(evt){
    var shape = evt.target;
    document.body.style.cursor = 'default';
    shape.strokeEnabled(false);
    layer.draw();
});

function fitStageIntoParentContainer(){
    var container = document.querySelector('#stage-parent');
    

    var containerWidth = container.offsetWidth;
    var scale = containerWidth / stageWidth;

    stage.width(stageWidth * scale);
    stage.height(stageHeight * scale);
    stage.scale({x:scale, y: scale});
    stage.draw(); 
}
fitStageIntoParentContainer();
window.addEventListener('resize', fitStageIntoParentContainer);


</script>
</body>
</html>

1

1 Answer 1

3

First thing when debugging these problems is to reduce your code to a small example.
Once you have that, then you can go into more complicated things.

Below is your code with working collision:

var stage = new Konva.Stage({
  width: 400,
  height: 200,
  container: 'container'
});
var layer = new Konva.Layer();
stage.add(layer);

layer.on('dragmove', function(e) {
  var target = e.target;
  var targetRect = e.target.getClientRect();
  layer.children.each(function(obj) {
    if (obj === target) {
      return;
    }
    if (haveIntersection(obj.getClientRect(), targetRect)) {
      alert("Intersection")
    }    
  });
});

function haveIntersection(r1, r2) {
  return !(
    r2.x > r1.x + r1.width/2 ||
    r2.x + r2.width/2 < r1.x ||
    r2.y > r1.y + r1.height/2 ||
    r2.y + r2.height/2 < r1.y
  );
}

// This will draw the image on the canvas.
function drawImage(source, konvaImage) {
  layer.add(konvaImage);
  var image = new Image();
  image.src = source;
  image.onload = function() {
    konvaImage.image(image);
    layer.draw();
  }
}


//1yen
var ichiYenImg = new Konva.Image({
  x: 20,
  y: 20,
  width: 100,
  height: 100,
  draggable: true
});
var sourceImg1 = "https://illustrain.com/img/work/2016/illustrain09-okane5.png";
drawImage(sourceImg1, ichiYenImg);

//piggy bank 1yen
var ichiYenpiggyImg = new Konva.Image({
  x: 300,
  y: 100,
  width: 100,
  height: 100,
  draggable: false
});
var sourceImg7 = "https://user-images.githubusercontent.com/31402838/63416628-a322b080-c3b4-11e9-96e8-e709ace70ec1.png";
drawImage(sourceImg7, ichiYenpiggyImg);
<!DOCTYPE html>
<html lang="en">

<head>
  <script src="https://unpkg.com/[email protected]/konva.min.js"></script>
</head>

<body>
  <div id="stage-parent">
    <div id="container"></div>
  </div>
</body>

</html>

The key here is the function haveIntersection there we assume that the collision boxes are squares 1/2 the with and height of the objects.

The conditions inside that functions are:

  • Is the RIGHT edge of r1 to the RIGHT of the LEFT edge of r2? OR
  • Is the LEFT edge of r1 to the LEFT of the RIGHT edge of r2? OR
  • Is the BOTTOM edge of r1 BELOW the TOP edge of r2? OR
  • Is the TOP edge of r1 ABOVE the BOTTOM edge of r2?

There are more details here:
http://jeffreythompson.org/collision-detection/rect-rect.php

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you so much for the explanation! Can you please give me more detail explanation of the calculation inside the function haveIntersection?
@Kijimu7 I added a few more details... but there is very little calculation in the haveIntersection I just decided to go with 1/2 the with and height because your images have a lot of white padding surrounding them ... what exactly is not clear there?
I understand the function haveIntersection now. Thank you so much for your help :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.