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 相关文章推荐
js 获取子节点函数 (兼容FF与IE)
Apr 18 Javascript
js实现无需数据库的县级以上联动行政区域下拉控件
Aug 14 Javascript
Js Jquery创建一个弹出层可加载一个页面
May 08 Javascript
jQuery.parseJSON(json)将JSON字符串转换成js对象
Jul 27 Javascript
JQuery EasyUI Layout 在from布局自适应窗口大小的实现方法
May 28 Javascript
使用JS实现图片展示瀑布流效果的实例代码
Sep 12 Javascript
js实现简单的网页换肤效果
Jan 18 Javascript
利用js给datalist或select动态添加option选项的方法
Jan 25 Javascript
vue和webpack打包项目相对路径修改的方法
Jun 15 Javascript
详解js location.href和window.open的几种用法和区别
Dec 02 Javascript
VUE前端从后台请求过来的数据进行转换数据结构操作
Nov 11 Javascript
如何用threejs实现实时多边形折射
May 07 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
PHP输出控制功能在简繁体转换中的应用
2006/10/09 PHP
对javascript和select部件的结合运用
2006/10/09 PHP
逆序二维数组插入一元素的php代码
2012/06/08 PHP
CI框架Session.php源码分析
2014/11/03 PHP
PHP文件类型检查及fileinfo模块安装使用详解
2019/05/09 PHP
javascript 动态添加表格行
2006/06/22 Javascript
jquery获取input表单值的代码
2010/04/19 Javascript
JS实现随机数生成算法示例代码
2013/08/08 Javascript
js返回前一页刷新本页重载页面
2014/07/29 Javascript
js实现进度条的方法
2015/02/13 Javascript
黑帽seo劫持程序,js劫持搜索引擎代码
2015/09/15 Javascript
jquery ui dialog替代confirm实例分析
2016/01/25 Javascript
深入理解bootstrap框架之第二章整体架构
2016/10/09 Javascript
原生js图片轮播效果实现代码
2016/10/19 Javascript
vue2笔记 — vue-router路由懒加载的实现
2017/03/03 Javascript
基于JavaScript实现瀑布流效果
2017/03/29 Javascript
vue源码入口文件分析(推荐)
2018/01/30 Javascript
对layui中表单元素的使用详解
2018/08/15 Javascript
利用Electron简单撸一个Markdown编辑器的方法
2019/06/10 Javascript
Python 用户登录验证的小例子
2013/03/06 Python
python urllib爬取百度云连接的实例代码
2017/06/19 Python
Python编写登陆接口的方法
2017/07/10 Python
python多线程socket编程之多客户端接入
2017/09/12 Python
Python中使用Counter进行字典创建以及key数量统计的方法
2018/07/06 Python
Pytorch 实现权重初始化
2019/12/31 Python
python中的itertools的使用详解
2020/01/13 Python
python第三方库学习笔记
2020/02/07 Python
windows上彻底删除jupyter notebook的实现
2020/04/13 Python
俄罗斯游戏商店:Buka
2020/03/01 全球购物
输入N,打印N*N矩阵
2012/02/20 面试题
投标人廉洁自律承诺书
2014/05/26 职场文书
生活部的活动方案
2014/08/19 职场文书
司法局群众路线教育实践活动开展情况总结
2014/10/25 职场文书
CAD实训总结范文
2015/08/03 职场文书
《没有任何借口》读后感:完美的执行能力
2020/01/07 职场文书
position:sticky 粘性定位的几种巧妙应用详解
2021/04/24 HTML / CSS