【问题标题】:Dragging collisions拖动碰撞
【发布时间】:2013-03-22 05:40:45
【问题描述】:

我对 CANVAS 和 Kineticjs 都很陌生,但我觉得我正在尝试的事情应该比我想象的要容易得多。基本上这是我到目前为止所拥有的:

我尝试使用的代码来自 kineticjs Stop drag to a shape when overlaps with another 解决方案,但无法使其正常工作。

请查看直播 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;
}

这样做的想法是让粉红色方块可以拖动但被橙色框阻挡,一旦在橙色框周围拖动,粉红色框“接触”蓝色框并且应该会弹出。

我不确定使用 kineticjs 是否是实现这一点的最简单方法?

任何想法、提示或帮助我都将不胜感激。

【问题讨论】:

    标签: javascript collision-detection kineticjs collision


    【解决方案1】:

    是的,因为 KineticJS 没有碰撞测试,你必须自己做。

    这是任意 2 个 kineticJS 矩形之间的碰撞测试:

    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());
    }
    

    下面是你如何调用盒子和障碍物之间的碰撞测试:

    if( theyAreColliding(box,obstacle){
          // obstacle is blocking box
          alert("You are being blocked!");
    }
    

    下面是你如何调用盒子和目标之间的碰撞测试:

    if( theyAreColliding(box,target){
          // box touched the goal
          alert("Goal!");
    }
    

    要阻止盒子直接穿过障碍物,你必须给盒子一个自定义的拖动函数,如下所示:

    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 });
        }
    }
    

    您可以在以下演示中查看其工作原理:http://www.html5canvastutorials.com/kineticjs/html5-canvas-drag-and-drop-bounds-tutorial-with-kineticjs/

    [编辑:指定每个代码的去向]

    我将这些部分放在下面的工作 sn-p 中。我确实发现了一件不幸的事情。用户可以快速拖动粉色框以穿过障碍物——KineticJS 的反应速度不够快,无法阻止非常快速的拖动。

    还有——哎呀。我在上面的 theyAreColliding 函数中更正了一些缺少的括号。

    dragBoundFunc 作为盒子构造函数的补充(见下面的代码)。

    您可以通过在盒子的“dragmove”处理程序中进行测试来测试用户是否有目标,如下所示:

      box.on('dragmove', function() {
        if (theyAreColliding(box, target)) {
            // box touched the goal
            alert("Goal!");
        }      
      });
    

    这是代码和小提琴: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>
    

    【讨论】:

    • 很好的解释以及dragBoundFunc中的实现
    • 谢谢,令人惊奇的解释,尽管我很难让 if 语句在正确的时间运行。目前它们只是在刷新时自动运行,然后再也不运行了?他们需要准备好文件声明还是我遗漏了什么?这是我的意思的 jsfiddle 链接:link 编辑:或者是因为它测试的是图层而不是正方形?所以他们总是在感动?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-24
    • 2013-01-15
    • 1970-01-01
    • 1970-01-01
    • 2013-09-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多