Throw a ball with a sling physics Flash tutorial: Part 2 by Kevin Ward

Only 2 days. That's how much time Kevin Ward needed to solve and publish the solution of the problem posted in Throw a ball with a sling physics Flash tutorial.

You may know Kevin for his excellent post about a different approach to create a game like Line Rider, and now he come with the second part of the sling tutorial.

Take your honour, Kevin, you deserve it!!

This is the movie Kevin created:

And this is the actionscript, with comments in some critical parts:

ACTIONSCRIPT:
  1. var ball:MovieClip = _root.attachMovie("ball", "ball", 2, {_x:250, _y:100});
  2. var elastic:MovieClip = _root.createEmptyMovieClip("elastic", 1);
  3. var point1:MovieClip = _root.attachMovie("sling", "point1", 3, {_x:50, _y:200});
  4. var point2:MovieClip = _root.attachMovie("sling", "point2", 4, {_x:450, _y:200});
  5. var gravity = 0.1;
  6. var angle1:Number = 0;
  7. var angle2:Number = 0;
  8. var radius:Number = 13.0;
  9. // Or whatever half the width of your ball is.
  10. var elasticCoefficient:Number = 0.001;
  11. // This number will affect the stretchiness of the sling.  The greater the number
  12. // the tighter the elastic will be.     
  13. var released:Boolean = true;
  14. var forced:Boolean = false;
  15. var acc:Object = {x:0, y:0};
  16. var vel:Object = {x:0, y:0};
  17. _root.onMouseDown = function() {
  18.     ball._x = _root._xmouse;
  19.     ball._y = _root._ymouse;
  20.     ball.startDrag();
  21.     _root.released = false;
  22.     vel.x = 0;
  23.     vel.y = 0;
  24. };
  25. _root.onMouseUp = function() {
  26.     ball.stopDrag();
  27.     _root.released = true;
  28. };
  29. ball.onPress = function() {
  30.     ball.startDrag();
  31.     _root.released = false;
  32.     vel.x = 0;
  33.     vel.y = 0;
  34. };
  35. ball.onRelease = function() {
  36.     ball.stopDrag();
  37.     _root.released = true;
  38. };
  39. _root.onEnterFrame = function() {
  40.     elastic.clear();
  41.     elastic.lineStyle(3, 0xFF0000);
  42.     if (released) {
  43.         ball._x += vel.x;
  44.         ball._y += vel.y;
  45.     }
  46.     if (ball._y>=187) {
  47.         /* This area differs from the code in the tutorial.
  48.         The reason for that is I didn't read the code, I just looked at the examples.
  49.         I try to gain experience with problem-solving by doing things as close to by myself as possible. */
  50.         forced = true;
  51.         var x1:Number = ball._x-point1._x;
  52.         var y1:Number = ball._y-point1._y;
  53.         var x2:Number = point2._x-ball._x;
  54.         var y2:Number = point2._y-ball._y;
  55.         var distance1:Number = Math.sqrt(x1*x1+y1*y1);
  56.         var distance2:Number = Math.sqrt(x2*x2+y2*y2);
  57.         _root.angle1 = Math.atan2(y1, x1);
  58.         _root.angle2 = Math.atan2(y2, x2);
  59.         var xOffset:Number = Math.cos(angle1+Math.PI/2)*radius;
  60.         var yOffset:Number = Math.sin(angle1+Math.PI/2)*radius;
  61.         var xOffset2:Number = Math.cos(angle2+Math.PI/2)*radius;
  62.         var yOffset2:Number = Math.sin(angle2+Math.PI/2)*radius;
  63.         angle1 += Math.sin(radius/distance1);
  64.         angle2 += Math.sin(radius/distance2)*-1;
  65.         elastic.moveTo(point1._x, point1._y);
  66.         elastic.lineTo(ball._x+xOffset, ball._y+yOffset);
  67.         elastic.moveTo(point2._x, point2._y);
  68.         elastic.lineTo(ball._x+xOffset2, ball._y+yOffset2);
  69.     } else {
  70.         forced = false;
  71.         elastic.moveTo(point1._x, point1._y);
  72.         elastic.lineTo(point2._x, point2._y);
  73.     }
  74.     acc.x = 0;
  75.     acc.y = 0;
  76.     acc.y = gravity;
  77.     if (released && forced) {
  78.         /* This section applies the force of the sling to the ball in terms of acceleration based on the stretching of
  79.         the sling, in the direction of the displacement, scaled by a coefficient that also encapsulates the mass of
  80.         the ball. */
  81.         acc.x += distance1*Math.sin(angle2)*elasticCoefficient;
  82.         acc.y += -distance1*Math.cos(angle1)*elasticCoefficient;
  83.         acc.x += distance2*Math.sin(angle1)*elasticCoefficient;
  84.         acc.y += -distance2*Math.cos(angle2)*elasticCoefficient;
  85.     }
  86.     if (released) {
  87.         vel.x += acc.x;
  88.         vel.y += acc.y;
  89.     }
  90. };

This is an excellent solution to the problem, and I think this should be an inspiration for the ball physics Flash game design competition.

Download the source and say "good work Kevin!".

Improve the blog rating this post
Tell me what do you think about this post. I'll write better and better entries.
1 Star2 Stars3 Stars4 Stars5 Stars (2 votes, average: 5 out of 5)
Loading ... Loading ...

» Flash Templates provided by Template Monster are pre-made web design products developed using Flash technology.
They can be easily customized to meet the unique requirements of your project.

8 Responses to “Throw a ball with a sling physics Flash tutorial: Part 2 by Kevin Ward”

  1. Throw a ball with a sling physics Flash tutorial at Emanuele Feronato on August 16th, 2007 10:45 am

    [...] Throw a ball with a sling physics Flash tutorial Published August 13th, 2007 in Flash. August 16th update: 2nd part released by Kevin Ward [...]

  2. Monkios on August 16th, 2007 2:55 pm

    Great Tut Kevin.

    The only problem I see from your solution is that when the ball goes on either side of the sling, the elastic automagicly goes and gets the ball making it impossible for it to fall off-screen.

    When your like if the ball’s y is lower than bot points, you should also look if it’s x is to the left of Point1 (xP2 ie: 450)

    You should also change the ball’s reference point for something else beacause if the points are not placed on y=200, your check for ball’s y = 187 will be wrong.

    The same tutorial with moveable points would be great.

  3. Matthew on August 17th, 2007 8:24 pm

    Forgive me if im wrong but because Im only 12 i don’t realy understand the maths that well. So I made a much easier way to do this which although it doesnt look exactly the same you hardly notice it.
    Below is the code (if you want to use it just copy it to the main timeline, youll need three balls in your library linkaged as ball,node1 and node2. Also center the registration points of the two nodes and for the ball choose the middles bottom one)

    //Attach some movieclips to the stage
    var node1:MovieClip = _root.attachMovie(”node1″, “node11″, 3, {_x:50, _y:350});
    var node2:MovieClip = _root.attachMovie(”node2″, “node22″, 4, {_x:650, _y:350});
    var ball:MovieClip = _root.attachMovie(”ball”, “balll”, 5, {_x:350, _y:200});
    var node2:MovieClip = _root.attachMovie(”node2″, “node22″, 4, {_x:650, _y:350});
    //The movieclips we will use as lines
    var line1:MovieClip = _root.createEmptyMovieClip(”lines1″, 1);
    var line2:MovieClip = _root.createEmptyMovieClip(”lines2″, 2);
    line1.lineStyle(2,0×000000);
    line2.lineStyle(2,0×000000);
    line1.moveTo(node1.x,node1.y);
    line1.lineTo(node2.x,node2.y);
    //Define some variables we can use later on
    var friction:Number = 0.99;
    var xspeed:Number = 0;
    var yspeed:Number = 0;
    var gravity:Number = 0.5;
    var spring:Number = 1;
    var dragging:Boolean = false;
    //These are for dragging the ball

    ball.onPress = function() {
    this.startDrag();
    yspeed = 0;
    xspeed = 0;
    gravity = 0;
    spring = 0;
    dragging = true;
    };

    ball.onRelease = function() {
    this.stopDrag();
    yspeed = 0;
    gravity = 0.5;
    spring = 1;
    dragging = false;
    };

    //When you click on one of the nodes the ball is placed back in its original position
    node1.onRelease = function() {
    _root.ball._x = 350;
    _root.ball._y = 200;
    xspeed = 0;
    yspeed = 0;
    };
    node2.onRelease = function() {
    _root.ball._x = 350;
    _root.ball._y = 200;
    xspeed = 0;
    yspeed = 0;
    };

    //The main function
    this.onEnterFrame = function() {
    //Moves the ball
    yspeed = gravity;
    ball._y = yspeed;
    xspeed *= friction;
    ball._x = xspeed;
    line1.clear();
    line2.clear();
    //If its lower than the node
    if (ball._y>node1._y) {
    //Check how far to the right and left the nodes are
    var xpos1:Number = node1._x-ball._x;
    var xpos2:Number = node2._x-ball._x;
    xpos1 = -xpos1;
    //If your not dragging the ball
    if (dragging == false) {
    //If it is further to the right than the left
    if (xpos1>xpos2) {
    //Move it to the left
    xspeed -= 0.3;
    }
    //Other way round
    if (xpos2>xpos1) {
    xspeed = 0.3;
    }
    }
    //Otherwise it would keep going down
    yspeed -= spring;
    //Draw the lines again so they are connected to the ball
    line1.lineStyle(2,0×000000);
    line2.lineStyle(2,0×000000);
    line1.moveTo(node1._x,node1._y);
    line1.lineTo(ball._x,ball._y);
    line2.moveTo(node2._x,node2._y);
    line2.lineTo(ball._x,ball._y);

    } else {
    //If it isnt below the two points draw the line so it connects the two nodes
    line1.lineStyle(2,0×000000);
    line1.moveTo(node1._x,node1._y);
    line1.lineTo(node2._x,node2._y);
    }
    };

  4. Matthew on August 17th, 2007 9:43 pm

    oops I just relised it doesnt add the plus symbol for some reason so
    in your code change

    yspeed = gravity;
    ball._y = yspeed;
    xspeed *= friction;
    ball._x = xspeed;

    to

    yspeed (plus symbol)= gravity;
    ball._y (plus symbol)= yspeed;
    xspeed *= friction;
    ball._x (plus symbol)= xspeed;

    obviously replaing the (plus symbol) with the actual symbol

    also you will need to change any quotation marks to normal ones
    just delete them and then put them in again as normal ones

    o and gd luck to everyone entering the Jayisgames comp :)

  5. Matthew on August 17th, 2007 9:47 pm

    o and also change this:
    if (xpos2>xpos1) {
    xspeed = 0.3;
    }

    to

    if (xpos2>xpos1) {
    xspeed (plus symbol)= 0.3;
    }

  6. Izy on August 17th, 2007 10:20 pm

    You’re very correct. I’ve made some consideration on that, but I didn’t want to take too large a step from Emanuele’s original tutorial.

    A good tweak would also be to allow the two points to be at different elevations.

  7. herman on September 17th, 2007 5:55 pm

    hey could somebody help me? I don’t understand these lines ->

    var xOffset:Number=
    Math.cos(angle1+Math.PI/2)*radius;

    var yOffset:Number = Math.sin(angle1+Math.PI/2)*radius;

    How can you know ,you should add “Math.PI/2″
    to get to the right position?

    Please tell me the idea !

  8. peter on October 5th, 2007 4:44 pm

    toworth matthew
    its funny how u can write actionscript so well and not know math :) but anyway
    i’ve been putting ur codes in a flash movie, and besides the faults u said there is also this one

    at least at my flashstage (pro 8)
    all the lines like this one give errors, because the asterix * gets changed to a “x”
    line1.lineStyle(2,0*000000);

    oh and i just noticed, (i was changing the coordinates to get the things in screen) and u have the node2 2 times in the top lines, u create it 2 times? i don’t realy see use for it i deleted it and it still works :) just that u know its double ;)

    i placed ur game here
    http://users.telenet.be/architectural_inspiration_peter_stals/matthew.swf

Leave a Reply