使用JavaScript进行碰撞检查

时间:2019-02-09 02:59:30

标签: javascript jquery collision-detection collision boundary

我正在创建一个游戏,用户在公墓中徘徊,并收集来自不同坟墓的故事。这是一款经典的自上而下的游戏。我正在构建一个脚本,如果用户走进坟墓中,他们的动作将停止,但是在设置碰撞时会遇到麻烦。我正在使用jQuery。这是我到目前为止的内容:

var position = -1;
var $char = $('#char');
var keyCode = null;
var fired = false;
var $stones = $('.stones div');
var collision = null;

document.onkeydown = function(e) {

keyCode = e.which || e.keyCode;

if (!fired) {
    position = -1;
    fired = true; 
    switch (keyCode) {
        case 38: position = 0; break; //up
        case 40: position = 1; break; //down
        case 37: position = 2; break; //left
        case 39: position = 3; break; //right
    }

    walking();
    stepping = setInterval(walking,125);
}

};

document.onkeyup = function(e) {
  //standing
  clearInterval(stepping);
  stepping = 0;
  fired = false;
};


function walking() {

$stones.each(function() { //check all the stones...

    collision = collision($(this), $char, position); ...for collisions

    if (collision) { //if any, then break loop
        return false; 
    }

});

if (!collision) { //check if there was a collision
   //if no collision, keep walking x direction
}


function collision($el, $charEl, position) {

var $el = $el[0].getBoundingClientRect();
var $charEl = $charEl[0].getBoundingClientRect();

var elBottom = parseInt($el.bottom);
var elRight = parseInt($el.right);
var elLeft = parseInt($el.left);
var elTop = parseInt($el.top);

var charBottom = parseInt($charEl.bottom);
var charRight = parseInt($charEl.right);
var charLeft = parseInt($charEl.left);
var charTop = parseInt($charEl.top);

//this is where I'm stuck

}
}

我尝试了各种不同的代码,但是似乎没有任何效果。我一直遇到一个问题,如果我继续前进,然后撞上墓碑,转身就被困住了。这是我的意思的示例代码:

if (position == 0 && 
    !(elTop > charBottom ||
    elBottom < charTop ||
    elRight < charLeft + 1 ||
    elLeft > charRight - 1)
   ) {
    return true; 
}


if (position == 1 && 
    !(elTop > charBottom ||
    elBottom < charTop ||
    elRight < charLeft + 1 ||
    elLeft > charRight - 1)
   ) {
    return true; 
}

return false;

enter image description here

我看过this questionthis questionthis question,到目前为止我还没有任何运气。有人可以帮助我解决逻辑问题或提供示例代码来说明我需要做什么吗?

谢谢。

2 个答案:

答案 0 :(得分:2)

您的游戏看起来很帅!

我最近写了一些碰撞检测,并遇到了完全相同的问题。问题是,一旦您的坐标在碰撞情况下为真,那么在其他任何运动中它们都将永远为真。

您需要存储角色所处的先前位置并返回原位置,或者在更改角色坐标之前执行检查。

答案 1 :(得分:1)

由于stwitz的想法和脚本,我设法找到了以下解决方案:https://magently.com/blog/detecting-a-jquery-collision-part-iv/

var position = -1;
var $char = $('#char');
var keyCode = null;
var fired = false;
var stepSize = 32;
var $stones = $('.stones div');

//new
var cancelTop = cancelRight = cancelLeft = cancelBottom = false;

var charEl = $char[0].getBoundingClientRect();
var charLeft = parseInt(charEl.left);
var charRight = parseInt(charEl.right);
var charTop = parseInt(charEl.top);
var charBottom = parseInt(charEl.bottom);

function walking() {

if (position == 0 && !cancelTop) {
    //if moving up & is safe to move up
} else if (position == 1 && !cancelBottom) {
    //if moving down & is safe to move down
} else if (position == 2 && !cancelLeft) {
   //if moving left and is safe to move left
} else if (position == 3 && !cancelRight) {
   //if moving right and is safe to move right
}

cancelTop = cancelRight = cancelLeft = cancelBottom = false; //mark all as safe until we check

$stones.each(function() {

    collision($(this));

});

}

document.onkeydown = function(e) {

keyCode = e.which || e.keyCode;

if (!fired) {
    position = -1;
    fired = true; 
    switch (keyCode) {
        case 38: position = 0; break; //up
        case 40: position = 1; break; //down
        case 37: position = 2; break; //left
        case 39: position = 3; break; //right
    }

    walking();
    stepping = setInterval(walking,125);
}

};

document.onkeyup = function(e) {
  //standing
  clearInterval(stepping);
  stepping = 0;
  fired = false;
};


function collision($el) {

var el = $el[0].getBoundingClientRect();

var elBottom = parseInt(el.bottom);
var elRight = parseInt(el.right);
var elLeft = parseInt(el.left);
var elTop = parseInt(el.top);

if ( 
    (elRight == charLeft) &&
    (elBottom - stepSize >= charBottom && charBottom >= elTop + stepSize)
    ) { 
    cancelLeft = true;
    return true;  
}

if ( 
    (elLeft == charRight) &&
    (elBottom - stepSize >= charBottom && charBottom >= elTop + stepSize)
    ) { 
    cancelRight = true;
    return true;  
}

if ( 
    (elTop + stepSize > charBottom) && 
    (elTop <= charBottom) && 
    (elLeft < charRight) && 
    (elRight > charLeft) 
    ) 
{ 
    cancelBottom = true;
    return true; 
}

if ( 
    (elBottom - stepSize < charTop) && 
    (elBottom >= charTop) && 
    (elLeft < charRight) && 
    (elRight > charLeft) 
    ) 
{ 
    cancelTop = true;
    return true; 
}

return false;
}