JS/HTML5游戏常用算法之追踪算法实例详解


Posted in Javascript onDecember 12, 2018

本文实例讲述了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来说,需要进行同样的处理即可。

JS/HTML5游戏常用算法之追踪算法实例详解

基于以上这个简单算法的原理,可以来尝试一个简单的例子。

<!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.3water.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轴方向上的分量。

JS/HTML5游戏常用算法之追踪算法实例详解

将上面的简单算法,按照视线追踪算法进行改写:

<!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.3water.com/code/HtmlJsRun测试运行上述代码,可得到如下运行结果:

JS/HTML5游戏常用算法之追踪算法实例详解

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

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
js实现的仿新浪微博完美的时间组件升级版
Dec 20 Javascript
推荐30个新鲜出炉的精美 jQuery 效果
Mar 26 Javascript
转义字符(\)对JavaScript中JSON.parse的影响概述
Jul 17 Javascript
jQuery实现列表自动循环滚动鼠标悬停时停止滚动
Sep 06 Javascript
在Node.js中实现文件复制的方法和实例
Jun 05 Javascript
JS实现的仿QQ空间图片弹出效果代码
Feb 23 Javascript
jQuery特殊符号转义的实现
Nov 30 Javascript
JavaScript解析机制与闭包原理实例详解
Mar 08 Javascript
Node爬取大批量文件的方法示例
Jun 28 Javascript
解决layer.open弹出框不能获取input框的值为空的问题
Sep 10 Javascript
解决VUE自定义拖拽指令时 onmouseup 与 click事件冲突问题
Jul 24 Javascript
JavaScript语句错误throw、try及catch实例解析
Aug 18 Javascript
js使用swiper实现层叠轮播效果实例代码
Dec 12 #Javascript
如何制作一个Node命令行图像识别工具
Dec 12 #Javascript
JS遍历JSON数组及获取JSON数组长度操作示例【测试可用】
Dec 12 #Javascript
ionic使用angularjs表单验证(模板验证)
Dec 12 #Javascript
微信小程序自定义导航教程(兼容各种手机)
Dec 12 #Javascript
express express-session的使用小结
Dec 12 #Javascript
解决vue移动端适配问题
Dec 12 #Javascript
You might like
《破坏领主》销量已超100万 未来将继续开发新内容
2020/03/08 其他游戏
用php守护另一个php进程的例子
2015/02/13 PHP
php类的自动加载操作实例详解
2016/09/28 PHP
JavaScript 嵌套函数指向this对象错误的解决方法
2010/03/15 Javascript
Easy.Ajax 部分源代码 支持文件上传功能, 兼容所有主流浏览器
2011/02/24 Javascript
javascripit实现密码强度检测代码分享
2013/12/12 Javascript
confirm的用法示例用于按钮操作时确定是否执行
2014/06/19 Javascript
JS获取浏览器语言动态加载JS文件示例代码
2014/10/31 Javascript
javascript学习笔记整理(概述、变量、数据类型简介)
2015/10/25 Javascript
jQuery EasyUI框架中的Datagrid数据表格组件结构详解
2016/06/09 Javascript
js 原型对象和原型链理解
2017/02/09 Javascript
利用JS判断客户端类型你应该知道的四种方法
2017/12/22 Javascript
在 Angular-cli 中使用 simple-mock 实现前端开发 API Mock 接口数据模拟功能的方法
2018/11/28 Javascript
vue组件文档(.md)中如何自动导入示例(.vue)详解
2019/01/25 Javascript
JS数组方法push()、pop()用法实例分析
2020/01/18 Javascript
跟老齐学Python之坑爹的字符编码
2014/09/28 Python
Python多线程结合队列下载百度音乐的方法
2015/07/27 Python
Python实现删除当前目录下除当前脚本以外的文件和文件夹实例
2015/07/27 Python
完美解决安装完tensorflow后pip无法使用的问题
2018/06/11 Python
Python错误处理操作示例
2018/07/18 Python
python实现输出一个序列的所有子序列示例
2019/11/18 Python
详解用Pytest+Allure生成漂亮的HTML图形化测试报告
2020/03/31 Python
CSS3对背景图片的裁剪及尺寸和位置的设定方法
2016/03/07 HTML / CSS
纯css3实现宠物小鸡实例代码
2018/10/08 HTML / CSS
Willer台湾:日本高速巴士/夜行巴士预约
2017/07/09 全球购物
eBay爱尔兰站:eBay.ie
2019/08/09 全球购物
雷蛇美国官网:Razer
2020/04/03 全球购物
生产部主管岗位职责
2014/01/06 职场文书
黄继光的英雄事迹材料
2014/02/13 职场文书
数学检讨书1000字
2014/02/24 职场文书
公司爱心捐款倡议书
2014/05/14 职场文书
小学运动会演讲稿
2014/08/25 职场文书
大学生上课迟到检讨书
2014/10/15 职场文书
2014旅游局党组书记党建工作汇报材料
2014/11/02 职场文书
Python基于百度API识别并提取图片中文字
2021/06/27 Python
TypeScript 使用 Tuple Union 声明函数重载
2022/04/07 Javascript