Archive

Archive for the ‘Mobile’ Category

The Grid State: Movement in Mobile

February 12, 2012 4 comments

GridStateRelMatrix Work

As our desktop screens soar to new heights in size, we find ourselves coping with smaller platforms for mobile viewing. To address this problem, developers simply move from one cell, grid or section to another. Each new cell becomes the full screen. For example, a 3 x 3 matrix has 9 cells (grid sections or just ‘grids’). The matrix can be seen as a “game universe” and each cell is the current “stage” for interaction. Some of you old-timers may remember the Star Trek games from the early days of desktop computing. Your starship would be an asterisk and you’d go from grid cell to grid cell chasing or chased by Romulans or Klingons, and when you came to the edge of a section you’d just change sections and with it came a new “stage.”

I have no idea of the programming behind those games, but the concept is perfectly clear. As you change sections, you get a new ‘map’ of that section. To get a sense of what’s going on, click the Play button to view the desktop version of the game, and then the Download button to get all of the code and objects in FLA and SWC files:
play buttondownload this sucker

Movement Rules

To get started building this game, I wanted to begin with simple movement rules. So I decided that movement would only be up, down, left, right. No diagonal movement allowed. For example, if an object were in Grid 7, it could go either to Grid 4 or Grid 8. No movement to Grid 5 or off the grid allowed. The opponent character is randomly placed into one of the grids, and the player moves from grid to grid until he finds the opponent. Figure 1 shows an example:

two sams

Figure 1: The player's samurai and opponent meet in a grid cell

The four Japanese characters are buttons for movement direction—North (up), South (down), West (left) and East (right). The buttons are simple ones and use a TouchEvent to slip in images behind the button set and characters. A single “Attack” button does nothing more than animate the characters [for now]. Eventually, I want the movement of the individual samurai objects to move across each grid and then jump to the next grid once he reaches a border. I also want the character to move faster along roads than non-road terrain. For example, in Figure 2, the character would be able to move speedily along roads to the next grid cell moving north, south or east, but moving west (left) movement would be slower because the lack of a road. Also, he would be able to move at road speed across the bridge (bottom right), but he would move across the river with no bridge at a much slower rate if at all.

Figure 2: Movement options (iPhone screen shot)

At this juncture, all I have is the movement through grids and not within a grid. In order to facilitate movement, I’ve employed a State Design Pattern (See Class and File Diagrams in earlier posts). Each state class shows the options. For example, State 5 is right in the middle of the grid (see grid map at the beginning of this 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
package 
{
	public class Grid5State implements IGrid
	{
		private var context:Context;
 
		public function Grid5State(context:Context)
		{
			this.context = context;
		}
 
		public function goWest():uint
		{
			context.setState(context.getGrid4State());
			return 4;
		}
		public function goEast():uint
		{
			context.setState(context.getGrid6State());
			return 6;
 
		}
		public function goNorth():uint
		{
			context.setState(context.getGrid2State());
			return 2;
		}
		public function goSouth():uint
		{
			context.setState(context.getGrid8State());
			return 8;
		}
	}
}

As you can see, all four directions are available to a player in Grid 5. However, if we look at Grid 9, the player can only go north or west as shown in the following 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
package 
{
	public class Grid9State implements IGrid
	{
		private var context:Context;
 
		public function Grid9State(context:Context)
		{
			this.context = context;
		}
 
		public function goWest():uint
		{
			context.setState(context.getGrid8State());
			return 8;
		}
		public function goEast():uint
		{
			return 9;
		}
		public function goNorth():uint
		{
			context.setState(context.getGrid6State());
			return 6;
		}
		public function goSouth():uint
		{
			return 9;
		}
	}
}

If the player tries to go south or east, the class simply returns to value of the current grid and the player goes nowhere. Likewise, no context is changed. A choice of north or west results in the appropriate change in context and the next grid cell is slipped in.

The Client, Context and State Interface

Like all State Design Patterns, the Client makes its calls through the context. In this case the Client is pretty big because it is also setting the state with buttons and whatnot. However, once in place, the navigation and attack buttons no longer need to be called because the backgrounds are slipped beneath them. You can see how this works in Client 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
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
package 
{
	import flash.display.Sprite;
	import flash.display.MovieClip;
	import fl.controls.Button;
	import flash.display.SimpleButton;
	import flash.events.TouchEvent;
	import flash.ui.Multitouch;
    import flash.ui.MultitouchInputMode;
 
	public class Client extends Sprite
	{
		private static var sam1:MovieClip=new Sam1();
		private static var sam2:MovieClip=new Sam2();
		private static var context:Context=new Context();
		private var grid:Sprite=new Sprite();
 
		private var foeGrid:uint = uint(Math.random() * (9 - 1) + 1);
		private var gridNow:uint;
 
		private static var attackBtn:Button=new Button();
 
		private static var westBtn:SimpleButton=new West();
		private static var eastBtn:SimpleButton=new East();
		private static var northBtn:SimpleButton=new North();
		private static var southBtn:SimpleButton=new South();
 
		private var grid1:Sprite=new Grid1();
		private var grid2:Sprite=new Grid2();
		private var grid3:Sprite=new Grid3();
		private var grid4:Sprite=new Grid4();
		private var grid5:Sprite=new Grid5();
		private var grid6:Sprite=new Grid6();
		private var grid7:Sprite=new Grid7();
		private var grid8:Sprite=new Grid8();
		private var grid9:Sprite=new Grid9();
 
		public function Client()
		{
			grid = this["grid" + context.randomStart()];
			addChildAt(grid,0);
			sam1.x = 350,sam1.y = 220;
			addChild(sam1);
			sam1.gotoAndStop(1);
			sam2.x = 400,sam2.y = 100;
			sam2.gotoAndStop(1);
			setControls();
		}
 
		private final function setControls():void
		{
			Multitouch.inputMode = MultitouchInputMode.TOUCH_POINT;
			northBtn.x = 67,northBtn.y = 5;
			northBtn.addEventListener(TouchEvent.TOUCH_TAP,northNow);
			addChild(northBtn);
 
			westBtn.x = 5,westBtn.y = 80;
			westBtn.addEventListener(TouchEvent.TOUCH_TAP,westNow);
			addChild(westBtn);
 
			eastBtn.x = 150,eastBtn.y = 80;
			eastBtn.addEventListener(TouchEvent.TOUCH_TAP,eastNow);
			addChild(eastBtn);
 
			southBtn.x = 67,southBtn.y = 160;
			southBtn.addEventListener(TouchEvent.TOUCH_TAP,southNow);
			addChild(southBtn);
 
			//Animate
			attackBtn.width = 50,attackBtn.label = "Attack!";
			attackBtn.x = 15,attackBtn.y = 360;
			attackBtn.addEventListener(TouchEvent.TOUCH_TAP,attackNow);
			addChild(attackBtn);
		}
 
		private final function northNow(e:TouchEvent):void
		{
			if(gridNow==foeGrid)
			{
				removeChild(sam2);
			}
			removeChild(grid);
			gridNow = context.doNorth();
			if (gridNow==foeGrid)
			{
				addChild(sam2);
			}
			grid = this["grid" + gridNow];
			addChildAt(grid,0);
		}
 
		private final function westNow(e:TouchEvent):void
		{
			if(gridNow==foeGrid)
			{
				removeChild(sam2);
			}
			removeChild(grid);
			gridNow = context.doWest();
			if (gridNow==foeGrid)
			{
				addChild(sam2);
			}
			grid = this["grid" + gridNow];
			addChildAt(grid,0);
		}
 
		private final function eastNow(e:TouchEvent):void
		{
			if(gridNow==foeGrid)
			{
				removeChild(sam2);
			}
			removeChild(grid);
			gridNow = context.doEast();
			if (gridNow==foeGrid)
			{
				addChild(sam2);
			}
			grid = this["grid" + gridNow];
			addChildAt(grid,0);
		}
 
		private final function southNow(e:TouchEvent):void
		{
			if(gridNow==foeGrid)
			{
				removeChild(sam2);
			}
			removeChild(grid);
			gridNow = context.doSouth();
			if (gridNow==foeGrid)
			{
				addChild(sam2);
			}
			grid = this["grid" + gridNow];
			addChildAt(grid,0);
		}
 
		//Toggle button
		private static function attackNow(e:TouchEvent):void
		{
			if (e.target.label == "Attack!")
			{
				sam1.gotoAndPlay(1);
				sam2.gotoAndPlay(1);
				attackBtn.label = "Cease!";
			}
			else
			{
				sam1.gotoAndStop(1);
				sam2.gotoAndStop(1);
				attackBtn.label = "Attack!";
			}
		}
	}
}

One of the features in the Client class that I don’t like is the use of conditional statements in the calls to the different directions. I found that the “Foe Samurai” was a bit of a problem. He’s only allowed in the random cell that has been selected, and if I didn’t remove the sam2 object, he’d get over stacked whenever the player object (sam1) entered the cell. There’s probably some more elegant way to deal with that issue, but I didn’t see it.

I decided to use grid numbers—unsigned integers—in the hope of making the code more efficient. The grid number is knitted to a “grid” from a Sprite class stored in the Library. All grids are instantiated and assigned values at the outset and so they’re not re-instantiated; just added and removed from the stage–sort of like the magic trick where the table cloth is pulled quickly from a table and all the dishes and silverware remain on top.

The IGrid interface and Context class are pretty simple. The interface has methods for the four directions:

?View Code ACTIONSCRIPT
1
2
3
4
5
6
7
8
9
10
11
12
package 
{
	//Interface
 
	public interface IGrid
	{
		function goWest():uint;
		function goEast():uint;
		function goNorth():uint;
		function goSouth():uint;
	}
}

Given the polymorphism that goes into each of these methods with the nine concrete states, it’s really nice to have this kind of interface. It’s a mix of flexibility, simplicity and possibilities.

The Context is also fairly simple, but it is at the heart of the State pattern because it keeps track of the current state. By doing so, no matter what state (grid cell) the samurai is in, not only does it know what cell it in, the connected concrete State class provides all the options available—without a single conditional statement.

?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
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
package 
{
	//Context class
 
	class Context
	{
		private var grid1State:IGrid;
		private var grid2State:IGrid;
		private var grid3State:IGrid;
		private var grid4State:IGrid;
		private var grid5State:IGrid;
		private var grid6State:IGrid;
		private var grid7State:IGrid;
		private var grid8State:IGrid;
		private var grid9State:IGrid;
		private var stateNow:IGrid;
		private var rndNow:uint;
 
		public final function Context()
		{
			trace("States Set");
			grid1State = new Grid1State(this);
			grid2State = new Grid2State(this);
			grid3State = new Grid3State(this);
			grid4State = new Grid4State(this);
			grid5State = new Grid5State(this);
			grid6State = new Grid6State(this);
			grid7State = new Grid7State(this);
			grid8State = new Grid8State(this);
			grid9State = new Grid9State(this);
 
			rndNow=uint(Math.random() * (9-1) +1);
			stateNow = this["grid"+rndNow+"State"];
		}
 
		public final function randomStart():uint
		{
			return rndNow;
		}
		public final function doWest():uint
		{
			return stateNow.goWest();
		}
 
		public final function doEast():uint
		{
			return stateNow.goEast();
		}
 
		public final function doNorth():uint
		{
			return stateNow.goNorth();
		}
 
		public final function doSouth():uint
		{
			return stateNow.goSouth();
		}
 
		public final function setState(stateNow:IGrid):void
		{
			this.stateNow = stateNow;
		}
 
		public final function getGrid1State():IGrid
		{
			return this.grid1State;
		}
		public final function getGrid2State():IGrid
		{
			return this.grid2State;
		}
		public final function getGrid3State():IGrid
		{
			return this.grid3State;
		}
		public final function getGrid4State():IGrid
		{
			return this.grid4State;
		}
		public final function getGrid5State():IGrid
		{
			return this.grid5State;
		}
		public final function getGrid6State():IGrid
		{
			return this.grid6State;
		}
		public final function getGrid7State():IGrid
		{
			return this.grid7State;
		}
		public final function getGrid8State():IGrid
		{
			return this.grid8State;
		}
		public final function getGrid9State():IGrid
		{
			return this.grid9State;
		}
	}
}

Note that all of the grid state properties are typed as IGrid types—that’s Programming to the interface instead of the implementation. This provides the properties with far more flexibility and reduces binding. Likewise, the return types on the getter functions were all typed to the IGrid interface, and so changes are easy because objects are not bound to the implementation.

Some (More) Mobile Tweaks

In the original version of this app, I used the SimpleButton timeline with different states for Up/Over/Down/Hit. I noticed that the Over state did not work but the buttons did—sort of. However, the movement was gummy and I often had to tap the button several times. I removed all of the states except for Up state and the movement event handling went much smoother. I could probably just as well use Sprite objects for buttons and I may change that.

Another feature that I want to work on is a New Game button of some sort. Given the sparse real estate on a mobile device I may have to have some kind of popup menu with different options for a new game, attacking and defending. I’d like to clear out memory and re-set where the “opponent” samurai goes—fresh start the whole thing.

Finally, I’m going to have to integrate intra-cell and inter-cell movement. All movement within a cell will uses the current State pattern so that when the samurai reaches the border it will jump to the next cell. This kind of movement may require an additional set of state classes, but right now I’m not sure. Likewise, I want to set it up so that simultaneous movement of the player samurai and the robot samurai can attack/defend. The Symmetric Proxy Pattern (Chapter 13) can possibly be employed so that each combat movement is judged simultaneously.

Share

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

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

ActionScript Design Patterns Transcend Changes at Adobe

November 10, 2011 18 comments

If you think everyone is heading for HTML5 now, you're nuts!

If you think everyone is heading for HTML5 now, you're nuts!

A lot of you may have heard the announcement from Adobe about dropping support for mobile browsers. It’s been a year and a half since we posted the article about the spat between Adobe and Apple, and now again, an announcement from Adobe has shaken things up.

According to The Economist (Oct 8-14, 2011), in 1993 there were 100 million PCs. By 2008, PCs had topped 1 billion. Many of us tapped into that market one way or another, and some of us came out well rewarded—Adobe certainly did. By 2020 (barely 8 years from now), they expect 10 billion mobile connected devices. In looking at the number consider this: The current #1 Free App on iOS devices is called ‘Hair Plucker’ and who knows how many people bought ‘Angry Birds’, 2010′s top paid for app? Among other apps I saw was a ‘Halloween Mouth’ selling for 99¢–it’s a picture of a mouth you hold up to your face. (How long would that take to create?) Another popular app is not one, but several, that make farting sounds–with prices ranging from free to $1.99.

Latest Update on Flex’s Fate!: Because so many questions about Flex were asked (e.g. Is this the end of Flex?) Adobe posed the following:

Adobe settles concerns about Flex and Flash.

Now let’s say, that you create a simple app using a Factory Method. You’ve got 10 billion units out there. We’ll say that you have a ‘Sneezing App’ that makes different sneezing sounds, and it sells for 99¢. If just 1% of 1% of 1% of 1% of 1% of 1% bought your app, that’s $10,000–a half million Indian rupees. If 1 person in 10,000 bought that app, you’d be a millionaire. (The good thing about language-independent apps like the ‘Halloween Mouth’ and ‘Fart Factory’ is that they are language independent.)

20 Billion Mobile Connected Devices Can’t Be Wrong!

I have no idea how many people will be using PCs as we know them. Maybe they’ll go the way of the 5 1/4 inch floppy and all we’ll have is some kind of tablet that we can connect up to the Internet. Development may be done with apps that we rent from a cloud. What is important and key now and later are mobile devices. At this point in time very few Web developers are actively developing apps for mobile devices, and tools like AIR for iOS, Android and Blackberry provide us with a key opportunity.

So, you can be certain that Adobe did not bow out of the Flash-Player-in-the-Mobile-Browser market because they thought it was not going to be a huge market. Look for Dreamweaver to be optimized for HTML5 and some HTML5 development tools. The development tool from Adobe for mobile, though, will be Flash Builder and Flash Pro working with AIR.

A Browser/AIR Mobile Strategy

Keeping in mind that I have nothing against HTML5 and it’s ability to do many things Flash has done for years—Canvas features some great elements and attributes—let’s look at a new strategy for development in Flash (including AS3 and the different flavors of AIR).

First off, if you’ve done much with with mobile browsers, you must have learned they have little to offer, and they are a mixed bag of HTML5 implementation. (The non-mobile browsers are an equal mixed bag as far as having implemented HTML5.) It’s only the mobile browsers that Adobe is no longer supporting. Not too many years ago, there were no mobile browsers; so basically, Adobe is doing what it has always done as far as providing a Flash plugin for the browsers on our computers. It’s just not going to make them for mobile browsers. I developed several apps for iOS, and while most have been simple and small, I was able to use the same programming structures I did for “regular” AS3.

Second, Adobe has been making big strides with Flash Builder and Flash Professional in creating AIR tools for working with mobile devices. This allows us to create ActionScirpt 3.0 apps for mobile devices—forget Web pages. Imagine knocking together an app that does something useful (like calculating the best point in relationship to a parabolic mirror to place a kettle to boil water) that can be used worldwide. Or even a game using some of the little structures we’ve been developing and discussing on this blog that you can sell for 99¢ (or more!). So quit thinking of yourself as just a “Web site developer/designer.” You’re an app developer/designer.

Everyone Runs to HTML5! Not!

Earlier this year I wrote a book (Smashing HTML5) published by Wiley, and one of the chores I encountered was testing the examples against several different browsers, including mobile ones. There was not a lot of compatibility, and most mobile browsers were successful with only a small subset of the HTML5 elements. Over time, let’s hope this improves because if it doesn’t we’ll enter the Second Dark Age of incompatible browsers.

In order to get most of the cooler stuff to work, you need either JavaScript or PHP, and so I included chapters on both. (PHP seems to be more compatible for all browsers than anything else–probably because of the simpler subset of HTML it generates.) I added as much OOP to both as possible, and some of the reviewers didn’t like the fact that it was not more oriented to the DOM or that I didn’t use more procedural examples in the PHP/JavaScript section. What I was trying to do was to write an HTML5 book for 2011 and not 2001, which meant that I used several examples of dealing with a mobile environment. Further, some OOP in JavaScript/PHP is a good thing; so I hope that will move some folks towards structure in both JavaScript and PHP.

However, without Flash in the mix, creating Web apps and pages is frustrating, not because JavaScript and PHP aren’t good programming tools but rather because of browser incompatibility. I’ve got a feeling that to effectively use HTML5 and all of the related CSS3, developers are going to be spending a lot of JavaScript code determining which browser is being used and making the appropriate accommodations. Who wants to sub-code for every possible browser? This includes mobile browsers. My hunch is that they’ll all head for the lowest common denominator, which is probably one of the mobile browsers that is just slightly better than HTML4.

So, I’ve started thinking “Build an App; Not a Web Page.” Let’s hear your thoughts on Adobe’s decisions.

Share
Categories: ActionScript, AIR, Mobile

Back to Statements and Algorithms: New Wine in Old Bottles

October 23, 2011 2 comments

As ActionScript 3.0 grows and changes, we can apply the old design patterns and begin looking for new patters to accommodate some changes.

As ActionScript 3.0 grows and changes, we can apply the old design patterns and begin looking for new patters to accommodate some changes.

Chandima and I have exhausted the set of design patterns that the Gang of Four published in 1995, and we even started looking at the new design patterns developed for parallel programming in Parallel Programming with Microsoft.NET: Design Patterns for Decomposition and Coordination on Multicore Architectures (2010), whose authors include Ralph Johnson, one of the original GoF. The problem with that route (at this time) is that C# has a bunch of statements for parallel programming and ActionScirpt 3.0 does not. There’s a lot edging its way to the front of the shelf as developers and Adobe work on Flex, Flash and Flash Builder. One technology, Pixel Bender provides a way to work with both the CPU and GPU. Pixel Bender has been around for a while, but it represents a feature of the future—accessing multiple processors from ActionScript 3.0.

AIR for Androids, iOS and Blackberry

Currently, the focus of most of the posts on this blog have been design patterns using ActionScript 3.0 with an occasional visit to some interesting structures such as dependency injection and skip lists. Now, a lot of the discussion will shift to newer statements and elements that make up the Flex/Flash family of APis and platforms. In particular you will want to take a look at the AIR 3 reference guide. Herein lie the statements, packages and namespaces that make up a lot of the new features we need to consider. Adobe helpfully marks each AIR class with a little red triangles with balls on the points.AIR In creating an AIR app, whether for a mobile device or computer, there are differences depending on the hardware device. Once we’ve covered several and created sample examples, we can cast them into design patterns. So, consider this next set of posts to be a temporary detour that will take the knowledge set forward but keep the utility of what has passed.

Share

ActionScript 3.0 Flash Builder App in Apple iOS: Decorator and State

September 5, 2011 4 comments

Change orientation with device position

Change orientation with device position

Decorator and State Patterns in Mobile Game Development
While I’m trying to find the best graphic tool to use in conjunction with mobile devices and ActionScript 3.0, I’ve decided to stick with wholly programmed images. (I’m a better programmer than artist, but my images do not improve because they’re programmed.) For this example, I used the ActionScript Mobile Project option in Flash Builder 4.5.1. If you’re using Flash Pro 5.5, you can use the same code by selecting AIR for iOS from the Flash main start-up menu. With both, everything is pure ActionScript 3.0—none of the drawing tools, components or other gizmos available in either FB or FP are employed—código puro in both. Click the button below to download the files for Flash Builder. (I also included the files for Flash Pro; so no one is left out.)
kilroy

Reminder: We’ve placed all of the downloads on the University of Hartford’s Multimedia Web Design and Development download page. Just select the bottom on the ActionScript 3.0 files and click the download button.

Flash Builder Tip: First create an ActionScript Project so that you can test it as you develop. Once you have it all developed, create an ActionScript Mobile Project and just copy and paste the files from the AS Project.

Re-Decorating

In this first part all I want to do with this mobile game is to build and decorate the warrior and put it on an iOS mobile device using Flash Builder. The mechanics are very similar to previous posts on using the Decorator pattern to arm a character (See here and here.) Figure 1 shows a file diagram of the Decorator implementation:

<em><strong>Figure 1:</strong>Decorator File Diagram</em>

Figure 1:Decorator File Diagram

Since this thing is going to be in pure code, we need to create a “warrior” in code, which was not done in the previous posts linked above. So outside of the pattern, we need a graphic image, as provided in 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
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
package
{
	import flash.display.Shape;
	import flash.display.Sprite;
 
	public class BuildWarrior extends Sprite
	{
		private var head:Shape=new Shape();
		private var torso:Shape=new Shape();
		private var lftArm:Shape=new Shape();
		private var rtArm:Shape=new Shape();
		private var lftLeg:Shape=new Shape();
		private var rtLeg:Shape=new Shape();
 
		public function assemble():Sprite
		{
			this.addChild(makeHead());
			this.addChild(makeTorso());
			this.addChild(makeLftArm());
			this.addChild(makeRtArm());
			this.addChild(makeLftLeg());
			this.addChild(makeRtLeg());
			return this;
		}
 
		private function makeHead():Shape
		{
			head.graphics.lineStyle(1,0x6F74B3);
			head.graphics.beginFill(0x6F91A6,.50);
			head.graphics.drawRect(30,17,10,3);
 
			head.graphics.lineStyle(0.25,0x0066ff);
			head.graphics.beginFill(0x035AA6,.40);
			head.graphics.drawCircle(35, 7,10);
			head.graphics.lineStyle(1,0x6F74B3);
			head.graphics.moveTo(30,6);
			head.graphics.lineTo(34,6);
			head.graphics.moveTo(36,6);
			head.graphics.lineTo(40,6);
			head.graphics.moveTo(32,12);
			head.graphics.lineTo(38,12);
			graphics.endFill();
			return head;
		}
 
		private function makeTorso():Shape
		{
			torso.graphics.lineStyle(1,0x6F74B3);
			torso.graphics.beginFill(0x6F91A6,.50);
			torso.graphics.drawTriangles(Vector.<number>([10,20, 60,20, 35,90]));
			torso.graphics.endFill();
			return torso;
		}
 
		private function makeLftArm():Shape
		{
			lftArm.graphics.lineStyle(1,0x6F74B3);
			lftArm.graphics.beginFill(0x6FB3A7,.75);
			lftArm.graphics.drawRect(10,20,10,40);
			lftArm.graphics.drawRect(10,60,40,8);
			lftArm.graphics.endFill();
			return lftArm;
		}
 
		private function makeRtArm():Shape
		{
			rtArm.graphics.lineStyle(1,0x6F74B3);
			rtArm.graphics.beginFill(0x6FB3A7,.75);
			rtArm.graphics.drawRect(50,20,10,40);
			rtArm.graphics.drawRect(51,60,8,40);
			rtArm.graphics.endFill();
			return rtArm;
		}
 
		private function makeLftLeg():Shape
		{
			lftLeg.graphics.lineStyle(1,0x6F74B3);
			lftLeg.graphics.beginFill(0x6FB3A7);
			lftLeg.graphics.drawRect(23,70,12,45);
			lftLeg.graphics.drawRect(24,115,10,45);
			lftLeg.graphics.endFill();
			return lftLeg;
		}
 
		private function makeRtLeg():Shape
		{
			rtLeg.graphics.lineStyle(1,0x6F74B3);
			rtLeg.graphics.beginFill(0x6FB3A7);
			rtLeg.graphics.drawRect(36,70,12,45);
			rtLeg.graphics.drawRect(37,115,10,45);
			rtLeg.graphics.endFill();
			return rtLeg;
		}
	}
}

All of the concrete decorators similarly implement coded graphic representations. Of course, all of these are “outside” of the design pattern but are useful to see in the contact of the pattern.

The Client

In the actual mobile client, you begin with a super(); call and support for auto orientation in the iOS device. The code is automatically generated:

?View Code ACTIONSCRIPT
1
2
3
// support autoOrients
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;

I tossed out the super(); call, and generated the following client:

?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
package
{
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
 
	public class MobileDecState extends Sprite
	{
		private var warrior:Component=new Warrior();
		private var warriorSpirit:Sprite=new Sprite();
		public function MobileDecState()
		{
			warriorSpirit.addChild(warrior.getarmor());
			warriorSpirit.x=50,warriorSpirit.y=50;
			addChild(warriorSpirit);
 
			warrior=new DecBodyArmor(warrior);
			warriorSpirit.addChild(warrior.getarmor());
 
			warrior=new DecShield(warrior);
			warriorSpirit.addChild(warrior.getarmor());
 
			warrior=new DecHelmet(warrior);
			warriorSpirit.addChild(warrior.getarmor());
 
			warrior=new DecParticleCompressor(warrior);
			warriorSpirit.addChild(warrior.getarmor());
 
			// support autoOrients
			stage.align = StageAlign.TOP_LEFT;
			stage.scaleMode = StageScaleMode.NO_SCALE;
		}
	}
}

Publishing for Mobile

For some reason, more steps are involved in publishing for Flash Builder than Flash Pro. However, once you have your certificate (it has a .p12 extension) and your provisioning file created using the tools available to Apple developers; it’s pretty simple. If you don’t know about the Apple iOS developer program for both Windows and Mac users, you need to go there first.

Here’s how to publish using Flash Builder: (Download the Beta version/update of Flash Builder 4.5.1. While you’re at it, download the beta version of Adobe AIR 3.)

1. Open a New > New ActionScript Mobile Project (Figure 2)

<em><strong>Figure 2: </strong> Open a New ActionScript Mobile Project </em>

Figure 2: Open a New ActionScript Mobile Project

2. Specify your target platform as Apple iOS with Automatically reorient selected and click Next. (Figure 3)

<em><strong>Figure3: </strong> Mobile Settings </em>

Figure3: Mobile Settings

3. Click the Platform Setting and select Platform and Target devices (Figure 4)

<em><strong>Figure 4: </strong> Specify Platformsettings </em>

Figure 4: Specify Platformsettings

4. Build Paths provides the opportunity to add SWC folders or a project. Figure 5 shows using the default settings.

<em><strong>Figure 5: </strong> Include additional or different paths if requires </em>

Figure 5: Include additional or different paths if requires

5. The next step in creating your app will not come until you are finished coding it all. Then when you press the green arrow (Run) button at the top, you will begin the Run Configurations sequence. Figure 6 shows the On device radio button selected. You are likely to see some red circles with white ‘X’s in them, but don’t worry. If there’s one next to the Packaging setting click the [Configure] link.

<em><strong>Figure 6: </strong> Run Configurations </em>

Figure 6: Run Configurations

6. Set the Certificate and Provisioning file. Both of these should be ready using the software that the Apple iOS Developer program provides. Use the Browse buttons to locate yours. (These cannot be generated using Adobe software.)

<em><strong>Figure 7: </strong> Setting Certificate and Provisioning files </em>

Figure 7: Setting Certificate and Provisioning files

Once the certificate and provisioning file are set, click the Apply button and then click OK.

7. If all has gone right you will see the Packaging Completed window shown in Figure 8. At this point you will have to open iTunes on your computer, and make sure that your mobile device is connected to your computer. You will need to locate the .ipa package and drop it into the iTunes library. It’s easiest to just click the (Reveal package in Finder) to get the .ipa package.

<em><strong>Figure 8: </strong> Completed Window </em>

Figure 8: Completed Window

8. Figure 9 shows the bin-debug folder opened with the .ipa package. Be sure that the Apps window on your iTunes library is selected and drag the .ipa package into the iTunes library.

<em><strong>Figure 9 </strong> Drag .ipa package into iTunes Apps Library </em>

Figure 9 Drag .ipa package into iTunes Apps Library

9. The final step requires that you select the connected device (shown right above Little Richard Greatest Songs in Figure 10 ) and then find your new app in the Sync Apps window. Be sure to check the box next to the app. Then click the Apply button. Clicking the Apply button will then begin the Sync process. Once it is finished you should see the icon.

<em><strong>Figure 10: </strong>Adding the app to an iOS device</em>

Figure 10: Adding the app to an iOS device


When you click the icon on your iOS mobile device, you will see the image shown at the top of this post. If you turn your device, the object will re-orient itself to the object’s orientation.

Adding the State Design

With this and the previous posts for mobile devices, you’ve seen that design patterns work well with mobile app development. All of the advantages found in design pattern development for computers can be found in creating applications for mobile devices.

In the next post, this process will be continued by adding a State pattern to the app to create a game. If you don’t have a mobile device, you can use the same coding for making the app for your computer.

Share
Categories: Decorator, Mobile, State

ActionScript 3.0 Design Patterns and iOS: A New Home for Apps

August 15, 2011 1 comment

Make Your Own Apps with Design Patterns

Make Your Own Apps with Design Patterns

It’s Easy Once You Get Your Certificate and Provisioning Profile

Having finally got my magical combination of permissions set up just so, the process began coming fairly easily. The problem is not Adobe, but rather getting the files from Apple just right. Once you get the files, you can use them over an over. One is a certificate file with a .p12 extension, and the other is a provisioning file. It looks like a lot of people are having the same problem because when I finally found a solution on the Web at StackOverflow several other developers indicated (with heart-felt thanks) that they were encountering the same problem. (The solution that worked for me was to start over and delete all provisioning profiles and login keychain.) So if you got your Apple iOS Developer ticket ($99 or free to University students/faculty), that’s just the first part. The next part is to hook up your iOS device (mine is a 3S iPhone) and using the Xcode development tools, go through a process that generates the files you need. The following image shows what these little gems look like. If you put those two files in with your AIR iOS files, it’s a piece of cake. (Go ahead and download the files as well.)

Same files can be used with different apps

Same files can be used with different apps


kilroy

Apple provides videos and a whole slew of tools and aids, and if you follow the instructions, you should be able to develop the right files. (Sad experience had led me to suggest that you take your time and follow instructions carefully.) Anyway, whether you get the certificate and provisioning files on the first time or whether you struggle like I did, once you’ve got them; they’re good for about four months. You can develop on either a Mac or Windows PC and re-use the same files on different apps. (I haven’t gone through the process that Apple has for getting an app in the App Store; so you’re on your own in that department.) The image on the right is a screenshot taken with an iPhone:

Animated tween, text and graphic

Animated tween, text and graphic

Step-By-Step

This section walks you through the process of working with a Flash Pro project set up for use with iOS. In the previous post on iOS, the sample project was to create banners that can be used in a Factory Method context by loading external .SWF files. On the iPhone, that didn’t work. The problem seemed to be the mobile device’s inability to grab the external .SWF files even though, the .SWF files were included in the General settings for the Included files window. So, using the same tweens, I created MovieClips and put them in the Flash Pro library and then set them up as classes. Then in the concrete product files, I just instantiated classes with the tweens instead of loading external .SWF files, and the rest of the program was unchanged. (That is where design patterns really shine—easy to make changes.)

Okay, now to step through the process. This was all done using AIR 3.0, Flash Player 11 public betas on a iMac running the new Lion OS. After you open a new AIR for iOS and write all of your code and add any graphics and text, the first step is to select the FLA file, make sure that nothing is selected on the stage and then click the little wrench icon next to the Player selection where it should indicate ‘AIR for iOS.’ That will open the AIR for iOS Settings window as shown in Figure 1:

<em><strong>Figure 1:</strong> General Settings of AIR for iOS</em>

Figure 1: General Settings of AIR for iOS

For getting started, choose Full screen instead of Auto orientation. Use the CPU for the Rendering processor, specify your device and choose the Standard resolution. The included files will be an .SWF and .XML file. Leave those alone, and for this app, you do not need to add any others.

For this next step, you’ll need both the certificate and provisioning files in the same folder with the other class files. So if you haven’t created those files and linked them to the device you’re testing it on; do so now. The click the Deployment button next to the General button at the top of the AIR for iOS Settings window. Figure 2 shows the deployment settings:

<em><strong>Figure 2:</strong> Deployment window</em>

Figure 2: Deployment window

The password for the certificate is the one you entered when you created the certificate—not one associated with your computer. Use the search folder to find your Provisioning profile file. The App ID is the name you gave your initial FLA file—I’m in the habit of calling all of mine “Client,” but now I’ve got to think about what users will see on their mobile device..

This post does not get into the iOS deployment beyond the local development stage. So, select the “Quick publishing for device testing” or “Quick publishing for device debugging.” I selected the former because I chose to do the debugging using the standard Flash tools. After all I went through to get the certificate and mobile provision files to work right, I wasn’t about to tempt fate just yet and do more than the minimum.

This final step is fun. You can easily create your own iOS icon. Here’s what you need to do to get started:

  1. Create a square image with your logo or some symbol you want to use to identify you application. Save it as a .PNG file. (In the image at the top of this post, you can see the two application icons using the Sandlight logo.) Be sure that the image has equal width and height.
  2. Save three images in sizes 29 pixel square, 57 pixel square and 512 pixel square. Depending on the mobile device, you may want to create other sizes as well. I started off with the Adobe Illustrator version and saved each size as a PNG file.
  3. Place the three image files in a folder named “icons” and place the icons folder in the directory where you are creating your mobile app.

In Figure 3, you can see the preview window showing the image used for the application described in this post.

<em><strong>Figure 3:</strong> Assigning icons for app image</em>” title=”Fig3″ width=”500″ height=”694″ class=”size-full wp-image-6158″ /><p class=Figure 3: Assigning icons for app image

Be sure to click each icon size for each of the three sizes and load the URL (icons/iconXX.png) before you click OK. Note also that two of the icons are settings for iPads, and so if you have an iPad, create image files for those as well.

Installing your iOS on your Mobile Device

Now you’re set to Publish your files required for an iOS mobile app. When you click “Publish” you will find that it takes a while to process everything. Once you’re finished, you will see all the files generated for your iOS device. Figure 4 shows the files you will see—including the all-important .IPA file.

<em><strong>Figure 4:</strong> Files used and generated</em>

Figure 4: Files used and generated

As you can see in Figure 4, one of the files is named BannerFactory.ipa. That is the file that will install your app onto your iOS mobile device. Connect your iPhone or iPad or iWhatever that runs on iOS, and double-click the IPA file and it will upload your app into the iTunes Apps folder. (On your iTunes, click Apps in the LIBRARY folder, and you should see your new application as shown in Figure 5.)

<em><strong>Figure 5:</strong> iTunes Apps folder</em>

Figure 5: iTunes Apps folder

If you see your application icon and file, you’ve been successful—up to this point. The last step is to install your app onto your mobile device. The final step is to select your device and then check your application Sync. Figure 6 shows iTunes with your application selected (checkbox) and ready for Sync.

<em><strong>Figure 6</strong>App set for installing in iPhone</em>

Figure 6: App set for installing in iPhone

Note in Figure 6 that the iOS device is selected under DEVICES in the left panel and that the new application (BannerFactory) has a check next to it. Click the Sync button (or Apply and then Sync) and if you have your device properly identified, you will see your icon and app on your mobile device.

Share

Mobile Banner Factory for iOS

Animated Banners are easy with Flash

Animated Banners are easy with Flash

Surprise your Users!

I’ve never been a big animated banner fan. They are contrary to everything I know about good Information Design. However, done right, they can add pizazz to a page. The trick is to make sure that after the banner has performed its show once to stop it. Like a twice told joke; the animation is only interesting the first time. After that, the banner needs to serve as a branding decoration. Further, you can make your opening page a bit more interesting by having multiple banners randomly appear. Every time the visitor opens the mobile app, he/she can look forward to seeing a different banner appear. Using a Factory Method design pattern, that can be easy to create and (more importantly) update. In this post I want to get set up with a simple (but handy) Factory Method design pattern for calling up different banners; so it can be regarded as a beginner’s introduction to the Factory Method pattern.

The plan is to walk through an iOS implementation of ActionScript 3.0 in both Flash Pro and Flash Builder. However, first I want to get the design pattern squared away, and then we can provide total focus on the iOS issues. Further, if you would rather create an app using Android or Blackberry, you can just use the code and design pattern is this post and forget about the subsequent iOS posts that use the design pattern shown in this post. I did not provide the downloads for this post because I used a generic ActionScript 3.0 implementation, and so you can just cut and paste the code in the listings that are part of this post. (The downloads for the iOS implementations will be provided in subsequent posts.) To get an idea of what this does, click the Play button and refresh the HTML page to see how one of two animated banners appear.
play

The Factory Method in an iPhone

Here, I want to use the Factory Method, but I’m not going to explain it (again.) That’s been done here in our blog and in Chapter 2 in our book. Here I just want to explain how it is used to generate random banners for an iPhone (or whatever other mobile or non-mobile device you want to use it with.) The factory (Creator) instantiates any number of concrete Product instances. As implemented in this example, each concrete product requires a concrete factory instance. I added a helper class, RandomSelector to generate random numbers in a range. The Client pulls in a random value (between 0 and 1) and then using a switch statement calls a method to request a SWF file to play an animated banner. (Those among you who want to create your own SWF banner and pull it up instead of the ones you see in the example can do so easily.) Figure 1 shows the File Diagram of the Factory Method as used in this implementation to provide an overview.

<em><strong>Figure 1:</strong> File Diagram of Factory Method Implementation</em>

Figure 1: File Diagram of Factory Method Implementation

As you can see in Figure 1, the Client makes the requests through the ICreator (factory) interface, the concrete factories instantiate the concrete products, which load the SWF files for display. The RandomSelector class sits off by the side providing a random value.
Read more…

Share
Categories: Factory Method, Mobile

Flash Builder Mobile ActionScript 3.0 Design Pattern

Flexible Design Pattern Re-used with Flash Builder Development

Flexible Design Pattern Re-used with Flash Builder Development

Easy Update

A couple of days ago, we had an example for beginners creating a mobile application using Flash Professional. We used an Android example because everyone can get the tools they need for emulating an Android. (By the way, partnering up with Google-Android and Flash was a brilliant move by Android. Being an “Apple Guy,” I thought I’d be doing nothing but apps for my iPhone and iPads; however, Android made it a lot easier to develop apps for Android using some kind of ActionScript 3.0 development tool, and Blackberry’s not far behind. So I am very happy to know that iOS is now available, but they’ll just have to wait their turn for a beginner’s post.) As promised, I wanted to create a beginner’s example using Flash Builder. This example uses the same Strategy Pattern as the Flash mobile tutorial. However, as you will see, there are some key differences when dealing with Flash Pro and Flash Builder. Also, I hope you see that a very different logo (FB instead of Sandlight) and text. All that was changed for this difference was swapping the image used for the logo and the text in the external text file. Also, I had to change some settings in the BringText class, but that too was easy and didn’t upset the program. Why? Because it was a design pattern!

Stepping Through Flash Builder Mobile

This is going to be the same walk-through with Flash Builder as with Flash Pro but with a few differences. The Flash Builder work flow is slightly different, but you will find more similarities than differences. Before we get going download Flash Builder 4.5.1. (You can use the 30-day free trial version.) You can probably work with FB 4 with all of the updates, including the Android SDK, but everything in this example was done with FB 4.5.1. (If you are a student or faculty, you can get a free educational version of FB if you contact Adobe with your student or faculty ID. Faculty can get it free for their classrooms and labs as well.) Install to the defaults. Go to Adobe Labs download and install both Adobe AIR 3 (beta) and Adobe Flash Player 11 (beta) and let’s get started:

First, open Flash Builder and select File > New > ActionScript Mobile Project. (Note: You will find both a Flex Mobile Project and an ActionScript Mobile Project; be sure to select ActionScript Mobile Project.) In the Project name window, name the project FBmoStrat as shown in Figure 1 :

<em><strong>Figure 1:</strong> New ActionScript Mobile Project window</em>

Figure 1: New ActionScript Mobile Project window

I used the default location and the default SDK, which was Flex 4.5.1. Click Next.

Second, when The Create an ActionScript Mobile AIR Project window appears with the Mobile Settings tab selected, you will see that all Target platforms (Apple iOS, BlackBerry Tablet OS and Google Android) are checked as shown in Figure 2.

<em><strong>Figure 2:</strong>Initial Create Window</em>

Figure 2:Initial Create Window

Third, uncheck both the Apple iOS and BlackBerry Tablet OS. When you do that, the Permissions for Android appear as shown in Figure 3:

<em><strong>Figure 3: </strong> Android Permissions</em>

Figure 3: Android Permissions

Be sure that the Platform is Google Android and that the only permission checked is INTERNET. The default is to Automatically reorient the screen in the Application settings. Leave that default checked and click the Next button.

Fourth, in the Build Paths step, you will see a set of default selections you can leave alone except for the Main application file that you want to change from FBmoStrat.as to Client.as. Figure 4 shows the step correctly configured:

<em><strong>Figure 4:</strong> Build Paths step</em>

Figure 4: Build Paths step

If your Build Paths steps looks like Figure 4, click Finish. You should see the following script automatically generated:

?View Code ACTIONSCRIPT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package
{
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
 
	public class Client extends Sprite
	{
		public function Client()
		{
			super();
 
			// support autoOrients
			stage.align = StageAlign.TOP_LEFT;
			stage.scaleMode = StageScaleMode.NO_SCALE;
		}
	}
}

The Stage Align and StageScaleMode built-in ActionScript 3.0 classes will help align the application when it is turned in different directions. The super() method invokes the parent class Sprite. You will be leaving the constructor function as is but add more materials for the Client class. Before doing that, go ahead and test the problem and download all of the files with the buttons below:
playkilroy

You still will need to test the file from Flash Builder and contend with one last set of settings. So gather up all of the files and read on before testing.

Read more…

Share
Categories: Mobile, Strategy Pattern