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/konva#4.0.5/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>
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/konva#4.0.5/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
I have tried following
first load the image into the stage.
function loadPhoneImage() {
phoneImageStage = new Konva.Stage({
container: 'phoneContainer',
width: 600,
height: 550
});
phoneImageLayer = new Konva.Layer();
phoneImageStage.add(phoneImageLayer);
var phoneImg = new Konva.Image({
x: 30,
y: 20,
width: 450,
height: 500
});
phoneImageLayer.add(phoneImg);
var phoneImage = new Image();
var self = this;
phoneImage.onload = function () {
phoneImg.image(phoneImage);
phoneImageLayer.draw();
};
phoneImage.src = '../Content/Avaya_Phone.png';
}
Then programmatically added some labels on it
function loadPhoneNumberLabel(label) {
var phoneText = new Konva.Text({
x: 135,
y: 73,
text: label,
fontSize: 9,
width: 200,
fontFamily: 'Calibri',
fill: 'black',
align: 'right'
});
phoneImageLayer.add(phoneText);
}
After this i want to scale this image as per the browser size and also label position should not be changed on the image.so i have tried this
function fitStageIntoParentContainer() {
//var stageWidth = document.getElementsByClassName("msgbox")[0].offsetWidth;
//var stageHeight = document.getElementsByClassName("msgbox")[0].clientHeight;
var stageWidth=$( window ).width();
var stageHeight=$( window ).height();
//var stageWidth=$('#phoneContainer').width();;
//var stageHeight=$('#phoneContainer').height();
console.log(stageWidth);
console.log(stageHeight);
var container = document.querySelector('#phoneContainer');
if(container){
// now we need to fit stage into parent
var containerWidth = $('#phoneContainer').width();
var containerHeight = $('#phoneContainer').height();
// to do this we need to scale the stage
var scale = (containerWidth/ stageWidth);
scale=1;
console.log(scale);
phoneImageStage.width(containerWidth);
phoneImageStage.height(containerHeight);
//phoneImageStage.width(containerWidth);
//phoneImageStage.height(containerWidth);
phoneImageStage.scale({ x: scale, y: scale });
var phoneImg = new Konva.Image({
x: 30,
y: 20,
width: 200,
height: 300
});
phoneImageLayer.add(phoneImg);
var phoneImage = new Image();
var self = this;
phoneImage.onload = function () {
phoneImg.image(phoneImage);
phoneImageLayer.draw();
};
phoneImage.src = '../Content/Avaya_Phone.png';
phoneImageStage.draw();
}
}
it scaling the image but not in the same scale as browser.
Would appreciate any help on this.
I am simply trying to render an image with Kinetic, but nothing appears, nor do i get an error.
The fiddle can be found here.
Source code:
$( function() {
var stage = new Kinetic.Stage({
container: 'container',
width: 400,
height: 800
});
var layer = new Kinetic.Layer();
var yoda = new Kinetic.Image({
x: 0,
y: 0,
width: 200,
height: 400
});
var imageObj = new Image();
imageObj.src = 'http://farm6.staticflickr.com/5448/9408019718_88934b087e_b.jpg';
imageObj.onload = function() {
yoda.setImage(imageObj);
layer.draw();
};
layer.add(yoda);
stage.add(layer);
});
You must use <div> container for KineticJS Stage:
<div id="container"></div>
http://jsfiddle.net/ro1zpkaL/1/
I have a KineticJS Stage with one layer. Here is a demo: http://jsfiddle.net/confile/7QTmz/
var stage = new Kinetic.Stage({
container: 'container',
width: 578,
height: 200
});
var layer = new Kinetic.Layer();
var imageObj = new Image();
imageObj.onload = function () {
var yoda = new Kinetic.Image({
x: 200,
y: 50,
image: imageObj,
width: 106,
height: 118
});
// add the shape to the layer
layer.add(yoda);
// add the layer to the stage
stage.add(layer);
stage.size({
width: 100,
height: 200
});
layer.draw();
stage.draw();
};
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/yoda.jpg';
How can I resize the stage such that stage.toDataUrl() will return an image with the new dimensions?
You can 2X the stage and its content like this (also...thanks to #Greg for info on stage.size):
var scaleFactor=2;
stage.size({width:stage.width()*scaleFactor,height:stage.height()*scaleFactor});
stage.scaleX(scaleFactor);
stage.scaleY(scaleFactor);
stage.draw();
my function draw an image, and another image on another layer with Kinetic.js but i want to crop the second image which is named smsTopBg_image
window.onload = function() {
//INITIALISATION
var stage = new Kinetic.Stage({
container: "iPhone",
width: 480,
height: 720
});
//LAYERS
var background_layer = new Kinetic.Layer();
var sms_layer = new Kinetic.Layer();
var text_layer = new Kinetic.Layer();
//ELEMENTS
var iPhoneBg = new Image();
iPhoneBg.onload = function() {
var iPhoneBg_image = new Kinetic.Image({
image: iPhoneBg
});
background_layer.add(iPhoneBg_image);
stage.add(background_layer);
}
iPhoneBg.src = "iPhoneBg.jpg";
//--------------------------------------------------
var smsTopBg = new Image();
smsTopBg.onload = function() {
var smsTopBg_image = new Kinetic.Image({
image: smsTopBg,
x: 10,
y: 10,
});
sms_layer.add(smsTopBg_image);
stage.add(sms_layer);
}
smsTopBg.src = "iPhoneBg.jpg";
};
Thanks !
You can add an optional crop object to the main attributes object in your Image constructor.
It has an x, y, width and height properties.
var smsTopBg_image = new Kinetic.Image({
image: smsTopBg,
x: 10,
y: 10,
// random values, choose your own :
crop: {
x: 20,
y: 3,
width: 100,
height: 42
}
});
Ok ifound the complete solution with your help, it's necessary to add height and with to the image before crop like that :
var smsTopBg = new Image();
smsTopBg.onload = function() {
var smsTopBg_image = new Kinetic.Image({
image: smsTopBg,
x: 200,
y: 20,
width: 50,
height: 20,
crop: {
x: 20,
y: 10,
width: 50,
height: 50
}
});
sms_layer.add(smsTopBg_image);
stage.add(sms_layer);
}
Thanks !
Refer this url for Image Crop in Kinetic.js : http://jsfiddle.net/umhm7/