使用kineticJS进行碰撞检测(getIntersection功能不起作用)

时间:2014-02-13 07:37:54

标签: javascript html5-canvas collision-detection kineticjs

我正在尝试重新制作游戏http://www.sinuousgame.com/并开始学习 html5画布 kineticJS

最近我遇到了getIntersection函数,并且找到了很多关于它的细节。但是我用它做了一个代码,使用 getIntersection()函数完成碰撞检测。 但它似乎没有起作用。

如您所见,我的小提琴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();

我需要检测到碰撞。我在这里写的函数是 checkCollide ,并在 kinetic.Animation 函数中调用它。

任何人都可以帮我解决这个问题吗? (如果你不知道解决方案,请像帖子一样,我需要解决方案很糟糕)

1 个答案:

答案 0 :(得分:2)

问题的根源

getIntersection(point)表示“此时任何对象”。

由于您使用的是玩家的位置,getIntersection将始终返回true,因为玩家总是处于自己的位置!

一个解决方案

将你的玩家放在一层,将所有敌人放在一个单独的层上。

这样你就可以在没有玩家对象干扰的情况下对敌人进行测试。

代码和演示: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>

另一种解决方案

以数学方式测试玩家对抗每一个敌人:

警告:未经测试的代码 - 可能需要进行一些调整

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