Creation of a Ragdoll with Flash part 2: Constraints

It’s time to introduce another feature involved in Ragdoll creation.
In part 1 you saw Verlet integration, now it’s time to see what is a constraint.

In mathematics, a constraint is a condition that a solution to an optimization problem must satisfy. So basically a constraint is a condition that must be respected. In our ragdoll world, this condition (or those conditions) refers to a distance from a particle to another, no matter if particles are moving or not.

Let’s imagine a real world example: a steel, rigid, unbendable, unbreakable, undeformable stick. This stick has two important points, one at its beginning and one at its end. Being the stick rigid, unbreakable and so on, we can say that the distance between those two points will always be the same, no matter what happens to the stick.

This is a constraint: the condition that says that the distance between start and end points must always be the same.

This is very easy to satisfy when the points do not move: we simply place two points at a given distance and the game is done.

Real problems come when there is a reason (any reason) why points could move, and we have to find a way to move points and satisfy constraints at the same time.

The first thing we are going to do is coding a function where we pass two points (in our case two movieclips) and the distance (in pixels) between them. The function will output the points in a way that satisfies the distance.

Line 1: Function declaration: particle1 and particle2 are the movieclips, and distance is the distance in pixels between movieclips (the constraint).

Line 2: Calculating the horizontal distance between particles

Line 3: Calculating the vertical distance between particles

Line 4: Calculating the distance between particles using the Pythagorean Theorem

Line 5: Calculating the angle between particles using Trigonometry. You can find more information about trigonometry in this tutorial

Line 6: Defining the error: the error is the difference between the actual distance as calculated in line 4 and the constraint distance passed in line 1

Now that we know the error, we have to fix it. How can we fix it? Simply moving the points in order to have an error = 0

Line 7: Calculating the new _x position of the first particle using trigonometry

Line 8: Same thing with the _y position

Lines 9-10: Same thing with the second particle

Notice that in this function the error is splitted in two equal parts (error/2): this means we are going to move both particles in the same amount of pixels in order to fix the error. This is the default and more intuitive way of moving particles, but we’ll see later how in some cases we have to distribute the error in other ways.

Now that this principle is clear (I hope so), let’s see a real Flash example.

I created only one movieclip with a circle in it, and linked as “part” (just like in the verlet tutorial, but this time I have only one movieclip)

Then, this is the actionscript:

Line 1: Creation of an empty movie clip called “line”, where I will draw the line connecting the particles

Line 2: Placing the first particle on the movie

Line 3: Placing the second particle on the movie. Please notice that both particles are placed at _x:240 and _y:165. This means that particles are in the same point, so their distance is zero. You will see how the script will place both particle in order to satisfy constraints.

Line 4: Beginning of the main routine to be executed at every frame

Lines 5-6: Placing the first particle in the mouse position. This is just to let you move the particle and see what happens

Line 7: Clearing the line movieclip

Line 8: Defining the drawing style as a red 3 pixels thick pencil. To know more about drawing styles refer to this tutorial

Line 9: Call the constraint function between particles 1 and 2 with a distance of 100

Lines 21-22: This is the only change to the constraint function you saw before, to draw a line between particles

Here you are: you can move the draggable particle as you want, and the constraint is always respected.

This was a very easy case, because we were moving a particle while the other did not move by itself, just followed the dragged particle. I’ll demonstrate how this function will work even in an environment where all particles have their own lives, but now it’s time to talk about error distribution.

In the previous function, once determined the error, it was distributed half in the first particle and half in the second particle, so particles position were adjusted by the same amount of pixels.

This limits our function, because in real life there should be fixed particles or particles that move less than others.

To manage error distribution, we need to change a bit the main function

Line 1: The function has a new parameter: error_on_1st. This is a value from 0 to 1 that represents the amount of error distribution to the 1st particle. 0 means there is no error distribution (all adjustments are done by moving the 2nd particle while the first remains fixed), 1 means there is full error distribution (all adjustments are done moving the 1st particle while the second remains fixed) and all values in between balance the error distribution more in a particle or in another. The previous function worked as if error_on_1st was 0.5

Line 2: Obviously, error_on_2nd, the error distribution on the second particle, is determined by 1-error_on_1st

Lines 8-11: Particle adjustment are done according to error_on_1st and error

Thanks to this new feature, we can have fixed particles that respect constraint as in this example

Line 9: Calling the constraint in this way, will make particle error adjust only on one particle. The result is a fixed particle in the centre of the movie and the other one following the mouse but respecting the constraint.

As you can imagine, an accurate error balance can create different gameplays starting from the same actionscript.

Now, let’s introduce more particles… we’ll create a triangle

There is not much to say about this script, except three things:

1) If you move the mouse quickly, you will see how the triangle deforms. This will be fixed later

2) This is a very dirty way to create actionscript and manage constraints… imagine a complex figure (a ragdoll?) created in this way… we need to store all constraints in an array

3) I designed the constraints in a way they can be satisfied at the same time. A complex environment can have constraints that cannot be satisfied so we will handle non-fixed errors

We’ll see this, and more, in next tutorial. Meanwhile drawing your ragdoll on a paper and measuring the right constraints, you should be able to design some kind of ragdoll

Then, download the source code and give me feedback

  • hansa

    thanks

  • Math.atan2 should be called with y, x distances, not x, y. And x components are usually mapped to cos, while y components mapped to sin. In this case these two things seem to cancel each other out so you get the same results, but if you were to draw out the angles and distances and relationships, it would get pretty confusing.

    When doing this, I’ve generally created a Point object and a Stick object. The stick is composed of two points and the constraint between them. Points are stored in a points array and sticks are stored in a sticks array. Both are updated each frame with for loops. I don’t see it as particularly messy, but I’m interested in what you’ve come up with.

  • is it possible to do something like the first example of this page but constrain the “non-mouse” controlled point (the pushed/pulled point) to a path (bezier or similar)? I’m interested in the dragging dragging of things on along path.

    J

  • Luiz Fernando

    Cool. In opensources flash physics engine, like flade, the script is similar, but more powerfull, that is, can handle collisions and everything more.

  • Eblup

    hey iam trying to make a mace i can swing around
    or a sword and all i have is youre code written
    in moive clips. can you help?

    +++++

    onClipEvent (load) {
    dx = 0;
    dy = 0;
    dis = 0;
    angle = 0;
    Max = 100;
    }

    onClipEvent (enterFrame) {
    dx = _root.dot._x-_x;
    dy = _root.dot._y-_y;
    dis = Math.sqrt((dx*dx)+(dy*dy));
    angle = ((Math.atan2(dx,dy)/(Math.PI/180))-180);
    if (dis!=max) {
    _x = _root.dot._x+100*Math.sin(angle*(Math.PI/180));
    _y = _root.dot._y+100*Math.cos(angle*(Math.PI/180));
    }
    }

  • Emanuele, thanks for these tutorials. They are very clear and easy to follow. Looking forward to the next installment!

  • Pingback: James()

  • Kit Evans

    These are fantastic – the only place I’ve found a tutorial that doesn’t use stupidly long words! Please update soon! Cheers :)

  • sweet!!!! thanx!

  • Questo

    how do you make a stickfigure

  • Pingback: APE - Actionscript Physics Engine tutorial : Emanuele Feronato - blog of an italian geek()

  • N00b

    coooooooooooooolnesssssssssssss

  • Pingback: Creation of a Ragdoll with Flash part 2: Constraints at Flash Game Script()

  • Hawdon

    I would like to make gravity so that my ragdoll is beeing pulled down so that it looks less fake… I dont know how so could some1 tell me. Please!

  • Pingback: MochiLand » Blog Archive » Lesson 1()

  • emanuel

    hi nice tut when r u going to make the third part i always wandered hoe to make a good ragdoll

  • Orava

    Is it possible to add gravity to those balls?
    (now i got 1 ball (o) in the middle, holding up 3 other balls by sticks (\|/) but i don’t seem to get gravity involved)

    O O O
    \|/
    o
    so the 3 other balls (O) would go like
    o
    /|\
    O O O

    i hope my little drawings made it more clear

  • PLEASE…

    …submit the next tutorial! PLEASE!

  • Nathan

    Are you going to make the third step, I would really like it!

  • Spider

    Hi… i have a little problem…
    My circles are going in a strange line when I put 3 joins…(on 2 its working)
    plz contact me :(

    onClipEvent (load) {
    var vecx = _x-_root.ball2._x;
    var vecy = _y-_root.ball2._y;
    var dist1 = Math.sqrt(vecx*vecx+vecy*vecy);
    vecx = _root.ball2._x – _root.ball3._x;
    vecy = _root.ball2._y – _root.ball3._y;
    var dist2 = Math.sqrt(vecx*vecx+vecy*vecy);
    vecx = _root.ball3._x – _x;
    vecy = _root.ball3._y – _y;
    var dist3 = Math.sqrt(vecx*vecx+vecy*vecy);
    function react(m1:MovieClip, m2:MovieClip, distance) {
    vecx = m1._x-m2._x;
    vecy = m1._y-m2._y;
    var tmpdist = Math.sqrt(vecx*vecx+vecy*vecy);
    var error = tmpdist-distance;
    if (error != 0) {
    var angle = Math.atan2(vecy, vecx);
    m1._x = m1._x+Math.cos(angle)*error/2;
    m1._y = m1._y+Math.sin(angle)*error/2;
    m2._x = m2._x+Math.cos(angle)*error/2;
    m2._y = m2._y+Math.sin(angle)*error/2;
    }
    }
    }
    onClipEvent (mouseMove) {
    _x = _root._xmouse;
    _y = _root._ymouse;
    react(this,_root.ball2,dist1);
    react(this,_root.ball3,dist3);
    react(_root.ball3,_root.ball2,dist2);
    }

  • Spider

    solved! :)

    m1._x = m1._x+Math.cos(angle)*error/2;
    m1._y = m1._y+Math.sin(angle)*error/2;
    m2._x = m2._x+Math.cos(angle)*error/2;
    m2._y = m2._y+Math.sin(angle)*error/2;

    =

    m1._x = m1._x-Math.cos(angle)*error/2;
    m1._y = m1._y-Math.sin(angle)*error/2;
    m2._x = m2._x+Math.cos(angle)*error/2;
    m2._y = m2._y+Math.sin(angle)*error/2;

  • Hey, has the next part of this article become vapourware? Are you ever going to continue it? I’m really interested by ragdoll physics, and I was very dissappointed to find that a 3rd part had never been made :(
    Please make it!

  • shp

    you can remove the sin, cos and atan to speed up the processing

    function constraint(particle1, particle2, distance) {
    dist_x = particle1._x-particle2._x;
    dist_y = particle1._y-particle2._y;
    actual_distance = Math.sqrt(dist_x*dist_x+dist_y*dist_y);

    error = actual_distance-distance;

    particle1._x -= (error/2)*dist_x/actual_distance;
    particle1._y -= (error/2)*dist_y/actual_distance;

    particle2._x += (error/2)*dist_x/actual_distance;
    particle2._y += (error/2)*dist_y/actual_distance;
    line.moveTo(particle1._x, particle1._y);
    line.lineTo(particle2._x, particle2._y);
    }

  • Xodus

    I would really like the 3rd part…..

  • Please publish a 3rd part to this tutorial ; ) its great and i would love to see the next steps.

  • rolf

    Searched your site with google for a while now… but it seems the third article keeps missing. Would love to see it, as your style to write and explain makes it easy to understand and learn.

    Thanks so far :)

  • Hi,

    Really like the scripts, but I was wondering if they could be converted to act like a train for example. I have build 2 rollercoaster simulations, but want to improve them with some good scripts. I think I need the ragdoll maths to do it, car1 follows the track, but car 2 till 6 f.e. get off track.

    Thnx :)

  • Ryan

    make the third bit >:

    i want to know how to stop the triangle deforming

  • Great stuff. Are there more lessons in this ragdoll series?

  • Tyler

    Do you know when or if you are going to be pasting another tutorial because this one was extremely helpful?

  • nminhtai

    Thanks for great guides!

  • antoan

    I’d really like to see the third part of this tutorial. I’ve always thought making ragdolls in flash is impossible for me, but thanks to your tutorials it seems not as hard as I thought :)

  • Vladimir

    Same here, cant wait for the third part..

  • thing guy

    third part anyone?

    • the replier

      YOU HAve no idea how much i want third part. Even though AS2 old language, it will work as a basis for making ragdolls in many languages…DO WANT

  • John

    so I am going to go ahead and assume that this tutorial is never going to be made, even with the numerous requests for it. 3 years? really?

  • Naveen

    what is the next tutorial link for this tutorial??
    plz give me the link…

  • Naveen

    Plz give me the link for the next tutorial of this tutorial..

  • Alan Chang

    I have read this article 2 years ago and followed and successfully duplicate what was taught in Actionscript 3.0. However,

    “I’ll demonstrate how this function will work even in an environment where all particles have their own lives, but now it’s time to talk about error distribution.”

    Unfortunately, seeing how this tutorial was written years ago I wouldn’t be surprised if part 3 will never ever be released.

    I tried to implement the “each particles have their own life” part myself, adding physics (just gravity) to each and every particle but have not succeed. I realize with what was taught here so far this model only works with only one “active” particles where other particles is dependent on the other particles.

    Can anyone who figured it out, briefly explain how am I going to give every single particle their own “life”? E.g. pulling both ends of a string of particles.