I am pretty new to both CANVAS and Kineticjs but I feel what I am attemping should be much easier then I am making it out to be. Basically this is what I have so far:
The code I am attempting to use is from kineticjs Stop drag to a shape when overlaps with another solution but was unable to get it to work.
Please check the live jsfiddle code
var isRectCollide = function(target, box) {
if (target.x - target.width >= box.x + box.width &&
target.y - target.height >= box.y + box.height &&
target.x + target.width <= box.x + box.width &&
target.x + target.height <= box.y - box.height )
return false;
else
return true;
}
The idea of this is for the pink square to be draggable but blocked by the orange box, once dragged around the orange box and the pink box 'touches' the blue box and pop up should occur.
I am not sure if using kineticjs is the simplest way to implement this though?
Any ideas, tips or help would me much appreciated.
Yes, since KineticJS doesn't have collision testing you must do your own.
Here is a collision test between any 2 kineticJS rectangles:
function theyAreColliding(rect1, rect2) {
return !(rect2.getX() > rect1.getX()+rect1.getWidth() ||
rect2.getX()+rect2.getWidth() < rect1.getX() ||
rect2.getY() > rect1.getY()+rect1.getHeight() ||
rect2.getY()+rect2.getHeight() < rect1.getY());
}
And here is how you would call the collision test between the box and obstacle:
if( theyAreColliding(box,obstacle){
// obstacle is blocking box
alert("You are being blocked!");
}
And here is how you would call the collision test between the box and the goal:
if( theyAreColliding(box,target){
// box touched the goal
alert("Goal!");
}
To stop the box from dragging right through the obstacle, you must give box a custom drag function like this:
dragBoundFunc: function(pos){
if(theyAreColliding(box,obstacle){
// box is touching obstacle
// don't let box move down
return({ x:pos.x, y:obstacle.getY()-1 });
} else{
// box is not touching obstacle
// let it move ahead
return({ x:pos.x, y:pos.y });
}
}
You can see how this works in a demo at: http://www.html5canvastutorials.com/kineticjs/html5-canvas-drag-and-drop-bounds-tutorial-with-kineticjs/
[Edit: specify where each code goes]
I put the pieces together into a working snippet below. I did find one unfortunate thing. It’s possible for the user to drag the pink box fast enough to go right through the obstacle—KineticJS can’t react fast enough to stop a very fast drag.
Also--oops on me. I corrected some missing parentheses in the theyAreColliding function above.
The dragBoundFunc goes as an addition to the box constructor (see code below).
You can test if the user has a goal by testing in the box’s “dragmove” handler, like this:
box.on('dragmove', function() {
if (theyAreColliding(box, target)) {
// box touched the goal
alert("Goal!");
}
});
Here is code and a Fiddle: http://jsfiddle.net/uCAys/
<!DOCTYPE HTML>
<html>
<head>
<style>
body {
margin: 0px;
padding: 20px;
}
canvas {
border: 1px solid #777;
}
</style>
</head>
<body>
<div id="container"></div>
<script src="http://www.html5canvastutorials.com/libraries/kinetic-v4.3.1-beta2.js"></script>
<script>
var stage = new Kinetic.Stage({
container: 'container',
width: 300,
height: 300
});
var layer = new Kinetic.Layer();
//Dragable Pink box
var box = new Kinetic.Rect({
x: 100,
y: 50,
width: 100,
height: 50,
fill: 'pink',
stroke: 'black',
strokeWidth: 2,
draggable: true,
// this causes box to be stopped if contacting obstacle
dragBoundFunc: function(pos){
if(theyAreColliding(box,obstacle)){
// box is touching obstacle
// don't let box move down
return({
x: pos.x,
y: Math.min( obstacle.getY()-box.getHeight()-1, pos.y)
});
} else{
// box is not touching obstacle
// let it move ahead
return({ x:pos.x, y:pos.y });
}
}
});
box.on('dragmove', function() {
if (theyAreColliding(box, target)) {
// box touched the goal
box.setX(100);
box.setY(50);
alert("Goal!");
}
});
// End goal blue box
var target = new Kinetic.Rect({
x: 100,
y: 200,
width: 100,
height: 50,
fill: 'blue',
stroke: 'black',
strokeWidth: 2
});
// Obstacle/blocker orange box
var obstacle = new Kinetic.Rect({
x: 125,
y: 145,
width: 50,
height: 30,
fill: 'orange',
stroke: 'black',
strokeWidth: 2
});
function theyAreColliding(rect1, rect2) {
return !(rect2.getX() > rect1.getX() + rect1.getWidth() || //
rect2.getX() + rect2.getWidth() < rect1.getX() || //
rect2.getY() > rect1.getY() + rect1.getHeight() || //
rect2.getY() + rect2.getHeight() < rect1.getY()); //
}
layer.add(box);
layer.add(obstacle);
layer.add(target);
stage.add(layer);
</script>
</body>
</html>