Проверка столкновений с помощью JavaScript

Я создаю игру, в которой пользователь бродит по кладбищу и собирает истории из разных могил. Это классическая игра с видом сверху. Я создаю сценарий, в котором, если пользователь входит в могилу, его движение останавливается, но у меня возникают проблемы с настройкой столкновений. Я использую 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;

введите описание изображения здесь

Я просмотрел этот вопрос и этот вопрос и этот вопрос, и пока мне не везет. Может ли кто-нибудь помочь мне с логикой или предоставить пример кода того, что мне нужно сделать?

Спасибо.


person Kenton de Jong    schedule 09.02.2019    source источник


Ответы (2)


Твоя игра выглядит молодцом!

Я недавно написал об обнаружении столкновений и столкнулся с той же проблемой. Проблема в том, что если ваши координаты верны для случая столкновения, они всегда будут верны для любого другого движения.

Вам нужно сохранить предыдущую позицию, в которой был ваш персонаж, и вернуться к ней ИЛИ выполнить проверку перед изменением координат вашего персонажа.

person stwilz    schedule 09.02.2019

Мне удалось найти следующее решение, благодаря stwitz 'about idea, а также этому скрипту: 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;
}
person Kenton de Jong    schedule 10.02.2019