您好,登錄后才能下訂單哦!
本文實(shí)例講述了JS/HTML5游戲常用算法之碰撞檢測(cè) 包圍盒檢測(cè)算法。分享給大家供大家參考,具體如下:
檢測(cè)物體碰撞實(shí)際上是需要檢測(cè)物體是否相交,而實(shí)際應(yīng)用中物體的形狀大小各異,如果直接對(duì)物體的邊緣進(jìn)行碰撞檢測(cè),實(shí)際計(jì)算過(guò)程的代價(jià)非常高昂。如果物體的數(shù)量太多,比如像網(wǎng)絡(luò)游戲中,通常少則幾千用戶,多則上萬(wàn)、幾十萬(wàn)用戶同時(shí)在線,而這些碰撞都要通過(guò)服務(wù)器檢測(cè),這樣計(jì)算的消耗,即使是大型服務(wù)器也會(huì)崩潰,所以通常不需要十分精確的碰撞檢測(cè)情況下,使用包圍盒算法,即把物體放在一個(gè)多邊形中,這個(gè)多邊形就是包圍盒。
基于這樣一個(gè)概念,通常情況下我們就使用了最簡(jiǎn)單的幾種多邊形,比如圓形、矩形等。
先來(lái)看看如何使用圓形包圍盒算法,圓形包圍盒算法就是使用圓形作為包圍盒將物體包圍起來(lái),檢測(cè)的時(shí)候只需要檢測(cè)兩個(gè)圓形是否碰撞即可。檢測(cè)圓形的碰撞比較容易,假設(shè)圓 A 的坐標(biāo)(x1, y1),半徑是 r1,圓 B 的坐標(biāo)(x2, y2),半徑是 r2,則如果滿足不等式(y2−y1)2+(x2−x1)2≤(r1+r2)2則表示兩個(gè)圓發(fā)生了碰撞,其實(shí)就是圓心之間的距離小于兩個(gè)圓的半徑之和即可,由于計(jì)算距離需要用到開(kāi)方運(yùn)算,效率較低,所以直接比較距離的平方。
關(guān)鍵代碼:
function hitTest( source, target ) { /* 源物體和目標(biāo)物體都包含 x, y 以及 width, height */ return !( Math.pow((source.x - target.x),2) + Math.pow((source.y - target.y),2) > Math.pow((source.r + target.r),2) ); }
完整示例代碼:
<!DOCTYPE html> <html lang="en"> <head> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"> <meta charset="UTF-8"> <title>盒包圍碰撞算法-圓形</title> <style> #stage { border: 1px solid lightgray; } </style> </head> <body> <h2>是否碰撞:<span class="hitTest">否</span></h2> <canvas id="stage"></canvas> </body> <script> window.onload = function () { var stage = document.querySelector('#stage'), ctx = stage.getContext('2d'); stage.width = 400; stage.height = 400; document.onkeydown = function (event) { var e = event || window.event || arguments.callee.caller.arguments[0]; //根據(jù)地圖數(shù)組碰撞將測(cè) switch (e.keyCode) { case 37: console.log("Left"); if (balls[0].x > 0) { balls[0].x -= 2; } break; case 38: console.log("Top"); if (balls[0].y > 0) { balls[0].y -= 2; } break; case 39: console.log("Right"); if (balls[0].x < stage.width) { balls[0].x += 2; } break; case 40: console.log("Bottom"); if (balls[0].y < stage.height) { balls[0].y += 2; } break; default: return false; } }; stage.addEventListener('click', function (event) { var x = event.clientX - stage.getBoundingClientRect().left; var y = event.clientY - stage.getBoundingClientRect().top; balls[0].x = x - balls[0].r/2; balls[0].y = y - balls[0].r/2; }); var player = { x: stage.width / 2 - 20, y: stage.height / 2 - 20, r: 40, c: "red" },balls = []; balls.push(player); for (var i = 0; i < 10; i++) { var ball = { x: 60 * i, y: 60 * i, r: 40, c: "blue" }; balls.push(ball); } function createBall(x, y, r, c) { ctx.beginPath(); ctx.fillStyle = c; ctx.arc(x, y, r, 0, Math.PI*2); ctx.fill(); } function hitTest( source, target ) { /* 源物體和目標(biāo)物體都包含 x, y 以及 width, height */ return !( Math.pow((source.x - target.x),2) + Math.pow((source.y - target.y),2) > Math.pow((source.r + target.r),2) ); } function update() { ctx.globalAlpha=1; ctx.clearRect(0, 0, 400, 400); document.querySelector('.hitTest').innerHTML = "否"; for (var i = 1, len = balls.length; i < len; i++) { createBall(balls[i].x, balls[i].y, balls[i].r, balls[i].c); var flag = hitTest(balls[0],balls[i]); if(flag){ document.querySelector('.hitTest').innerHTML = "是"; ctx.globalAlpha=0.5; } } createBall(balls[0].x, balls[0].y, balls[0].r, balls[0].c); requestAnimationFrame(update); } update(); }; </script> </html>
這里使用在線HTML/CSS/JavaScript代碼運(yùn)行工具:http://tools.jb51.net/code/HtmlJsRun 測(cè)試上述代碼運(yùn)行結(jié)果如下:
github地址:https://github.com/krapnikkk/JS-gameMathematics
更多關(guān)于JavaScript相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《JavaScript數(shù)學(xué)運(yùn)算用法總結(jié)》、《JavaScript數(shù)據(jù)結(jié)構(gòu)與算法技巧總結(jié)》、《JavaScript數(shù)組操作技巧總結(jié)》、《JavaScript排序算法總結(jié)》、《JavaScript遍歷算法與技巧總結(jié)》、《JavaScript查找算法技巧總結(jié)》及《JavaScript錯(cuò)誤與調(diào)試技巧總結(jié)》
希望本文所述對(duì)大家JavaScript程序設(shè)計(jì)有所幫助。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。