国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

JS/HTML5游戲常用算法之追蹤算法實例詳解

2019-11-19 12:21:12
字體:
來源:轉載
供稿:網友

本文實例講述了JS/HTML5游戲常用算法之追蹤算法。分享給大家供大家參考,具體如下:

追蹤算法在動作游戲中非常常見,從很早的游戲《吃豆人》到大型的街機機戰類游戲,到處可見追蹤效果的身影。一個好的追蹤算法將會大大提高游戲的可玩性和玩家的興趣。

【簡單算法】

先來看一個簡單的跟蹤算法,如下圖所示,假設在canvas坐標系中存在物體A和B,物體A將把B作為追蹤目標,物體在二維空間中的運動可以分解為坐標系中X、Y軸的運動,其在X和Y方向的速度決定了物體運行的方向和速率。別忘了,速度是有方向和大小的,于是物體A的速度在X、Y軸方向分解成vx、vy,B物體也是一樣,這樣,如果物體A要追蹤到B,只需要比較兩個物體分別在 X、Y 方向的速度即可。設物體 A 坐標為(x1, y1),A 的速度分解為(vx, vy),物體B 坐標為(x2, y2),B 的速度分解為(vx1, vy1),假設A 要追到B,對于水平X 方向分量來說,如果x2>x1,表示B在A的右邊,這時候必須設置vx為某一個正值,反之,則需要將vx設置成一個負值,同樣的道理,對于垂直方向Y來說,需要進行同樣的處理即可。

基于以上這個簡單算法的原理,可以來嘗試一個簡單的例子。

<!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></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;    balls = [];    var ball = {      x: stage.width / 2 - 20,      y: stage.height / 2 - 20,      r: 20,      c: "red"    };    balls.push(ball);    for (var i = 0; i < 30; i++) {      var trace = {        x: Math.ceil(Math.random() * (stage.width - 20) + 10),        y: Math.ceil(Math.random() * (stage.height - 20) + 10),        r: 10,        c: "blue"      };      balls.push(trace);    }    function createBall(x, y, r, c) {      ctx.beginPath();      ctx.fillStyle = c;      ctx.arc(x, y, r, 0, Math.PI * 2);      ctx.fill();    }    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].y = y;    });    function update() {      ctx.clearRect(0, 0, 400, 400);      ctx.fillStyle = "black";      ctx.rect(0, 0, 400, 400);      ctx.fill();      createBall(balls[0].x, balls[0].y, balls[0].r, balls[0].c);      for (var i = 1, len = balls.length; i < len; i++) {        //簡單算法        balls[i].x -= ( balls[0].x>balls[i].x)?-1:1;        balls[i].y -= ( balls[0].y>balls[i].y)?-1:1;        createBall(balls[i].x, balls[i].y, balls[i].r, balls[i].c);      }      requestAnimationFrame(update);    }    update();  };</script></html>

感興趣的朋友可以使用在線HTML/CSS/JavaScript代碼運行工具http://tools.VeVB.COm/code/HtmlJsRun測試運行上述代碼,觀察運行效果。

采用這種算法的方塊的行動比較突兀,方塊的變向比較突然,效果看起來不是非常理想,于是,就產生了下面的視線追蹤算法。

【視線追蹤算法】

視線追蹤算法,采用這種算法,追蹤者將會始終保持著和目標對象的直線進行移動,如下圖所示,看起來就好像追蹤捕食的獵豹一樣,死死地盯著目標不放。

如果要達到這種效果,實際上就表示在任意時刻,A 的速度方向必須保持在 AB 之間連接的直線上面,那么這個時候如何獲取A的速度在x軸和y軸方向上的分量呢?

這里我們可以采用向量來解決問題,向量是一種只有方向和大小而沒有位置的概念,由向量的知識可知,假設任意時刻物體 A 向量表示為 v1(x1, y1),物體 B 向量表示為 v2(x2, y2),則由A 指向B 位置的向量v3=(x2−x1, y2−y1)。這3 個向量的關系可以由圖6-4 表示出來,設向量v3的長度為VLen = (x2−x1)²+(y2−y1)² ,則向量v3標準化后可以用v4=((x2−x1)/VLen,(y2−y1)/VLen)表示。最后得到的v4在x軸方向上的分量就可以作為物體A在該時刻X軸方向上的分量,v4在Y軸方向上的分量就可以作為物體A在該時刻Y軸方向上的分量。

將上面的簡單算法,按照視線追蹤算法進行改寫:

<!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></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;    balls = [];    var ball = {      x: stage.width / 2 - 20,      y: stage.height / 2 - 20,      r: 20,      c: "red"    };    balls.push(ball);    for (var i = 0; i < 30; i++) {      var trace = {        x: Math.ceil(Math.random() * (stage.width - 20) + 10),        y: Math.ceil(Math.random() * (stage.height - 20) + 10),        r: 10,        c: "blue"      };      balls.push(trace);    }    function createBall(x, y, r, c) {      ctx.beginPath();      ctx.fillStyle = c;      ctx.arc(x, y, r, 0, Math.PI * 2);      ctx.fill();    }    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].y = y;    });    function update() {      ctx.clearRect(0, 0, 400, 400);      ctx.fillStyle = "black";      ctx.rect(0, 0, 400, 400);      ctx.fill();      createBall(balls[0].x, balls[0].y, balls[0].r, balls[0].c);      for (var i = 1, len = balls.length; i < len; i++) {        //視線追蹤算法        var vx = balls[i].x - balls[0].x,          vy = balls[i].y - balls[0].y,          rlen = Math.sqrt(vx * vx + vy * vy),          dx = vx / rlen,          dy = vy / rlen;        balls[i].x -= dx;        balls[i].y -= dy;        createBall(balls[i].x, balls[i].y, balls[i].r, balls[i].c);      }      requestAnimationFrame(update);    }    update();  };</script></html>

使用在線HTML/CSS/JavaScript代碼運行工具http://tools.VeVB.COm/code/HtmlJsRun測試運行上述代碼,可得到如下運行結果:

github地址:https://github.com/krapnikkk/JS-gameMathematics

更多關于JavaScript相關內容感興趣的讀者可查看本站專題:《JavaScript數學運算用法總結》、《JavaScript數據結構與算法技巧總結》、《JavaScript數組操作技巧總結》、《JavaScript排序算法總結》、《JavaScript遍歷算法與技巧總結》、《JavaScript查找算法技巧總結》及《JavaScript錯誤與調試技巧總結

希望本文所述對大家JavaScript程序設計有所幫助。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 鞍山市| 乡宁县| 连云港市| 璧山县| 临安市| 偏关县| 达日县| 东乡| 格尔木市| 福安市| 新蔡县| 冕宁县| 珲春市| 苏尼特左旗| 乌兰浩特市| 兴隆县| 彭泽县| 故城县| 二手房| 璧山县| 菏泽市| 神池县| 左权县| 银川市| 临沧市| 布拖县| 施秉县| 年辖:市辖区| 绿春县| 迁安市| 广平县| 双城市| 叙永县| 隆子县| 台山市| 综艺| 施秉县| 鄂托克旗| 来宾市| 乌拉特后旗| 凤台县|