Free ActionScript

Flash AS2 & AS3 Tutorials, Game Code, Effects, Source Files & Sample Downloads

Pixel Perfect Collision Detection

6 Comments »

Preview v1.0.1

Download Fla Sample

Download Fla Sample

This script was based on an example by Mike Chambers: Using BitmapData.hitTest for Collision Detection.

Update – v1.0.1
Added dynamic clip highlighting on hit

6 Responses

Does this work for any kind of complex object?

  • Hi Dito,

    This will work with any movieclip/shape/object, since the actual collision detection happens on a “per pixel” level.

    PR

  • This only works if the objects have their registration point at the top left corner (0,0). Does anyone know how to update the code to work with registration points in the center? anywhere?

  • Seemed to be missing a lot of obvious collisions… tested it with slow moving objects and sometimes one would pass right through the middle of the other without the collision being detected..
    I finally figured out the problem though, and fixed it.
    I added 2 new variables to the script and these 2 lines
    _maxWidth = Math.max(_oneRectangle.width, _twoRectangle.width);
    _maxHeight = Math.max(_oneRectangle.height, _twoRectangle.height);

    Then on the lines that create the new bitmapdata objects I used _maxWidth and _maxHeight instead of the individual widths/heights… seems to work perfectly now.

  • Here’s a more fixed version for different kind of registration points
    ///

    public function complex(clip1:DisplayObjectContainer, clip2:DisplayObjectContainer):Boolean
    {

    _returnValue = false;

    _twoRectangle = clip1.getBounds(clip1)// get bounds will only get it’s none rotate x,y,width,height
    _oneOffset = clip1.transform.matrix;

    // registation point always top left to make the bitmapdata draw every pixel of the movieclip.
    _oneOffset.tx = (clip1.x – clip2.x)-_twoRectangle.x;
    _oneOffset.ty = (clip1.y – clip2.y)-_twoRectangle.y;

    _twoClipBmpData = new BitmapData(clip1.width, clip1.height, true, 0);
    _twoClipBmpData.draw(clip1, _oneOffset);

    _oneRectangle = clip2.getBounds(clip2);
    _oneClipBmpData = new BitmapData(clip2.width, clip2.height, true, 0);

    _twoOffset = clip2.transform.matrix;
    _twoOffset.tx = (clip2.x – clip2.x)-_oneRectangle.x;
    _twoOffset.ty = (clip2.y – clip2.y)-_oneRectangle.y;

    _oneClipBmpData.draw(clip2, _twoOffset);

    _onePoint = new Point(_oneRectangle.x, _oneRectangle.y);
    _twoPoint = new Point(_twoRectangle.x, _twoRectangle.y);

    if(_oneClipBmpData.hitTest(_onePoint, 255, _twoClipBmpData, _twoPoint, 255))
    {
    // pixels that have a slight alpha will not detect. make sure theres not alpha.
    _returnValue = true;
    }

    _twoClipBmpData.dispose();
    _oneClipBmpData.dispose();

    return _returnValue;
    }

    //

    • UPDATE! made it work for any size now.

      public function complex(clip1:DisplayObjectContainer, clip2:DisplayObjectContainer):Boolean
      {

      _returnValue = false;

      _twoRectangle = clip1.getBounds(clip1)// get bounds will only get it’s none rotate x,y,width,height
      _oneOffset = clip1.transform.matrix;

      // registation point always top left to make the bitmapdata draw every pixel of the movieclip.
      _oneOffset.tx = (clip1.x – clip2.x)-_twoRectangle.x;
      _oneOffset.ty = (clip1.y – clip2.y)-_twoRectangle.y;

      _twoClipBmpData = new BitmapData(_twoRectangle.width, _twoRectangle.height, true, 0);
      _twoClipBmpData.draw(clip1, _oneOffset);

      _oneRectangle = clip2.getBounds(clip2);
      _oneClipBmpData = new BitmapData(_twoRectangle.width,_twoRectangle.height, true, 0);

      _twoOffset = clip2.transform.matrix;
      _twoOffset.tx = (clip2.x – clip2.x)-_oneRectangle.x;
      _twoOffset.ty = (clip2.y – clip2.y)-_oneRectangle.y;

      _oneClipBmpData.draw(clip2, _twoOffset);

      _onePoint = new Point(_oneRectangle.x, _oneRectangle.y);
      _twoPoint = new Point(_twoRectangle.x, _twoRectangle.y);

      if(_oneClipBmpData.hitTest(_onePoint, 255, _twoClipBmpData, _twoPoint, 255))
      {
      // pixels that have a slight alpha will not detect. make sure theres no alpha.
      _returnValue = true;
      }

      _twoClipBmpData.dispose();
      _oneClipBmpData.dispose();

      return _returnValue;
      }

  • Leave a Reply

    You must be logged in to post a comment.