Nevin
Nevin

Reputation: 3298

Collision detection using kineticJS (getIntersection function not working)

I am trying to recreate the game http://www.sinuousgame.com/ and started studying html5 canvas and kineticJS.

Recently i came across the getIntersection function and coudnt find much details regarding it.But with what i had ,i did make a code to get the Collision detection done using getIntersection() function. But it doesnt seem to be working.

As you can see, My Fiddle: http://jsfiddle.net/p9fnq/8/

   //The working player code
var LimitedArray = function(upperLimit) {
    var storage = [];

    // default limit on length if none/invalid supplied;
    upperLimit = +upperLimit > 0 ? upperLimit : 100;

    this.push = function(item) {
        storage.push(item);
        if (storage.length > upperLimit) {
            storage.shift();
        }
        return storage.length;
    };

    this.get = function(flag) {
        return storage[flag];
    };

    this.iterateItems = function(iterator) {
        var flag, l = storage.length;
        if (typeof iterator !== 'function') {
            return;
        }
        for (flag = 0; flag < l; flag++) {
            iterator(storage[flag]);
        }
    };
};

var tail = new LimitedArray(50);

var flag = 0, jincr = 0;
var stage = new Kinetic.Stage({
    container: 'container',
    width: window.innerWidth,
    height: window.innerHeight,
    listening: true
});
var layer = new Kinetic.Layer({
    listening: true
});
stage.add(layer);
var player = new Kinetic.Circle({
    x: 20,
    y: 20,
    radius: 6,
    fill: 'cyan',
    stroke: 'black',
    draggable: true
});
var line = new Kinetic.Line({
    points: [],
    stroke: 'cyan',
    strokeWidth: 2,
    lineCap: 'round',
    lineJoin: 'round'
});
layer.add(line);
layer.add(player);

// move the circle with the mouse
stage.getContent().addEventListener('mousemove', function() {
    player.position(stage.getPointerPosition());
    var obj = {
        x: stage.getPointerPosition().x,
        y: stage.getPointerPosition().y
    };

    tail.push(obj);
    var arr = [];
    tail.iterateItems(function(p) {
        arr.push(p.x, p.y);
    });
    line.points(arr);
});

var x = 0;
var y = 0;
var noOfEnemies = 200;
var enemyArmada = new Array();


createEnemy();

function createEnemy() {
    for (var i = 0; i < noOfEnemies; i++) {
        var enemy = new Kinetic.Circle({
            x: Math.random() * window.innerWidth,
            y: Math.random() * window.innerHeight,
            radius: 4.5 + 1.5 * Math.random(),
            fill: 'red',
            stroke: 'black'
        });
        enemy.speedX = enemy.speedY = (0.5 + Math.random() * 50);
        enemyArmada.push(enemy);
        layer.add(enemy);
    }
}


 var checkCollide = function() {
        var position = stage.getPointerPosition();
        if(position == null)
            position = player.position();
        if(position == null)
            position = {x:0,y:0};
        var collided = stage.getIntersection(position); 
        console.log(position);
        if (typeof collided !== 'Kinetic.Shape') {
            console.log("not shape");
        }
        else {
            console.log("BOOOM!!!");
        }
    };

var anim = new Kinetic.Animation(function(frame) {
    checkCollide();
    for (var i = 0; i < noOfEnemies; i++) {
        var e = enemyArmada[i];
        e.position({
            x: e.position().x - e.speedX * (frame.timeDiff / 400),
            y: e.position().y + e.speedY * (frame.timeDiff / 400)
        });

        if (e.position().y < 0 || e.position().x < 0) {
            e.position({
                x: (Math.random() * (window.innerWidth + 600)),
                y: -(Math.random() * window.innerHeight)
            });
        }
    }

}, layer);
anim.start();

I need the collision to be detected. The function i have written here is checkCollide and its called within the kinetic.Animation function.

Can anyone help me out with this?? (If you don't know the solution,please do like the post,i need the solution badly)

Upvotes: 1

Views: 1634

Answers (1)

markE
markE

Reputation: 105015

The source of the problem

getIntersection(point) means "is any object at this point".

Since the point you're using is the player's position, getIntersection will always return true because player is always at its own position !

One solution

Put your player on one layer and all enemies on a separate layer.

That way you can hit test the enemy layer without the interference of the player object.

Code and a Demo: http://jsfiddle.net/m1erickson/JCfW8/

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Prototype</title>
    <script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
    <script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v5.0.1.min.js"></script>
<style>
body{padding:20px;}
#container{
  border:solid 1px #ccc;
  margin-top: 10px;
  width:350px;
  height:350px;
}
</style>        
<script>
$(function(){

    var stage = new Kinetic.Stage({
        container: 'container',
        width: 350,
        height: 350
    });
    var enemyLayer = new Kinetic.Layer();
    stage.add(enemyLayer);
    var playerLayer = new Kinetic.Layer();
    stage.add(playerLayer);

    var player = new Kinetic.Circle({
        x:100,
        y:100,
        radius: 10,
        fill: 'green',
        draggable: true
    });
    player.on("dragmove",function(){
        if(enemyLayer.getIntersection(player.position())){
            this.fill("red");
            playerLayer.draw();
        }
    });
    playerLayer.add(player);
    playerLayer.draw();

    var enemy = new Kinetic.Circle({
        x:200,
        y:100,
        radius: 20,
        fill: 'blue',
        draggable: true
    });
    enemyLayer.add(enemy);
    enemyLayer.draw();

}); // end $(function(){});

</script>       
</head>

<body>
    <h4>Drag the green player<br>Player will turn red if it collides<br>with the blue enemy</h4>
    <div id="container"></div>
</body>
</html>

Another solution

Mathematically test the player against every enemy:

Warning: untested code--some tweaking might be required

function playerEnemyCollide(){
    var playerX=player.x();
    var playerY=player.y();
    var playerRadius=player.radius();

    for(var i=0;i<enemyArmada.length;i++){
        var e=enemyArmada[i];
        if(circlesColliding(playerX,playerY,playerRadius,e.x,e.y,e.radius)){
            return(true);
        }
    }
    return(false);
}

function circlesColliding(cx1,cy1,radius1,cx2,cy2,radius2){
    var dx=cx2-cx1;
    var dy=cy2-cy1;
    return(dx*dx+dy*dy<(radius1*2+radius2*2);
}

Upvotes: 2

Related Questions