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+xml技术实现分页浏览
Jul 27 Javascript
jQuery代码优化之基本事件
Nov 01 Javascript
JavaScript常用对象的方法和属性小结
Jan 24 Javascript
JS远程获取网页源代码实例
Sep 05 Javascript
AngularJS的内置过滤器详解
May 14 Javascript
javascript中attachEvent用法实例分析
May 14 Javascript
点击按钮出现60秒倒计时的简单js代码(推荐)
Jun 07 Javascript
如何理解jQuery中的ajaxSubmit方法
Mar 13 Javascript
Vue指令的钩子函数使用方法
Mar 20 Javascript
解决vuejs 使用value in list 循环遍历数组出现警告的问题
Sep 26 Javascript
layui使用及简单的三级联动实现教程
Dec 01 Javascript
深入详解JS函数的柯里化
Jun 09 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
浅析iis7.5安装配置php环境
2015/05/10 PHP
JavaScript 乱码问题
2009/08/06 Javascript
JavaScript toFixed() 方法
2010/04/15 Javascript
跨浏览器的 mouseenter mouseleave 以及 compareDocumentPosition的使用说明
2010/05/04 Javascript
兼容主流浏览器的jQuery+CSS 实现遮罩层的简单代码
2014/10/14 Javascript
详解JavaScript ES6中的模板字符串
2015/07/28 Javascript
jquery带翻页动画的电子杂志代码分享
2015/08/21 Javascript
jquery取消事件冒泡的三种方法(推荐)
2016/05/28 Javascript
基于JS如何实现类似QQ好友头像hover时显示资料卡的效果(推荐)
2016/06/09 Javascript
jQuery实用小技巧_输入框文字获取和失去焦点的简单实例
2016/08/25 Javascript
网页瀑布流布局jQuery实现代码
2016/10/21 Javascript
AngularJS+Bootstrap实现多文件上传与管理
2016/11/08 Javascript
JS实现简单的二元方程计算器功能示例
2017/01/03 Javascript
基于Vue实现后台系统权限控制的示例代码
2017/08/29 Javascript
vue2.0+vue-dplayer实现hls播放的示例
2018/03/02 Javascript
基于node搭建服务器,写接口,调接口,跨域的实例
2018/05/13 Javascript
详解.vue文件解析的实现
2018/06/11 Javascript
vue-cli 脚手架基于Nightwatch的端到端测试环境的过程
2018/09/30 Javascript
jQuery实现根据身份证号获取生日、年龄、性别等信息的方法
2019/01/09 jQuery
Vue+Element ui 根据后台返回数据设置动态表头操作
2020/09/21 Javascript
[03:20]2015国际邀请赛全明星表演赛
2015/08/08 DOTA
归纳整理Python中的控制流语句的知识点
2015/04/14 Python
python实现bucket排序算法实例分析
2015/05/04 Python
python 换位密码算法的实例详解
2017/07/19 Python
Python实现爬虫抓取与读写、追加到excel文件操作示例
2018/06/27 Python
将Python字符串生成PDF的实例代码详解
2019/05/17 Python
flask框架自定义过滤器示例【markdown文件读取和展示功能】
2019/11/08 Python
Django设置Postgresql的操作
2020/05/14 Python
浅谈python 类方法/静态方法
2020/09/18 Python
CSS3使用border-radius属性制作圆角
2014/12/22 HTML / CSS
html5菜单折纸效果
2014/04/22 HTML / CSS
PHP使用Redis队列执行定时任务实例讲解
2021/03/24 PHP
法院实习人员自我鉴定
2013/09/26 职场文书
山东省召开党的群众路线教育实践活动总结大会新闻稿
2014/10/21 职场文书
教师节感谢信
2015/01/22 职场文书
「回转企鹅罐」10周年纪念展「輪るピングドラム展」海报公开
2022/03/22 日漫