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 数据类型转换总结笔记
Jan 17 Javascript
js验证整数加保留小数点的简单实例
Dec 02 Javascript
Javascript 拖拽雏形中的一些问题(逐行分析代码,让你轻松了拖拽的原理)
Jan 23 Javascript
jquery实现浮动在网页右下角的彩票开奖公告窗口代码
Sep 04 Javascript
jQuery Chart图表制作组件Highcharts用法详解
Jun 01 Javascript
AngularJS 依赖注入详解和简单实例
Jul 28 Javascript
js实现的在线调色板功能完整实例
Dec 21 Javascript
ES6学习教程之模板字符串详解
Oct 09 Javascript
彻底理解js面向对象之继承
Feb 04 Javascript
Vue中的slot使用插槽分发内容的方法
Mar 01 Javascript
ES6的Fetch异步请求的实现方法
Dec 07 Javascript
vue 如何使用递归组件
Oct 23 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
根德YB400的电路分析
2021/03/02 无线电
提高PHP编程效率 引入缓存机制提升性能
2010/02/15 PHP
php权重计算方法代码分享
2014/01/09 PHP
php curl post 时出现的问题解决
2014/01/30 PHP
Yii2框架中日志的使用方法分析
2017/05/22 PHP
小程序微信退款功能实现方法详解【基于thinkPHP】
2019/05/05 PHP
JS判断不同分辨率调用不同的CSS样式文件实现思路及测试代码
2013/01/23 Javascript
使用JS 清空File控件的路径值
2013/07/08 Javascript
jquery中邮箱地址 URL网站地址正则验证实例代码
2013/09/15 Javascript
js判读浏览器是否支持html5的canvas的代码
2013/11/18 Javascript
JS实现仿微博可关闭弹出层效果
2015/09/21 Javascript
js文字横向滚动特效
2015/11/11 Javascript
jQuery通用的全局遍历方法$.each()用法实例
2016/07/04 Javascript
vue中SPA单页面应用程序详解
2017/11/07 Javascript
详解vue组件基础
2018/05/04 Javascript
详解使用mpvue开发github小程序总结
2018/07/25 Javascript
vue解决弹出蒙层滑动穿透问题的方法
2018/09/22 Javascript
浅析vue中的provide / inject 有什么用处
2019/11/10 Javascript
[39:00]Optic vs VP 2018国际邀请赛淘汰赛BO3 第三场 8.24
2018/08/25 DOTA
深入讲解Java编程中类的生命周期
2016/02/05 Python
Python实现随机选择元素功能
2017/09/14 Python
使用python 爬虫抓站的一些技巧总结
2018/01/10 Python
CentOS6.9 Python环境配置(python2.7、pip、virtualenv)
2019/05/06 Python
Flask模板引擎之Jinja2语法介绍
2019/06/26 Python
pandas-resample按时间聚合实例
2019/12/27 Python
把Anaconda中的环境导入到Pycharm里面的方法步骤
2020/10/30 Python
Dr. Martens马汀博士澳大利亚官网:马丁靴鼻祖
2019/07/02 全球购物
高校生生产实习自我鉴定
2013/09/21 职场文书
我的大学生活职业生涯规划
2014/01/02 职场文书
食品安全工作方案
2014/05/07 职场文书
品牌转让协议书
2014/08/20 职场文书
小学生推普周国旗下讲话稿
2014/09/21 职场文书
公证书格式
2015/01/23 职场文书
2015年大学班长个人工作总结
2015/04/24 职场文书
pycharm2021激活码使用教程(永久激活亲测可用)
2021/03/30 Python
Vue组件更新数据v-model不生效的解决
2022/04/02 Vue.js