JS/HTML5游戏常用算法之碰撞检测 包围盒检测算法详解【圆形情况】


Posted in Javascript onDecember 13, 2018

本文实例讲述了JS/HTML5游戏常用算法之碰撞检测 包围盒检测算法。分享给大家供大家参考,具体如下:

检测物体碰撞实际上是需要检测物体是否相交,而实际应用中物体的形状大小各异,如果直接对物体的边缘进行碰撞检测,实际计算过程的代价非常高昂。如果物体的数量太多,比如像网络游戏中,通常少则几千用户,多则上万、几十万用户同时在线,而这些碰撞都要通过服务器检测,这样计算的消耗,即使是大型服务器也会崩溃,所以通常不需要十分精确的碰撞检测情况下,使用包围盒算法,即把物体放在一个多边形中,这个多边形就是包围盒。

基于这样一个概念,通常情况下我们就使用了最简单的几种多边形,比如圆形、矩形等。

先来看看如何使用圆形包围盒算法,圆形包围盒算法就是使用圆形作为包围盒将物体包围起来,检测的时候只需要检测两个圆形是否碰撞即可。检测圆形的碰撞比较容易,假设圆 A 的坐标(x1, y1),半径是 r1,圆 B 的坐标(x2, y2),半径是 r2,则如果满足不等式(y2−y1)2+(x2−x1)2≤(r1+r2)2则表示两个圆发生了碰撞,其实就是圆心之间的距离小于两个圆的半径之和即可,由于计算距离需要用到开方运算,效率较低,所以直接比较距离的平方。

JS/HTML5游戏常用算法之碰撞检测 包围盒检测算法详解【圆形情况】

关键代码:

function hitTest( source, target ) {
   /* 源物体和目标物体都包含 x, y 以及 width, height */
   return !(
    Math.pow((source.x - target.x),2) + Math.pow((source.y - target.y),2) > Math.pow((source.r + target.r),2)
   );
  }

完整示例代码:

<!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>
<h1>是否碰撞:<span class="hitTest">否</span></h1>
<canvas id="stage"></canvas>
</body>
<script>
 window.onload = function () {
  var stage = document.querySelector('#stage'),
   ctx = stage.getContext('2d');
  stage.width = 400;
  stage.height = 400;
  document.onkeydown = function (event) {
   var e = event || window.event || arguments.callee.caller.arguments[0];
   //根据地图数组碰撞将测
   switch (e.keyCode) {
    case 37:
     console.log("Left");
     if (balls[0].x > 0) {
      balls[0].x -= 2;
     }
     break;
    case 38:
     console.log("Top");
     if (balls[0].y > 0) {
      balls[0].y -= 2;
     }
     break;
    case 39:
     console.log("Right");
     if (balls[0].x < stage.width) {
      balls[0].x += 2;
     }
     break;
    case 40:
     console.log("Bottom");
     if (balls[0].y < stage.height) {
      balls[0].y += 2;
     }
     break;
    default:
     return false;
   }
  };
  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].r/2;
   balls[0].y = y - balls[0].r/2;
  });
  var player = {
   x: stage.width / 2 - 20,
   y: stage.height / 2 - 20,
   r: 40,
   c: "red"
  },balls = [];
  balls.push(player);
  for (var i = 0; i < 10; i++) {
   var ball = {
    x: 60 * i,
    y: 60 * i,
    r: 40,
    c: "blue"
   };
   balls.push(ball);
  }
  function createBall(x, y, r, c) {
   ctx.beginPath();
   ctx.fillStyle = c;
   ctx.arc(x, y, r, 0, Math.PI*2);
   ctx.fill();
  }
  function hitTest( source, target ) {
   /* 源物体和目标物体都包含 x, y 以及 width, height */
   return !(
    Math.pow((source.x - target.x),2) + Math.pow((source.y - target.y),2) > Math.pow((source.r + target.r),2)
   );
  }
  function update() {
   ctx.globalAlpha=1;
   ctx.clearRect(0, 0, 400, 400);
   document.querySelector('.hitTest').innerHTML = "否";
   for (var i = 1, len = balls.length; i < len; i++) {
    createBall(balls[i].x, balls[i].y, balls[i].r, balls[i].c);
    var flag = hitTest(balls[0],balls[i]);
    if(flag){
     document.querySelector('.hitTest').innerHTML = "是";
     ctx.globalAlpha=0.5;
    }
   }
   createBall(balls[0].x, balls[0].y, balls[0].r, balls[0].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 相关文章推荐
用javascript实现的激活输入框后隐藏初始内容
Jun 29 Javascript
JS非Alert实现网页右下角“未读信息”效果弹窗
Sep 26 Javascript
javascript DIV实现跟随鼠标移动
Mar 19 Javascript
浅谈jQuery animate easing的具体使用方法(推荐)
Jun 17 Javascript
js HTML5 Canvas绘制转盘抽奖
Sep 13 Javascript
javascript工厂模式和构造函数模式创建对象方法解析
Dec 30 Javascript
php输出全部gb2312编码内的汉字方法
Mar 04 Javascript
JavaScript纯色二维码变成彩色二维码
Jul 23 Javascript
jquery鼠标悬停导航下划线滑出效果
Sep 29 jQuery
基于Angular中ng-controller父子级嵌套的相关属性详解
Oct 08 Javascript
如何用Node.js编写内存效率高的应用程序
Apr 30 Javascript
Javascript的promise,async和await的区别详解
Mar 24 Javascript
示例vue 的keep-alive缓存功能的实现
Dec 13 #Javascript
Element UI框架中巧用树选择器的实现
Dec 12 #Javascript
vue-cli中安装方法(图文详细步骤)
Dec 12 #Javascript
新版小程序登录授权的方法
Dec 12 #Javascript
加快Vue项目的开发速度的方法
Dec 12 #Javascript
关于自定义Egg.js的请求级别日志详解
Dec 12 #Javascript
JS/HTML5游戏常用算法之碰撞检测 像素检测算法实例详解
Dec 12 #Javascript
You might like
Blitz templates 最快的PHP模板引擎
2010/04/06 PHP
php curl 获取https请求的2种方法
2015/04/27 PHP
jquery+php实现导出datatables插件数据到excel的方法
2015/07/06 PHP
PHP生成唯一ID之SnowFlake算法
2016/12/17 PHP
php使用变量动态创建类的对象用法示例
2017/02/06 PHP
laravel实现前后台路由分离的方法
2019/10/13 PHP
Ruffy javascript 学习笔记
2009/11/30 Javascript
Javascript Math ceil()、floor()、round()三个函数的区别
2010/03/09 Javascript
动态加载jQuery的方法
2015/06/16 Javascript
JavaScript动态提示输入框输入字数的方法
2015/07/27 Javascript
jquery实现表单验证简单实例演示
2015/11/23 Javascript
bootstrap和jQuery.Gantt的css冲突 如何解决
2016/05/29 Javascript
javascript代码调试之console.log 用法图文详解
2016/09/30 Javascript
Webpack中css-loader和less-loader的使用教程
2017/04/27 Javascript
微信小程序上滑加载下拉刷新(onscrollLower)分批加载数据(一)
2017/05/11 Javascript
AngularJs 常用的过滤器
2017/05/15 Javascript
node中IO以及定时器优先级详解
2019/05/10 Javascript
在小程序中推送模板消息的实现方法
2019/07/22 Javascript
Vue简单实现原理详解
2020/05/07 Javascript
再也不怕 JavaScript 报错了,怎么看怎么处理都在这儿
2020/12/09 Javascript
vue element和nuxt的使用技巧分享
2021/01/14 Vue.js
[02:09:59]火猫TV国士无双dota2 6.82版本详解(下)
2014/09/29 DOTA
Python实现冒泡,插入,选择排序简单实例
2014/08/18 Python
Python os模块学习笔记
2015/06/21 Python
Python中shutil模块的常用文件操作函数用法示例
2016/07/05 Python
详解pandas.DataFrame中删除包涵特定字符串所在的行
2019/04/04 Python
python实现月食效果实例代码
2019/06/18 Python
基于python中__add__函数的用法
2019/11/25 Python
Vans荷兰官方网站:美国南加州的原创极限运动潮牌
2018/01/23 全球购物
俄罗斯一家时尚女装商店:Charuel
2019/12/04 全球购物
竞争性谈判邀请书
2014/02/06 职场文书
社区道德讲堂实施方案
2014/03/21 职场文书
社区青年志愿者活动总结
2015/05/06 职场文书
学生会任命书范本
2015/09/21 职场文书
公司开业的祝贺语大全(60条)
2019/07/05 职场文书
SQL SERVER触发器详解
2022/02/24 SQL Server