HTML5 / kineticJS getIntersection function implementation

前提是你 提交于 2019-12-29 07:53:28

问题


I am learning kineticjs through tutorials provided at http://www.html5canvastutorials.com, things are good and easy to understand but, I am having issue in understanding the getIntersection function that i want to use among different objects while dragging to detect collision / overlapping objects.

As far as I have understood the example the getIntersection function expects a position and checks if its intersecting with any other object or not..

Though I got them but with some issues.

I am unable to accomplish this..

Below is the code that I have tried up to now..

<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>

in the dragmove event you guyz can see I get the four corner positions of the dragging box {commented right now} and with this I was able to detect the overlap / collision but it has 2 issues:

1. very slow with only 3 objects in my test

2. if non of the corner points intersect it didn't fire the collision stuff {for this one box can be bigger so it can cover the other entirely}

I would highly apreciate if anyone can please help me accomplish this stuff..

[A] Any object dragging if by any mean overlaps any other object I want it to show collision.

[B] If possible make getIntersection to work on a particular layer group whichever is possible [C] any other workaround beside kineticJS to accomplish the above task

Regards


回答1:


Ok, the developer of KineticJS is working on improving the .getIntersections() function... or at least he said he is. But until the function is improved you have to make your own collision detection function. Assuming that your objects are rectangles or can be broken into a series of points you should go with something like this:

Create a function which determines if a point is in a shape (if the corner of a rectangle is inside another rectangle) like so:

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

then you can do a big loop which iterates through all objects in a layer to check collision, like so:

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

the checkCollide function I provided only checks the collision for the top left corner on each shape, so you have to modify the function to check all corners, it's not a long rewrite, and there are plenty tutorials even here on stackoverflow which deal with 'bounding rectangles collision detection'

This may seem like it is a very heavy function, but surprisingly it is still faster than .getIntersections(). Also, you should throw in extra if statements so that the function doesn't run through all the checks all the time.

I created a game myself and was using .intersects() and was having a lot of slow down. I switched over to this type of 'simpler' collision detection and now my game runs around 60FPS. http://cs.neiu.edu/~tsam/physics/index.phtml (test/test) if you want to check it out. You can view page source to see how I structured the collision detection to be more efficient (such as in checkIntersectsGoal() function.



来源:https://stackoverflow.com/questions/14875119/html5-kineticjs-getintersection-function-implementation

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