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 Split方法,indexOf方法、lastIndexOf 方法和substring 方法
Mar 21 Javascript
Jquery中增加参数与Json转换代码
Nov 20 Javascript
js各种验证文本框输入格式(正则表达式)
Oct 22 Javascript
js导航菜单(自写)简单大方
Mar 28 Javascript
jQuery实现限制文本框的输入长度
Jan 11 Javascript
Bootstrap缩略图的创建方法
Mar 22 Javascript
AngularJS中ng-class用法实例分析
Jul 06 Javascript
基于input动态模糊查询的实现方法
Dec 12 Javascript
Vue-Router模式和钩子的用法
Feb 28 Javascript
JS实现压缩上传图片base64长度功能
Dec 03 Javascript
ES6使用新特性Proxy实现的数据绑定功能实例
May 11 Javascript
JavaScript中Object、map、weakmap的区别分析
Dec 15 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
在字符串中把网址改成超级链接
2006/10/09 PHP
google地图的路线实现代码
2009/08/20 Javascript
利用google提供的API(JavaScript接口)获取网站访问者IP地理位置的代码详解
2010/07/24 Javascript
手机端网页点击链接触发自动拨打或保存电话的示例代码
2014/08/15 Javascript
js实现发送验证码后的倒计时功能
2015/05/28 Javascript
jQuery原型属性和原型方法详解
2015/07/07 Javascript
jQuery中的siblings用法实例分析
2015/12/24 Javascript
JavaScript小技巧整理
2015/12/30 Javascript
jQuery实现从身份证号中获取出生日期和性别的方法分析
2016/02/25 Javascript
JS简单实现浮动窗口效果示例
2016/09/07 Javascript
ES6深入理解之“let”能替代”var“吗?
2017/06/28 Javascript
vue开发调试神器vue-devtools使用详解
2017/07/13 Javascript
JavaScript实现无刷新上传预览图片功能
2017/08/02 Javascript
ES6 中可以提升幸福度的小功能
2018/08/06 Javascript
Vue $mount实战之实现消息弹窗组件
2019/04/22 Javascript
JS获取本地地址及天气的方法实例小结
2019/05/10 Javascript
利用Electron简单撸一个Markdown编辑器的方法
2019/06/10 Javascript
[03:49]DOTA2 2015国际邀请赛中国区预选赛第二日现场百态
2015/05/27 DOTA
Python实现直方图均衡基本原理解析
2019/08/08 Python
HTML中fieldset标签概述及使用方法
2013/02/01 HTML / CSS
为有想象力的人提供的生活方式商店:Firebox
2018/06/04 全球购物
印度最大的时尚购物网站:Myntra
2018/09/13 全球购物
阿玛尼意大利官网:Armani意大利
2018/10/30 全球购物
施华洛世奇匈牙利官网:SWAROVSKI匈牙利
2019/07/06 全球购物
OSPF有什么优点?为什么OSPF比RIP收敛快?
2013/02/13 面试题
计算机毕业大学生推荐信
2013/12/01 职场文书
学生期末评语大全
2014/04/30 职场文书
植树节标语
2014/06/27 职场文书
五一活动标语
2014/06/30 职场文书
中国梦演讲稿3分钟
2014/08/19 职场文书
中华在我心中演讲稿
2014/09/13 职场文书
任命通知范文
2015/04/21 职场文书
关于保护环境的建议书
2019/06/24 职场文书
会议承办单位欢迎词
2019/07/09 职场文书
MySQL中InnoDB存储引擎的锁的基本使用教程
2021/05/26 MySQL
Java基础-封装和继承
2021/07/02 Java/Android