Flex Blog

Search:
  • Home
  • Examples
    • Thumb

      Flex Examples

      Check out our Flex Examples!

    • Thumb

      Flash Builder Examples

      Check out our Flash Builder Examples!

    • Thumb

      AIR Examples

      Check out our AIR Examples!

    • Thumb

      Flex Mobile Examples

      Check out our Flex Mobile Examples!

    Adobe® Flex, Adobe® Flash Builder and Adobe® AIR are registered trademarks of Adobe Systems.
  • Components
    • Thumb

      WP Flex Contact Form

      Check out our WP Flex Contact Form!

    • Thumb

      Flash CountDown Plugin

      Check out our Flash CountDown Plugin!

    This is an overview of all our Flash/Flex based Components.
  • Jobs
  • Flex Books
  • Forum
  • Contact Us
Subscribe to Flex BlogSubscribe
  • Examples
  • iOS
Browse > Home / Examples, Guest Poster / Fountain Example

Fountain Example

25 July 2011

Line Break

Author: Janez Feldin (6 Articles) - Author Website

Janez likes to experiment with flash in his own free time. His other hobbies are playing volleyball, listening to the music, watching movies and above all else, paragliding.

Here is another example, this one more visually appealing (I hope). I made a class, Fountain, not particulary usefull by itself, but can be used to teach some basics for handling bitmap and bitmapdata objects.

I started by creating new flex project. Normal project for web application, and than created new class. I called it Fountain and extended UIComponent. UIComponent only so that bitmap can be added to it. Here is the code for that class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
package com.FlexBlog
{
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.events.Event;
    import flash.events.TimerEvent;
    import flash.filters.BlurFilter;
    import flash.geom.Point;
    import flash.utils.Timer;
    import flash.utils.getTimer;
   
    import mx.core.UIComponent;
    import mx.events.FlexEvent;
   
    public class Fountain extends UIComponent
    {
        /* declaration of bitmapdata which will show
           our particles, and bitmap for our bitmapdata */

        private var bmd:BitmapData;
        private var bm:Bitmap;
       
        /* Array of objects. In each object
           we store positions, speeds,...*/

        private var dp_particles:Array = new Array();
       
        /* delay for redrawing the particles
           (small number -> fast motion,
           high number -> slow motion */

        private var doMotionDelay:Number = 10;

        /* declaration of timer which calls
           continuously the function to redraw
           particles to bitmapdata */

        private var motion_timer:Timer;
       
        /* some of the variables to change the
           visual appearance (try experimenting a bit) */

        [Bindable] public var maxParticles:int = 300;
       
        /* defines how much particles can be created at once
           (it helps that particles doesn't appear in intervals) */

        [Bindable] public var maxParticlesAtOnce:Number = 15;
       
        /* x and y position where the particles will appear */
        [Bindable] public var sourcePoint:Point = new Point(350,700);
       
        /* defines the angle at wich particles will be shot */
        [Bindable] public var startAngle:Number = 0;
       
        /* particles can be shot at 45° different angle tan start angle */
        [Bindable] public var deltaAngle:Number = 45;
       
        [Bindable] public var maxStartSpeed:Number = 7;
       
        [Bindable] public var minStartSpeed:Number = 3;
       
        /* if the particles are bounding they never leave the visible area,
           so we need another criteria to know when to delete them.
           If dampingFactor is set to 1 particles won't loose
           speed when bouncing so they won't be deleted */

        [Bindable] public var minEndSpeed:Number = 1;
        [Bindable] public var gravityY:Number = 0.1;
        [Bindable] public var gravityX:Number = 0;
        [Bindable] public var blurFilter:BlurFilter = new BlurFilter(1.5,1.5,1);
       
        /* defines how much speed each particle keeps when
           bouncing of the walls (0 -> no bouncing, 1 -> continuous bouncing) */

        [Bindable] public var dampingFactor:Number = 0;
       
        /* array of colors for particles. Type color more times
           if you want more particles to have that color instead
           of other colors. */

        public var colors:Array = [0x0000FF,0x00FF00,0xFF0000,0x00FFFF,0xFF00FF,0xFFFF00];
       
        /* main function of the class, it gets called when
           you define the class */

        public function Fountain()
        {
            // since we extended UIComponent we need to inherit
            // all the properties of new UIcomponent. We achieve
            // that with calling super()
            super();
           
            // when the UIComponent initialize and is
            // fully created, we call the function appComplete
            this.addEventListener(FlexEvent.CREATION_COMPLETE, appComplete);
        }
       
        /* function to add bitmapdata and bitmap to stage, and
           to start our drawing by starting the motion_timer */

        private function appComplete(e:Event):void
        {
            // since we want the width and height of our fountain to
            // match the width and height set in mxml (or in actionscript
            // if we define new fountain with actionscript and not mxml)
            // for our component, we need to define new bitmapdata in
            // appComplete because before appcomplete gets called this.width
            // is not yet defined!
           
            bmd = new BitmapData(this.width,this.height,false,0x000000);

            // because we cannot add bitmapdata to stage (or another visual component)
            // we need to create new bitmap that holds our bitmapdata object
            bm = new Bitmap(bmd);
           
            // finnaly we can indirectly add our bitmapdata to UIComponent
            this.addChild(bm);
           
            // we create new timer, add event listener to it so we
            // can continuously redraw particles
            motion_timer = new Timer(doMotionDelay);
            motion_timer.addEventListener(TimerEvent.TIMER, doMotion);

            // after everything is set, we start the timer
            motion_timer.start();
           
        }
       
        // function that creates new particles when dp_particles
        // length is less than maxParticles
        private function createParticles():void
        {
            // some temp variables
            var i:int;
            var newParticles:int;
           
            // variable that stores tha number of particles
            // that will be created
            var temp_speed:Number;
            var temp_angle:Number;
           
            // if statment that checks if we can create all missing
            // particles at once (because of the maxParticlesAtOnce)
            // here more particles are missing, than we allow them to
            // spawn at a time
            if ( maxParticles-dp_particles.length > maxParticlesAtOnce )
            {
                // we get the random number which will define how much particles
                // will be created at once, because we can't create all the missing
                // particles, the random number must be lower than MaxParticlesAtOnce
                newParticles = Math.ceil(Math.random()*maxParticlesAtOnce);
            }
            else
            {
                // maxParticles-dp_particles.length defines the number of missing
                // particles, and also makes sure that our random number is not larger
                // than this one
                newParticles = Math.ceil(Math.random()*(maxParticles-dp_particles.length));
            }
           
            // for loop to create new particles
            for(i=0;i<newParticles;i++)
            {
                // calculates random speed betwen minStartSpeed and maxStartSpeed
                temp_speed = minStartSpeed + Math.random()*(maxStartSpeed-minStartSpeed);
               
                // calculate the starting angle (example: if we have startAngle=90
                // and deltaAngle 45 the starting angle can be anywhere between 45 and 135
                // with Math.PI/180 transforms angle from ° to radians
                temp_angle = (-90+startAngle+Math.random()*deltaAngle-deltaAngle/2)*Math.PI/180;
               
                // adds new object (particle) to our array of particles with
                // calculated starting values
                // with angle we split our speed to x and y direction (easier to draw
                // if we have x and y speed than speed and angle)
                // for color we generate random integer between 0 and colors.length
                // to randomly select color from our array of colors
                dp_particles.push({x: sourcePoint.x,y: sourcePoint.y,
                    vx: temp_speed*Math.cos(temp_angle),
                    vy: temp_speed*Math.sin(temp_angle),
                    color: colors[Math.floor(Math.random()*colors.length)]});
            }
        }
       
        // function which redraws our particles on bitmapdata
        private function doMotion(e:TimerEvent):void
        {
            var i:int;
           
            // temporary variable to know if the particle we are
            // curently rendering was deleted
            var particle_deleted:Boolean;
           
            // we apply the filter to bitmapdata to look cooler
            // also the filter is applied before the new position is calculated
            // because we want to blur the trail of the particle only and not
            // the particle itself
            bmd.applyFilter(bmd,bmd.rect,new Point(),blurFilter);
           
            // if statment to check if there are any particles
            // missing. If there are we call createParticles() to create new ones
            if ( dp_particles.length < maxParticles )
            {
                createParticles();
            }
           
            // for loop to go trought all particles and recalculate their new
            // position, also checks if any particles are out of visible range
            // and delete them
            for(i=0;i<dp_particles.length;i++)
            {
                // we set the particle_delted to false just to make sure
                // that it isn't set to true from last particle
                particle_deleted = false;
               
                // we redraw curently rendering particle, and than
                // calculates new x and y position (the order could be reverse)
                bmd.setPixel(dp_particles[i].x,dp_particles[i].y,dp_particles[i].color);
               
                // for new position we only add the speed to the curent position
                dp_particles[i].x = dp_particles[i].x+dp_particles[i].vx;
                dp_particles[i].y = dp_particles[i].y+dp_particles[i].vy;
               
                // two if statements to chek for bounce
                if ( dp_particles[i].x <= 0 || dp_particles[i].x >= this.width )
                {
                    // fro bounce from wall we reverse the direction
                    // of speed and also multiply the speed with dampingFactor
                    // so that we can set how particle bounce
                    dp_particles[i].vx = -dp_particles[i].vx * dampingFactor;
                }
                if ( dp_particles[i].y <= 0 || dp_particles[i].y >= this.height )
                {
                    dp_particles[i].vy = -dp_particles[i].vy * dampingFactor;
                }
               
                // if statement to check if particle has speed low enough
                // to be deleted or if it is out of visible range (actualy 5 pixels from  sides,
                // because particles that are bouncing will never leave the visible area)
                if ( Math.abs(dp_particles[i].vx) < minEndSpeed &&
                    Math.abs(dp_particles[i].vy) < minEndSpeed &&
                    (dp_particles[i].x < 5 || dp_particles[i].x > this.width-5
                        || dp_particles[i].y < 5 || dp_particles[i].y > this.height-5) )
                {
                    // we remove the particle from out array with splice function.
                    // First parameter (i) is the index, the second one is the count
                    // of the parameters that should be deleted, and next parameters
                    // would be the values to be added to array (we don't need this one)
                    dp_particles.splice(i,1);
                    particle_deleted = true;
                }
               
                // we need to check that particle wasn't deleted. If the particle
                // would be deleted and we still applied the gravity effect, we
                // would apply the gravity effect to wrong particle or get an
                // error(if the deleted particle would be the last one in our array)
                if ( !particle_deleted )
                {
                    dp_particles[i].vx += gravityX;
                    dp_particles[i].vy += gravityY;
                }
            }
        }
    }
}

After we have created the class we only need to add it to the stage. I did it with mxml, I also added a form which had some sliders in it to quickly change settings.
Here is the mxml code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
               xmlns:s="library://ns.adobe.com/flex/spark"
               xmlns:mx="library://ns.adobe.com/flex/mx"
               xmlns:FlexBlog="com.FlexBlog.*"
               minWidth="955" minHeight="600" xmlns:local="*">

    <!-- we add our fountain class to stage with mxml.
    Same could be achieved with actionscript by
    var name_for_variable:Fountain = new Fountain()-->
    <FlexBlog:Fountain id="_fountain" x="300" width="700" height="700" />
   
    <!-- Some form items to set the properties of the fountain.
    each form item is bind to some variable in our Fountain class
    this is only for quick settings -->
    <mx:Form left="10" top="10" width="280" bottom="10">
        <mx:FormItem label="Max particles" width="100%">
            <s:HSlider width="100%" minimum="1" maximum="1000"
                       value="@{_fountain.maxParticles}"/>
        </mx:FormItem>
        <mx:FormItem label="Max new Particles" width="100%">
            <s:HSlider width="100%" minimum="1" maximum="50"
                       value="@{_fountain.maxParticlesAtOnce}"/>
        </mx:FormItem>
        <mx:FormItem label="Source point x" width="100%">
            <s:HSlider id="slider_source_x" width="100%"
                       minimum="0" maximum="{_fountain.width}"
                       value="200"
                       change="_fountain.sourcePoint.x = slider_source_x.value"/>
        </mx:FormItem>
        <mx:FormItem label="Source point y" width="100%">
            <s:HSlider id="slider_source_y" width="100%"
                       minimum="0" maximum="{_fountain.height}"
                       value="200"
                       change="_fountain.sourcePoint.y = slider_source_y.value"/>
        </mx:FormItem>
        <mx:FormItem label="Start angle" width="100%">
            <s:HSlider width="100%" minimum="0" maximum="360"
                       value="@{_fountain.startAngle}"/>
        </mx:FormItem>
        <mx:FormItem label="Delta angle" width="100%">
            <s:HSlider width="100%" minimum="0" maximum="360"
                       value="@{_fountain.deltaAngle}"/>
        </mx:FormItem>
        <mx:FormItem label="Gravity x" width="100%">
            <s:HSlider width="100%" stepSize="0.05"
                       minimum="-1" maximum="1"
                       value="@{_fountain.gravityX}"/>
        </mx:FormItem>
        <mx:FormItem label="Gravity y" width="100%">
            <s:HSlider width="100%" stepSize="0.05"
                       minimum="-1" maximum="1"
                       value="@{_fountain.gravityY}"/>
        </mx:FormItem>
        <mx:FormItem label="Damping factor" width="100%">
            <s:HSlider width="100%" stepSize="0.1"
                       minimum="0" maximum="1"
                       value="@{_fountain.dampingFactor}"/>
        </mx:FormItem>
    </mx:Form>
   
   
</s:Application>

Here is a screenshot of the fountain in action (its animating in the real example, ofcourse):

Screenshot of the fountain in action

Related posts:

  1. TinyURL usage with Flash Builder

Written by Janez Feldin · Filed Under Examples, Guest Poster 

Was this post useful to you?

Please rate this post, follow us @ twitter, or link to this page from your website!

1 Star2 Stars3 Stars4 Stars5 Stars (1 votes, average: 5.00 out of 5)
Loading ... Loading ...

20308810618f0fce4f4f34952ed1a2e0delicious

Comments

Get Adobe Flash player

  • +1?

  • Support Flex Blog!

  • $ 13 raised
    • 2012/01/13 8:22 PM Russell Brown donated $ 3.00
    • 2011/10/31 4:43 PM Steve Dakin donated $ 5.00
    • 2011/05/11 3:37 PM Roelof Albers donated $ 5.00
  • Stay in touch!

  • Popular Tags

    • AdvancedDataGrid
    • AIR
    • ArrayCollection
    • baseColor
    • Button
    • CursorManager
    • DataGrid
    • Dynamic
    • Effects
    • File
    • FileStream
    • Flash Builder
    • Flash Builder 4
    • Flex 4
    • Flex Mobile
    • Framework
    • Icon
    • Image
    • itemRenderer
    • LinkBar
    • Mobile
    • PHP
    • ProgressBar
    • Repeater
    • Style
    • SWIZ
    • Timer
    • Tree
    • Twitter
    • ViewStack
  • Advertisements

  • Recent Posts

    • Spooky Frenzy – iPad Game
    • Fountain Example
    • Reading & Writing files in Adobe AIR
    • CheckBox in List using MobileIconItemRenderer for Flex Mobile
    • Data Dependent decoratorClass in MobileIconItemRenderer Example
    • Flex 4 Resize Effect Example
    • Jump to next field using the Focus Manager
    • Searching Data using a Class Example
    • Flex Mobile: Two finger tap gesture to toggle actionBar visibility in a View (AIR for Android)
    • TabbedMobileApplication Example in Flex Mobile (AIR for Android)
  • Categories

    • Examples
    • Guest Poster
    • iOS
  • Archives

    • September 2011
    • July 2011
    • May 2011
    • March 2011
    • February 2011
    • November 2010
    • October 2010
    • September 2010
    • August 2010
    • June 2010
    • May 2010
    • April 2010
    • March 2010
    • February 2010
    • January 2010
    • December 2009
    • November 2009
    • October 2009
    • March 2009
    • February 2009
  • Blogroll

    • Adobe Flex Jobs
    • NL for Business
  • Meta

    • Register
    • Log in
    • WordPress
    • XHTML

Copyright © 2010 Flex Blog · Adobe® and Adobe® Flex are registered trademarks of Adobe Systems.

WordPress Adobe Flex Adobe Flash Builder Adobe AIR Creative Commons License

  • Popular Posts

    • Progressbar in Datagrid Example 13 votes, average: 5.00 out of 513 votes, average: 5.00 out of 513 votes, average: 5.00 out of 513 votes, average: 5.00 out of 513 votes, average: 5.00 out of 5 (5.00 out of 5)
    • Data Dependant Tree Icon with Tree in AdvancedDataGrid with iconFunction 8 votes, average: 5.00 out of 58 votes, average: 5.00 out of 58 votes, average: 5.00 out of 58 votes, average: 5.00 out of 58 votes, average: 5.00 out of 5 (5.00 out of 5)
    • List Directory with AIR in Flex 4 7 votes, average: 5.00 out of 57 votes, average: 5.00 out of 57 votes, average: 5.00 out of 57 votes, average: 5.00 out of 57 votes, average: 5.00 out of 5 (5.00 out of 5)
    • Flex FlashVars in AS3 Example 7 votes, average: 5.00 out of 57 votes, average: 5.00 out of 57 votes, average: 5.00 out of 57 votes, average: 5.00 out of 57 votes, average: 5.00 out of 5 (5.00 out of 5)
    • Flex Dynamic Chart Example 4 votes, average: 5.00 out of 54 votes, average: 5.00 out of 54 votes, average: 5.00 out of 54 votes, average: 5.00 out of 54 votes, average: 5.00 out of 5 (5.00 out of 5)