Dragging collisions

独自空忆成欢 提交于 2019-11-30 09:58:38

问题


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.


回答1:


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>


来源:https://stackoverflow.com/questions/15563481/dragging-collisions

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!