使用 JavaScript 进行碰撞检查
Collision Checking With 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;
我已经看过 this question and this question and this question,但到目前为止我运气不好。有人可以帮助我理解逻辑或提供我需要做什么的示例代码吗?
谢谢。
你的游戏看起来不错!
我最近写了一些碰撞检测并且遇到了完全相同的问题。问题是,一旦您的坐标在发生碰撞的情况下为真,那么它们在任何其他运动中也将始终为真。
您需要存储您的角色之前所在的位置并恢复到该位置,或者在更改您的角色坐标之前执行检查。
感谢 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;
}
我正在创建一个游戏,用户可以在这个游戏中漫步在墓地周围,并从不同的坟墓中收集故事。这是一款经典的自上而下游戏。我正在构建一个脚本,如果用户走进坟墓,他们的动作就会停止,但我在设置碰撞时遇到了麻烦。我正在使用 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;
我已经看过 this question and this question and this question,但到目前为止我运气不好。有人可以帮助我理解逻辑或提供我需要做什么的示例代码吗?
谢谢。
你的游戏看起来不错!
我最近写了一些碰撞检测并且遇到了完全相同的问题。问题是,一旦您的坐标在发生碰撞的情况下为真,那么它们在任何其他运动中也将始终为真。
您需要存储您的角色之前所在的位置并恢复到该位置,或者在更改您的角色坐标之前执行检查。
感谢 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;
}