 00:00
00:00 AS:Constant Distance

8,133 Views | 40 Replies

AS:Constant Distance 2005-10-01 07:42:18

AS:Constant Distance
AS:Main

Saw there wasn't one of these yet, so decided to make one. Any errors/mistakes please alert me straight away.

Ever wanted to ensure 2 points (e.g movie clip co ordinates) are always a constant distance from eachother?

We can do this using trigonometry through Kinematics (or Inverse Kinematics)

-AS:Trigonometry by BleeBlap

-Basic knowledge of most AS:Main topics

Kinematics is the process of finding a point in space when given the length and angle of an armature.

Kinematics can be used to achieve effects such as a ragdoll, or to bind wheels on a car/bike together during gameplay.

I’m just going over the VERY BASICS in this tutorial; the possibilities for application of the concept are near endless. However going into detail here would be unnecessary and over complicated.

The Trig

First take a look at the example diagram .

Try dragging point 2 (bottom one) with the mouse, you will see that point 1 (top one) is pushed away to always keep a constant distance.

We work with the points as a triangle, with the distance between their _x co ordinates acting as side X, and the distance between their _y co ordinates acting as side Y.

Place your two point mc’s on stage, give them instance names point1_mc and point2_mc.

In our example, point 2 is made draggable when clicked, and will have authority over point 1, force changing its _x and _y values to always maintain a constant distance away.

This means our kinematics code will just be applied to point 1, as point 2 isn’t being affected.

(Bear in mind Flash works with radians instead of degrees while performing trigonometric equations)

I’m coding on the frame itself for simplicity purposes during the tutorial, but you can easily change yours to be placed onto the movie clips themselves.

var hypotenuse:Number = 170;

//Our defined hypotenuse side length (see diagram)

//This is important for finding the allowed X and Y sides of the triangle, and determines the distance the points will always be from eachother

_root.onEnterFrame = function() {

//Manipulates values every frame (example is running at 30 fps)

point2_mc.xDist = point1_mc._x-point2_mc._x;

//Finds the length of side X in the diagram by subtracting point 2's _x from point 1's

point2_mc.yDist = point1_mc._y-point2_mc._y;

//Finds the length of side Y in the diagram by doing the same with _y co ordinates

point2_mc.angle = Math.atan2(point2_mc.yDist, _root.point2_mc.xDist);

//Finds the Angle marked in the diagram using tangent (opposite side (Y) / adjacent side (X)

point1_mc._x = point2_mc._x + (Math.cos(point2_mc.angle)*hypotenuse);

// In triangles ,we know that an angles Cosine value is equal to the result of dividing the side adjacent to it (side X in the diagram) by the Hypotenuse side.

We can work this formula backwards to find the allowed value of side X when both the Angle and the Hypotenuse already have values.

We first find the cosine of the angle, using Math.cos()

We then multiply this value by the hypotenuse, to get side X. (remember Cosine = Side X / Hypotenuse). So side X is given a value based on the values of the Hypotenuse and the Angle.

As the Hypotenuse is always constant, the X value will be lengthened or shortened depending on the angle, and the effect will be that when the _y distance between the points become greater, the _x distance will become shorter in ratio.

We then have to add side X onto the _x co ordinate of point 2, to get point 1’s allowed _x co ordinate.

point1_mc._y = point2_mc._y + (Math.sin(point2_mc.angle)*hypotenuse);

This is basically the same method, but finds side Y instead of side X (because The Sine value of an angle = opposite side (side Y in diagram ) / hypotenuse).

Side Y is then added onto point 2’s _y co ordinate value to get point 1’s allowed _y value.

point2_mc.onPress = function() {
point2_mc.startDrag();
};

//Makes point 2 draggable when clicked

point2_mc.onRelease = function() {
point2_mc.stopDrag();
};

//Makes point 2 stay put when released

};

//End of enterFrame handler

Complete code on Frame

var hypotenuse:Number = 170;
_root.onEnterFrame = function() {
point2_mc.xDist = point1_mc._x-point2_mc._x;
point2_mc.yDist = point1_mc._y-point2_mc._y;
point2_mc.angle = Math.atan2(point2_mc.yDist, _root.point2_mc.xDist);
point1_mc._x = point2_mc._x+(Math.cos(point2_mc.angle)*hy
potenuse);
point1_mc._y = point2_mc._y+(Math.sin(point2_mc.angle)*hy
potenuse);
point2_mc.onPress = function() {
point2_mc.startDrag();
};
point2_mc.onRelease = function() {
point2_mc.stopDrag();
};
};

Examples and other Tutorials

Response to AS:Constant Distance 2005-10-01 07:46:12

Very useful for Artificial intelligence.
Extremely detailed and well explained.

Good job :D Response to AS:Constant Distance 2005-10-01 07:49:51

At 10/1/05 07:46 AM, -Toast- wrote: Very useful for Artificial intelligence.

Yeah I guess, it would be for realistic attacks and damage

Extremely detailed and well explained.

Thanks, glad there aren't any errors spotted yet cos I really screwed the last one of these I did up

Good job :D

<3

Response to AS:Constant Distance 2005-10-01 07:51:11

Yeah, I started learning this stuff a few weeks ago, and I have to say it's very fun to work with.

Pretty decent tutorial too. Response to AS:Constant Distance 2005-10-01 07:51:49

Maybe you could show a example of the what the AS can do. Could you?

Response to AS:Constant Distance 2005-10-01 07:53:47

At 10/1/05 07:51 AM, bigexplosions wrote: Maybe you could show a example of the what the AS can do. Could you?

Lol, I posted a couple at the bottom.

this gets sicker and funnyer every time i watch it

Response to AS:Constant Distance 2005-10-01 07:55:20

At 10/1/05 07:51 AM, bigexplosions wrote: Maybe you could show a example of the what the AS can do. Could you?

umm yeah he did plus he posted a bunch of links which expand on this alot more

And tost how would this be good for AI exactly?

Response to AS:Constant Distance 2005-10-01 07:56:05

At 10/1/05 07:51 AM, bigexplosions wrote: Maybe you could show a example of the what the AS can do. Could you?

If you learn IK (Inverse Kinematics) REALLY well, you can make stuff like this. But I wouldn't expect you to learn it that well. You can also do stuff like bone structure, or the simplest IK technique, IK chains. Response to AS:Constant Distance 2005-10-01 07:59:54

At 10/1/05 07:56 AM, Rantzien wrote:
At 10/1/05 07:51 AM, bigexplosions wrote: Maybe you could show a example of the what the AS can do. Could you?
If you learn IK (Inverse Kinematics) REALLY well, you can make stuff like this. But I wouldn't expect you to learn it that well. You can also do stuff like bone structure, or the simplest IK technique, IK chains.

Yeah I dont see why people have such orgasms over that fucking file. I mean www.teagames.com has a shit load of games using just as impressive realism (true physics) as that so why the wetness over it?

Response to AS:Constant Distance 2005-10-01 08:01:55

Yeah flade owns, Its really hard to do stuff where you have multiple points affecting eachother at the same time without the structure just shooting off screen.

That also have complex physics stuff like weighted colision with circles and really good friction simulation.

Its one of my favorite effects so far, got a few ideas for uses after me and NC finish priority 1

Response to AS:Constant Distance 2005-10-01 08:02:06

At 10/1/05 07:59 AM, Ninja-Chicken wrote: Yeah I dont see why people have such orgasms over that fucking file. I mean www.teagames.com has a shit load of games using just as impressive realism (true physics) as that so why the wetness over it?

Because it's open source ^^ Response to AS:Constant Distance 2005-10-01 08:02:43

Very nice but I don't see how to add physical simulation to kinematic'ed points. Response to AS:Constant Distance 2005-10-01 08:06:46

At 10/1/05 08:02 AM, F-13 wrote: Very nice but I don't see how to add physical simulation to kinematic'ed points.

Well I only really wanted to cover the basics here. I was going to mention at the bottom that you can assemble heirarchies from points, and use parent/child style labeling and put it into some sort of assesment function to see which one/s should be affected.

Thats where it starts to get complecated, I've only really experimented with stuff like that.

Response to AS:Constant Distance 2005-10-01 08:17:15

Nice tutorial, I might have a go at making something later. I'm impressed.

<3

Sup, bitches :) Response to AS:Constant Distance 2005-10-01 09:03:31

Yeah I origionally made a kinematics tutorial but my fucking computer crashed (again) and I lost it all

Response to AS:Constant Distance 2005-10-01 09:04:35

At 10/1/05 09:03 AM, Ninja-Chicken wrote: Yeah I origionally made a kinematics tutorial but my fucking computer crashed (again) and I lost it all

Yeah I felt bad for you while writing it <3

This one is Dedicated to NC's lost tut.

Response to AS:Constant Distance 2005-10-01 09:06:05

At 10/1/05 09:04 AM, T-H wrote:
At 10/1/05 09:03 AM, Ninja-Chicken wrote: Yeah I origionally made a kinematics tutorial but my fucking computer crashed (again) and I lost it all
Yeah I felt bad for you while writing it <3

This one is Dedicated to NC's lost tut.

lol maybe Ill make AS: Penetration (do you get it?)
no
okay Ill just go over here then

Response to AS:Constant Distance 2005-10-01 12:41:42

Very good tutorial. The diagrams are what did it for me. As people have already said this could be the start of NG's own ragdoll physics. I'm going to add some code for limiting the range of motion (ie set a limiting angle) between the two points and either write another tutorial or just spit the code back out in a FOSS. I have two full post it notes of little things like this I've been meaning to do though so no guarentees about a time frame. Damn, another thing I've been meaning to do is an AS: Kinematics like ninja mentioned. Or if I really want to kill myself AS: Newtonian Mechanics. Anyway, good tutorial and I hope I can add to it sometime soonish.

Response to AS:Constant Distance 2005-10-01 12:55:32

At 10/1/05 12:41 PM, BleeBlap wrote: Very good tutorial.........

That would be great, I'm no master of this stuff, I've not tried limiting angles yet, but build a heirarchy of points into half a doll.

A more advanced version of this would be extremely cool, "newtonian mechanics" heh, has me enthraled already.

And yeah I think this would be undesipherable without the diagram, thats why I linked to it about every other line heh.

Thanks

Response to AS:Constant Distance 2005-10-02 15:25:09

Well I made some progress. link At the moment the heiarchy is hardcoded and I'm going to convert it all to loops, draw a few diagrams and write a follow up tut but I thought I would post and ask for some suggestions first.

Response to AS:Constant Distance 2005-10-03 13:27:40

At 10/2/05 03:25 PM, BleeBlap wrote: thought I would post and ask for some suggestions first.

None as such, looking good so far.

If you can anchor the leftmost point then you will have yourself an arm

Response to AS:Constant Distance 2005-10-03 13:29:04

This actually rocks. GREAT tutorial man.

You learn something new every day.

*Bookmarked*

"Actually, the server timed out trying to remove all your posts..."

-TomFulp

Response to AS:Constant Distance 2005-12-15 08:49:35

How do you make both points dragable?

Response to AS:Constant Distance 2005-12-15 09:12:23

At 12/15/05 08:49 AM, Creeepy wrote: How do you make both points dragable?

anyone?

i dont think many gonna see this, so i might make a new topic about it or something! i mean... Come On guys!

Response to AS:Constant Distance 2005-12-15 09:22:47

You would have to do something like:

var hypotenuse:Number = 170;
onEnterFrame = function() {
xDist = dragee._x - dragger._x;
yDist = dragee._y - dragger._y;
angle = Math.atan2 (yDist, xDist);
dragee._x = dragger._x + (Math.cos (angle) * hypotenuse);
dragee._y = dragger._y + (Math.sin (angle) * hypotenuse);
};
point1_mc.onPress = function() {
this.startDrag();
dragger = this;
dragee = point2_mc;
};
point2_mc.onPress = function() {
this.startDrag();
dragger = this;
dragee = point1_mc;
};
point1_mc.onRelease = point2_mc.onRelease = function() {
stopDrag();
}; Response to AS:Constant Distance 2005-12-15 09:35:56

At 12/15/05 09:22 AM, Santazien wrote: You would have to do something like:

var hypotenuse:Number = 170;
onEnterFrame = function() {
xDist = dragee._x - dragger._x;
yDist = dragee._y - dragger._y;
angle = Math.atan2 (yDist, xDist);
dragee._x = dragger._x + (Math.cos (angle) * hypotenuse);
dragee._y = dragger._y + (Math.sin (angle) * hypotenuse);
};
point1_mc.onPress = function() {
this.startDrag();
dragger = this;
dragee = point2_mc;
};
point2_mc.onPress = function() {
this.startDrag();
dragger = this;
dragee = point1_mc;
};
point1_mc.onRelease = point2_mc.onRelease = function() {
stopDrag();
};

thank you ( but my engine still doesnt look exactly like i wanted!)
take alook here: http://img234.images..gintolooknice2wi.swf

Response to AS:Constant Distance 2005-12-15 12:18:13

nice tut, but i prefer the non trigonometry approach to IK, its faster although depending on your knowledge, possible more or less complicated

the trigometric approach here takes the angle between the two points, and then using sine and cosine finds the new position

the vector approach takes the vector between the two points, normalizes it, then scales it to the required distance to find the new position

xd = x1-x2; //where x1 is the x-coordinate of the parent point and x2 is of the point being moved
yd = y1-y2; //where y1 is the y-coordinate of the parent point and y2 is of the point being moved
d = Math.sqrt(xd*xd+yd*yd);
xd = (xd/d)*(d-5);
yd = (yd/d)*(d-5);
x2 += xd;
y2 += yd;

the advantages of this other the trigometric method is its faster

trig. method: atan2, sin, cos for each point
vec. method: sqrt for each point

id draw an image but i cant be bothered, basicly, its a way of finding out how much the point has to move along the x and y axis to be withing 5 pixels of the other point without using trigonometry, you can obviously change the '5' to however far the point should be Response to AS:Constant Distance 2005-12-16 05:18:13

I didnt really read it properly so I dont know if this is basically what you are doing but...

The other day I had an idea for this. I though if I calculated distance then if it wasnt the exact distance I wanted then I could make the second ball move towards it. So I came up with this

onClipEvent (enterFrame) {
while (Math.round (Math.sqrt(Math.pow(_root.b1._x-this._x, 2)+Math.pow(_root.b1._y-this._y, 2)))>100) {
ang = Math.atan2(this._x-_root.b1._x, this._y-_root.b1._y);
this._x -= Math.sin(ang);
this._y -= Math.cos(ang);
}
while (Math.round (Math.sqrt(Math.pow(_root.b1._x-this._x, 2)+Math.pow(_root.b1._y-this._y, 2)))<100) {
ang = Math.atan2(this._x-_root.b1._x, this._y-_root.b1._y);
this._x += Math.sin(ang);
this._y += Math.cos(ang);
}
}

The same effect.

Dont know how useful this is but I thought I'd post it

Response to AS:Constant Distance 2005-12-16 05:27:01

At 12/15/05 12:18 PM, -dELta- wrote: ...

Basically Pythagors then? I tried that way once, but it doesnt work very well for movement on slopes by two linked objects, but it is indeed a lot less intense and far simpler.

And NC, yeah that was pretty much the same but with less variables.

Response to AS:Constant Distance 2005-12-16 05:31:53

yeah cool

Also check this out

make a symbol and give it linkage name "ball"

add this to frame 1

for (i=0; i<21; i++) {
_root.attachMovie("ball", "b"+i, i, {_x:200, _y:200, parent:i+1, dist:10});
_root["b"+i].onEnterFrame = function() {
while (Math.round(Math.sqrt(Math.pow(_root["b"+t
his.parent]._x-this._x, 2)+Math.pow(_root["b"+this.parent]._y-this
._y, 2)))>this.dist) {
this.ang = Math.atan2(this._x-_root["b"+this.parent].
_x, this._y-_root["b"+this.parent]._y);
this._x -= Math.sin(this.ang);
this._y -= Math.cos(this.ang);
}
while (Math.round(Math.sqrt(Math.pow(_root["b"+t
his.parent]._x-this._x, 2)+Math.pow(_root["b"+this.parent]._y-this
._y, 2)))<this.dist) {
this.ang = Math.atan2(this._x-_root["b"+this.parent].
_x, this._y-_root["b"+this.parent]._y);
this._x += Math.sin(this.ang);
this._y += Math.cos(this.ang);
}
};
}
_root.attachMovie("ball", "b"+21, 21, {_x:500, _y:200});
_root.b21.onPress = function() {
this.startDrag(true);
};
_root.b21.onRelease = function() {
this.stopDrag ()
};

Does it lag for anyone??