Flash/flex Study Notes (40): elastic movement-spring

Source: Internet
Author: User

After the elastic movement and friction factors demonstrated in the previous article, the object will basically stop at the target position accurately. But let's look back at the springs in the real world. If one end of the spring is fixed (that is, equivalent to the target point), and the other end is tied with a ball, the ball is opened or compressed to a certain distance, and then let it go, in fact, the ball will never reach the Fixed End of the spring (because even if the spring is compressed to the most tight, there will always be a certain length)

So if you want to simulate the actual spring in flash, the actual target point is not the spring endpoint, but the target point is shifted to a distance (that is, the length of the spring when it is naturally stretched)

VaR ball: ball = new ball (6); addchild (ball); ball. y = 20; ball. X = 20; var targetx: Number = stage. stagewidth/2; var targety: Number = ball. y; var springlength = 100; // spring length var spring = 0.2; // elasticity coefficient var friction = 0.92; // friction coefficient // draw guides, to better understand graphics. linestyle (0.5, 0 xaaaaaa); graphics. moveTo (ball. x, ball. y); graphics. lineto (stage. stageWidth-ball.x, ball. y); graphics. moveTo (targetx, targetY-10); graphics. lineto (targetx, targety + 10); graphics. moveTo (targetx-springlength, targetY-8); graphics. lineto (targetx-springlength, targety + 8); var rect: rectangle = new rectangle (ball. x, ball. y, stage. stageWidth-ball.x * 2, 0); addeventlistener (event. enter_frame, enterframehandler); ball. addeventlistener (mouseevent. mouse_down, mousedownhandler); stage. addeventlistener (mouseevent. mouse_up, mouseuphandler); function enterframehandler (E: Event): void {ball. VX + = (targetx-springlength-ball. x) * spring; ball. VX * = friction; ball. X + = ball. VX;} function mousedownhandler (E: mouseevent): void((e.tar get as sprite ). startdrag (true, rect); removeeventlistener (event. enter_frame, enterframehandler);} function mouseuphandler (E: mouseevent): void {ball. stopdrag (); addeventlistener (event. enter_frame, enterframehandler);} ball. addeventlistener (mouseevent. mouse_out, function () {mouse. cursor = mousecursor. auto}); ball. addeventlistener (mouseevent. mouse_over, function () {mouse. cursor = mousecursor. hand });

Taking the two-dimensional coordinate spring movement into account, it is a little more complicated:

VaR ball: ball = new ball (10); addchild (ball); ball. y = 20; ball. X = 20; var targetx: Number = stage. stagewidth/2; var targety: Number = stage. stageheight/2; var springlength: uint = 100; // spring length var spring: Number = 0.2; // elasticity coefficient var friction: Number = 0.92; // friction coefficient var angle: number = 0; addeventlistener (event. enter_frame, enterframehandler); ball. addeventlistener (mouseevent. mouse_down, mousedownhandler); stage. addeventlistener (mouseevent. mouse_up, mouseuphandler); stage. addeventlistener (mouseevent. mouse_move, function () {drawline ()}); angle = math. atan2 (targety-ball. y, targetx-ball. x); // determine the angle trace (angle * 180/math. pi); function enterframehandler (E: Event): void {ball. VX + = (targetx-springlength * Math. cos (angle)-ball. x) * spring; // adjust the target point Ball. vy + = (targety-springlength * Math. sin (angle)-ball. y) * spring; ball. VX * = friction; ball. vy * = friction; ball. X + = ball. VX; ball. Y + = ball. vy; drawline ();} function drawline (): void {graphics. clear (); graphics. linestyle (1); graphics. moveTo (targetx, targetY-10); graphics. lineto (targetx, targety + 10); graphics. moveTo (targetX-10, targety); graphics. lineto (targetx + 10, targety); graphics. moveTo (targetx, targety); graphics. linestyle (0.5, 0 xaaaaaa); graphics. lineto (ball. x, ball. y);} function mousedownhandler (E: mouseevent): void((e.tar get as sprite ). startdrag (true); removeeventlistener (event. enter_frame, enterframehandler);} function mouseuphandler (E: mouseevent): void {ball. stopdrag (); addeventlistener (event. enter_frame, enterframehandler);} ball. addeventlistener (mouseevent. mouse_out, function () {mouse. cursor = mousecursor. auto}); ball. addeventlistener (mouseevent. mouse_over, function () {mouse. cursor = mousecursor. hand });

In the above example, the moving direction (angle) is fixed with the target point. If it is changed to dynamic (such as the current location of the mouse), the effect may be more realistic.

Function enterframehandler (E: Event): void {targetx = mousex; // change to dynamic target targety = Mousey; angle = math. atan2 (targety-ball. y, targetx-ball. x); // dynamic angle ball. VX + = (targetx-springlength * Math. cos (angle)-ball. x) * spring; ball. vy + = (targety-springlength * Math. sin (angle)-ball. y) * spring; ball. VX * = friction; ball. vy * = friction; ball. X + = ball. VX; ball. Y + = ball. vy; drawline ();}

If the two objects are elastically moving based on the position of the other object and the spring length and boundary detection are taken into account, as3 can be used to simulate a very realistic spring model:

var ball_1:Ball = new Ball(10,0xff0000);var ball_2:Ball = new Ball(10,0x0000ff);ball_1.x = stage.stageWidth * Math.random();ball_1.y = stage.stageHeight * Math.random();ball_2.x = stage.stageWidth/2;ball_2.y = stage.stageHeight/2;addChild(ball_1);addChild(ball_2);var spring:Number = 0.1;var springLength:uint = 100;var friction:Number = 0.9;var darggingBall:Ball;addEventListener(Event.ENTER_FRAME,EnterFrameHandler);ball_1.addEventListener(MouseEvent.MOUSE_DOWN,MouseDownHandler);ball_2.addEventListener(MouseEvent.MOUSE_DOWN,MouseDownHandler);stage.addEventListener(MouseEvent.MOUSE_UP,MouseUpHandler);stage.addEventListener(MouseEvent.MOUSE_MOVE,function(){DrawLine();});ball_1.addEventListener(MouseEvent.MOUSE_OVER,MouseOverHandler);ball_1.addEventListener(MouseEvent.MOUSE_OUT,MouseOutHandler);ball_2.addEventListener(MouseEvent.MOUSE_OVER,MouseOverHandler);ball_2.addEventListener(MouseEvent.MOUSE_OUT,MouseOutHandler);function MouseOutHandler(e:MouseEvent){Mouse.cursor = MouseCursor.AUTO;}function MouseOverHandler(e:MouseEvent){Mouse.cursor = MouseCursor.HAND;}function MouseDownHandler(e:MouseEvent):void{(e.target as Sprite).startDrag(true,new Rectangle(20,20,stage.stageWidth-40,stage.stageHeight-40));darggingBall = e.target as Ball;removeEventListener(Event.ENTER_FRAME,EnterFrameHandler);}function MouseUpHandler(e:MouseEvent):void{if (darggingBall!=null){darggingBall.stopDrag();darggingBall = null;addEventListener(Event.ENTER_FRAME,EnterFrameHandler);}}function EnterFrameHandler(e:Event):void{var dx1 = ball_2.x -ball_1.x;var dy1 = ball_2.y -ball_1.y;var angle1:Number = Math.atan2(dy1,dx1);ball_1.vx += (ball_2.x - springLength * Math.cos(angle1) - ball_1.x) * spring;ball_1.vy += (ball_2.y - springLength * Math.sin(angle1) - ball_1.y) * spring;ball_1.vx *= friction;ball_1.vy *= friction;ball_1.x += ball_1.vx;ball_1.y += ball_1.vy;var dx2 = ball_1.x -ball_2.x;var dy2 = ball_1.y -ball_2.y;var angle2:Number = Math.atan2(dy2,dx2);ball_2.vx += (ball_1.x - springLength * Math.cos(angle2) - ball_2.x) * spring;ball_2.vy += (ball_1.y - springLength * Math.sin(angle2) - ball_2.y) * spring;ball_2.vx *= friction;ball_2.vy *= friction;ball_2.x += ball_2.vx;ball_2.y += ball_2.vy;DrawLine();CheckBoundary(ball_1);CheckBoundary(ball_2);}function DrawLine():void{graphics.clear();graphics.lineStyle(0.5,0x666666);graphics.moveTo(ball_1.x,ball_1.y);graphics.lineTo(ball_2.x,ball_2.y);}function CheckBoundary(b:Ball){if (b.x>stage.stageWidth-b.width/2 || b.x<=b.width/2){b.x -= b.vx;b.vx *= -1;}if (b.y>stage.stageHeight-b.height/2 || b.y<=b.height/2){b.y -= b.vy;b.vy *= -1;}}

If you are playing crazy, put more balls and set the second to the first and the third to the second... the last one takes the first one as the target and forms a ring like this:

VaR spring: Number = 0.1; var springlength: uint = 150; var friction: Number = 0.8; // friction var darggingball: ball; var ballnumber: uint = 3; // Number of balls var arrbballs: array = new array (ballnumber); For (var I: uint = 0, j = arrbballs. length; I <j; I ++) {arrbballs [I] = new ball (20, math. random () * 0 xffffff); VaR _ ball: ball = arrbils [I]; _ ball. X = stage. stagewidth * Math. random (); _ ball. y = stage. stageheight * Math. random (); addchild (_ ball); _ ball. add Eventlistener (mouseevent. mouse_over, mouseoverhandler); _ ball. addeventlistener (mouseevent. mouse_out, mouseouthandler); _ ball. addeventlistener (mouseevent. mouse_down, mousedownhandler);} addeventlistener (event. enter_frame, enterframehandler); stage. addeventlistener (mouseevent. mouse_up, mouseuphandler); stage. addeventlistener (mouseevent. mouse_move, function () {drawline () ;}); // switch the cursor function mouseouthandler (E: Mouse Event) {mouse. cursor = mousecursor. auto;} // switch the cursor function mouseoverhandler (E: mouseevent) {mouse. cursor = mousecursor. hand;} // start to drag function mousedownhandler (E: mouseevent): void (e.tar get as sprite ). startdrag (true, new rectangle(20,20,stage.stagewidth-40,stage.stageheight-40?#darggingball=e.tar get as ball; removeeventlistener (event. enter_frame, enterframehandler);} // drag the end function mouseuphandler (E: mouseevent ): Void {If (darggingball! = NULL) {darggingball. stopdrag (); darggingball = NULL; addeventlistener (event. enter_frame, enterframehandler) ;}} function enterframehandler (E: Event): void {for (var I: uint = 0, j = arrbils. length-1; I <j; I ++) {springto (arrbils [I], arrbils [I + 1]);} springto (arrbils [arrbils. length-1], arrbils [0]); drawline (); for (I = 0, j = arrbils. length; I <j; I ++) {checkboundary (arrbils [I]) ;}// draw the function drawline (): void {graphics. clear (); graphics. linestyle (0.5, 0x666666); // graphics. moveTo (ball_1.x, ball_1.y); // graphics. lineto (ball_2.x, ball_2.y); For (var I: uint = 0, j = arrbils. length-1; I <j; I ++) {graphics. moveTo (arrbils [I]. x, arrbils [I]. y); graphics. lineto (arrbils [I + 1]. x, arrbils [I + 1]. y);} graphics. lineto (arrbils [0]. x, arrbils [0]. y);} // function springto (targetball: ball, moveball: ball): void {var DY = targetball. y-moveBall.y; var dx = targetball. x-moveBall.x; var angle1: Number = math. atan2 (dy, dx); moveball. VX + = (targetball. x-springlength * Math. cos (angle1)-moveball. x) * spring; moveball. vy + = (targetball. y-springlength * Math. sin (angle1)-moveball. y) * spring; moveball. VX * = friction; moveball. vy * = friction; moveball. X + = moveball. VX; moveball. Y + = moveball. vy;} // check the boundary function checkboundary (B: ball) {If (B. x> stage. stageWidth-b.width/2 | B. x <= B. width/2) {B. x-= B. VX; B. VX * =-1;} If (B. y> stage. stageHeight-b.height/2 | B. Y <= B. height/2) {B. y-= B. vy; B. vy * =-1 ;}}

Think about it: Why is this not an endless loop?

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.