Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...
lgeis

Technique: Combine ThrowPropsPlugin, TransformAroundPoint Plugin

Recommended Posts

Greetings from Beautiful Boise!

 

I have some playing card (rectangular) MovieClips on the Stage.

 

I want to startDrag() them via MOUSE_DOWN, and stopDrag() them via MOUSE_UP, measuring the speed of the motion and decaying it via ThrowPropsPlugin.

 

Easy enough, and that's complete/fully functional.

 

But what I'd also like to do is have the rectangle respond to the direction of motion by rotating around the mouseX and mouseY point so that it is drug behind the cursor until MOUSE_UP. I have tried the RotateAroundPointPlugin and cannot seem to configure it properly. I can trace() the proper x and y (the local x & y of the Rectangle MC vice the global x & y on the Stage), and I can get appropriate atan2() traces as well...but the doggone rectangle won't rotate properly when being drug.

 

I've got all of the physics for the drag & throw successfully coded, but cannot recognize a way to get the rectangle to properly follow the cursor.

 

Any thoughts or suggestions...?

 

Thanks!

Leo

 

//Variables

 

var x1:int;

var y1:int;

var time1:Number;

var time2:Number;

var xVelocity:Number;

var yVelocity:Number;

var throwAngleDegs:Number;

var grabPoint:Point = new Point();

var rotatePoint:Point = new Point();

 

//Card Event Listeners & Functions

cardA.addEventListener(MouseEvent.MOUSE_DOWN, dragCard, false, 0, true);

cardA.addEventListener(MouseEvent.MOUSE_UP, throwCard, false, 0, true);

 

//Dragging Function

function dragCard(e:MouseEvent):void {

Mouse.cursor = MouseCursor.HAND;

TweenLite.killTweensOf(cardA);

this.addChild(cardA);

x1 = cardA.x;

y1 = cardA.y;

time1 = getTimer()

cardA.startDrag(false, dragBoundsRectangle);

rotateCard();

}

 

//Throwing Function

function throwCard(e:MouseEvent):void {

Mouse.cursor = MouseCursor.AUTO;

cardA.stopDrag();

time2 = (getTimer() - time1)/1000;

xVelocity = (cardA.x - x1) / time2;

yVelocity = (cardA.y - y1) / time2;

TweenLite.to(cardA, 3, {throwProps:{x: {velocity: xVelocity, max: 400, min: 150}, y: {velocity:

yVelocity, max: 300, min: 100}}});

}

 

function rotateCard():void {

throwAngleDegs = (Math.atan2(y1 - mouseY, x1 - mouseX) * 180/Math.PI);

//Find the cursor "grab point" in the card (rectangle) Object...

grabPoint.x = mouseX;

grabPoint.y = mouseY;

//Establish a point of rotation based on the cursor's "grab point" in the card (rectangle)...

rotatePoint = cardA.globalToLocal(grabPoint);

//Tween the rotation so that the card (rectangle) "follows" the drag. This will then be adapted into an

//ENTER_FRAME so that it constantly updates during dragging...

TweenLite.to(cardA, .2, {transformAroundPoint: {point: cardA.globalToLocal(rotatePoint), rotation:

throwAngleDegs}});

}

Link to post
Share on other sites

Looking around-just a thought in pseudocode:

 

angleDegs = atan2(mouseY - cardY, mouseX - cardX);

var angleRads = angleDegs * Math.PI/180

TweenLite.to (card, .5, {rotation: angleDegs});

 

I'll look more into RotateAroundPointPlugin in a bit. Any advice welcome.

 

Thanks!

Leo

Link to post
Share on other sites

It's tough to visualize exactly what's happening or not happening without having a sample .fla file to publish, but I'll throw out a few tips that might get you on your way:

  1. By default, the transformAroundPoint expects a point that is in the target object's parent coordinate system. If you prefer to feed it one in its local coordinates (like the point is INSIDE the target), you can set pointIsLocal:true inside the transformAroundPoint object. Your code looked like it was defining a local point but you forgot to put the pointIsLocal flag in there.
  2. Your code looked like it was translating TWICE - you used globalToLocal() and got that point and did another globalToLocal() on it. That'll definitely mess up the results. Just do it once :)
  3. Your code above (in your second post, not your first) looks like it's defining the rotation in radians instead of degrees.

For more info on the transformAroundPoint plugin, see http://api.greensock.com/as/com/greensock/plugins/TransformAroundPointPlugin.html

 

Does that help?

  • Like 1
Link to post
Share on other sites

Jack, I've found a couple of examples of the behaviors I'd like to TweenLite/TweenMax.

 

Here's the first example: http://www.myflashxml.com/dynamic_photo_gallery/friction/index.html

 

In that first example there is an elasticity that may or may not be necessary.

 

Here's another example: http://www.sideroller.com/wck/

 

In the second example, the top Flash Window is a Box2D demo. The first demo has a bunch of shapes on Stage, which you can Click & Drag-they exhibit similar physics.

 

The Object follows the Cursor as it should via startDrag(), but the Object responds to the Point at which the Cursor clicks and when it is drug, it simulates inertia: it aligns along the motion of the drag.

 

Also, I do apologize for activating a Plugin twice in my code earlier...I'm sure this obligates me to purchase two GreenSock memberships! Ha!

Link to post
Share on other sites

Yes, duplicate plugin activations require additional licensing fees. Ha ha. :P

 

As for rotating your object in the direction of movement, that should be as simple as using an ENTER_FRAME handler (or timer or something like that) and compare the new mouse position to the old one, using Math.atan2() to get the angle and feed that into a rotation tween. If you want the mouse to be the pivot point, you'd need to manually just reposition the object on each frame so that the same spot on the Sprite/MovieClip is where the mouse pointer is. Let the tween handle the rotation, and you use localToGlobal() and globalToLocal() to translate the spot inside the Sprite to the coordinates on the parent DisplayObjectContainer where you'd position the Sprite. In fact, it might actually be easier to wrap it in another Sprite and reposition it on MOUSE_DOWN so that visually nothing changes, but behind the scenes you're moving the registration point of the container Sprite to exactly where the mouse is and offsetting the child Sprite to compensate visually.

 

I hope that helps!

Link to post
Share on other sites

Well Jack, I guess we've just run into my own personal brick wall.

 

BTW...I can't find a ShortRotationPlugin syntax for use with the RotateAroundPointPlugin in the documentation-but am not sure it could be used anyway.

 

Here's the code (.fla). Everything works great except the Rotation (lines 72 & 73 below). Would you accept a feature request for a RotateAroundCursorPlugin with a LocalPoint Parameter? Ha!

 

If there's something I'm doing wrong relative to the greensock stuff and it's obvious and no bother, let me know, please.

 

//imports/activations/initializations
import com.greensock.TweenLite;
import com.greensock.easing.Quad;
import com.greensock.plugins.TweenPlugin;
import com.greensock.plugins.BlurFilterPlugin;
import com.greensock.plugins.MotionblurPlugin;
import com.greensock.plugins.ThrowPropsPlugin;
import com.greensock.plugins.ShortRotationPlugin;
import com.greensock.plugins.TransformMatrixPlugin;
import com.greensock.plugins.TransformAroundPointPlugin;
import com.greensock.OverwriteManager;
import flash.geom.Point;
import flash.events.Event;
TweenPlugin.activate([blurFilterPlugin, MotionblurPlugin, ThrowPropsPlugin, ShortRotationPlugin, TransformMatrixPlugin, TransformAroundPointPlugin]);
OverwriteManager.init(OverwriteManager.AUTO);
TweenLite.defaultEase = Quad.easeOut;
//dragBounds
var dragBoundsWidth:int = 500;
var dragBoundsHeight:int = 350;
var dragBoundsX:int = 25;
var dragBoundsY:int = 25;
var dragBoundsRectangle:Rectangle = new Rectangle(dragBoundsX, dragBoundsY, dragBoundsWidth, dragBoundsHeight);
//Variables
var x1:int;
var y1:int;
var time1:Number;
var time2:Number;
var xVelocity:Number;
var yVelocity:Number;
var throwAngleDegs:Number;
var grabPointA:Point = new Point();
var grabPointB:Point = new Point();
var rotatePointLocal:Point = new Point();
var rotatePointGlobal:Point = new Point();
//buttonMode/cursors
cardA.buttonMode = true;
cardA.addEventListener(MouseEvent.MOUSE_OVER, buttonCursor, false, 0, true);
cardA.addEventListener(MouseEvent.MOUSE_OUT, normalCursor, false, 0, true);
function buttonCursor(e:MouseEvent):void {
Mouse.cursor = MouseCursor.BUTTON;
}
function normalCursor(e:MouseEvent):void {
Mouse.cursor = MouseCursor.AUTO;
}
//Card Event Listeners & Functions
cardA.addEventListener(MouseEvent.MOUSE_DOWN, dragCard, false, 0, true);
cardA.addEventListener(MouseEvent.MOUSE_UP, throwCard, false, 0, true);
function dragCard(e:MouseEvent):void {
TweenLite.killTweensOf(cardA, false);
Mouse.cursor = MouseCursor.HAND;
x1 = cardA.x;
y1 = cardA.y;
time1 = getTimer();
grabPointA.x = stage.mouseX;
grabPointA.y = stage.mouseY;
rotatePointLocal = cardA.globalToLocal(grabPointA);
cardA.startDrag(false, dragBoundsRectangle);
cardA.addEventListener(Event.ENTER_FRAME, rotateCard, false, 0, true);
}
function throwCard(e:MouseEvent):void {
Mouse.cursor = MouseCursor.AUTO;
cardA.stopDrag();
time2 = (getTimer() - time1)/1000;
xVelocity = (cardA.x - x1) / time2;
yVelocity = (cardA.y - y1) / time2;
TweenLite.to(cardA, 2.5, {throwProps:{x: {velocity: xVelocity, max: 400, min: 150}, y: {velocity: yVelocity, max: 300, min: 100}}});
}
function rotateCard(e:Event):void {
grabPointB.x = stage.mouseX;
grabPointB.y = stage.mouseY;
throwAngleDegs = (Math.atan2(grabPointB.y - grabPointA.y, grabPointB.x - grabPointA.x) * 180/Math.PI);
TweenLite.to(cardA, 0, {transformAroundPoint: {point: rotatePointLocal,
 pointIsLocal: true, rotation: -throwAngleDegs}, onComplete: stopAnimation});
}
function stopAnimation (e:Event):void {
cardA.removeEventListener(Event.ENTER_FRAME, rotateCard);
}

Link to post
Share on other sites

I think the problem was that your code relies on the TransformAroundPointPlugin adjusting the pivot point on-the-fly for pointIsLocal:true tweens, but the plugin wasn't set up for that. However, I just posted an update that should accommodate that behavior. Please download the latest version of the bonus plugin (in v12) and try again. https://www.greensock.com/account/

Link to post
Share on other sites

Well, Jack-thanks very much for your very gracious help, but this is one I'm going to have to abandon. I'm just not able to "get it," I guess. Maybe over the New Year when I have some spare time I'll dive in just for grins-and if I do stumble into a solution I'll forward it on... Happy New Year!

Link to post
Share on other sites

So the revised version of the TransformAroundPoingPlugin didn't help you? I thought for sure that's resolve the issue you were running into. What am I missing?

Link to post
Share on other sites

Oh-goodness, I don't think you're missing anything. It's much more likely that my comprehension is flawed. I'm trying to establish a rotation point using offsets from the Registration point to gain some understanding into the matter. I don't want to be a high-maintenance subscriber... Am spending a bit of time working out various potentials. Will certainly post it up if I can engineer a solution... Thanks! L

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

×