JS/HTML5游戲常用算法之碰撞檢測 地圖格子算法實(shí)例詳解
本文實(shí)例講述了JS/HTML5游戲常用算法之碰撞檢測 地圖格子算法。分享給大家供大家參考,具體如下:
這種算法經(jīng)常用于RPG(早期的《最終幻想》、《DQ》、《仙劍奇?zhèn)b傳》)、SLG(《炎龍騎士團(tuán)》、《超級機(jī)器人大戰(zhàn)》)、PUZ(《俄羅斯方塊》、《寶石謎陣》)類型的游戲。這類游戲中,通常情況下整個(gè)地圖都是由一些地圖塊元素組成,在制作的時(shí)候首先給制作出地圖所需要的最基本的元素進(jìn)行編號,然后把這些編號的地圖塊組合起來就可以根據(jù)需要形成任意大小的地圖。
早期的RPG類型或者SLG類型的游戲可以明顯地看出游戲中的地圖是由一些小的地圖塊格子而成,采用這種方式組成地圖的好處是節(jié)約內(nèi)存的使用,并且不需要太多的地圖元素就可以任意組合成足夠大的地圖,簡單靈活,缺陷就是最后制作出的地圖不太美觀。但實(shí)際上為了便于游戲中的碰撞檢測,比如人物碰到NPC或者是碰到不可跨越的障礙等情況,在游戲中實(shí)際上還是保存了一張看不見的邏輯層。這個(gè)層的大小和地圖等大,并且也進(jìn)行了格子劃分,主要目的就是為了碰撞檢測,通常我們在游戲中對這個(gè)碰撞邏輯層使用一個(gè)數(shù)組描述信息,使用 1 表示不可以通過,0表示可以通過,假設(shè)人物和NPC在游戲中行走,這種情況下我們就很容易檢測地圖中人物是否碰到了NPC或者障礙物。
var mapArr = [ 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1 ];
代碼如下:
<!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> <canvas id="stage"></canvas> </body> <script> window.onload = function () { var stage = document.querySelector('#stage'), ctx = stage.getContext('2d'); stage.width = 400; stage.height = 400; var mapArr = [ 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1 ],rectIdx = 5; //柵格線條 function drawGrid(context, color, stepx, stepy) { context.strokeStyle = color; context.lineWidth = 0.5; for (var i = stepx + 0.5; i < context.canvas.width; i += stepx) { context.beginPath(); context.moveTo(i, 0); context.lineTo(i, context.canvas.height); context.stroke(); } for (var i = stepy + 0.5; i < context.canvas.height; i += stepy) { context.beginPath(); context.moveTo(0, i); context.lineTo(context.canvas.width, i); context.stroke(); } } function createRect(x, y, r, c) { ctx.beginPath(); ctx.fillStyle = c; ctx.rect(x, y, r, r); ctx.fill(); } document.onkeydown = function (event) { var e = event || window.event || arguments.callee.caller.arguments[0]; //根據(jù)地圖數(shù)組碰撞將測 switch (e.keyCode){ case 37: console.log("Left"); if (rectIdx - 1 >= 0 && (rectIdx - 1) % 4 !== 3 && !mapArr[rectIdx - 1]) { rectIdx -= 1; } break; case 38: console.log("Top"); if (rectIdx - 4 >= 0 && !mapArr[rectIdx - 4]) { rectIdx -= 4; } break; case 39: console.log("Right"); if ((rectIdx + 1) % 4 !== 0 && !mapArr[rectIdx + 1]) { rectIdx += 1; } break; case 40: console.log("Bottom"); if (rectIdx + 4 < mapArr.length && !mapArr[rectIdx + 4]) { rectIdx += 4; } break; default: return false; } }; function update() { ctx.clearRect(0, 0, 400, 400); drawGrid(ctx, 'lightgray', 100, 100); var rect = { x: rectIdx % 4 * 100, y: rectIdx % 4 === 0 ? rectIdx / 4 * 100 : Math.floor(rectIdx / 4) * 100, r: 100, c: "blue" }; createRect(rect.x, rect.y, rect.r, rect.c); //根據(jù)地圖數(shù)組創(chuàng)建色塊 for (var i = 0, len = mapArr.length; i < len; i++) { if (mapArr[i]) { createRect(i % 4 * 100, i % 4 === 0 ? i / 4 * 100 : Math.floor(i / 4) * 100, 100, "red"); } } requestAnimationFrame(update); } update(); }; </script> </html>
使用在線HTML/CSS/JavaScript代碼運(yùn)行工具:http://tools.jb51.net/code/HtmlJsRun測試運(yùn)行上述代碼,可得到如下運(yùn)行結(jié)果:
github地址:https://github.com/krapnikkk/JS-gameMathematics
采用這種方式判斷邏輯極其簡單,效率也比較高,但不太精確,如果A物體的大小比格子小很多,則物體行動(dòng)的時(shí)候可能看起來離B物體有些距離就無法行走了,所以做這種類型游戲最好保證格子足夠小或者保證人物大小和格子相差不大
更多關(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é)》
希望本文所述對大家JavaScript程序設(shè)計(jì)有所幫助。
相關(guān)文章
JavaScript為事件句柄綁定監(jiān)聽函數(shù)實(shí)例詳解
這篇文章主要介紹了JavaScript為事件句柄綁定監(jiān)聽函數(shù)的方法,結(jié)合實(shí)例詳細(xì)分析了常見的事件句柄綁定監(jiān)聽函數(shù)的實(shí)現(xiàn)技巧,并實(shí)例講解了跨瀏覽器的實(shí)現(xiàn)方法,需要的朋友可以參考下2015-12-12微信小程序報(bào)錯(cuò): thirdScriptError的錯(cuò)誤問題
這篇文章主要介紹了微信小程序報(bào)錯(cuò): thirdScriptError,本文給大家分享解決方法,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-06-06如何使用require.context實(shí)現(xiàn)優(yōu)雅的預(yù)加載
這篇文章主要介紹了使用require.context實(shí)現(xiàn)優(yōu)雅的預(yù)加載?,需要的朋友可以參考下2023-05-05JavaScript輪播停留效果的實(shí)現(xiàn)思路
輪播停留與無線滾動(dòng)十分類似,都是利用屬性及變量控制移動(dòng)實(shí)現(xiàn)輪播。下面通過本文給大家分享JavaScript輪播停留效果的實(shí)現(xiàn)思路,感興趣的朋友一起看看吧2018-05-05JavaScript中innerHTML使用方法實(shí)例
js中常常用到innerHTML,其作用就是獲取到標(biāo)簽里面的內(nèi)容,同時(shí)也可以為標(biāo)簽添加內(nèi)容,下面這篇文章主要給大家介紹了關(guān)于JavaScript中innerHTML使用方法的相關(guān)資料,需要的朋友可以參考下2022-10-10微信二次分享報(bào)錯(cuò)invalid signature問題及解決方法
基于微信公眾號開發(fā)的h5頁面(使用jssdk接口),由用戶A分享給用戶B,用戶B再次分享這個(gè)頁面時(shí),不能成功分享。這篇文章主要介紹了微信二次分享報(bào)錯(cuò)invalid signature問題及解決方法,需要的朋友可以參考下2019-04-04淺析location.href跨窗口調(diào)用函數(shù)
本文詳細(xì)介紹了location.href跨窗口調(diào)用函數(shù),具體的使用方法及實(shí)例,有需要的朋友可以參考下2016-11-11