Reputation: 19
There is a collision function to find the border of both divs (circle and rectangle), the first condition is working but not the rest, and up to this point I don't know what i'm doing wrong. Basically, the idea is for the circle not to go beyond the edges of the rectangle.
const $circle = document.getElementById("circle");
const $box = document.getElementById("box");
let mtop = 0;
let mleft = 0;
let boxTop = 0;
let boxLeft = 0;
let boxRight = 0;
let boxBottom = 0;
document.addEventListener("keydown", (e) =>{
if(e.keyCode == "39") {
mleft++;
$circle.style.marginLeft = mleft +"px";
colission();
}
if(e.keyCode == "37"){
mleft --;
$circle.style.marginLeft = mleft +"px"
// colission();
}
if(e.keyCode == "38"){
mtop --;
$circle.style.marginTop = mtop + "px";
//colission();
}
if(e.keyCode == "40"){
mtop ++;
$circle.style.marginTop = mtop + "px";
//colission();
}
e.preventDefault();
})
function colission(){
let boxPos = $box.getBoundingClientRect();
let boxTop = boxPos.top;
let boxLeft = boxPos.left;
let boxRight = boxPos.right;
let boxBottom = boxPos.bottom;
let circlePos = $circle.getBoundingClientRect();
let circleTop = circlePos.top;
let circleLeft = circlePos.left;
let circleRight = circlePos.right;
let circlebottom = circlePos.bottom;
if(Math.round(circleRight) == Math.round(boxRight)){
mleft = mleft - 2;
}
/*if(Math.round(circleLeft) == Math.round(boxLeft)){
mleft = mleft - 2;
}
if(Math.round(circleTop) == Math.round(boxTop)){
mtop = mtop -2;
}
if(Math.round(circlebottom) == Math.round(boxBottom)){
mtop = mtop -2;
}*/
}
Upvotes: 1
Views: 304
Reputation: 31833
Here is a solution to your problem, the collision
function returns true
in case of a collision, else false
. You can then implement some logic to prevent the last user action in case of a collision (try the demo with keyboard arrows):
document.addEventListener('keydown', (function() {
function collision(box, circle) {
const {
top: boxTop,
left: boxLeft,
right: boxRight,
bottom: boxBottom,
} = box.getBoundingClientRect();
const {
top: circleTop,
left: circleLeft,
right: circleRight,
bottom: circleBottom,
} = circle.getBoundingClientRect();
const circleRadius = (circleBottom - circleTop ) / 2;
const circleCenterX = (circleLeft + circleRight ) / 2;
const circleCenterY = (circleTop + circleBottom ) / 2;
/**
* Distance between the center of the circle and the nearest point of
* the rectangle (on the X axis)
*/
const deltaX = circleCenterX - Math.max(boxLeft, Math.min(circleCenterX, boxRight));
/**
* Distance between the center of the circle and the nearest point of
* the rectangle (on the Y axis)
*/
const deltaY = circleCenterY - Math.max(boxTop, Math.min(circleCenterY, boxBottom));
/**
* Is the distance between the center of the circle and the nearest point
* of the rectangle inferior to the circle radius ?
*/
return deltaX ** 2 + deltaY ** 2 < circleRadius ** 2;
}
const circle = document.getElementById('circle');
const rectangle = document.getElementById('rectangle');
let circleTop = 26;
let circleLeft = 8;
return function(e) {
e.preventDefault();
if(e.keyCode === 37) {
circleLeft -= 1;
}
if(e.keyCode === 38) {
circleTop -= 1;
}
if(e.keyCode === 39) {
circleLeft += 1;
}
if(e.keyCode === 40) {
circleTop += 1;
}
circle.style.top = `${circleTop}px`;
circle.style.left = `${circleLeft}px`;
if (collision(rectangle, circle)) {
rectangle.style['background-color'] = 'red';
circle.style['background-color'] = 'red';
}
else {
rectangle.style['background-color'] = 'blue';
circle.style['background-color'] = 'blue';
}
}
})());
.shape {
position: absolute;
background-color: blue;
}
#circle {
border-radius: 50%;
height: 20px;
width: 20px;
}
#rectangle {
height: 20px;
width: 50px;
top: 40px;
left: 40px;
}
<div>Use the keyboard arrows to move the circle</div>
<div class="shape" id="circle"></div>
<div class="shape" id="rectangle"></div>
Edit: The actual question is about a circle that should not go outside a rectangle
Then just check if the boundaries of the circle are inside the boundaries of the rectangle:
document.addEventListener('keydown', (function() {
function isInInterval(value, interval) {
const [min, max] = interval;
return value >= min && value <= max;
}
function collision(box, circle) {
const {
top: boxTop,
left: boxLeft,
right: boxRight,
bottom: boxBottom,
} = box.getBoundingClientRect();
const {
top: circleTop,
left: circleLeft,
right: circleRight,
bottom: circleBottom,
} = circle.getBoundingClientRect();
return !(
isInInterval(circleLeft, [boxLeft, boxRight]) &&
isInInterval(circleRight, [boxLeft, boxRight]) &&
isInInterval(circleTop, [boxTop, boxBottom]) &&
isInInterval(circleBottom, [boxTop, boxBottom])
);
}
const circle = document.getElementById('circle');
const rectangle = document.getElementById('rectangle');
let circleTop = 26;
let circleLeft = 8;
return function(e) {
e.preventDefault();
if(e.keyCode === 37) {
circleLeft -= 1;
}
if(e.keyCode === 38) {
circleTop -= 1;
}
if(e.keyCode === 39) {
circleLeft += 1;
}
if(e.keyCode === 40) {
circleTop += 1;
}
circle.style.top = `${circleTop}px`;
circle.style.left = `${circleLeft}px`;
if (collision(rectangle, circle)) {
rectangle.style['background-color'] = 'red';
circle.style['background-color'] = 'red';
}
else {
rectangle.style['background-color'] = 'blue';
circle.style['background-color'] = 'blue';
}
}
})());
.shape {
position: absolute;
background-color: red;
}
#circle {
border-radius: 50%;
height: 20px;
width: 20px;
}
#rectangle {
height: 20px;
width: 50px;
top: 40px;
left: 40px;
}
<div>Use the keyboard arrows to move the circle</div>
<div class="shape" id="circle"></div>
<div class="shape" id="rectangle"></div>
Upvotes: 1
Reputation: 19
thanks for your answer, I could already solve the problem
const $circle = document.getElementById("circle");
const $box = document.getElementById("box");
let mtop = 0;
let mleft = 0;
let boxTop = 0;
let boxLeft = 0;
let boxRight = 0;
let boxBottom = 0;
document.addEventListener("keydown", (e) =>{
e.preventDefault();
let boxPos = $box.getBoundingClientRect();
let boxTop = boxPos.top;
let boxLeft = boxPos.left;
let boxRight = boxPos.right;
let boxBottom = boxPos.bottom;
let circlePos = $circle.getBoundingClientRect();
let circleTop = circlePos.top;
let circleLeft = circlePos.left;
let circleRight = circlePos.right;
let circlebottom = circlePos.bottom;
if(e.keyCode === 39) {
mleft++;
$circle.style.marginLeft = mleft +"px";
if(Math.trunc(circleRight) === Math.trunc(boxRight)){
mleft = mleft - 5;
}
}
if(e.keyCode === 37){
mleft--;
$circle.style.marginLeft = mleft +"px"
if(Math.trunc(circleLeft) === Math.trunc(boxLeft)){
mleft = mleft + 5;
}
}
if(e.keyCode === 38){
mtop--;
$circle.style.marginTop = mtop + "px";
if(Math.trunc(circleTop) === Math.trunc(boxTop)){
mtop = mtop + 5;
}
}
if(e.keyCode === 40){
mtop++;
$circle.style.marginTop = mtop + "px";
if(Math.trunc(circlebottom) === Math.trunc(boxBottom)){
mtop = mtop - 5;
}
}
})
:root {
--main-color: red;
--second-color: blue;
}
.container {
background-color: var(--main-color);
border: black;
width: 50%;
height: 60%;
position: absolute;
}
#circle{
position: absolute;
width: 60px;
height: 60px;
left: 0;
right: 0;
border-radius: 100%;
background-color: var(--second-color);
padding: 10px;
}
<div id="box" class="container">
<div id="circle"></div>
</div>
Upvotes: 0