Archive

Archive for the ‘Speed Tweaks’ Category

ActionScript 3.0 TouchEvent: Guaranteed Mobile Speedup

January 15, 2012 11 comments

Tap screen

MouseEvent Works but TouchEvent Works better

The TouchEvent Object

I suppose old habits die hard, especially when those habits still work. (Some programmers are fond of saying, If it ain’t broke, don’t fix it! and the similarly dull-witted proverb, Don’t re-invent the wheel!) Well, with mobile devices, you’d better think about breaking old habits, and I put myself at the top of the dullard list for taking so long to make some adoptions. One of the first changes to make when creating mobile apps is to use the TouchEvent instead of the MouseEvent. In working on a game, I merrily kept using MouseEvent until I noticed that my apps kept getting stuck in the mud when I put them on a mobile device. So, I decided to give TouchEvent a try. Naturally, I couldn’t test in Flash Pro CS5.5; so I had to wait until I launched it in my iPhone. When I did, the difference was night and day. The sluggishness disappeared.

The good news is that MouseEvent and TouchEvent classes work pretty much the same as far as programming them into an app. I have no idea what’s going on with either under the hood, and I shouldn’t have to concern myself with those issues other than to know that one works better with mobile devices than the other. To get started, we’ll take a look at the sequence for setting up for TouchEvents, and while almost identical to MouseEvent, there are programming differences. First, though, click the Play button to see the little testing app on your computer. You can also download the Flash 5.5 Fla file and Client class by clicking on the Download button.
play button

As you can see it’s a simple little app to move a “Samurai” character left and right; up and down. The buttons are in Japanese, and if you read Japanese, you’ll realize that the characters look like a first-grader’s attempts to learn how to write in Japanese. (Feel free to make some better simple buttons using Japanese characters and send them along with any comments you may have.)

Possible Controversy: After I had finished this post, I ran across the following:

http://help.adobe.com/en_US/as3/dev/WSb2ba3b1aad8a27b0-6ffb37601221e58cc29-8000.html

In it is a note of caution:

Note: Listening for touch and gesture events can consume a significant amount of processing resources (equivalent to rendering several frames per second), depending on the computing device and operating system. It is often better to use mouse events when you do not actually need the extra functionality provided by touch or gestures. When you do use touch or gesture events, consider reducing the amount of graphical changes that can occur, especially when such events can be dispatched rapidly, as during a pan, rotate, or zoom operation. For example, you could stop animation within a component while the user resizes it using a zoom gesture.

That certainly makes sense, but I found that even using TOUCH_TAP, it was a quicker and far more responsive than listening for a CLICK event. There’s only one way to resolve this issue; try it yourself with a mobile app on a mobile device–any one you want. Use the Comment section to report what you’ve found. The sample app is as good as any for a trial, but feel free to create one of your own choosing.

As Chico Marx remarked in Duck Soup, Well, who you gonna believe, me or your own eyes? Believe your eyes and give it a whirl!

Just the Right Touch

Setting up the TouchEvent includes three imports:

  • import flash.events.TouchEvent;
  • import flash.ui.Multitouch;
  • import flash.ui.MultitouchInputMode;

That contrasts with the single MouseEvent import required when using the mouse event. However, prior to using the TouchEvent class you have to set up your mobile context with the following line:

Multitouch.inputMode = MultitouchInputMode.TOUCH_POINT;

That statement focuses the input mode to touch instead of a mouse event. I was unable to get the TouchEvent to work without the statement; so, don’t forget to include it in your program.

Finally, you need an event listener, and it has the same format as a mouse event except you use TouchEvent. Also, instead of using CLICK, use TOUCH_TAP, as the following illustrates:

upBtn.addEventListener(TouchEvent.TOUCH_TAP,moveNow);

With that knowledge, you’re all set to set up an app using TouchEvent.

Many Ears; One Handler

One of the big memory hogs in programming, especially noticeable in mobile devices, is event listening. Each event listener sets up a series of operations that have to keep listening for an event. Having a single event won’t help, but it’s a step in the direction of having a single listener (which will help). The following Client sets up an example of using the TouchEvent. All of the buttons are SimpleButton objects and the background is a big Sprite. Likewise, Sam3 is a Sprite that you can move around using tap on your mobile device.

?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
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
package 
{
	import flash.display.Sprite;
	import flash.display.SimpleButton;
	import flash.events.TouchEvent;
	import flash.ui.Multitouch;
	import flash.ui.MultitouchInputMode;
 
	public final class Client extends Sprite
	{
 
		private static var leftBtn:SimpleButton=new Left();
		private static var rightBtn:SimpleButton=new Right();
		private static var upBtn:SimpleButton=new Up();
		private static var downBtn:SimpleButton=new Down();
		private static var bkground:Sprite=new Background();
		private var sam3:Sprite=new Sam3();
 
		public function Client()
		{
			addChildAt(bkground,0);
			setControls();
			setSamurai();
		}
 
		private final function setControls():void
		{
			Multitouch.inputMode = MultitouchInputMode.TOUCH_POINT;
			upBtn.x = 825,upBtn.y = 19;
			upBtn.addEventListener(TouchEvent.TOUCH_TAP,moveNow);
			addChild(upBtn);
 
			leftBtn.x = 740,leftBtn.y = 106;
			leftBtn.addEventListener(TouchEvent.TOUCH_TAP,moveNow);
			addChild(leftBtn);
 
			rightBtn.x = 873,rightBtn.y = 105;
			rightBtn.addEventListener(TouchEvent.TOUCH_TAP,moveNow);
			addChild(rightBtn);
 
			downBtn.x = 825,downBtn.y = 202;
			downBtn.addEventListener(TouchEvent.TOUCH_TAP,moveNow);
			addChild(downBtn);
		}
 
		private final function setSamurai():void
		{
			sam3.x=(960/2); sam3.y=(640/2)+100;
			addChild(sam3);
		}
 
		private final function moveNow(e:TouchEvent):void
		{
			switch(e.target.name)
			{
				case "instance11":
				sam3.y -=5;
				break;
 
				case "instance1":
				sam3.x -=5;
				break;
 
				case "instance6":
				sam3.x +=5;
				break;
 
				case "instance16":
				sam3.y +=5;
				break;
 
			}
		}
	}
}

I set it up to be viewed from a landscape perspective because of a larger project I’m developing. Also, as you can see in the moveNow method, there are no “brakes” on the movement, and so the character can move anywhere, including right off the stage. Currently, I have a nicely working global movement system set up using a State Pattern, and I’d like to integrate both local and global movement into a single movement. Not only would this cut down on the number of listeners, but it would also provide a more interesting game. Figure 1 shows how it looks on an iPhone, and I’d like any feedback if tried on Android or other non-iOS devices.

The 960 x 640 size is compressed to fit in an iPhone environment

You also might want to swap out the TouchEvent for a MouseEvent and try it again in a mobile device. You’ll find that it gets “stuck” after a few clicks. As always, we’re interested in your comments and feedback.

Share
Categories: Mobile, Speed Tweaks

ActionScript 3.0 Single Class Event Handler

January 13, 2012 11 comments

reachout

Reaching out to Single Class for Event Handling

One Object:Several Events

The first time I read Scott Petersen’s article on optimizing code for iOS devices, I got it wrong in terms of what he was trying to do in one of the optimizations. In re-reading it, I discovered an interesting structure Scott included, and while not a speed tweak in and of itself, I thought it deserved a short discussion and example.

The idea is to have one object with several methods handle all event requests. A single method handles a single request. As you know, event-requests expect one parameter–the event-object listening for the event. Once initiated, the event.target object can be used to determine an appropriate course of action. To see how this works, I put together a simple class for handling requests. It does nothing more than trace back the label of the UI that makes the initial request.

?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
package 
{
	import flash.events.MouseEvent;
 
	public final class OneNav
	{
		public final function navNorth(e:MouseEvent):void
		{
			trace(e.target.label);
		}
 
		public final function navSouth(e:MouseEvent):void
		{
			trace(e.target.label);
		}
		public final function navEast(e:MouseEvent):void
		{
			trace(e.target.label);
		}
		public final function navWest(e:MouseEvent):void
		{
			trace(e.target.label);
		}
	}
}

With the OneNav class, the Client can then address all event handlers to the same class (object) and just append the specific method to the object. The general format is:

listeningObj.addEventListener(MouseEvent.CLICK,actionObj.actionMethod);

So now the developer can have everything to be handled in a single class with methods taking care of the details. If the details change, the developer can just go change the methods to reflect the changed details. To test it out, I’ve included the following Client class:

?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 fl.controls.Button;
	import flash.events.MouseEvent;
 
	public final class Client extends Sprite
	{
		private var btnNorth:Button=new Button();
		private var btnSouth:Button=new Button();
		private var btnEast:Button=new Button();
		private var btnWest:Button=new Button();
		private var navNow:OneNav=new OneNav();
 
		public function Client()
		{
			btnNorth.addEventListener(MouseEvent.CLICK,navNow.navNorth);
			btnNorth.x=50;btnNorth.y=50;
			btnNorth.label="North";
			addChild(btnNorth);
 
			btnSouth.addEventListener(MouseEvent.CLICK,navNow.navSouth);
			btnSouth.x=50;btnSouth.y=80;
			btnSouth.label="South";
			addChild(btnSouth);
 
			btnEast.addEventListener(MouseEvent.CLICK,navNow.navEast);
			btnEast.x=50;btnEast.y=110;
			btnEast.label="East";
			addChild(btnEast);
 
			btnWest.addEventListener(MouseEvent.CLICK,navNow.navWest);
			btnWest.x=50;btnWest.y=140;
			btnWest.label="West";
			addChild(btnWest);
		}
	}
}

In some respects, this technique can add more work for the developer as he tries to figure out how to get the events to spark something on the viewing area even if he’s using a design pattern. This particular implementation reflects work I’ve been doing on the navigation portion of a game I’m developing, but the technique could apply to virtually any project. I would have to have the OneNav method call a State Pattern to get the appropriate image to show up on the stage. The would take a bit of doing. However, for some other kind of application, it might be just the thing you need.

A Final Word

One of the speed tweaks that Scott points out in this same article is using final in marking classes and methods. If you’re not subclassing a given class, you can mark it final as done in the Client class. Marking a class final allows compile-time determination of the exact function being called. When some methods of a class can be overridden, you cannot mark the class final but you can mark the individual method as final, as was done in the OneNav class.

As a matter of fact, I cannot think of a single use case where I would subclass a Client class, and so, it’s probably a safe bet to mark all Client classes as final. When developing with ActionScript 3.0 for mobile devices, every single speed tweak matters.

Share
Categories: Mobile, Speed Tweaks

Speed Tweaks: Reuse Objects

October 23, 2011 2 comments

speedy

Reuse Static Objects to Reduce Garbage Collection

Green Code

When I recycle, I’m doing green. The same idea for functions is equally helpful in avoiding garbage collection. Instead of writing a separate function, reuse one you’ve got. I got the idea from an article by Scott Pertersen, but while working on this post I realized that Scott was talking about something else. He noted that using function objects instead of events cuts down on program allocations. Following that thought, he suggests listening for an event just once. One event handler deals with the event for multiple clients. (Sounds like an Observer design pattern—always a good idea.)

Taking these two thoughts together, I made a single pair of event handlers for multiple objects. That wasn’t Scott’s meaning. He’s pointing out that the fewer events the better; not lots of events handled by fewer functions. However, creating a static method that handles any number of different static properties seemed to be a good idea because both the static method and properties were re-used. (Some other time, I’ll look into how to listen for an event once. It makes sense to do so.)

Static Drag

For now, I’d like to take a look at reusing two event handlers—start and stop drag with mouse down/up. I realize that this doesn’t use any kind of special mobile ActionScript 3.0 (AIR statements to be used in conjunction with mobile devices), and we’ll get to that in further posts. For now, I just want to focus on writing a single pair of static methods for event targets. Using the drag states is simple and explains the idea. (You can download the files if you wish—click the download button.)
playkilroy
To keep things clean, I created a class that makes shapes that can be used by a direct call. Then, I used a Client class to call the shapes (in Sprite objects) for dragging around a mobile stage. Note that it is flush with static properties:

?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
46
47
48
49
package
{
	import flash.display.Sprite;
 
	public class ShapeSelect extends Sprite
	{
 
		private static var ball:Sprite = new Sprite  ;
		private static var box:Sprite = new Sprite  ;
		private static var triangle:Sprite = new Sprite  ;
 
		public function doBall():Sprite
		{
			return makeBall();
		}
 
		public function doBox():Sprite
		{
			return makeBox();
		}
 
		public function doTriangle():Sprite
		{
			return makeTriangle();
		}
		//Color: B9121B,4C1B1B,F6E497,FCFAE1,BD8D46
		private static function makeBall()
		{
			ball.graphics.beginFill(0xB9121B);
			ball.graphics.drawCircle(50,50,50);
			return ball;
		}
 
		private static function makeBox():Sprite
		{
			box.graphics.beginFill(0xBD8D46,.8);
			box.graphics.drawRect(10,10,80,80);
			return box;
		}
 
		private static function makeTriangle():Sprite
		{
			triangle.graphics.beginFill(0x4C1B1B,.7);
			triangle.graphics.drawTriangles(Vector.<number > ([10,20,20,90,150,90]));
			triangle.graphics.endFill();
			return triangle;
		}
	}
}

As you can see the public functions return a ball, box or triangle Sprite pulled from three private static functions. No great shakes, but it’s clean and clear. All of the static functions mean that the objects are built in compile-time.

Next, they’re called from a Client class. The MOUSE_DOWN and MOUSE_UP events are called and all objects use the same start/stop drag functions. This reduces the number of methods required, but it is not doing anything for reducing the resources used in calling an event. That I’d like to take up in a future post.

?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
package
{
	import flash.display.Sprite;
	import flash.events.MouseEvent;
 
	public class Client extends Sprite
	{
		private static var ball:Sprite=new Sprite();
		private static var box:Sprite=new Sprite();
		private static var triangle:Sprite=new Sprite();
		private static var shapeSelect:ShapeSelect=new ShapeSelect();
 
		public function Client()
		{
			ball = shapeSelect.doBall();
			ball.x = 50,ball.y = 20;
			addChild(ball);
			ball.addEventListener(MouseEvent.MOUSE_DOWN,doDrag);
			ball.addEventListener(MouseEvent.MOUSE_UP,noDrag);
 
			box = shapeSelect.doBox();
			box.x = 70,box.y = 80;
			addChild(box);
			box.addEventListener(MouseEvent.MOUSE_DOWN,doDrag);
			box.addEventListener(MouseEvent.MOUSE_UP,noDrag);
 
			triangle = shapeSelect.doTriangle();
			triangle.x = 100,triangle.y = 120;
			addChild(triangle);
			triangle.addEventListener(MouseEvent.MOUSE_DOWN,doDrag);
			triangle.addEventListener(MouseEvent.MOUSE_UP,noDrag);
		}
		//All of the event calls use the same two static functions
		private static function doDrag(e:MouseEvent)
		{
			e.target.startDrag();
		}
		private function noDrag(e:MouseEvent)
		{
			stopDrag();
		}
	}
}

I tried this out using iOS AIR and when I tried it out in my iPhone, it worked quite smoothly.

Share
Categories: Speed Tweaks

Speed Tweaks: Static Objects and Methods

Add ActionScript 3.0 Speed Tweaks to Mobile Apps

Add ActionScript 3.0 Speed Tweaks to Mobile Apps

Time to Look at the Details

When I first started writing ActionScript 3.0 for mobile devices, I wrote it pretty much like I did for desktop or laptop computers. One of the early programs included a simple tween that would move a logo from the middle of the page to the top left corner revealing a center-page main image. Instead of getting a spiffy movement to get the viewer’s attention, on my mobile phone I got a slow-as-mud tween that seemed to get stuck in the middle. (The image to the left shows the logo taking its sweet time moving from the middle to the top of an iPhone.)

Both on this blog and in our book, the focus has been on design patterns and related topics—loose binding, reusability and class/object relationships. The issue of speed has been relegated to the back seat with only occasional references to optimizing speed in programs. The Flyweight, skip-list and a few other posts are among those exceptions. Now, we’re going to look at speed tweaks (and invite you to share your own.) Our first is using static properties and methods.

What’s Up with Static?

The idea of a static property or function is usually one of immutability—unchangeable. Isn’t that that same thing as a constant? In some respects, yes, but it’s more than that. Besides, why is a static object faster? After all, that’s the important consideration for a speed tweak.

At the base of a static object is what is called static memory allocation. Basically, this process occurs during compilation before run-time when the program is executed. Think of it as calling in an order (compile-time) at a take-out restaurant. When you show up at the restaurant, your order is ready. That’s a lot faster than making the order and then waiting around while they’re fixing the order at run-time.

Static objects are something like private accessors and something like CONSTANTS. First, static properties are accessible only through a defining class or when returned by arguments. Second, when immutable values are used when a variable is statically defined, it does not have to be re-defined. In our book in both Chapter 3 (Singletons) and Chapter 6 (Composite) you will find several examples of static variables at work. They are especially popular in use with Singletons, so be careful. (For an unbiased discussion of Singletons, see these posts.)

Static Easy

Static properties are not all that difficult to create. In the following listing, which I created using an Android AIR template, you can see a simple constant literal set as a static property and a static method called from a Client class, which also uses static variables:

?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
//Static property and method
package
{
	import flash.display.Sprite;
 
	public class StaticObject extends Sprite
	{
		private static const AS3DP:String = "ActionScript 3.0 Design Patterns";
 
		public function StaticObject()
		{
			showStatic();
		}
		private static function showStatic()
		{
			trace(AS3DP);
		}
	}
}
 
//Static variable
package
{
	import flash.display.Sprite;
 
	public class Client extends Sprite
	{
		private static var statObject:StaticObject;
		public function Client()
		{
			statObject=new StaticObject();
		}
	}
}

I tend to think about static variables in the same way as I do private accessors—but for different purposes. I try and use private accessors for encapsulation and forcing myself to write better OOP. For static properties, I just think more speed. Scott Petersen has a good article on these and other issues involving mobile device optimization for iOS, and you should take a look at what he has to say about static objects as well.

Share
Categories: Speed Tweaks