【问题标题】:Actionscript 3 pixel perfect collision. How to? (learning purposes)Actionscript 3像素完美碰撞。如何? (学习目的)
【发布时间】:2011-03-12 21:08:55
【问题描述】:

我知道有人为此创建课程(即http://coreyoneil.com/portfolio/index.php?project=5)。但我想自己学习如何做,这样我就可以按照自己的方式创造我需要的一切。

我已经阅读过有关 BitMap 和 BitMapData 的信息。我应该能够将 MovieClips 绘制到 BitMap 上,这样我就可以循环像素以查找碰撞。但是,处理偏移量很奇怪和令人困惑。它看起来像 MyBitMap.rect 总是 x = 0 和 y = 0 ......我无法找到东西的原始位置......

我正在考虑先做一个hitTestObject,然后如果这是肯定的,我会调查movieclips矩形之间的交叉点以进行像素碰撞。 但是还有另一个问题(影片剪辑的旋转)...

...我需要一些关于如何做到这一点的启发。 请,任何帮助将不胜感激..

【问题讨论】:

    标签: actionscript-3 bitmap rotation pixel collision


    【解决方案1】:

    如果您使用具有透明度的 BitmapData 对象,您可以使用BitmapData.hitTest(firstPoint:Point, firstAlphaThreshold:uint, secondObject:Object, secondBitmapDataPoint:Point = null, secondAlphaThreshold:uint = 1):Boolean

    您必须从全局坐标更改为本地 BitmapData 坐标,如果旋转则需要一些数学运算。这很容易实现(在 wiki 上查找仿射变换以获取更多信息):

    var coordTransform:Matrix = new Matrix();
    
    coordTransform.rotate(rotationRadians);
    coordTransform.translate(x, y);
    
    coordTransform.transformPoint(/* your point */);
    

    【讨论】:

    • 我不想简单地测试它们是否发生碰撞。我想学习如何手动操作,因为据我所知,我需要找到您提到的函数未返回的碰撞角度等信息。但是..在您的代码中,您是在谈论使用旋转矩阵更改位图中的所有像素位置吗?是吗?
    • 碰撞角度?您能否详细说明(即它们碰撞位置的切线的法线)。手动执行此操作的方法是遍历一个位图的每个像素,看看它是否接触到另一个位图的像素。然后,如果任何像素接触另一个像素的另一个像素,则位图在某处重叠。现在您应该使用一些启发式方法来限制您测试的像素,因为这种方法效率极低。
    • 坐标变换是在位图旋转的情况下给出的。例如:您的 bmd 是一个 20x20 像素的正方形,其左上角位于 (0,0)。您将其顺时针旋转 45 度以使其成为菱形(同样,左上角位于 (0,0) 处)。如果您想查看舞台位置 (0, 25) 是否与 bmd 接触(确实如此),那么您不能使用 (0, 25) 进行 hitTest,因为 hitTest 测量的是相对于 bmd 的位置。您需要将该位置转换为 (25/sqrt(2), 25/sqrt(2)),这就是我示例中的代码的用途。
    • 我有什么:2 个具有 speedX 和 speedY 的影片剪辑碰撞角度。我想我会怎么做:actionscript3 有 hitTestObject。我可以查看 mc1 和 mc2 外盒是否与此测试发生冲突。如果是,那么我需要将它们转换为像素,并查看它们是否在同一坐标中至少有 2 个不透明像素(但我只会在两个影片剪辑外框之间的相交矩形中测试这个)。如果发生这种情况,他们正在碰撞,我可以找出碰撞的角度
    • 问题不在于算法或数学。这是要知道每件事的作用,以及限制是什么。当我将 MovieClip1 绘制到 BitMap1 中,然后我在 BitMap2 中绘制 MovieClip2 时会发生什么?事物的坐标……这种方法是如何工作的。这是我需要找出的..
    【解决方案2】:

    flash 中像素完美碰撞检测的经典参考是 Grant Skinner's article。它是 AS2,但 AS3 的逻辑是相同的(如果你用谷歌搜索一下,就有可用的端口)。

    如果我没记错的话,只要两个测试对象具有相同的父对象,这个特定的实现就可以工作,但这可以修复。

    关于 BitmapData xy 值,我知道这可能会造成混淆;但是,它的工作方式对我来说很有意义。 BitmapData 顾名思义:像素数据。不是显示对象,不能在显示列表中;因此,如果您考虑一下,将xy 与 0 不同并没有任何意义。处理这个问题的最简单方法可能是存储源对象(您从中绘制的显示对象)的(x,y) 偏移量并将其转换为全局坐标空间,以便您可以比较任何对象,无论它们在显示列表(使用类似var globalPoint:Point = source.parent.localToGlobal(new Point(source.x,source.y))

    【讨论】:

    • 我记得 Grant Skinner 的方法只有在两个对象都是舞台的直接子对象时才能正常工作。
    【解决方案3】:

    我之前使用过 Troy Gilbert 的像素完美碰撞检测类(改编自 Andre Michelle、Grant Skinner 和 Boulevart),效果非常好(处理旋转、不同的父对象等):

    http://troygilbert.com/2007/06/pixel-perfect-collision-detection-in-actionscript3/
    http://troygilbert.com/2009/08/pixel-perfect-collision-detection-revisited/

    从那里他还链接到了这个项目(我没有使用过,但看起来确实令人印象深刻):

    http://www.coreyoneil.com/portfolio/index.php?project=5

    【讨论】:

      【解决方案4】:

      毕竟我设法做到了,而且我已经为碰撞检测、/碰撞角度和其他附加功能编写了我的课程。

      最令人困惑的过程可能是正确对齐位图以进行比较。当将一个movieclip draw() 变成一个BitmapData 时,如果我们addChild() 对应的Bitmap 我们可以看到它的那部分是不可见的。它似乎只从中心向右和向下绘制,使顶部和左侧部分远离蜜蜂绘制。解决方案是在 draw 方法的第二个参数中给出一个变换矩阵,对齐位图并使其全部绘制。

      这是我的类中创建用于比较的位图的函数示例:

          static public function createAlignedBitmap(mc: MovieClip, mc_rect: Rectangle): BitmapData{
                      var mc_offset: Matrix;
                      var mc_bmd: BitmapData;
      
                      mc_offset = mc.transform.matrix;
                      mc_offset.tx = mc.x - mc_rect.x;
                      mc_offset.ty = mc.y - mc_rect.y;
                      mc_bmd = new BitmapData(mc_rect.width, mc_rect.height, true, 0);
                      mc_bmd.draw(mc, mc_offset);
      
                      return mc_bmd;
      }
      

      为了使用它,如果你在时间线上,你这样做:

      className.createAlignedBitmap(myMovieClip, myMovieClip.getBounds(this))
      

      注意 getBounds 的使用,它返回嵌入影片剪辑的矩形。这允许计算偏移矩阵。

      此方法与此处显示的http://www.mikechambers.com/blog/2009/06/24/using-bitmapdata-hittest-for-collision-detection/ 非常相似

      顺便说一句,如果这对您来说很有趣,请查看我稍后会发布的另一个问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-20
        • 1970-01-01
        • 1970-01-01
        • 2015-09-22
        • 2012-06-06
        相关资源
        最近更新 更多