I’ve got a fever, and the only prescription is more cowbell.

Bouncy Ball Animation In Flex 3

In this project, I took an image that was in the shape of a ball and gave it a bouncy ball animation.  This bouncy ball animation includes a stretch animation during flight and squash animation when it makes contact with the ground.  I also gave it a horizon and a reflection just for kicks.

To start off, I created a normal Flex project using the Flex Builder 3 Plugin for Eclipse.  My project is named BouncyBall, so naturally my main mxml file is BouncyBall.mxml.  In addition, I have a globe image and a couple of components.  I created the BallPanel.mxml file to hold the bouncy ball.  To create the reflection, I used the actionscript based component, Reflector, from this LiveReflector Project.  I also created a gradient that would serve as my horizon or floor.  This is how things started to shape up.

BouncyBall.mxml (skeleton)

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
    xmlns:comp="components.*" width="300" height="350"
    backgroundColor="0xffffff" backgroundGradientAlphas="[1.0, 1.0]" backgroundGradientColors="[#FFFFFF, #FFFFFF]"
    horizontalScrollPolicy="off" verticalScrollPolicy="off"
    creationComplete="init()">
  <mx:Script>
    <![CDATA[
      private function init():void {

      }
    ]]>
  </mx:Script>

  <mx:UIComponent id="floorWrapper" x="0" y="280" height="70" width="100%" />
  <comp:Reflector id="myReflector" target="{ballPanel}" y="310" alpha="0.4" falloff="0.2" blurAmount="0.2" width="100%" />
  <comp:BallPanel id="ballPanel" width="100%" height="300" left="0" ballSquashScale="1.75" />
</mx:Application>

BallPanel.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml"
    horizontalScrollPolicy="off"
    verticalScrollPolicy="off"
    creationComplete="init()">
  <mx:Script>
    <![CDATA[
      import mx.controls.Alert;

      [Bindable] public var ballX:Number;
      [Bindable] public var ballSquashScale:Number = 2;
      [Bindable] public var ballSquashX:Number;

      private function init():void {
        ballX = (width - ball.width) / 2;
        ballSquashX = ballX - ((ball.width * ballSquashScale - ball.width) / 2);
        ball.x = ballX;
      }

      public function get ballSquashScaleX():Number {
        return ballSquashScale;
      }

      public function get ballSquashScaleY():Number {
        return 1 / ballSquashScale;
      }
    ]]>
  </mx:Script>

  <mx:Image id="ball" source="assets/globe.png" x="0" y="0" height="49" width="50" />
</mx:Canvas>

The only thing left is the bounce sequence that I created that makes everything work together.  There are 4 sets of animations that need to take place: the drop(strech), squash, unsquash, and bounce up(unstretch).

BouncyBall.mxml > bounce:Sequence

<mx:Sequence id="bounce" target="{ballPanel.ball}" duration="{1000 * durationFactor}" repeatCount="0">
  <mx:Parallel>
    <mx:AnimateProperty property="y"
        fromValue="0"
        toValue="{ballPanel.height - ballPanel.ball.height * (1 + .2 * squishyFactor)}"
        easingFunction="{Cubic.easeIn}"/>
    <mx:AnimateProperty property="scaleY"
        fromValue="1"
        toValue="{1 + .2 * squishyFactor}"
        easingFunction="{Sine.easeIn}"/>
  </mx:Parallel>
  <mx:Parallel duration="{200 * durationFactor}">
    <mx:AnimateProperty property="y"
        fromValue="{ballPanel.height - ballPanel.ball.height * (1 + .2 * squishyFactor)}"
        toValue="{ballPanel.height - ballPanel.ball.height * ballPanel.ballSquashScaleY}"                 easingFunction="{Cubic.easeOut}"/>
    <mx:AnimateProperty property="scaleY"
        fromValue="{1 + .2 * squishyFactor}"
        toValue="{ballPanel.ballSquashScaleY}"
        easingFunction="{Cubic.easeOut}"/>
    <mx:AnimateProperty property="scaleX"
        toValue="{ballPanel.ballSquashScaleX}"
        easingFunction="{Cubic.easeOut}"/>
    <mx:AnimateProperty property="x"
        toValue="{ballPanel.ballSquashX}"
        easingFunction="{Cubic.easeOut}"/>
  </mx:Parallel>
  <mx:Parallel duration="{200 * durationFactor}">
    <mx:AnimateProperty property="y"
        fromValue="{ballPanel.height - ballPanel.ball.height * ballPanel.ballSquashScaleY}"
        toValue="{ballPanel.height - ballPanel.ball.height * (1 + .2 * squishyFactor)}"                 easingFunction="{Cubic.easeIn}"/>
    <mx:AnimateProperty property="scaleY"
        toValue="{1 + .2 * squishyFactor}"
        easingFunction="{Cubic.easeIn}"/>
    <mx:AnimateProperty property="scaleX"
        toValue="1"
        easingFunction="{Cubic.easeIn}"/>
    <mx:AnimateProperty property="x"
        toValue="{ballPanel.ballX}"
        easingFunction="{Cubic.easeIn}"/>
  </mx:Parallel>
  <mx:Parallel>
    <mx:AnimateProperty property="y"
        toValue="0" fromValue="{ballPanel.height - ballPanel.ball.height * (1 + .2 * squishyFactor)}"
        easingFunction="{Cubic.easeOut}"/>
    <mx:AnimateProperty property="scaleY"
        toValue="1"
        easingFunction="{Sine.easeOut}"/>
  </mx:Parallel>
</mx:Sequence>

I also need to write the necessary actionscript to jumpstart this process.  In the earlier code, I am calling the init function upon creationComplete of the application tag.  Below is the init function, import statements, and variable definitions needed.

BouncyBall.mxml > Script

import mx.effects.easing.Sine;
import mx.effects.easing.Cubic;

private var floor:Sprite;
[Bindable] private var durationFactor:Number = 1;
[Bindable] private var squishyFactor:Number = 2;

private function init():void {
  floor = new Sprite();
  var colors:Array = [0xffffff, 0xdddddd];
  var ratios:Array = [0, 255];
  var matrix:Matrix = new Matrix();
  matrix.createGradientBox(300, 50, -Math.PI / 2);
  floor.graphics.beginGradientFill(GradientType.LINEAR, colors, null, ratios, matrix);
  floor.graphics.drawRect(0, 0, 300, 50);
  floorWrapper.addChild(floor);
  bounce.play();
}

Here is the resulting swf.

This movie requires Flash Player 9

I was inspired to begin working with this bouncy ball animation by reading several ball animation articles at Codedependent.  Specifically, I enjoyed Stretch & Squash for Flex 3.  First, I switched the logic from using a gradient ball to an image of my choice.  The switch meant going from skewing height and width values to skewing scaleX and scaleY values which was a whole new ball game.  I hope somebody gets some use out of my tireless hours in front of my laptop.

Here is the Flex Project.

[Download not found]

This website uses IntenseDebate comments, but they are not currently loaded because either your browser doesn't support JavaScript, or they didn't load fast enough.

5 Comments to Bouncy Ball Animation In Flex 3

  1. Skinny Chris's GravatarSkinny Chris
    July 21, 2009 at 7:57 am | Permalink

    over my head jon, way over…..

  2. Eric Brown's GravatarEric Brown
    September 13, 2009 at 12:14 am | Permalink

    Hey Jon,

    Very cool effect!

    I need to create an object that rises slightly with a mouseOver, then settles back to it's original position. Not nearly as complicated as a bounce. I was using your code as a guide to managing the live reflection. However, my reflection effect takes a moment to update after the object it's reflecting has already completed its move. Any idea why that happens?

    In any event, thanks for sharing your animation. I've learned alot from it.

  1. By on August 1, 2009 at 3:17 am

Leave a Reply

You can use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Subscribe

Search

You Can Find Me On ...

Categories

RSS Other Articles By Me

  • reCAPTCHA: Blocking Spam and More
    A few months ago, I developed a ColdFusion/Mach-II implementation of the reCAPTCHA API.  This type of CAPTCHA requires the person to enter two words rather than a single sequence of random letters.  In addition to protecting your website from spam, reCAPTCHA helps digitize text books.  They do this by using a mystery word as one of the two words, until there […]
  • Using Friendfeed to Automatically Post Your Blog Entries on Twitter
    Friendfeed is a feed aggregator that groups together updates from twitter, facebook, digg, youtube, your blog and much more.  It can also publish entries from your friendfeed to twitter.  This article shows you how to tap into that twitter publishing feature of friendfeed to automate the posting of your blog entries to twitter.  Watch my screencast to create […]
  • Intense Debate Now on the Sitepro Blog!
    Recently on the Sitepro Blog, we have switched to using an enhanced commenting system called Intense Debate.  Intense Debate provides many features that will supercharge the community, increase comments, and increase pageviews.  Some notable features include commenter profiles, reputation scores, email notifications, reply by email, and facebook integration. […]
  • Sitepro Developers Attend TCCFUG
    Last Thursday, a few Sitepro developers attended the Twin Cities Coldfusion User Group at University of St. Thomas.  We were introduced to the future of Coldfusion, specifically Coldfusion 9.  There was free admission, free food, free shirt, prizes, and an abundance of new Coldfusion features. […]