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弹簧振子超简洁版 完全符合能量守恒,胡克定理
Oct 25 Javascript
innerhtml用法 innertext用法 以及innerHTML与innertext的区别
Oct 26 Javascript
javascript iframe编程相关代码
Dec 28 Javascript
jQuery获得内容和属性示例代码
Jan 16 Javascript
JS实现图片高亮展示效果实例
Nov 24 Javascript
为Jquery EasyUI 组件加上清除功能的方法(详解)
Apr 13 jQuery
jQuery实现点击关注和取消功能
Jul 03 jQuery
浅谈node中的exports与module.exports的关系
Aug 01 Javascript
jquery写出PC端轮播图实例
Jan 26 jQuery
vue中引用阿里字体图标的方法
Feb 10 Javascript
Webpack之tree-starking 解析
Sep 11 Javascript
Mint UI组件库CheckList使用及踩坑总结
Dec 20 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安全性需要注意的几点事项
2014/07/17 PHP
symfony表单与页面实现技巧
2015/01/26 PHP
jQuery右键菜单contextMenu使用实例
2011/09/28 Javascript
面向对象的Javascript之二(接口实现介绍)
2012/01/27 Javascript
基于jquery的多功能软键盘插件
2012/07/25 Javascript
如何用JavaScript动态呼叫函数(两种方式)
2013/05/03 Javascript
简介JavaScript中substring()方法的使用
2015/06/06 Javascript
javascript模拟C#格式化字符串
2015/08/26 Javascript
AngularJS ng-controller 指令简单实例
2016/08/01 Javascript
基于JavaScript实现随机颜色输入框
2016/12/10 Javascript
JS实现多张图片预览同步上传功能
2017/06/23 Javascript
浅谈React前后端同构防止重复渲染
2018/01/05 Javascript
基于node下的http小爬虫的示例代码
2018/01/11 Javascript
NodeJS安装图文教程
2018/04/19 NodeJs
vue中接口域名配置为全局变量的实现方法
2018/09/20 Javascript
对vue v-if v-else-if v-else 的简单使用详解
2018/09/29 Javascript
对angularJs中controller控制器scope父子集作用域的实例讲解
2018/10/08 Javascript
详解vue几种主动刷新的方法总结
2019/02/19 Javascript
使用 vue 实现灭霸打响指英雄消失的效果附demo
2019/05/06 Javascript
JavaScript实现图片放大预览效果
2020/11/02 Javascript
Python2.6版本中实现字典推导 PEP 274(Dict Comprehensions)
2015/04/28 Python
使用Python简单的实现树莓派的WEB控制
2016/02/18 Python
Python数据分析之如何利用pandas查询数据示例代码
2017/09/01 Python
Python给你的头像加上圣诞帽
2018/01/04 Python
python for循环输入一个矩阵的实例
2018/11/14 Python
python-opencv颜色提取分割方法
2018/12/08 Python
Python如何利用Har文件进行遍历指定字典替换提交的数据详解
2020/11/05 Python
aec加密 php_php aes加密解密类(兼容php5、php7)
2021/03/14 PHP
CSS3 清除浮动的方法示例
2018/06/01 HTML / CSS
Zatchels官网:英国剑桥包品牌
2021/01/12 全球购物
销售人员自我评价怎么写
2013/09/19 职场文书
档案室主任岗位职责
2014/02/12 职场文书
如何写好建议书
2014/03/13 职场文书
意外事故赔偿协议书
2016/03/22 职场文书
基于Apache Hudi在Google云构建数据湖平台的思路详解
2022/04/07 Servers
iOS 16进一步确认,一共支持16款iPhone
2022/04/28 数码科技