Monday, 2 August 2010

Click and drag rotation in Flash AS2

In Flash I often find that some things which seem hard, are easy, and some things which ought to be easy are hard. Making things rotate when you click and drag them is, for me, one of the latter. It doesn't take much code, but figuring the code out hurt my brain.

You'd think this would be easier - you'd think there would be a class already in existence for this. But as there isn't here's an ActionScript 2 solution.

The Script With Comments

The comments explain how it works:

/*sets starting points for the maths that comes later*/
var objectnewdeg = 0;
var objectdeg = 0;
/* This is the Rotate Object function, it updates the rotation of the object continuously as the user drags */
rotateobject = function () {
    curpoint = (Math.atan2(_root._ymouse-_root.object_mc._y, _root._xmouse-_root.object_mc._x)/Math.PI)*180;
    objectnewdeg = objectdeg+(curpoint-objectstartdeg);
    _root.object_mc._rotation = objectnewdeg;
};
/* This initiates the
Rotate Object function when the user clicks on the object */
_root.object_mc.onPress = function() {
    /* This finds the position around the object that is first clicked in degrees and sets it as a variable that is used in the function above */
    objectstartdeg = (Math.atan2(_root._ymouse-_root.object_mc._y, _root._xmouse-_root.object_mc._x)/Math.PI)*180;
    /* starts the function above and sets the repeat frequency as 10 */
    objectrotInterval = setInterval(rotateobject, 10);
};
/* This stops the
Rotate Object function when the user releases the object, so it stays where the user left it, then records the new rotation of the object as objectdeg ready for when it is rotated again. */
_root.object_mc.onRelease = function() {
    /* stops the function above */
    clearInterval(objectrotInterval);
    /*records the new rotation of the object as set by the user's drag as variable objectdeg, ready for next time they drag */
    objectdeg = objectnewdeg;
};
/* This is almost a repeat of the release code above, but takes account of the fact the user might drift off the object when they drag it, hence onReleaseOutside. */
_root.object_mc.onReleaseOutside = function() {
    /* stops the function above */
    clearInterval(objectrotInterval);
    /* records the new rotation of the object as set by the user's drag as variable objectdeg, ready for next time they drag */
    objectdeg = objectnewdeg;
};



The Script Without Comments

And if that code above looks scary, it's not so bad without comments - only 19 lines.

var objectnewdeg = 0;
var objectdeg = 0;
rotateobject = function () {
curpoint = (Math.atan2(_root._ymouse-_root.object_mc._y, _root._xmouse-_root.object_mc._x)/Math.PI)*180;
objectnewdeg = objectdeg+(curpoint-objectstartdeg);
_root.object_mc._rotation = objectnewdeg;
};
_root.object_mc.onPress = function() {
objectstartdeg = (Math.atan2(_root._ymouse-_root.object_mc._y, _root._xmouse-_root.object_mc._x)/Math.PI)*180;
objectrotInterval = setInterval(rotateobject, 10);
};
_root.object_mc.onRelease = function() {
clearInterval(objectrotInterval);
objectdeg = objectnewdeg;
};
_root.object_mc.onReleaseOutside = function() {
clearInterval(objectrotInterval);
objectdeg = objectnewdeg;
};


Copy and paste the code into the first frame. Then place a MovieClip on the stage and give it the instance name 'object_mc'.

Test the movie and you should be able to click the object anywhere and drag it to rotate it.

The centre of rotation is the Registration point that you set when you made the object into a MovieClip.

If you want to re-use the code yourself, just replace every instance of the name object_mc with the instance name of your object.

Try It



Applying it to something useful

I originally developed this for use with my VirtualCompass teaching aid This uses drag rotation to allow the user to position several different elements on the screen.

7 comments:

  1. Great post, I have been looking for that...

    -Regards
    Bennett

    ReplyDelete
  2. thaks, nice post.

    ReplyDelete
  3. How can Add momentum to the rotation? Like the "Drag and drop (with momentum) tutorial? Please help.

    ReplyDelete
  4. How can i add momentum to the rotation?

    ReplyDelete
  5. Hi Vishal, interesting question. I don't have time to answer this in full at the moment, but the logic is this.

    While dragging you need to test the rotation angle at intervals and compare current angle with previous angle last time you tested. This will give you a value to use as a "velocity" of rotation.

    Once you have this when the dragging is stopped you simply continue the rotation going at the same value as your last test, each interval. You add friction by dividing the rotation value by a friction factor on each interval until it becomes zero. Use an IF to test when it is nearly zero, make it actually zero and cancel the interval.

    Something like that. Maybe I will have time to make this code soon, but give it a try if possible.

    ReplyDelete
  6. Anonymous29/7/12 21:35

    Hi, I'm making a poseable mannequins. Will it work on different parts of the body or just one object?

    ReplyDelete
  7. Hi Anonymous,

    The code I have written will work with only one object, but if you repeat the code as a block, specifying a different _root.object_mc with each code repetition you could use it to provide rotation for any number of objects. Think of the code as the engine for rotating one object. If you add a second object, repeat the code, but change the _root.object_mc name to match the instance name of the second object, and so on for all objects.

    The alternative is to use some object oriented approach, but that would mean a rewrite. So this is the easiest way to simply reuse the existing code for what you need. Good luck :-)

    ReplyDelete