【问题标题】:HTML5 / kineticJS getIntersection function implementationHTML5 / kineticJS getIntersection 函数实现
【发布时间】:2013-02-14 12:42:02
【问题描述】:

我正在通过http://www.html5canvastutorials.com 提供的教程学习kineticjs,事情很好且易于理解,但是,我在理解getIntersection 函数时遇到问题,我想在不同对象之间使用dragging检测collision / overlapping 对象。

据我所知,getIntersection 函数需要一个位置并检查它是否与任何其他对象相交..

虽然我得到了它们,但有一些问题。

我无法做到这一点..

下面是我到目前为止尝试过的代码..

<script>

var stage = new Kinetic.Stage({
    container: 'container',
    width: 1000,
    height: 500,
    opacity: 0.5
});

var layer = new Kinetic.Layer();
var previous_position;
var new_position;
var collision = false;
var colors = ['red', 'orange', 'yellow', 'green', 'blue', 'purple'];
var yellowBox = null;
for(var n = 0; n < 6; n++) {
    // anonymous function to induce scope
    (function() {
        var i = n;
        if(n < 3){
            y = 50;
            x = i * 100 + i * 10;
        }else{
            y = 150;
            x = (i - 3) * 100 + (i - 3) * 10 ;
            if(n == 3){
                x = 0;
            }

        }
        var box = new Kinetic.Rect({
            x: x,
            y: y,
            width: 100,
            height: 50,
            fill: colors[i],
            stroke: 'black',
            strokeWidth: 4,
            draggable: true,
            name: colors[i]
        });

        box.on('dragstart', function() {
            previous_position =     {
                                        x: this.attrs.x,
                                        y: this.attrs.y 
                                    }; 
        });

        box.on('dragend', function() {
            if(collision){
                //this.setPosition(previous_position);
                layer.draw();
                collision = false;
            }else{
                //this.setPosition(new_position);
                layer.draw();
            }
        });

        box.on("dragmove", function(evt) {
            console.log(layer.children.length);
            if(layer.children.length > 1){
                console.log('dragging');
                new_position = {x: this.attrs.x,
                            y: this.attrs.y};
        //              var posBL = {x: this.attrs.x,
        //                          y: this.attrs.height + this.attrs.y};
        //              var posTR = {x: this.attrs.x    + this.attrs.width,
        //                          y: this.attrs.y};
                var posBR = {x: this.attrs.x    + this.attrs.width,
                            y: this.attrs.y + this.attrs.height };
                var collisionTL = this.getStage().getIntersections(new_position);
        //              var collisionBL = this.getStage().getIntersections(posBL);
        //              var collisionTR = this.getStage().getIntersections(posTR);
        //              var collisionBR = this.getStage().getIntersections(posBR);

                console.log(collisionTL);
                console.log(collisionTL.shapes);

        //              if(collisionTL.length > 1 || collisionBL.length > 0 || collisionTR.length > 0 || collisionBR.length > 0){
                if(collisionTL.length > 1){
                    console.log(collisionTL.shapes);
                    collision = true;
                }else{ //if(collisionBR.length > 0){
                    collision = true;
                }
        //              for(i=0; i < collision.length; i++){
        //              //  console.log(collision[i]._id);
        //              }
            }
        });


        if(colors[i] === 'yellow') {
            yellowBox = box;
        }

        layer.add(box);
    })();
}

stage.add(layer);

</script>

dragmove 事件中,你可以看到我得到了拖动框的四个角位置{立即评论},通过这个我能够检测到重叠/碰撞,但它有两个问题:

1.非常慢,我的测试中只有 3 个对象

2.如果没有角点相交,则不会触发碰撞事件{因为这个盒子可以更大,所以它可以完全覆盖另一个盒子}

如果有人能帮我完成这件事,我会非常感激..

[A] 任何拖动的对象如果以任何方式与我希望它显示碰撞的任何其他对象重叠。

[B] 如果可能,请让getIntersection 处理特定的图层组,无论哪一个都是可能的 [C] 除了kineticJS 之外的任何其他解决方法来完成上述任务

问候

【问题讨论】:

    标签: html collision-detection kineticjs


    【解决方案1】:

    好的,KineticJS 的开发人员正在努力改进 .getIntersections() 函数……或者至少他说他是。但在功能改进之前,您必须制作自己的碰撞检测功能。假设您的对象是矩形或可以分成一系列点,您应该使用以下内容:

    创建一个函数来确定一个点是否在一个形状中(如果一个矩形的角在另一个矩形内),如下所示:

     function checkCollide(pointX, pointY, objectx, objecty, objectw, objecth) { // pointX, pointY belong to one rectangle, while the object variables belong to another rectangle
          var oTop = objecty;
          var oLeft = objectx; 
          var oRight = objectx+objectw;
          var oBottom = objecty+objecth; 
    
          if(pointX > oLeft && pointX < oRight){
               if(pointY > oTop && pointY < oBottom ){
                    return 1;
               }
          }
          else
               return 0;
     };
    

    然后你可以做一个大循环,遍历层中的所有对象以检查碰撞,如下所示:

     var children = layer.getChildren();
     for( var i=0; i<children.length; i++){  // for each single shape
         for( var j=0; j<children.length; j++){ //check each other shape
             if(i != j){ //skip if shape is the same
                if(checkCollide(children[i].getX(), children[i].getY(), children[j].getX(), children[j].getY(), children[j].getWidth(), children[j].getHeight()))
                    alert('top left corner collided');
             }
         }
     }
    

    我提供的 checkCollide 函数只检查每个形状左上角的碰撞,所以你必须修改函数来检查所有角,这不是一个很长的重写,甚至在 stackoverflow 上也有很多教程可以处理使用“边界矩形碰撞检测”

    这似乎是一个非常繁重的函数,但令人惊讶的是它仍然比 .getIntersections() 快。此外,您应该添加额外的 if 语句,以便函数不会一直运行所有检查。

    我自己创建了一个游戏并使用 .intersects() 并且速度很慢。我切换到这种“更简单”的碰撞检测,现在我的游戏运行在 60FPS 左右。 http://cs.neiu.edu/~tsam/physics/index.phtml(测试/测试)如果你想检查一下。您可以查看页面源代码以了解我如何将碰撞检测构造得更高效(例如在 checkIntersectsGoal() 函数中。

    【讨论】:

    • 您的链接现在已损坏 *(
    • 对不起。该页面已被删除。
    猜你喜欢
    • 2014-03-11
    • 2013-01-13
    • 2014-06-08
    • 1970-01-01
    • 2012-09-22
    • 2014-08-20
    • 1970-01-01
    • 2012-08-26
    • 2014-03-24
    相关资源
    最近更新 更多