email sol follow sol rss feed of the blog wishlist Sol::Tutorials

Spring Toys

Springs are fun, and one of those places where adding a tiny bit of actual physics in your application can have a very dramatic effect.

First the boring stuff. Let's define springs as we mean them.

Imagine that the above picture has a piece of roof, with three equal weights hanging from the roof with three equal springs. The middle weight is in rest (i.e. not moving), while the left and rightmost weights display different positions of motion, with the spring shrunk (on the left) or expanded (on the right). The distance from the rest position ('0') is -y and y. The names and signs of these variables is not too important at the moment, but anyway.

Springs are these funny things that want to be in rest, and if you shrink or expand them, they want to get back to the rest position. They are especially funny in the way how, when they are pulled apart more, they want even more to get back to the original position. The formula for the spring force (and direction) is as follows:

You'll just have to trust me on this, as I'm not going too deep in it. I just read it from a book, and if wiser people have seen it fit to be written in a book, it's good enough for me (as long as it works). Hey, at least I didn't read it from the internet!

The force F is how much the end points want to move towards each other or further away from each other. y is the distance, like we defined earlier, and 'k' says how rigid the spring is. The more rigid, the stronger the spring pulls towards the rest state.

I've implemented these on top of my SDL / 2d OpenGL framework, which can be found on my "code" page - look for 'basecode' for the most recent version. This one will work with at least version 2.0. Replace the main.cpp from the basecode with this one to play with it.

Now then, there's a init() function where we define the springy thingy. We define four mass points, p1, p2, p3 and p4, and some springs between these. If we just define three springs (the first three), we get a construct which is something like this:

I've also added code that moves the first mass point to wherever the mouse cursor is while the mouse button is pressed, so you can play around with the spring toys with the mouse. The three-spring thing is actually quite fun to play with:

If released, or moved near the borders (mostly the bottom in this case), the spring collapses. The springs try to retain their lengths, so the result is pretty realistic:

But lets turn the toy into a more solid object. Adding the fourth spring will turn the chain into a box:

Unfortunately this is a rather fragile construct, as there's nothing holding the box together. If we stick one mass point somewhere for a while, the two "side" points will end up in the same space:

The solution is simply to add a new diagonal spring.

Unfortunately, it's easy to force the box into a bad shape, flipping one corner around the diagonal - just try to push the box to a corner for example..

So what can we do? Well, we can add another spring of course -

This construct can take quite a lot of damage; it can still get flipped, resulting in a mirror image, though. Still, it's much more stable now:

Adjusting the 'k' factor can be used to tweak just how rigid the springs are. Making the springs stronger forces the box to keep its shape, but even small movements of some of the mass points will cause lots of vibration. Increasing the value too much will cause the physics to blow up. Tuning the 'k' constant down will make the object to be more jelly-like, and going down enough will make it impossible for the box to keep its shape due to gravity.

All sorts of cool things can be done by creating more complicated shapes from mass points and springs, and adding some more interesting collision shapes than just the borders of the screen..

Springs are actually surprisingly cheap to calculate, so you can fearlessly toss in a couple hundred without breaking sweat. The collision response for the blue circles in the example above was simply to move the mass point to the edge of the circle if collision was detected.

I hope this little tutorial-ish has shed a little light on springs. The approach I've made is rather brute-forceish, and I'm pretty certain there are better ways of doing things. Still, I think I've shown that you can do rather cool things with little effort like this.

What I found especially cool about springs is that you can create all sorts of rubbery objects and don't need to care about rotation of objects and stuff - everything just "works".

Comments etc.. appreciated.

Site design & Copyright © 2017 Jari Komppa
Possibly modified around: May 02 2010