EaselJS Pixel Perfect Collision Detection for Bitmaps with Alpha Threshold

I just finished the first version of a pixel perfect collision detection for EaselJS Bitmaps and BitmapAnimations.
Get it from Github: https://github.com/olsn/Collision-Detection-for-EaselJS

Here is an example (play around with the alpha threshold and toggle the detection mode):

  • Andy

    Hey mate, this looks great, and exactly what I needed. However, as soon as two of my objects get close enough to trigger _getIntersectingImagePart, I’m getting the following error:
    Unable to get image data from canvas because the canvas has been tainted by cross-origin data.
    I’ve just started out with easel, so any pointers in the right direction on what I might be doing wrong would be appreciated!

    Andy

    • olsn

      Hi Andy,
      You are most likely testing in an local environment and with Google Chrome (so your URL is somelike like: file:///E:/projects/index.html) and for security reasons your browser (usually Chrome) prevents certain operations when you use your app from the local filesystem.
      To fix this, you can either use arguments to disable those security features, see here: http://stackoverflow.com/questions/3102819/chrome-disable-same-origin-policy
      or you can test your app on a webserver or setup XAMPP to test is on a local webserver.

      The operation causing this issue is: context.getImageData(); this “issue” is not limited to the collision detection, there are also parts of EaselJS that will trigger this security issue when running files from a local path.

      Hope this helps, cheers
      olsn

      • Andy

        Many thanks olsn, for your help and for the runner tutorial that I’m using to learn this stuff! I should have guessed it was because I was running locally.

      • george

        Your code is brilliant man! Thanx
        You saved my game.

  • http://none Uros

    Hello!

    Your example and pixel perfect collision detection is awesome peace of code. But I have one little problem that is really making me crazy for a couple of hours now. When I use
    var collision = ndgmr.checkPixelCollision(bitmap1,bitmap2,alphaThreshold); using your shelter and star .pngs the collision returns false when images don’t collide, it returns object when they do collide, but what is bothering me is that collision returns null when star enters the rectangular area of the shelter image…meaning that it detects collision between star and image area independent of alphathreshold setting. Am I missing something? Because when I look at your example above everything seems just perfect.

    Uros

    • olsn

      Hi Uros,

      Instead of (collision == false) you could have used (!collision) this also takes care of cases like “null” or “undefined” and not just boolean values.
      But also: Thanks for pointing this out, I updated the method, you can pull the update from github, it should work correctly then. Let me know if there are still issues.

      cheers
      olsn

      • http://none Uros

        Tnx for the tip, I have downloaded the correction. The method of overlapping images is quite intensive for average mobile device with android system. Any way to circumvent image rectangle to image rectangle collision? Sorry for being annoying.

      • olsn

        Hm, the basic issue is that, you need some kind of rectangle to limit the amount of pixels to test, otherwise the you would have to do 480.000 comparisons(worst case) for an area of 800×600 pixels (which is not uncommon on mobile devices) reading values of two arrays that both have a length of 1.920.000 – this would be something even desktop computers struggle to do in javascript on a frame-to-frame speed. So calculating a rectangle first will actually help to improve the performance.

        I know that the collision detection and the calculation of the bounding rectangles is quite intensive, but at this point there is not much that can be done to improve it. As far as I know the performance issues with those kind of operations is one of the reasons why this is not yet implemented in EaselJS (if you derived from AS3.0 you would expect to get such a method natively).

        And don’t worry, no one’s being annoying, others will thank you for asking and by that things will be improved! :)

        • http://none Uros

          Thank you for the answers, and keep up the superb work!

  • manish

    hi thanks for creating such a usefull mehod its work fine when i collide two bitmap would but working with two animated bitmap (which contain two spritesheet) how can i get it work

    thanks

    • olsn

      there are animated bitmaps in by example, and it works there, but of course there might be still some bugs, it would be best if you posted a link to check out your case, without that there is not much of debugging I could do ;)

  • manish

    thanks for your quick reply

    http://skidos.com/ipad/game.html

    instruction -cannon works with swipe event .
    in every four second a para shoot appear

    bullet and parashoot collision works fine

    a plane travel left to right on the screen and fire three bombs. Bullet can collide with firing bombs
    bombs collision with bullet works sometime works and sometime not
    code is not yet classified in a poper way

    can u help me to fix this problem

    may be this method not works when the registration point of a animated bitmap is center (half of its width)
    or two animated bitmap ( registration point is center) moves in x y direction and collide with each other

    • olsn

      Hi,
      good catch, there was indeed an issue with BitmapAnimations that used regX and/or regY values and rotation – I fixed that now, please pull the new version from GitHub and see if that works correctly now.
      cheers
      olsn

  • manish

    hi thanks a lot can you provide us link its a very useful method

  • manish chauhan

    thanks very much its working fine now :)

  • Alexis B.

    Hey olsn, thanks a lot for your work. By the way I have a little request / question about the collision system. Is it possible to predict a collision before it happens? I mean if my obj1 is too fast (for example obj1.y += 10), it passes through the obj2. (And sometimes compressed / pixelated).

    Thanks again.

    • olsn

      Hi Alexis,

      no, a passing-through check is currently not implemented. The reason for this is:
      It very rarely happens that an object is so fast that it may pass through other objects, usually it’s very small objects with a very high velocity. If this was the case, I would try to bring up the framerate, because with a lower framerate the ‘+= X’ has to be higher -> less checks. Another (more accurate, but heavy) approach would be to loop the movement of object1: if the velocity is 10, move the object by 5, do a check and then again by 5 and do another check.

      I was thinking about implementing something like this, to retun a flag and inform the user that the object did not collide, but pass through, but it’s really a whole different operation. But a simple pass-through check can be done in basiacally 2 lines ;)

  • Alexis B.

    Thanks for your reply olsn :)

    I have successfully, I think, implanted the pass-through check. It’s not perfect, or the good way to do it, but it works for my own use.

    ndgmr.Collision.js: calculateIntersection(… (dx <= 0 && dy <= 0) {…
    player.js: if (intersection) { this.y -= intersection.height; …

  • Yudhi

    Hi, first of all, cool code man, it helps me alot, in a few ways.
    But somehow i got problem with the pixel collision.

    I tried using:
    var collision = ndgmr.checkPixelCollision(pil,stove,0);
    if(collision) {
    ‘do something’
    }

    But when the two objects collided, nothing happened.

    In this link, i use ndgmr.checkRectCollision(pil,stove), and it works fine
    catchfood1

    In this link i use var collision = ndgmr.checkPixelCollision(pil,stove,0), and nothing happens
    catchfood2

    any sollutions?

  • Kim Long

    Hi, I did use createJS Toolkit to export a flash scene to HTML5/Javascript. I’m using your code to check pixel collision between two MovieClip objects but it’s not working. May be it’s not support for MovieClip ?

    • olsn

      Sorry, no support for MovieClip, MovieClips (as well as Shapes ect…) :-( – Those Objects don’t have a width or height so making a Collision-Dection for those is a ‘little’ more tricky, but I haven’t had the time yet to do something like that. You could get some dimensions by caching the MovieClip or Shape…but in that case you could use a Bitmap after all :)

  • Kim Long

    I’m going to find another way ! Thanks too much. ^_^

  • Mukul Bhardwaj

    Hey, obviously you got something real cool!
    But I caught a bug(I guess) :D
    I was working with bitmaps, bitmap1 and bitmap2 collide PERFECT!
    but I used the property “bitmap2.sourceRect()” while writing code, and then I found that (I don’t know why) the non-visible part of bitmap2 was also being used to check for collision. bitmap2 is collection of 8 objects in a line, but instead of checking whether the visible part is colliding, it tested whether whole bitmap2(whether visible or not visible) is colliding or not. So I got some weird collision detection.

    In simple words, please modify the code to check for collision for only visible part of bitmap and not for whole image whether visible or not visible
    (Thanks to ngdmr.debug = true for this bug, I screwed my head for two days to find this out!)

    I am hoping I get the solution for this soon

    • olsn

      That’s right, the sourceRect is currently not considered for the collision-check – good catch.
      I’m currently very busy, but I will try to fix this towards the end of the week.

      • Mukul Bhardwaj

        Thank you for your attention, I hope I will soon be notified for an updated version as I require it as soon as possible. Thanks! you are awesome.!

        • olsn

          I just pushed an update to Github that includes support for ‘sourceRect’ – I did not do any extensive testing, just some basic cases, so let me know if there are any issues for you.
          cheers

          • Mukul Bhardwaj

            You rock!
            The script now works perfect
            I hope you continue to make changes to this script, as there is no other script that I know of, which detects collision.
            Your work is awesome..!

            Thank you

  • Vijendra

    I’m getting this on collision …

    Uncaught TypeError: Cannot read property ‘rect’ of null

    Could you please help me out in to this. I’m using a bitmap and a bitmap animation for collision detection.

    • olsn

      In order to help you, you should post some code, so I can take a look at it ;)
      Best thing, you post a link to the project or paste it to jsfiddle.
      What EaselJS version are you using?

      cheers

  • Brad Manderscheid

    Hey,
    Any plans on updating this to work with Sprite in 0.7?
    Thanks!

    • olsn

      Hi!

      I’m currently pretty busy, but as soon as I find time, I will update it to 0.7
      I haven’t yet checked the full set of changes, maybe it might be enough to just change the class-names?

      Cheers!

      • Brad Manderscheid

        Yea, I just changed BitmapAnimation to Sprite and it worked. Probably could use some updates though, just to utilize getBounds and other stuff added to the API.

  • Friebel

    Thanks man! Very easy to use and works like charm!!! Great tool

  • Rustem

    Hello! Thanks a lot for your work! But code has some bug. When i’m trying to find collision between two moving bitmaps, nothing happens first time. But when they collide again, collision detects. Where may be problem?

  • Rustem

    Here is example of my problem: try to click to side of arrow (it must be deleted in moment) then try it again:
    http://rustem.ucoz.com/collision/index.html

  • http://murteira.pt Filipe Murteira

    Hy,

    Nice class, but its not working on news release of Creatjs, do you have any update for that?

    Thanks a lot!

    • olsn

      There is an update available on GitHub now to work with the latest verion of EaselJS v0.7.1

  • Mark

    Does that project support collision detection between two moving bitmaps? In your example, is there a possibility to extend the code to detect collision between stars? I try to use it in my project, and it doesn’t work for me and I don’t know whether I do it wrong or there isn’t such opportunity.

    • olsn

      It supports collisions between any bitmaps, moving or non-moving.
      So yes, that should work.

  • Filipe Murteira

    Hy,

    Thanks for the update, but can you do this to work with movieclip plugin?

    Thanks in advance!

    • olsn

      Sorry, it does not work with movie clip out of the box, but if all the children of a movie-clip were Bitmaps then you could make it work. The simple rect-collision could work with movieclips out of the box, this is not tested though.

  • Benjamin

    There might be a bug in the _collisionDistancePrecheck function. Shouldn’t it be
    return ( (Test on X) || (Test on Y) )
    instead of
    return ( (Test on X) && (Test on Y) ) ?

    Great work by the way!

    • olsn

      This checks if the distances of the X and the Y value are even close enough to possibly collide, if you only check for X OR Y, then it might be possible that the full check is executed if the X-distance=0 and the Y-distance=999999.
      So it should work like it is ;-)
      But I could have probably commented the code a little better :)

  • Gerardo Montoya

    Hello!

    I’m just here to say thank you!! I wish there was an easier way to find this link cause it’s really helpful. Great work!!

    • olsn

      Maybe the guys from CreateJS might want to implement this(or a better version of it ;) ) into the framework, that would make searching for such a link obsolete ;)

  • paul

    Hi. I’m trying to use this with 0.7.1 checking between a bitmap and a sprite sheet and no Collision is detected. Is this possible?

    The sprite sheet is created like this:
    var guy_ss = new createjs.SpriteSheet(ssdata);
    guy= new createjs.Sprite(ss );

  • Justin

    I had a problem with objects that were negatively scaled, which createJS uses to flip an object yet keeping the same position. So, I added Math.abs to those properties in your script, especially in the _collisionDistancePrecheck method, and now it works for flipped objects. Awesome plugin, thanks for the work!

  • Sandeep Devadas

    Hi olsn, Im new to this and easeljs and createjs and couldnt get your collision detector to work on my PC. I have copied all the .js files to a js folder,moved the png’s to an assets folder,copied the ngmr to the source and run the index.html file. But all it does is it shows the button and the text field. I have attached the index file which i use

  • Sandeep Devadas

    Here is the image of my output .

  • seb am

    Hi, I try to detect collision between 2 bitmaps. Each bitmap have a specific rotation 45° or 90°. The collsion isn’t well done. Any help or example ? Tks

  • seb am

    Tks Olaf for your work and the solution :
    fix the bug(at least temporarily) by commenting out the
    lines 68-71 in the ndgmr.Collision.js

    //areObjectsCloseEnough = _collisionDistancePrecheck(bitmap1,bitmap2);
    //if ( !areObjectsCloseEnough ) {
    //return false;
    //}

  • Craig Bartlett

    I get the expected result when using ndgmr.checkRectCollision but I am getting the following error in my console when trying to use ndgmr.checkPixelCollision. I would like the transparent areas not be detected in the collision.

    TypeError: image is undefined
    ctx.drawImage(image,0,0,image.width,image.height);

    • Craig Bartlett

      Solved, I just created a get function in MyObject class that returns my Sprite.

      var collision = ndgmr.checkPixelCollision(obj01.getImage(),obj02.getImage(), 1);

      Works perfectly!

  • http://shahnashok.com Ashok Shah

    Thanks for the post. It really worked perfectly.
    But it wasted a lot of my time to test two circle graphics.
    Lastly I know it only works it bitmap

  • rarema
    • Olivier C

      Hey, I’ve encountered the same issue using Chrome.
      I’ve edited the line 173 with return ctx.getImageData(0, 0, Math.max(1, intersetion. Math.max(1, intersetion.height)).data;
      now it works…

      • Ehka

        hi! olsn

        when i use this JS

        it’s tell me wrong:

        ndgmr.Collision.js:173 Uncaught TypeError: Cannot read property ‘max’ of undefined
        at _intersectingImagePart (ndgmr.Collision.js:173)
        at Object.checkPixelCollision (ndgmr.Collision.js:89)
        at Function.tick (game.js:265)
        at createjs.min.js:12
        at Function.b._dispatchEvent (createjs.min.js:12)
        at Function.b._dispatchEvent (createjs.min.js:12)
        at Function.b.dispatchEvent (createjs.min.js:12)
        at Function.a._tick (createjs.min.js:12)
        at a._handleTimeout (createjs.min.js:12)