By paddloPayday loans

Home > AIR, Algorithms, Mobile > ActionScript 3.0 GestureEvent: Working with Gestures on Mobile

ActionScript 3.0 GestureEvent: Working with Gestures on Mobile

Developing Gesture Apps Requires Actions with No Equivalent in MouseEventsUsing Gestures

When working with high level and complex structures like Design Patterns, the focus is squarely on the relationship between objects—classes, inheritance, composition, implementation, interfaces and related concepts and structures. The “details” are the details of these various relationships and how they work in concert. Using Algorithm 1 or Algorithm 2 is only pertinent insofar as it relates to a method or property that needs to be loosely bound to some other object. If you start thinking about algorithm details as a primary concern and fretting over internals, you can easily lose sight of the larger structures that are under development and never really understand Design Patterns.

Seismic Shift

Every now and again we encounter a seismic shift in the way things are done, and you have to make adjustments.(Some of you may remember the Commodore 64 that went the way of the Dodo Bird. At one time it was the most popular personal computer on earth, but if you insisted on sticking with it, you probably don’t have any clients for your services.) In my own case, shift to mobile devices forced me to spend some quality time with the event processes in ActionScript 3.0. Going to the base, I reviewed how the Display List is handled in Flash and by AS3. Then I went to look at the AS3 Event Flow and among the several articles I read, one of the best is Jody Hall’s. Adobe has several good ones as well, and I’m sure many more are available that some of you may want to share.

On to Gestures

I wrote some gesture events and handlers. The results were unsatisfactory. It wasn’t that they didn’t work, but after one would work, another would not. Very baffling and frustrating. My goal was to create a ‘workbench’ where I could try all kinds of gesture events, but I had very poor luck with just about everything at some point. So I backed away and tried an application with only two gestures; neither available with MouseEvent. One was Rotate and the other Zoom. Christian Cantrell has a good article on using gestures, and in addition to getting some good information on using gesture events, I also got a nice little piece on using gestures with bitmaps. (I had been having a devil of a time with Sprite objects in the Library with gestures.) Click the download button below to get the source code and FLA files for Flash Pro 5.5, 5 and 4 along with the image files and ActionScript 3.0 code:

download this sucker

In my last post, I was convinced that TOUCH_TAP from TouchEvent works better than CLICK from MouseEvent with a mobile device. That conclusion was not based on the inner-workings of events and event handling, but rather from testing the different event handlers using my iOS device, a 4S iPhone. In the Adobe documentation, they point out that it might be better to use a MouseEvent rather than a TouchEvent or GestureEvent. It depends on the app, device and device OS. That pretty much makes it an empirical question.

In this application, there was no choice to use MouseEvent because it does not contain the required finger-flipping gestures I can make on my iPhone—GESTURE_ZOOM and GESTURE_ROTATE. Likewise, TouchEvent did not have the kinds of gestures; so I had to use TransformGestureEvent. The following code shows how it is employed in a simple picture flipping/zooming app:

?View Code ACTIONSCRIPT
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
package 
{
	import flash.display.Bitmap;
	import flash.display.Sprite;
	import flash.events.TransformGestureEvent;
	import flash.ui.Multitouch;
	import flash.ui.MultitouchInputMode;
 
	[SWF(width=640, height=960, frameRate=24, backgroundColor=0xcc0000)]
	public class PicFlip extends Sprite
	{
		[Embed(source = "vanBillz.png")]
		public static var BillzImage:Class;
		private static var billzBitmap:Bitmap = new BillzImage();
		private static var carrier:Sprite = new Sprite();
 
		public function PicFlip()
		{
			carrier.x = 320, carrier.y = 550;
			carrier.addChild(billzBitmap);
 
			billzBitmap.x = (320 - (billzBitmap.bitmapData.width / 2)) * -1;
			billzBitmap.y = (480 - (billzBitmap.bitmapData.height / 2)) *-1;
 
			this.addChild(carrier);
 
			Multitouch.inputMode = MultitouchInputMode.GESTURE;
			carrier.addEventListener(TransformGestureEvent.GESTURE_ZOOM, doZoom);
			carrier.addEventListener(TransformGestureEvent.GESTURE_ROTATE, doRotate);
		}
 
		private final function doZoom(e:TransformGestureEvent):void
		{
			carrier = e.target as Sprite;
			carrier.scaleX *=  e.scaleX;
			carrier.scaleY *=  e.scaleY;
		}
 
		private final function doRotate(e:TransformGestureEvent):void
		{
			carrier = e.target as Sprite;
			carrier.rotation +=  e.rotation;
		}
	}
}

I tested it on an iPhone, but there’s no reason it won’t work perfectly well on an Android or some other mobile device. Further, I found it to be very responsive. The zooming seemed to work quite well with bitmapped graphics, and so I assumed that it would work just as well, if not better with a vector object in the Library. So I put together a little test symbol using the drawing tools in Flash and stored it as Sprite class in the Library. (By the way, in case you were not aware, to make a Sprite class in the Library, when you create a New Symbol, just classify it as a MovieClip and in the Base Class window change the type from flash.display.MovieClip -> flash.display.Sprite. The Library icon turns from Blue to Green to indicate it is now a Sprite.)

I used the following code:

?View Code ACTIONSCRIPT
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
package 
{
	import flash.display.Sprite;
	import flash.events.TransformGestureEvent;
	import flash.ui.Multitouch;
	import flash.ui.MultitouchInputMode;
 
	public class PicFlipLib extends Sprite
	{
		private static var carrier:Sprite = new Sprite();
		private static var billzVector:Sprite=new BillzVector();
 
		public function PicFlipLib()
		{
			carrier.x = 220, carrier.y = 350;
			carrier.addChild(billzVector);
 
			this.addChild(carrier);
 
			Multitouch.inputMode = MultitouchInputMode.GESTURE;
			carrier.addEventListener(TransformGestureEvent.GESTURE_ZOOM, doZoom);
			carrier.addEventListener(TransformGestureEvent.GESTURE_ROTATE, doRotate);
		}
 
		private final function doZoom(e:TransformGestureEvent):void
		{
			carrier = e.target as Sprite;
			carrier.scaleX *=  e.scaleX;
			carrier.scaleY *=  e.scaleY;
		}
 
		private final function doRotate(e:TransformGestureEvent):void
		{
			carrier = e.target as Sprite;
			carrier.rotation +=  e.rotation;
		}
	}
}

One of the features that seemed to make a difference was that instead of having the event listener connected directly to the Library Sprite (BillzVector), I used an object container Sprite, carrier. Figure 1 shows the zoom and rotation on an iPhone 4S. This was used with both the bitmap and the vector Sprite objects, and they both worked quite well.

rotate

Figure 1: Both rotation and zoom worked fined with the vector-based Sprite

Back to Design Patterns

I was going to post my final matrix motion solution, but I got jammed up with event handling. Next time, I should be able to post the next stage in my Samurai game. It uses a State design pattern to move through nine cells in a 3 X 3 matrix. Everything was working well except that my event handlers were not as crisp as I wanted. I’ll have a chance to see now whether the time-out with AS3 event handlers was enough. The Design Pattern does its job; I just was not getting the event handlers to do theirs. In the next post you’ll be able to see whether they are all working well together in a mobile environment.

Share
Categories: AIR, Algorithms, Mobile
  1. Julio
    May 3, 2012 at 7:46 pm | #1

    hi friend, and would do to limit the zoom?

    • William B. Sanders
      May 6, 2012 at 9:17 am | #2

      Hi Julio,

      Right off the top of my head, I’d add a zoom limit variable. The code would look something like this:

      ?View Code ACTIONSCRIPT
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      
      private var zoomLimitX:Number=10;
      private var zoomLimitY:Number=8;
      private final function doZoom(e:TransformGestureEvent):void
      {
            carrier = e.target as Sprite;
            if (carrier.scaleX <= zoomLimitX && carrier.scaleY <= zoomLimitY)
            {
      	   carrier.scaleX *=  e.scaleX;
      	   carrier.scaleY *=  e.scaleY;
           }
      }

      There might be a better way, but try that for now.

      Kindest regards,
      Bill

  2. Ruslan
    April 1, 2013 at 3:35 pm | #3

    hello, and would do to always centered in the middle?

  3. Alex
    June 22, 2013 at 8:41 pm | #4

    Hi,
    i just finished app for android, and i used GESTURE_ZOOM, and GESTURE_ROTATE, for zoom and rotate, but i used mouse drag for moving objects on screen. And it was all on top of camera working behind movable objects, it works like a charm. It worked a bit slow, until i used BitmapMatrix on movable objects, and aimed GPU when publishing.
    After that, it worked great. Tested on iPad2 also, it works smooth also, but i think BitmapMatrix doesnt help much there(at least i read it doesn’t)
    Below is the code, and you can see app on google play:
    https://play.google.com/store/apps/details?id=air.com.simplycation.plazmaXXL

    refSym.addEventListener(TransformGestureEvent.GESTURE_ZOOM , onZoom);
    refSym.addEventListener(TransformGestureEvent.GESTURE_ROTATE, onRotate);
    refSym.addEventListener(MouseEvent.MOUSE_UP, onMouseU);
    refSym.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDwn);

    function onMouseU(e:MouseEvent)
    {
    e.currentTarget.stopDrag();
    //Multitouch.inputMode = MultitouchInputMode.GESTURE;
    }
    function onMouseDwn(e:MouseEvent)
    {
    //Multitouch.inputMode = MultitouchInputMode.TOUCH_POINT;
    e.currentTarget.startDrag();
    }

    function onZoom (e:TransformGestureEvent):void
    {
    e.currentTarget.stopDrag();
    e.currentTarget.scaleX *= e.scaleX;
    e.currentTarget.scaleY *= e.scaleX;
    }

    function onRotate(e:TransformGestureEvent):void
    {
    e.currentTarget.stopDrag();
    //trace(e.rotation);
    e.currentTarget.rotation += e.rotation;
    }

  4. William B. Sanders
    June 25, 2013 at 9:52 am | #5

    Hi Alex,

    Very cool. and thanks for sharing with us. I’m curious as to why you used a TransformGesterEvent with zoom and a MouseEvent for dragging.

    Cheers,
    Bill

  1. No trackbacks yet.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may 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>