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 相关文章推荐
jquery select操作的日期联动实现代码
Dec 06 Javascript
分享27个jQuery 表单插件集合推荐
Apr 25 Javascript
分享精心挑选的23款美轮美奂的jQuery 图片特效插件
Aug 14 Javascript
利用JavaScript实现新闻滚动效果(实例代码)
Nov 27 Javascript
asm.js使用示例代码
Nov 28 Javascript
js解析json读取List中的实体对象示例
Mar 11 Javascript
jQuery获得document和window对象宽度和高度的方法
Mar 25 Javascript
Angular Js文件上传之form-data
Aug 28 Javascript
原生JS实现小小的音乐播放器
Oct 16 Javascript
关于js的三种使用方式(行内js、内部js、外部js)的程序代码
May 05 Javascript
mpvue开发音频类小程序踩坑和建议详解
Mar 12 Javascript
node使用mysql获取数据库数据中文乱码问题的解决
Dec 02 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
计算2000年01月01日起到指定日的天数
2006/10/09 PHP
防止MySQL注入或HTML表单滥用的PHP程序
2009/01/21 PHP
php access 数据连接与读取保存编辑数据的实现代码
2010/05/12 PHP
PHP读取PDF内容配合Xpdf的使用
2012/11/24 PHP
学习php设计模式 php实现命令模式(command)
2015/12/08 PHP
php判断str字符串是否是xml格式数据的方法示例
2017/07/26 PHP
关于Laravel参数验证的一些疑与惑
2019/11/19 PHP
50个比较实用jQuery代码段
2011/09/18 Javascript
比较不错的JS/JQuery显示或隐藏文本的方法
2014/02/13 Javascript
JavaScript Sort 的一个错误用法示例
2015/03/20 Javascript
javascript self对象使用详解
2016/10/18 Javascript
jQuery Easyui datagrid行内实现【添加】、【编辑】、【上移】、【下移】
2016/12/19 Javascript
HTML5+Canvas调用手机拍照功能实现图片上传(上)
2017/04/21 Javascript
Angular实现点击按钮控制隐藏和显示功能示例
2017/12/29 Javascript
AngularJS标签页tab选项卡切换功能经典实例详解
2018/05/16 Javascript
vue项目中使用百度地图的方法
2018/06/08 Javascript
JavaScript数据结构与算法之二叉树实现查找最小值、最大值、给定值算法示例
2019/03/01 Javascript
ES6实现图片切换特效代码
2020/01/14 Javascript
python发送邮件实例分享
2017/07/28 Python
Django中间件实现拦截器的方法
2018/06/01 Python
对Python 数组的切片操作详解
2018/07/02 Python
python自定义线程池控制线程数量的示例
2019/02/22 Python
Python操作excel的方法总结(xlrd、xlwt、openpyxl)
2019/09/02 Python
Django多数据库配置及逆向生成model教程
2020/03/28 Python
通过Python实现Payload分离免杀过程详解
2020/07/13 Python
PyCharm Ctrl+Shift+F 失灵的简单有效解决操作
2021/01/15 Python
英国女性时尚鞋类的潮流制造者:Koi Footwear
2018/10/19 全球购物
顶撞老师检讨书
2014/02/07 职场文书
《在大海中永生》教学反思
2014/02/24 职场文书
一年级评语大全
2014/04/23 职场文书
小学教师师德整改措施
2014/09/29 职场文书
党建工作目标管理责任书
2015/01/29 职场文书
幽默导游词开场白
2015/05/29 职场文书
亮剑观后感300字
2015/06/05 职场文书
2016年十一促销广告语
2016/01/28 职场文书
2016年教师党员创先争优承诺书
2016/03/24 职场文书