文章地址:https://www.cnblogs.com/sandraryan/
碰撞檢測這個東西寫小游戲挺有用der~~~
注釋寫的還挺全,所以就不多說了,看注釋
這是頁面結構。wrap存放生成的小球
box是用來檢測的元素
<div class="wrap"> <!-- 用於做碰撞檢測的一個元素 --> <div class="box"></div> </div>
css:
body { margin: 0; padding: 0; } .wrap { width: 100vw; height: 100vh; background-color: rgb(228, 243, 248); } .box { width: 70px; height: 70px; background-color: green; border-radius: 50%; position: fixed; top: 0; left: 0; } .wrap .item { position: fixed; border-radius: 50%; }
js
let wrap = document.querySelector('.wrap');
let box = document.querySelector('.box');
// 隨機數函數
function rn(a, b) {
return Math.round(Math.random() * (a - b) + b);
}
// 創建其他小球的函數
function create() {
// 創建div
let el = document.createElement('div');
// 從20-100之間隨機一個數作為小球的寬高(要是圓形,所以寬高相同)
let w = rn(20, 80);
el.style.width = w + 'px';
el.style.height = w + 'px';
// 設置top left值 該元素css有固定定位
//可以選擇把最大值設置為當前屏幕/父級寬高,然后減去元素最大隨即寬度(80)
el.style.top = rn(0, 500) + 'px';
el.style.left = rn(0, 1200) + 'px';
// 追加item作為類名
el.className = 'item';
// 獲取0-1之間的隨機數並取小數點后一位
let opa = Math.random().toFixed(1);
// 設置隨機顏色
// 不能先給一個變量隨機0-254,然后拼接變量,拼接出來red green blue顏色都一樣
el.color = 'rgba(' + rn(0, 254) + ',' + rn(0, 254) + ',' + rn(0, 254) + ',' + opa + ')';
el.style.background = el.color;
// 元素追加給wrap
wrap.appendChild(el);
}
// 利用循環創建20個小球
function balls() {
for (let i = 0; i < 20; i++) {
create();
}
}
balls();
// box半徑(理論上寫一個就好,是個正方形畫出來的圓嘛~)
let r1 = box.offsetWidth / 2;
// 獲取創建的小球們
let item = document.querySelectorAll('.item');
// console.log(item);
// 文檔注冊鼠標移動事件
document.onmousemove = function (ev) {
let e = ev || event;
// 獲取瀏覽器寬度/高度,減去要檢測的盒子寬高一半
let x = e.clientX - r1;
let y = e.clientY - r1;
// 設為要拿去做檢測的盒子左邊,上邊
// 鼠標移動的時候改變要拿去做碰撞檢測的元素的top left值(改變位置,讓他動起來,動的范圍是整個可視頁面-自己寬高,不會卡一半在外面)
box.style.left = x + 'px';
box.style.top = y + 'px';
for (let i = 0; i < item.length; i++) {
// item的半徑
let r2 = item[i].offsetHeight / 2;
// 生成的小球的左邊+半徑,減用來檢測的元素的左邊+半徑(兩個球圓心距)
let leftC = item[i].offsetLeft + r2 - (box.offsetLeft + r1);
// 生成的小球上邊加半徑-檢測小球的上邊加半徑
let topC = item[i].offsetTop + r2 - (box.offsetTop + r1);
// pow() 方法可返回 x 的 y 次冪的值。
// sqrt() 方法可返回一個數的平方根。
// 水平方向圓心距的2次冪 + 垂直方向的圓心距2次冪,的平方根(勾股定理?)
let dis = Math.sqrt(Math.pow(leftC, 2) + Math.pow(topC, 2));
// 求出來的值小於檢測的兩個球的半徑的和,碰撞上了,生成的小球變色
if (dis < r1 + r2) {
item[i].style.background = 'red';
} else {
item[i].style.background = item[i].color;
}
}
};
over
