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 相关文章推荐
syntaxhighlighter 使用方法
Jul 02 Javascript
jquery select多选框的左右移动 具体实现代码
Jul 03 Javascript
JavaScript设计模式之工厂模式和构造器模式
Feb 11 Javascript
jQuery事件绑定与解除绑定实现方法
Apr 15 Javascript
webpack+vue.js实现组件化详解
Oct 12 Javascript
js中string和number类型互转换技巧(分享)
Nov 28 Javascript
Vue2 使用 Echarts 创建图表实例代码
May 18 Javascript
Vue下滚动到页面底部无限加载数据的示例代码
Apr 22 Javascript
简化版的vue-router实现思路详解
Oct 19 Javascript
JavaScript数据结构之栈实例用法
Jan 18 Javascript
大转盘抽奖小程序版 转盘抽奖网页版
Apr 16 Javascript
ant-design-vue按需加载的坑的解决
May 14 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
创建数据库php代码 用PHP写出自己的BLOG系统
2010/04/12 PHP
域名和cookie问题(域名后缀)
2012/10/10 PHP
php使用exec shell命令注入的方法讲解
2013/11/12 PHP
在SAE上搭建最新wordpress的方法
2014/12/21 PHP
php中Socket创建与监听实现方法
2015/01/05 PHP
php+MySQL实现登录时验证登录名和密码是否正确
2016/05/10 PHP
Yii2实现同时搜索多个字段的方法
2016/08/10 PHP
PHP类相关知识点实例总结
2016/09/28 PHP
jquery异步调用页面后台方法&amp;#8207;(asp.net)
2011/03/01 Javascript
js的一些常用方法小结
2011/06/29 Javascript
JS链式调用的实现方法
2013/03/07 Javascript
JS获取浏览器版本及名称实现函数
2013/04/02 Javascript
javascript实现相同事件名称,不同命名空间的调用方法
2015/06/26 Javascript
基于MVC5和Bootstrap的jQuery TreeView树形控件(一)之数据支持json字符串、list集合
2016/08/11 Javascript
javascript的函数劫持浅析
2016/09/26 Javascript
Vue 组件间的样式冲突污染
2017/08/31 Javascript
EasyUI实现下拉框多选功能
2017/11/07 Javascript
express+mockjs实现模拟后台数据发送功能
2018/01/07 Javascript
旺旺在线客服代码 旺旺客服代码生成器
2018/01/09 Javascript
javascript局部自定义鼠标右键菜单
2020/12/08 Javascript
[40:03]RNG vs VG 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/17 DOTA
深入理解Django-Signals信号量
2019/02/19 Python
python如何实现数据的线性拟合
2019/07/19 Python
Pycharm使用远程linux服务器conda/python环境在本地运行的方法(图解))
2019/12/09 Python
Nike台湾官方商店:Nike.com (TW)
2017/08/16 全球购物
iostream与iostream.h的区别
2015/01/16 面试题
mysql有关权限的表都有哪几个
2015/04/22 面试题
啦啦队口号大全
2014/06/16 职场文书
夫妻分居协议书范本(有子女版)
2014/11/01 职场文书
四年级学生期末评语
2014/12/26 职场文书
2015年中秋节演讲稿
2015/03/20 职场文书
焦裕禄纪念馆观后感
2015/06/09 职场文书
2015入党个人自传范文
2015/06/26 职场文书
先进个人主要事迹范文
2015/11/04 职场文书
golang switch语句的灵活写法介绍
2021/05/06 Golang