2019独角兽企业重金招聘Python工程师标准>>>

canvas中的碰撞检测笔记

时间 2016-01-19 08:29:00  博客园精华区
原文    http://www.cnblogs.com/zichi/p/5141044.html
主题  Canvas

用 canvas 做小游戏或者特效,碰撞检测是少不了的。本文将会涉及普通的碰撞检测,以及像素级的碰撞检测。(本文的碰撞检测均以 矩形 为例)

普通碰撞检测

普通的矩形碰撞检测比较简单。即已知两个矩形的各顶点坐标,判断是否相交,如相交,则为碰撞。

leetcode 有道题是给出两个矩形的坐标,求其相交面积( 223. Rectangle Area ), 代码 可以直接拿过来用,如果面积大于 0,则为碰撞。

如果只需判断是否相交或者相交面积,非常简单,可以参考 这里 。

为了程序的可扩展性,如果碰撞,最好还能求得相交矩形的坐标信息(为像素级碰撞检测作准备),完善后的检测代码如下:

// 矩形一 top-left 坐标 (A, B), C 为 width, D 为 height
// 矩形二 同上
// 如果没有相交,返回 [0, 0, 0, 0]
// 如果相交,假设相交矩形对角坐标 (x0, y0) (x1, y1) -- x1 > x0 & y1 > y0
// return [x0, y0, x1, y1]
function check(A, B, C, D, E, F, G, H) {// 转为对角线坐标C += A, D += B, G += E, H += F;// 没有相交if (C <= E || G <= A || D <= F || H <= B)return [0, 0, 0, 0];var tmpX, tmpY;if (E > A) {tmpX = G < C ? [E, G] : [E, C];} else {tmpX = C < G ? [A, C] : [A, G];}if (F > B) {tmpY = H < D ? [F, H] : [F, D];} else {tmpY = D < H ? [B, D] : [B, H];}return [tmpX[0], tmpY[0], tmpX[1], tmpY[1]];
}// 相交矩形坐标信息
var rect = check(fish.pos.x, fish.pos.y, fish.size.x, fish.size.y, cat.pos.x, cat.pos.y, cat.size.x, cat.size.y);// 相交面积大于 0 即为碰撞
var isHit = (rect[2] - rect[0]) * (rect[3] - rect[1]) > 0;

像素级碰撞检测

为什么要有像素级检测?一图以蔽之。

一般游戏或者动画中的精灵都是矩形,仅仅判断矩形相交是不准确的,比如上图中,图片所在矩形已经相交,但是精灵其实并没有碰撞,所以我们需要进行像素级别的碰撞检测。

方法一:

同时检测两图在相交矩形内的像素,若存在一点在两个图上的 alpha 值不为 0,则发生碰撞。

因为还要对原始的图像(fish 图和 cat 图)分别提取像素点(进行判断),所以需要一个离屏的 canvas 。这里用了 canvas 的 getImageData 方法提取像素点 rgba 信息。

// a, b 为精灵对象
// a, b 分别拥有键值 img(精灵图像 DOM元素), pos(精灵瞬间位置 top-left 坐标), size(wdith, height 数据)
// rect 参数为 check() 函数返回值
function checkInDetail(a, b, rect) {// 离屏 canvasvar canvas = document.createElement_x('canvas');_ctx = canvas.getContext('2d');_ctx.drawImage(a.img, 0, 0, a.size.x, a.size.y);// 相对位置var data1 = _ctx.getImageData(rect[0] - a.pos.x, rect[1] - a.pos.y, rect[2] - rect[0], rect[3] - rect[1]).data;_ctx.clearRect(0, 0, b.size.x, b.size.y);_ctx.drawImage(b.img, 0, 0, b.size.x, b.size.y);var data2 = _ctx.getImageData(rect[0] - b.pos.x, rect[1] - b.pos.y, rect[2] - rect[0], rect[3] - rect[1]).data;canvas = null;for(var i = 3; i < data1.length; i += 4) {if(data1[i] > 0 && data2[i] > 0) return true; // 碰撞}return false;
}// 精灵对象实例
var fish = {img: document.getElementById('fish'), pos: new Vector2(), size: new Vector2()// ...
};

方法二:

先画一张图,然后将混合模式改为source-in,这时再画图, 新图片会仅仅出现与原有内容重叠的地方 ,其他地方透明度变为 0,这时就可以通过判断是否所有像素都透明来判断碰撞了。

// a, b 为精灵对象
// a, b 分别拥有键值 img(精灵图像 DOM元素), pos(精灵瞬间位置 top-left 坐标), size(wdith, height 数据)
// rect 参数为 check() 函数返回值
function _checkInDetail(a, b, rect) {// 离屏 canvasvar canvas = document.createElement_x('canvas');_ctx = canvas.getContext('2d');// 将 (0, 0) 作为基准点,将 a 放入 (0, 0) 位置_ctx.drawImage(a.img, 0, 0, a.size.x, a.size.y);_ctx.globalCompositeOperation = 'source-in';_ctx.drawImage(b.img, b.pos.x - a.pos.x, b.pos.y - a.pos.y, b.size.x, b.size.y);var data = _ctx.getImageData(rect[0] - a.pos.x, rect[1] - a.pos.y, rect[2] - rect[0], rect[3] - rect[1]).data;canvas = null;// 改回来(虽然并没有什么卵用)_ctx.globalCompositeOperation = 'source-over';for(var i = 3; i < data.length; i += 4) { if (data[i]) return true;  // 碰撞}return false;
}

我测试了几次,把相交的像素点都取了出来求得相交像素点总数,两种方法有时会相差一两个像素点。对于像素级碰撞检测来说,两种方法任取其一就可。

转载于:https://my.oschina.net/jinhengyu/blog/1571648

canvas中的碰撞检测笔记相关推荐

  1. WebQML笔记-qml获取canvas中元素是否被按下

    以前出了几个用QWebView,获取html前端数据的博文, 使用QWebElement可以直接获取html中元素的填充的值. 在此不在多提.这个是纯QML获取canvas中元素是否被按下的思路. 这 ...

  2. canvas笔记-canvas中用户与图形交互

    运行截图如下: 点击某个圆后: 代码如下: <!DOCTYPE html> <html lang="en"> <head><meta ch ...

  3. canvas笔记-在canvas中使用其他HTML元素

    这里使用的原理是使用css把div中关于html的元素通过布局位置,以及透明相关的设置,将其设置到canvas上,这样看起来就是在canvas绘制的按钮.然后使用JavaScript获取按钮的数据或者 ...

  4. 在Tiled Map中使用碰撞检测

    转 [转载] 在Tiled Map中使用碰撞检测 2014年11月17日 01:46:51 阅读数:6721更多 个人分类: cocos2dx 网上这篇教程的转载非常泛滥,本来以为没什么参考价值.但是 ...

  5. canvas 中的元素拖拽

    实验室要求实现在canvas的元素的拖拽,即在canvas放置一些图标,实现用户拖拽并连线. 需要的知识(1)canvas drawImage方法 function draw(){ var image ...

  6. 管理系统中计算机应用第四章重点,管理系统中计算机应用课堂笔记第四章(4)...

    管理系统中计算机应用课堂笔记第四章(4) 分类:自考 | 更新时间:2016-07-08| 来源:转载 这个分析和抽象工作可分以下三步进行: 5.2.1数据流程图的绘制 数据流程图既是对原系统进行分析 ...

  7. html2canvas input,html2canvas 将html绘制到canvas中 [不建议使用]

    这个有很多隐藏的bug, 不太建议在生产环境中使用 推荐使用vdom包装一层, 用fabric画到canvas中, 或者用后端去画, 再或者用无头浏览器去截图 而且对于mac和windows的chro ...

  8. html绘图环境,HTML_HTML5 在canvas中绘制文本附效果图,一、绘制文本 在绘图环境中提 - phpStudy...

    HTML5 在canvas中绘制文本附效果图 一.绘制文本 在绘图环境中提供了两种方法在canvas中绘制文本. strokeText(text,x,y) : 在(x,y)处绘制空心的文本. fill ...

  9. 矩形做成翻页的效果html5,HTML5 在canvas中绘制矩形附效果图

    一.绘制矩形 canvas使用原点(0,0)在左上角的坐标系统,x坐标向右递增,y坐标向下递增. 使用绘图环境的矩形绘制函数来绘制矩形. fillRect(x,y,width,height) : 绘制 ...

最新文章

  1. 服务器的操作系统分哪几类,服务器的操作系统分哪几类
  2. lscpu命令查看CPU统计信息
  3. boost::serialization相关的测试程序
  4. Python爬虫入门教程 6-100 蜂鸟网图片爬取之一
  5. 完整asp.net图形验证码程序
  6. 2016 10 26考试 NOIP模拟赛 杂题
  7. linux tar zcfp 打包,tar命令_Study-Everyday的技术博客_51CTO博客
  8. 全球软件巨头 Software AG 遭勒索攻击
  9. 简单的nios II 流水灯 软件部分
  10. python输出10行带标号的hello、world_Python输出hello world(各行命令详解)
  11. 栈基本操作的java代码实现(建栈,初始化栈、进栈、出栈)
  12. Windows 有哪些冷门但是非常值得推荐的软件?
  13. 手机远程控制电脑如何做到?
  14. 如何用GBD确认函数属于哪个库
  15. 谷歌退出中国谁对谁错
  16. 智能运维 | 六度亮剑SREcon,百度引领智能运维新风向
  17. Android Snackbar控件
  18. 百万调音师—Audition 压缩效果器
  19. vue+element上传图片到阿里云(可直接运行domo)
  20. 链表排序时间复杂度为(O(n log n) )

热门文章

  1. Centos 6.5 Pxe+kickstart 无人值守安装操作系统
  2. git切换ssh和http协议
  3. OpenERP里面继承的用法
  4. C#获得枚举类型的长度
  5. latex不能识别eps图片
  6. fedora22 无法联网的情况下rpm安装gcc5.1
  7. zabbix登山路——简单监控_各项参数解析
  8. 100天后 - 100-days-later
  9. 使用Eclipse与Pydev开发Python
  10. Flexbox Guide