Water ripples revisited (AS3-only version)

I’ve been thinking of changing my previous Pixel Bender water filter to an AS3-only version for some time (since FP10 is still in beta), but never got around to it. Until trusty old Nascom told me we might perhaps use it in a project. So here it is, added to the NascomASLib and ready for you to use :) I added some functionality so the appearance of the ripples can be altered. Overall, I’m quite happy with the performance, especially since it runs smoother with bigger ripples (and usually looks better too ;) ).

So enjoy the demo, and check the source here.

226 thoughts on “Water ripples revisited (AS3-only version)

  1. Hi David,

    I love the water ripples! It looks fantastic. I noticed in the demo that it produces some anomalies with the image. There’s a thin strip at the bottom poking out seemingly unaffected by the ripple effect. Also, the top and right side seem to be framed with other parts of the image, but still affected by the ripples. I’ve tried it myself with different images of various sizes and the same thing happens. Is there a fix for this?

    Even with the anomalies it is incredibly impressive…Great Work!!!

    Kind Regards,
    Clay

  2. Thanks Clay,

    Yup, that’s right. The thin strip at the bottom is, or so I suspect, a result of the scaling parameter, which I should fix asap. The other problem (the offset at the top and left) is because, at the moment, a displacement map is used to deform the image, with minimal value being black. The latter should be an easy fix, and I’ll commit it as soon as possible, for now I haven’t really had the time to take care of it :)

    Cheers,
    David

    EDIT: Alright, I took some time out for this, and now the anomalies are fixed :D

  3. Incredible piece of work, I’ve been searching for something like this for a few days now. I would just love it if you could tell me how to use it though. I tried almost everything and got errors like ” Instantiation attempted on a non-constructor” (i am a noobie, i know) and when i linked it with the Ripple class it kept changing the linkage to flash.display.BitmapData. A few lines on how to use would be great.
    10x a million i’ll keep on trin to get it to work.

  4. I eventualy managed to instantiate the class “Rippler” on a movieclip and got it to “drawRipple” on every mouse move but it’s nowhere near as fast as the “Ripple class” as i suppose it is with your demo. On top of that my movieclip is moved to right and bottom by the Size of the ripple and that creates two white lines, i hope you can help me out.

  5. Hi M Alex, and thanks :)

    Did you check the source ( https://www.derschmale.com/demo/rippler/srcview/ ) of this example? It’s using some Flex Builder meta-code, but it should work by just creating rippler = new Rippler(targetDisplayObject, strength, scale); and then using the drawRipple function. In any case, it’s not meant to be extended by library assets, but instead those are passed to the Rippler constructor.
    Internally, it’s using a convolution filter to create the ripple buffer images, which in turn is used as a DisplacementMap filter on the target display object. The speed of the Rippler class depends largely on the size of the source display object and the scale passed to the constructor (higher values actually use smaller ripple buffers for the convolution filter, and are therefore faster).
    I hope this helps, otherwise be sure to let me know. I’ll be glad to help you out; there’s a contact page in the Pages navigation menu, where you can send me a PM if you need to show an example or so.

  6. Not only the class is great but the fact that there are people willing to help you understand more about programming in general still astounds me. There are thousands of people offering this for some sums of money but still there are great men in this large world wide web.
    Thanks again David.

  7. Hi,

    first of, congrats, this looks great!

    But I do have the same issues as Clay, I notice that you said it’s been fixed, but I just tried it out and it seems that the strength is directly connect to this weird offset…is the source available the updated version? Or better yet, what did you do to fix this?

    Thanks for the source btw man ;)

  8. Hey Fatche,

    You’re welcome :)
    The updates were only made in the svn repository of the NascomASLib (I just noticed today that it was still the old version in the source view, actually, uncanny! ;) ). So now, if you view the source again and use that Rippler.as class, the offset issue -should- be fixed.

    Cheers,
    David

  9. sorry mate, I don’t think it’s fixed yet…I know it’s directly connect to the DisplacementMapFilter, so I set the mode to “color” and it worked, there are no clippings on the image, but it does get an offset equivalent to the strength parameter… if you can find a better solution, I’m all ears man!

  10. Hi, I just tested the version currently in the source view and it works without any offset. Are you sure you replaced the Rippler.as file in the be.nascom.flash.graphics package (not Ripple.as)? There should be a _colourTransform property which is the solution to the offset problem. Or if it’s still not working, it’d be glad to look at your code so I can try and fix the ripples :)

  11. Bloody right! The file wasn’t updated, just checked it out from the repository, it’s all fine and dandy ;) sorry to bother you mate,
    keep up the good work!

  12. Hi David,

    I’m very new to flash world and action script is greek to me. I have one (could be annoying) request. Would it be possible for you to guide me how to it?, in simple words

    Thank you for your time in advance

    cheers

  13. Hi Amit,

    I’m not sure if I understand correctly what you need exactly. Do you mean guide you through how to implement the Rippler class (that I can do ;) ), or ActionScript in general. In the latter case, I’d simply suggest Essential ActionScript 3.0 by Colin Moock (published by O’Reilly), since the scope is far too great and I wouldn’t have time for that.

  14. I’d love to get a copy with the source commented. I can follow most/much of it, but if you could do a short line-by-line commentary it would be great. I know when I get into a project I crank out the code, and it’s quite clear to me what I’m doing, but later it really helps to have each line clarified. To those of us coming at this new, it would explain a lot!

  15. Hi David,
    I am in the same boat as Amit and am very new to AS3 – are you able to guide me through the process as well please? Take care, cheers!
    – Rich McNabb

  16. Hi David,
    I have to echo everyone else in saying, “AMAZING!”

    I managed to implement this in Flash, using the source code containing the ColorTransform, however, I noticed the moment you call the “new Rippler”, the image on the screen flickers with the offset, then is immediately covered up with the correct alignment. (I removed the “drawRipple” portion to confirm). It is really obvious with larger images that have a bright sky and dark ground).

    I hoped to use your your incredible effect to transition between images, but the flicker is too noticeable. I tried finding a way to turn visability off during its creation. Although I followed some of the code, it is beyond me how to remove this flicker, and wondered if you could glance at it.

  17. Thanks Roger! I just quickly updated something which should fix the issue. If not, something really odd is up and I’ll have to spend some more time on it later :) I’d love to see the transition when it’s done, too!

  18. Unfortunately, the change seems to have made matters worse. I duplicated the new source code, verifying the change in the buffer creation parameter. Now, instead of flickering, the picture starts off with an offset in the opposite corner (the sky shows up below the ground), and then the pic appears to slowly float down to the lower right during the wave propagation to cover up the offset.

    If we can get this to work, I’ll attach a link where the finished project gets posted. Let me know if you have any other ideas, as I am definitely out of my league on this one. Thanks!

  19. Whoops, my mistake! The result of not having enough time and still wanting to fix something too quickly (mixed up the buffers)…
    I updated it once more, tested it, and it seems to work this time (for real!) :D

  20. Great job!! That fixed it and it looks pixel perfect now. I’m almost to the point where I can use it for a transition. It slows down to a crawl after about 50 transitions, so there must be something getting left over in memory. I’ll keep poking at it though….I think it’s worth it. Thanks again! :)

  21. If you’re creating new Rippler instances, be sure to call the destroy method once you’re done using an old instance that you don’t need anymore. That should clear all memory used by the buffers.

  22. Thanks. I was already doing that, but it’s important for others to know too. :)

    I found the fix though. I needed to tell it to “stop();” after I used the “rippler.destroy();”.

    In Flash, it made sense to save this effect as it’s own 3 second “sub-movie”. I dropped the sub-movie onto frame 2 of my main movie, and it did it’s own thing, but I forgot that it was going to keep looping. So now, when my main movie went back to frame 2, it must have initiated the effect again, even though it was probably still looping. Normally, this wouldn’t be a problem, since all the shapes are normally pre-existing going into frame 2, but apparently since the effect was still going on in memory, the “new” statement must have kept spawning new instances of it. Just a hypothesis, and I really would have expected some form of variable duplication error, but it exposed my own naivete in implementation. :P

  23. Hey – fairly ignorant to Flex and AS3, and trying to implement this effect in Flash. Could you provide a quick work through for that? I’ve tinkered with the source file and have kind of hit a dead end. Thanks!

  24. Glad to hear it’s working, Roger! It was indeed probably the Rippler instance being created over and over. As far as I know, ActionScript is far less strict when working on the timeline, so it accepts redeclarations of variables). For stuff like this, the profiler in Flex Builder (you can run it on normal swfs as well) is a huge help ;)

    Jesse, the simplest way to get started to use it in Flash is just to copy the “com” folder into the folder containing the fla (not the src) and, if you’re using the timeline, type in “import com.derschmale.graphics.Rippler;” at the top of the frame where you want to use it. Put something on the stage, give it an instance name (fe: “waterClip”) and put “_rippler = new Rippler(waterClip, 60, 6);” in the actionscript panel.
    From then on, whereever you want to start a ripple (x and y being numbers), just say: “_rippler.drawRipple(x, y, 20, 1);”
    You can mess around with the parameters to get different effects until you find what you need.

  25. Pingback: Robin’s - Schoolblog » Elfde week at MR!

  26. Dear David,
    I’m trying to implement this stuff in Flash as Jesse did. You told him some stuff about using the “com”-folder, not the “src”. Where do I get this com folder from?
    thx…

  27. Hi Bill. I’m sorry, I meant the “be” folder instead of the “com”. I’m getting my package names confused (probably need more sleep ;)).

  28. Thx Bill :)
    Yen, that’s the effect of an old version of the source (I think I might have forgotten to update the zip file in the source view). If you copy-paste the code from Rippler.as in the source view itself, it should work without any problems. I’ll update the source zipfile later on.

  29. Hello. This is a great effect, and so quick. As so many people were asking for help I made a commented .fla. I use CS4, but I made a .zip with a CS3 and CS4 version. You’ll need to go to the SVN and stick the be.etc etc files in your base actionscript directory, and tell the fla where that is in the publish settings. The file is on adobe share, link:

    https://share.acrobat.com/adc/document.do?docid=c86b2ac4-b11b-4b59-8cc5-a8411bc7210d

    and the code, for those who don’t need the fla:

    //import the code, this assumes you have the be/nascom/etc etc folder structure
    //(grabbed from the SVN) located in your global actionscript directory

    import be.nascom.flash.graphics.Rippler;

    //I’m using the timeline for speed here, but it’d be the same if you were
    //using a document class etc

    //I have a movieclip on the stage called ‘pic’, so now we’ll add
    //the ripple effect

    //first make a variable, you can call it anything, I called mine ‘myRipple’
    //the variable instantiates (makes a copy of, uses the code from) the Rippler.as file
    //and passes properties to it through the method (), sometimes called the constructor, or brackets
    //I’ve heard them called all sort of stuff

    var myRippler = new Rippler(pic, 60, 6);

    //now lets start the code running
    myRippler.drawRipple(x, y, 20, 1);

    //now you can alter the x, y etc to change the way to ripple works, or have it follow the mouse etc
    //but for now, at least you have it working :)

    //but, hey, let’s make it more useful/

    //add an event listener for mouse clicks
    addEventListener(MouseEvent.MOUSE_DOWN, rippleFun);

    function rippleFun(e:Event):void {
    myRippler.drawRipple(x, y, 20, 1);
    }

    //this runs the code on every click
    //hope that helps
    //Andrew, http://fingerpuk.tumblr.com

    //great effect too, thanks to David from https://www.derschmale.com :)

  30. Not a problem, thanks for the effect it saves me a bunch of time!

    One thing, it slows to a crawl if you fullscreen the SWF/Projector. If you then CTRL+ALT+DEL then hit Cancel, it’s running smooth. Any ideas? :s

  31. Hmm I haven’t tried that yet. Seems to me it’s a Flash Player hardware acceleration issue tho. Fullscreen filters are usually pretty slow as far as I know – but I didn’t know they’re fast after ctrl+alt+del :)

  32. David,
    I just want to to first of all thank you for the making this open source and developing a truly amazing effect. I’ve been working through the code for a few day trying to improve CPU efficiency because I’d like to use this effect as a background for an entire site.

    Is there a way to create a callback for when the ripples have completely faded. The only way I’ve been able to remove the Enter Frame thus far is to create a timer, start it and reset it every time the mouse moves, and then on Timer event, remove the EnterFrame. I’ve made my timer 7 seconds so I can be sure the ripples are completely gone.

    I’m not extremely familiar with the convolution filter or the displacement map filter so I don’t know if any of their arguments affect the quality of the filter. I’d be willing to lose a little quality to gain a few frames per second. Any other ideas about saving CPU would be welcome.

    Thanks in advance for the reply.

  33. Hi James,

    I think for now it’d be safer to use the timer option. I’m completely backed up at the moment, so I won’t have the time to work on it for a while. It shouldn’t be very hard to determine when it’s faded, though, so I might take a look at it later.

  34. Thanks for the quick reply! If you get do get a chance to look at it, it would be greatly appreciated but I can relate to being swamped.

    One more question I forgot, I’m not quite sure of the benefits of Flash Player 10. I know GPU acceleration isn’t all it’s cracked up to be. So I have FP 10 but I’m still using Flash CS3 and building for Flash Player 9. Do you think there would be performance gain if the movie was published for FP10.

    Also, is your pixel blender FP10 version more efficient?

    Sorry for all the questions.

  35. I’m not sure whether the PB version is more efficient, I never really did any comparison tests. I think they’ll roughly be the same, tho the pixelbender version is not as easy to use (another thing to do for me, create a usable version of that ;) )

Leave a Reply

Your email address will not be published. Required fields are marked *