• 碰撞检测


    目录

    引子

    碰撞检测(Collision Detection)这个东西,之前找 canvas 相关资料的时候碰到过,有些好奇,就去尝试了解一下。

    简介

    与碰撞检测有些类似的一个概念:命中检测(Hit-testing),也被广泛运用。

    在计算机图形编程中,命中检测是确定用户控制的光标(或触摸屏上的触摸点)是否与屏幕上绘制的给定图形对象(如形状)产生相交的过程。根据这个定义,web 开发中碰到鼠标点击下拉菜单等这些交互都属于这个范畴。

    碰撞检测用于检测多个不同图形对象的交叉点,不是光标与一个或多个图像对象的交叉点。在 web 游戏中也涉及到这些,2D 游戏中的碰撞检测算法,依赖于碰撞物体的形状(例如矩形与矩形、矩形与圆形、圆形与圆形)。基于 canvas,下面看看几种简单的情景。

    光标碰撞检测

    使用 canvas 创建交互时,在画布内点击,如果需要判断点击所在的图形,就需要做碰撞检测。思路比较简单,就是要检测光标点击的坐标是否在某个形状里面。在测试中发现几点需要注意:

    • 遍历形状的顺序,因为绘制的图形可能重叠,后绘制的一般在上层,这个时候倒序遍历才合理。
    • 获取点击坐标时,注意移动端和 PC 端对应属性,移动端 touch 属性中可能有多个坐标。
    • 图形的形状,规则图形和非规则图形判断的方式有差异。

    这是简单的示例,移动端访问如下:

    46-cursor

    基于像素颜色碰撞检测

    上面数学计算的方式,如果在一些图案信息较多的情况下,需要存储大量的数据,会非常的不方便。另外的一种方式就是取得像素块,检测它们的颜色。例如这个示例,移动端访问如下:

    46-pixel

    示例中矩形区域是图片,其中线条颜色都是黑色,实现的思路是在小球移动之前,先取包含了小球且比小球稍大的空间像素,遍历像素数据,判断是否有黑色且不透明,如果有就说明在下一次重绘时就会发生碰撞。在迷宫类的游戏实现中,这种方式就会很方便,见小游戏 Maze

    在测试中发现几点需要注意:

    • 选择图片时,需要注意图片中颜色的使用,因为要用来作为判断依据,色值不要随意混用。
    • 使用 getImageData 方法时,获取数据的位置是根据 canvas 实际的像素数据,而不是渲染显示的大小。

    矩形与矩形碰撞检测

    这里是指轴对齐(意味着没有旋转)的两个矩形碰撞检测。下面的一个算法可以用来进行判断:

    var rect1 = {x: 5, y: 5,  50, height: 50}
    var rect2 = {x: 20, y: 10,  10, height: 10}
    
    if (rect1.x <= rect2.x + rect2.width &&
       rect1.x + rect1.width >= rect2.x &&
       rect1.y <= rect2.y + rect2.height &&
       rect1.height + rect1.y >= rect2.y) {
        // collision detected!
    }
    

    上面的条件,以刚好碰撞的状态做对照,思考起来会比较方便理解。这是简单的示例,移动端访问如下:

    46-rect

    圆形与圆形碰撞检测

    这种形式的碰撞检测,通过两个圆心之间的直线距离,与两个圆的半径之和作比较。

    var circle1 = {radius: 20, x: 5, y: 5};
    var circle2 = {radius: 12, x: 10, y: 5};
    
    var dx = circle1.x - circle2.x;
    var dy = circle1.y - circle2.y;
    var distance = Math.sqrt(dx * dx + dy * dy);
    
    if (distance <= circle1.radius + circle2.radius) {
        // collision detected!
    }
    

    这是简单示例,移动端访问如下:

    46-circle

    从上面的示例中,发现如果使用在动态的场景下,效果并不一定如预期。

    参考资料

  • 相关阅读:
    libevent-2.0.so.5 (安装MEMCACHED问题)
    MySQL的show语句大全
    远程客户端连接MysqL数据库太慢解决方案
    用SQL命令查看Mysql数据库大小
    elasticsearch-head安装及启动
    logstash收集IIS日志
    备份并删除7天以前数据
    shell脚本递归压缩实践
    二目运算符 “->”
    关于int main( int argc, char *argv[] )
  • 原文地址:https://www.cnblogs.com/thyshare/p/12383923.html
Copyright © 2020-2023  润新知