Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/rust/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JavaScript";像素“-使用数学(可能是线性代数)实现旋转精灵的完美碰撞检测_Javascript - Fatal编程技术网

JavaScript";像素“-使用数学(可能是线性代数)实现旋转精灵的完美碰撞检测

JavaScript";像素“-使用数学(可能是线性代数)实现旋转精灵的完美碰撞检测,javascript,Javascript,我正在用JavaScript制作一个2D游戏。为此,我需要能够“完美地”检查两个精灵之间的碰撞,这两个精灵具有x/y位置(对应于它们的中心)、弧度旋转,当然还有已知的宽度/高度 在花了数周的时间(是的,我一点也不夸张)之后,我终于想出了一个可行的解决方案,不幸的是,这个解决方案太慢了,无法以任何有意义的方式进行优化。我完全放弃了从画布上实际绘制和读取像素的想法。这并不能解决问题,但请不要让我详细解释原因。这需要通过数学和“想象”的2D世界/网格来完成,通过与众多人交谈,基本想法变得显而易见。然而

我正在用JavaScript制作一个2D游戏。为此,我需要能够“完美地”检查两个精灵之间的碰撞,这两个精灵具有x/y位置(对应于它们的中心)、弧度旋转,当然还有已知的宽度/高度

在花了数周的时间(是的,我一点也不夸张)之后,我终于想出了一个可行的解决方案,不幸的是,这个解决方案太慢了,无法以任何有意义的方式进行优化。我完全放弃了从画布上实际绘制和读取像素的想法。这并不能解决问题,但请不要让我详细解释原因。这需要通过数学和“想象”的2D世界/网格来完成,通过与众多人交谈,基本想法变得显而易见。然而,实际执行情况并非如此。以下是我所做和想做的:

我已经做了什么 在程序开始时,每个精灵都是在其默认垂直位置查看的像素,并且一维数组中填充了与图像的alpha通道对应的数据:实心像素用1表示,透明像素用0表示。参见图3

其背后的想法是,这些1和0不再代表“像素”,而是“彼此之间距离完美的小数学球体”,它们可以在不“丢失”或“添加”数据的情况下进行旋转,如果一次旋转图像的角度不超过90度,像素就会发生这种情况

我自然会先做快速的“边界框”检查,看看是否需要精确计算。这已经完成了。问题是罚款/“确定”检查

我搞不懂什么 现在我需要确定精灵是否会碰撞,我需要使用“线性代数”(我不知道)构造某种数学表达式,以确定这些“数据点矩形”(正确定位和旋转)是否在重叠位置都有“1”

虽然理论非常简单,但实现这一点所需的实用代码超出了我的能力。我已经盯着代码看了好几个小时,问了很多人(并且很难清楚地解释我的问题),真的很努力。现在我终于想放弃了。我非常非常感谢你能把这件事做完。我甚至不能放弃使用图书馆来“作弊”,因为从我所知道的情况来看,我所发现的任何东西都无法解决这个问题。它们对我来说都是不可能理解的,而且在我的脑海中似乎有着完全不同的假设/要求。我所做的一切似乎都是特殊情况。真烦人

这是程序相关部分的伪代码:

function doThisAtTheStartOfTheProgram()
{
    makeQuickVectorFromImageAlpha(sprite1);
    makeQuickVectorFromImageAlpha(sprite2);
}

function detectCollision(sprite1, sprite2)
{
    // This easy, outer check works. Please ignore it as it is unrelated to the problem.
    if (bounding_box_match)
    {
        /*

            This part is the entire problem.
            I must do a math-based check to see if they really collide.

            These are the relevant variables as I have named them:

                sprite1.x
                sprite1.y
                sprite1.rotation // in radians
                sprite1.width
                sprite1.height
                sprite1.diagonal // might not be needed, but is provided

                sprite2.x
                sprite2.y
                sprite2.rotation // in radians
                sprite2.width
                sprite2.height
                sprite2.diagonal // might not be needed, but is provided

                sprite1.vectorForCollisionDetection
                sprite2.vectorForCollisionDetection

            Can you please help me construct the math expression, or the series of math expressions, needed to do this check?
            To clarify, using the variables above, I need to check if the two sprites (which can rotate around their centre, have any position and any dimensions) are colliding. A collision happens when at least one "unit" (an imagined sphere) of BOTH sprites are on the same unit in our imaginated 2D world (starting from 0,0 in the top-left).

        */

        if (accurate_check_goes_here)
            return true;
    }

    return false;
}
换句话说,“准确的检查”是我想知道它应该是什么。当然,它不需要是一个单一的表达,我更愿意看到它以“步骤”(带注释!)的方式完成,这样我就有机会理解它,但请不要将其视为“填鸭式”。我完全承认我数学很烂,这超出了我的能力。这只是事实。我想继续前进,做我自己能解决的事情

澄清一下:由于性能原因,1D阵列是1D而不是2D。事实证明,速度在JS世界中非常重要。 虽然这是一个非盈利项目,完全是为了满足私人需求,但我没有时间和精力去订购一些数学书,坐下来从头开始学习。我并不以缺乏数学技能而自豪,这对我很有帮助,但在这一点上,我需要完成这场比赛,否则我会发疯的。这个特殊的问题使我很长时间无法完成任何其他工作

我希望我已经很好地解释了这个问题。然而,最令人沮丧的感觉之一是,当人们发送善意的回复时,不幸地表明帮助者没有阅读问题。我不是在侮辱你们——我只是希望这次不要发生这种事!对不起,如果我的描述不好。我真的尽了最大的努力想说清楚

好的,所以我需要“声誉”来发布我花时间制作的插图来说明我的问题。因此,我将其链接到:

插图
  • (由Stackoverflow审查)
  • (由Stackoverflow审查)

  • 嗯。这个网站甚至不允许我链接到这些图片。只有一个。然后我会选择最重要的一个,但是如果我可以链接到其他的,那会有很大帮助…

    尽管您已经说过,您不认为渲染到画布并检查数据是一个可行的解决方案,我想提出一个想法,你可能已经想到了,也可能没有想到,而且应该是合理有效的

    此解决方案依赖于这样一个事实:将任何像素以半不透明的方式渲染到画布上两次将导致像素完全不透明。步骤如下:

    • 调整测试画布的大小,以使两个精灵都适合它(这也将清除画布,因此不必每次需要测试冲突时都创建新元素)
    • 变换精灵数据,使具有任何不透明度或颜色的任何像素在不透明度为50%时设置为黑色
    • 以适当的距离和相对位置渲染精灵
    • 循环遍历生成的画布数据。如果任何像素的不透明度为100%,则检测到碰撞。返回true
    • 否则,返回false
    • 清洗,漂洗,重复
    这种方法应该运行得相当快。现在,对于优化——这里的瓶颈可能是最终的不透明度检查(尽管将图像渲染到画布可能会很慢,清除/调整其大小也可能会很慢):

    • 在最后一步中,通过更改循环中通过最终数据像素的增量来降低不透明度检测的分辨率。
      <html>
      <script type="text/javascript">
      var s1 = {
        'pix': new Array(0,0,1,1,0,0,1,0,0,1,1,0),
        'x': 1,
        'y': 2,
        'width': 4,
        'height': 3,
        'rotation': 45};
      
      var s2 = {
        'pix': new Array(1,0,1,0,1,0,1,0,1,0,1,0),
      
        'x': 0,
        'y': 1,
        'width': 4,
        'height': 3,
        'rotation': 90};
      
      pixLocs(s1);
      console.log("now rotating the second sprite...");
      
      pixLocs(s2);
      console.log("collision detector says " + collision(s1, s2));
      
      function pixLocs(s) {
        var i;
        var x, y;
        var l1, l2;
        var ca, sa;
        var pi;
        s.locx = new Array();
        s.locy = new Array();
        pi = Math.acos(0.0) * 2;
        var l = new Array();
        ca = Math.cos(s.rotation * pi / 180.0);
        sa = Math.sin(s.rotation * pi / 180.0);
        i = 0;
        for(x = 0; x < s.width; ++x) {
          for(y = 0; y < s.height; ++y) {
            // offset to center of sprite
            if(s.pix[i++]==1) {
              l1 = x - (s.width - 1) * 0.5;
              l2 = y - (s.height - 1) * 0.5;
              // rotate:
              r1 = ca * l1 - sa * l2;
              r2 = sa * l1 + ca * l2;
              // add position:
              p1 = r1 + s.x;
              p2 = r2 + s.y;
              console.log("rotated pixel [ " + x + "," +  y + " ] is at ( " +  p1 + "," + p2 + " ) " );
              s.locx.push(p1);
              s.locy.push(p2);
            }
            else console.log("no pixel at [" + x + "," + y + "]");
          }
        }
      }
      
      function collision(s1, s2) {
        var i, j;
        var dx, dy;
        for (i = 0; i < s1.locx.length; i++) {
          for (j = 0; j < s2.locx.length; j++) {
            dx = Math.abs(s1.locx[i] - s2.locx[j]);
            if(dx < 1) {
              dy = Math.abs(s1.locy[i] - s2.locy[j]);
              if (dx*dx + dy+dy < 1) return 1;
            }
          }
        }
        return 0;
      }
      </script>
      </html>