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固定DIV高度,超出部分自动添加滚动条的简单方法
Jul 10 Javascript
javascript打印html内容功能的方法示例
Nov 28 Javascript
使用ngView配合AngularJS应用实现动画效果的方法
Jun 19 Javascript
超赞的动手创建JavaScript框架的详细教程
Jun 30 Javascript
AngularJS基础 ng-src 指令简单示例
Aug 03 Javascript
Bootstrapvalidator校验、校验清除重置的实现代码(推荐)
Sep 28 Javascript
如何给ss bash 写一个 WEB 端查看流量的页面
Mar 23 Javascript
通过源码分析Vue的双向数据绑定详解
Sep 24 Javascript
微信小程序使用video组件播放视频功能示例【附源码下载】
Dec 08 Javascript
elementUI 设置input的只读或禁用的方法
Oct 30 Javascript
微信小程序页面传多个参数跳转页面的实现方法
May 17 Javascript
vue单应用在ios系统中实现微信分享功能操作
Sep 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将文件夹打包成zip文件的简单实现方法
2016/10/04 PHP
Array对象方法参考
2006/10/03 Javascript
用javascript getComputedStyle获取和设置style的原理
2008/10/10 Javascript
jQuery学习笔记之控制页面实现代码
2012/02/27 Javascript
让低版本浏览器支持input的placeholder属性(js方法)
2013/04/03 Javascript
Javascript学习笔记之数组的遍历和 length 属性
2014/11/23 Javascript
深入分析Javascript事件代理
2016/01/30 Javascript
js实现华丽的九九乘法表效果
2017/03/29 Javascript
ES6的Fetch异步请求的实现方法
2018/12/07 Javascript
浅谈关于JS下大批量异步任务按顺序执行解决方案一点思考
2019/01/08 Javascript
js取小数点后两位四种方法
2019/01/18 Javascript
vue-cli随机生成port源码的方法
2019/09/02 Javascript
解决Vue使用bus总线时,第一次路由跳转时数据没成功传递问题
2020/07/28 Javascript
vue element实现表格合并行数据
2020/11/30 Vue.js
[04:55]完美世界副总裁蔡玮:DOTA2的自由、公平与信任
2013/12/18 DOTA
TensorFlow实现MLP多层感知机模型
2018/03/09 Python
Python实现字典(dict)的迭代操作示例
2018/06/05 Python
Python爬虫包BeautifulSoup异常处理(二)
2018/06/17 Python
Python使用Selenium爬取淘宝异步加载的数据方法
2018/12/17 Python
Python 获取ftp服务器文件时间的方法
2019/07/02 Python
Python之修改图片像素值的方法
2019/07/03 Python
python自动化测试之DDT数据驱动的实现代码
2019/07/23 Python
Python3 chardet模块查看编码格式的例子
2019/08/14 Python
Python使用百度api做人脸对比的方法
2019/08/28 Python
python GUI库图形界面开发之PyQt5图片显示控件QPixmap详细使用方法与实例
2020/02/27 Python
django序列化时使用外键的真实值操作
2020/07/15 Python
Python爬虫scrapy框架Cookie池(微博Cookie池)的使用
2021/01/13 Python
整理HTML5中表单的常用属性及新属性
2016/02/19 HTML / CSS
物流专业大学生的自我鉴定
2013/11/13 职场文书
优秀应届毕业生推荐信
2014/02/18 职场文书
化学系大学生自荐信范文
2014/03/01 职场文书
校本教研活动总结
2014/07/01 职场文书
2014年妇委会工作总结
2014/12/10 职场文书
基于Python实现的购物商城管理系统
2021/04/27 Python
如何使用pdb进行Python调试
2021/06/30 Python
Python机器学习应用之工业蒸汽数据分析篇详解
2022/01/18 Python