Circular Wander


click here for the source code It’s relatively clean, even contains some comments.

I get about 20 fps with 3000 small particles (radius1). This can vary depending on other settings like max/min degree of rotation…

So how did this come about? Funny you should ask…

While working at Sony Back in 2003, I made an “all around preloader”, which was to be used for flash showcases, apps, tutorials etc. At the moment Sony was using these “blobs” in their branding:

you make it a sony

Armed with Flash6, I used the drawing API to make it into a dynamic animation:


sony loader
Click image to see it in its never ending glory ;)

That’s the only working version I could find. There is an FLA, but I dare not open it.

Unfortunately, the loader never saw the light of day, as Sony rebranded within weeks of me finishing the code :D

The most interesting aspect of the loader was the random movement of the blobs. It’s not what I wanted. I wanted the circular wander motion. Time just ran out back then. Every now and then I’ve pondered going back to the problem. I was inspired to finally get off my ass by Grant Skinners recent post about his Wander Class. So it took me 7 years…

The basic premise is simple:

circular wander explanation 1

Any particle travelling along the perimeter of a circle, can “smoothly” switch circles, as long as the next ones center is along a line perpendicular to the particles current moving direction.

The problem is, how do you restrict this movement to stay within a given rectangle?

The solution is easy to see when visualizing it:

circular wander explanation 2

There are a few “maximum circle sizes” along the blue “axis line” which fit the wandering bounds. Once the radii of those circles are discovered, it’s just a matter of randomly selecting a point along the line, between the “maximums”.

But how to find those magical maximum radii?

There are probably several ways. After blankly staring at a few sketches, I was suddenly reminded of my Highschool Math teacher Mr. Rosko. He would say the term “Isosceles Triangle” in a tone of voice, that sounded like it was something that could get you laid.

Needless to say I never tried that one on the ladies, but for this baby, it did just the trick.

Not only do isosceles triangles have two equal angles, they also have two sides that are the same length.

Now, let’s look at another mindblowing illustration:

circular wander explanation 3

In other words, due to the nature of a circle, an isosceles triangle appears between the current position of the particle, the maximum radius center, and the edge of a boundary. So at this point, here’s what we know about that triangle:

  • All the angles in the triangle. These can be deciphered with simple arithmetic.
  • The point currently occupied by the particle.
  • The equation of the line between the particle, and the new center.
  • The X (or y) of the point which intersects with the bounds.

In a nutshell, we pwn that sob.

There was some trials and tribulations with maintaining the correct direction when switching circles, and choosing the best circle for the job… more about that if you look at the code :)

enjoy!

Tags: ,

6 Responses to “Circular Wander”

  1. polyGeek Says:

    Very cool. I love playing with stuff like this. It’s even one of my new years resolutions to do more.

    Suggestion: make the color of the lines the same as the ball that makes it so that each path sticks out.

  2. sakri Says:

    Cheers dude :)

    That’s just a demo, the code should be easy to use so… I’m looking forward to using it for a bunch of experiments I’ve already planned out. Just grab the code and have fun!

  3. makc Says:

    lol @ post style

  4. nicoptere Says:

    good to read from you again :D
    the illustrations really enlightened my day !
    the class will prove useful, thanks for sharing!

  5. V Says:

    very interestinG!

  6. rur Says:

    Thats cool only one small bug I noticed in the CircularWander source code:

    CircularWander :: createStartingPoint(…)
    {
    ..
    // will always create a rect with w & h = 0
    rect.inflate(-bounds.width*.5,-bounds.height*.5);
    ..
    }

Leave a Reply