Support & Tutorials  »  Multitouch Flick Tutorial

Tutorial: Multitouch Flick

Download the sample application
Download Download the sample application

Introduction

Learn how to dynamically flick objects on stage using the GESTURE_FLICK event. The GESTURE_FLICK event is triggered by when a touch point rapidly accelerates while moving over a touch object. In this tutorial, you will learn how to attach a GESTURE_FLICK event listener on a display object and control its location using dynamic output from the captured GESTURE_FLICK event. This tutorial requires Adobe Flash CS4 and GestureWorks (download a free trial).

Creating Your Document Class

The document class, also known as the “Application” class, is the root object class for your application. The primary purpose of the document class is to extend the main timeline; it does this in the form of a custom MovieClip. This means that all other objects in your application are placed within it.

To set the document class for your application, open mainApp.fla. Then, in the main menu, go to File > Publish Settings. In the Flash tab, select the Script “settings” button. Then, in the “Advanced Actionscript 3 Settings” window, set the “Document Class” to “Main“. Press the “OK” button and apply the changes to publishing settings.

In the main menu go to: File > New. Then in the “New Document” window, select “Actionscript File” and press the “OK” button. Save the file as “Main.as” and make sure it is saved in the same folder as your application file.

In the first line of your ActionScript file, add the following code to open a new package structure:

1
package {

This defines the beginning of the root package, which defines the code used in your root class “Main”. This tells Flash which script to include when extending “Main”.

Importing Flash Libraries

The first thing we are going to do next is import the Flash display package into the package of our root class. Essentially this allows Flash to correctly reference and retrieve all the object resources that may be needed to display objects on stage. In this case, we will only need the MovieClip class, as we will be using MovieClips from the library.

2
import flash.display.MovieClip;

In this example, we are going to use the “ENTER_FRAME” event to time our motion. We’ll need the ability to track events that occur within the Loader object, so we need to import “Event” libraries that allow us to attach listeners which monitor the procession of frames.

3
import flash.events.Event;

 

Importing GestureWorks Libraries

Importing the “Application” package instantiates libraries and builds a framework of control structures for managing multitouch events and methods for object tracking within Flash. To edit these settings, open “How to Customize Application.xml”

5
import id.core.Application;

A display level class must be set up to be used for stage objects. To do this, we import the TouchSprite class libraries. TouchSprite builds multitouch onto the Sprite class. This means that TouchSprite inherits all the properties of Sprite and adds new event targeting features that act systematically to determine multitouch event ownership at the object level.

6
import id.core.TouchSprite ;

Since we are going to be using gesture events, we will need to import these classes into our file. As with importing other packages, importing the GestureEvents package provides a reference to all available gesture analysis modules via their class name.

7
import gl.events.GestureEvent;

 

Creating Your App

In order to build our multitouch application, we are going to create what is essentially a custom class in Flash. We begin this process by extending the “Application” class & setting up our new class to automatically inherit a multitouch framework that will manage touch events behind the scenes.

9
public class Main extends Application {

In this example we are going to add some basic physics to our touch object. The physics behavior will be simulated using simple “onEnterframe” events. The event handlers that control our touch object will be outside the main function, so in order for the handlers to access our touch object and its “physical” properties, we need to create them as private variables at the head of our “Main” class.

10
11
12
13
private var ball:MovieClip;
private var container:TouchSprite;
private var friction:Number = 0.985;
private var dx:Number = 0;

In most cases, the document class should be defined as public so that it can be called (and instances created) from outside the package.

15
public function Main() {

Next we are going to build a container object for the library item ball. To make sure that anything inside the “container” responds correctly to touch, we must initialize the container as a new instance of TouchSprite() class.

16
container = new TouchSprite();

Then initialize “ball” and a new instance of the library object “rubberBall()”.

17
ball = new rubberBall();

To put the “ball” inside the “container” we simply nest one object inside the other using the “addChild()” method.

18
container.addChild(ball);

The container is then placed at the center of the stage area.

20
21
container.x = stage.stageWidth/2;
container.y = stage.stageHeight/2;

To make sure that all touch points placed over the container object are explicitly associated with that object, we need to set the “blobContainerEnabled” property to true.

22
container.blobContainerEnabled = true;

In this example we want our touchable object “ball” to respond to a FLICK gesture. To do this we simply add a “GESTURE_FLICK” listener to the “container”. Each time the FLICK gesture is detected over the container, the function “gestureFlickHandler” is called.

23
container.addEventListener(GestureEvent.GESTURE_FLICK, gestureFlickHandler);

Then add the container object to the stage so that it is automatically added to the display list at runtime.

24
addChild(container);

The FLICK gesture can be described as a single touch point that accelerates (velocity increases) as the touch point is dragged over a particular object. To give an appropriate simulated physical response to the object that is “flicked,” it must be given an instantaneous velocity proportional to the peak velocity of the flick. The value returned from the flick gesture is an average of the measured velocity in the last few frames of the gesture from touch down to touch up. In this example, we are only interested in the horizontal velocity and so can specify “velocityX” as a measure of the peak horizontal velocity of the GESTURE_FLICK.

Next, we need to create a function “gestureFlickHandler()” that changes the position of our object by an amount equal to horizontal velocity returned from the GESTURE_FLICK event. Then an ENTER_FRAME event listener is added to the stage that will call the function “onEnterFrameHandler()” every time our animation moves from one frame to the next.

27
28
29
30
private function gestureFlickHandler(e:GestureEvent):void {
    dx = e.velocityX
    addEventListener(Event.ENTER_FRAME, onEnterFrameHandler);
}

In the “onEnterFrameHandler()” function we need to include some logic to dictate how the position of our ball changes each time the animation enters a new frame. This effectively sets how the velocity of our ball changes as time passes.

32
private function onEnterFrameHandler(e:Event):void {

The first step is to make sure that our ball behaves as though it is confined to a box. To do this, we “bounce” the ball off the sides of the stage. When a physical object bounces in real life, the direction of its velocity changes. So in our logical statement, when the ball tries to move beyond the left or right edge of the stage, the direction of its velocity is reversed.

33
34
35
36
37
38
39
40
if(container.x < ball.width/2){
    dx =- dx;
    container.x = ball.width/2
}
if(container.x > stage.stageWidth - ball.width/2){
    dx =- dx;
    container.x = stage.stageWidth - ball.width/2
}

To make the behavior of our ball appear more physically accurate, we are going to make sure it gradually slows down after being flicked. One elegant way to do this is to mimic how friction behaves and reduce the amount the ball moves in each frame by a fixed ratio. For a ratio to reduce the number it multiplies, the ratio must be less than 1. In this example the ratio “friction” has been set to 0.985 .This value was obtained by empirically testing the animation to make sure the animation convincingly simulated a “real” object when running at 60 frames per second.

As our object slows, it will eventually reach a velocity of less than one pixel per frame which will cause the ball to snap form one coordinate to the next while animating. To avoid this, code must be put in place to stop the ball moving when its velocity drops below 1. This is done by setting the velocity to zero and removing the ENTER_FRAME listener.

41
42
43
44
if (Math.abs(dx) <= 1) {
    dx = 0;
    removeEventListener(Event.ENTER_FRAME, onEnterFrameHandler);
}

All the preceding logic has dealt with bouncing and stopping the ball but, in the majority of the frames, the ball will be moving in a constant direction. To move our object in the same direction by a specific amount, we simply add the desired change in position to the current position.

45
container.x += dx;

To make sure that the velocity gradually decreases we multiply the current value for the change in position by “friction” (0.985) each frame.

46
dx *= friction;

The combined effect of these logical conditions is to initialize the horizontal motion of the ball when it has been flicked (horizontally) and then control the ball in such a way as to cause it to gradually slow while bouncing between two walls. The faster the ball is flicked, the faster it initially moves and the longer it remains in motion.

Complete Example 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
package {
    import flash.display.MovieClip;
    import flash.events.Event;

    import id.core.Application;
    import id.core.TouchSprite;
    import gl.events.GestureEvent;
   
    public class Main extends Application {
        private var ball:MovieClip;
        private var container:TouchSprite;
        private var friction:Number = 0.985;
        private var dx:Number = 0;

        public function Main() {           
            container = new TouchSprite();
                ball = new rubberBall();
                container.addChild(ball);
               
                container.x = stage.stageWidth/2;
                container.y = stage.stageHeight/2;
                container.blobContainerEnabled = true;
                container.addEventListener(GestureEvent.GESTURE_FLICK, gestureFlickHandler);
            addChild(container);
        }
       
        private function gestureFlickHandler(e:GestureEvent):void {
            dx = e.velocityX
            addEventListener(Event.ENTER_FRAME, onEnterFrameHandler);
        }
       
        private function onEnterFrameHandler(e:Event):void {
            if(container.x < ball.width/2) {
                dx =- dx;
                container.x = ball.width/2
            }
            if(container.x > stage.stageWidth - ball.width/2) {
                dx =- dx;
                container.x = stage.stageWidth - ball.width/2
            }
            if (Math.abs(dx) <= 1) {
                dx = 0;
                removeEventListener(Event.ENTER_FRAME, onEnterFrameHandler);
            }
        container.x += dx;
        dx *= friction;
        }
       
    }
}

 

Testing Your Application

There are various ways to test your multitouch application. If you have a multitouch imput device, events can be directly streamed to your Flash application via TUIO. If you do not have a device that can output multitouch events, you can use the built-in simulator in GestureWorks. To test your app in the main menu, go to Control > Test Movie or press “Ctrl + Enter” on the keyboard. Alternatively, you can publish your application as a self-contained executable by following these steps:

  • In your open Flash application “myApp.fla”, go to File > Publish Settings.
  • Then in the Formats tab, select “Windows Projector” or “Macintosh Projector,” then press the “Publish” button.
  • The application will be published to your app folder. From there, you can simply double click on myApp.exe (Windows) or myApp.app (Mac) and run your multitouch application.

NOTE - To build and test these tutorials on a computer without a touchscreen display, pressing “Shift” or “Control” while clicking on an object with the mouse will create additional touch points within the simulator. To remove touch points, simply click them.

Other Tutorials In The “Getting Started With Gestures” Series

These tutorials cover the basics of how to integrate touch and gesture events into your Flash applications: