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 学习之旅 (1)
Feb 05 Javascript
jquery 输入框数字限制插件
Nov 10 Javascript
Javascript 类型转换方法
Oct 24 Javascript
javascript 获取图片尺寸及放大图片
Sep 04 Javascript
JS阻止用户多次提交示例代码
Mar 26 Javascript
jQuery 删除/替换DOM元素的几种方式
May 20 Javascript
详解用webpack2搭建angular2的项目
Jun 22 Javascript
Less 安装及基本用法
May 05 Javascript
vue悬浮可拖拽悬浮按钮的实例代码
Aug 20 Javascript
electron 安装,调试,打包的具体使用
Nov 06 Javascript
原生JS实现贪吃蛇小游戏
Mar 09 Javascript
如何用vue实现网页截图你知道吗
Nov 17 Vue.js
示例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求两个目录的相对路径示例(php获取相对路径)
2014/03/27 PHP
PHP入门之常量简介和系统常量
2014/05/12 PHP
浅谈PHP接收POST数据方式
2015/06/05 PHP
PHP二分查找算法示例【递归与非递归方法】
2016/09/29 PHP
javascript 鼠标拖动图标技术
2010/02/07 Javascript
JQuery UI的拖拽功能实现方法小结
2012/03/14 Javascript
利用了jquery的ajax实现二级联互动菜单
2013/12/02 Javascript
JS获取浮动(float)元素的style.left值为空的快速解决办法
2017/02/19 Javascript
浅谈mvvm-simple双向绑定简单实现
2018/04/18 Javascript
vue中动态添加class类名的方法
2018/09/05 Javascript
jquery获取并修改触发事件的DOM元素示例【基于target 属性】
2019/10/10 jQuery
mpvue 页面预加载新增preLoad生命周期的两种方式
2019/10/17 Javascript
微信小程序国际化探索实现(附源码地址)
2020/05/20 Javascript
[04:16]DOTA2英雄梦之声_第09期_斧王
2014/06/21 DOTA
[05:13]TI4 中国战队 机场出征!!
2014/07/07 DOTA
[09:59]DOTA2-DPC中国联赛2月7日Recap集锦
2021/03/11 DOTA
python通过zlib实现压缩与解压字符串的方法
2014/11/19 Python
Python实现查找匹配项作处理后再替换回去的方法
2017/06/10 Python
Python实现将16进制字符串转化为ascii字符的方法分析
2017/07/21 Python
Numpy数据类型转换astype,dtype的方法
2018/06/09 Python
python openCV获取人脸部分并存储功能
2019/08/28 Python
python3.x 生成3维随机数组实例
2019/11/28 Python
Pycharm激活方法及详细教程(详细且实用)
2020/05/12 Python
keras中的loss、optimizer、metrics用法
2020/06/15 Python
PyQT5 实现快捷键复制表格数据的方法示例
2020/06/19 Python
python openssl模块安装及用法
2020/12/06 Python
Roots加拿大官网:加拿大休闲服饰品牌
2016/10/24 全球购物
我的珠宝盒:Ma boîte à bijoux
2019/08/27 全球购物
JDK安装目录下有哪些内容
2014/08/25 面试题
农业大学毕业生的个人自我评价
2013/10/11 职场文书
《我要的是葫芦》教学反思
2014/02/23 职场文书
运动会加油稿20字
2014/11/15 职场文书
贪污受贿检讨书范文
2014/11/19 职场文书
2015年消防工作总结
2015/04/24 职场文书
泰坦尼克号观后感
2015/06/04 职场文书
Nginx跨域问题解析与解决
2022/08/05 Servers