Pushbutton Engine – Working With Virtual Controls

In this article we’re going to look at how you can add virtual controls to your games. This is especially useful if you are looking to port or convert your games to alternative platforms such as tablets and smartphones that tend to be touch-screen driven. I’m not going to go over the process of creating virtual controls in this article as I have already covered this in detail in the article “Virtual Controllers For Touch Based Devices”. You can read part 1 here and part 2 here.
In fact, the thumbstick control used here is the very same one described in that article.

Creating the Boilerplate
As with most of the articles in this series, you’ll need to start with some boilerplate code. Don’t worry if you don’t want to copy and paste the code below – you can just grab the source code for this article from the Related Files section. It is worth noting that this was created using Flash Builder 4.5 and the new ActionScript mobile project that comes with it, so if you want to test the example code I suggest you grab a trial copy of Flash Builder 4.5 otherwise it won’t compile correctly).

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
package
{
	import com.flashgen.gaming.controllers.KeyboardController;
	import com.pblabs.engine.PBE;
	import com.pblabs.engine.entity.IEntity;
	import com.pblabs.engine.entity.PropertyReference;
	import com.pblabs.engine.entity.allocateEntity;
	import com.pblabs.rendering2D.SimpleSpatialComponent;
	import com.pblabs.rendering2D.SpriteRenderer;
	import com.pblabs.rendering2D.ui.SceneView;
 
	import flash.display.Sprite;
	import flash.geom.Point;
 
	[SWF(width="1024", height="600", frameRate="30", backgroundColor="0xCCCCCC")]
	public class Main extends Sprite
	{
 
		private var _sceneView		:SceneView;
 
		public function Main()
		{
			PBE.startup(this);
 
			initializeScene();
			initializeHero();
			initializeBackground()		
		}
 
		private function initializeBackground():void
		{
			var _bg		:IEntity = allocateEntity();
 
			var _spatial		:SimpleSpatialComponent = new SimpleSpatialComponent();
			_spatial.position = new Point(0, 0);
 
			_bg.addComponent(_spatial, "Spatial");
 
			var _renderer	:SpriteRenderer = new SpriteRenderer();
			_renderer.fileName = "assets/sprites/starfield.png";
			_renderer.layerIndex = 1;
			_renderer.scene = PBE.scene;
 
			_renderer.positionProperty = new PropertyReference("@Spatial.position");
 
			_bg.addComponent(_renderer, "Renderer");
 
			_bg.initialize();
		}
 
 
		private function initializeHero():void
		{
			var _hero	:IEntity = allocateEntity();
 
			var _spatial	:SimpleSpatialComponent = new SimpleSpatialComponent();
			_spatial.size = new Point(50, 50);
			_spatial.position = new Point(0, 0);
 
			_hero.addComponent(_spatial, "Spatial");
 
			var _renderer		:SpriteRenderer = new SpriteRenderer();
			_renderer.fileName = "assets/sprites/ufo.png";
			_renderer.layerIndex = 10;
			_renderer.scene = PBE.scene;
 
			_renderer.positionProperty = new PropertyReference("@Spatial.position");
 
			_hero.addComponent(_renderer, "Renderer");
 
			var _input	:KeyboardController = new KeyboardController();
			_input.positionProperty = new PropertyReference("@Spatial.position");
 
			_hero.addComponent(_input, "Controller");
 
			_hero.initialize();
		}
 
 
		private function initializeScene():void
		{
			_sceneView = new SceneView();
			_sceneView.width = 1024;
			_sceneView.height = 600;
 
			_sceneView.name = "MainView";
 
			PBE.initializeScene(_sceneView);
		}
	}
}


If you’ve been following the series you’ll already be familiar with this structure. If not here is a brief recap: there are three methods invoked by the constructor, each one deals with initializing an aspect of the game. Firstly there is the scene view – basically the game playing field. Second, there is the player character – often referred to as the ‘hero’. Finally, in this example there is the background. We’re not going to be doing a great deal with these methods in this article but it is beneficial for you to know what each aspect does. Instead we’re going to look at how you go about adding in the virtual controls I mentioned at the beginning and for that you don’t need to interact with Pushbutton Engine (PBE). (Well you do but I’ll clarify this point when we come to it.)

Adding In Your Controls
First you need to create a new method called initializeControls() and invoke it right after the initializeBackground() method in your constructor. Inside this method you just instantiate the controllers – in this case just a single thumbstick control. You’ll notice in the code below that once the x and y positions have been set you invoke a call to _sceneView.addDisplayObject() and pass it a reference to the thumbstick.

1
2
3
4
5
6
7
8
private function initializeController():void
{
	var _js 	:ThumbStick = new ThumbStick();
	_js.x = 100;
	_js.y = 380;
 
	_sceneView.addDisplayObject(_js);
}


If you track back the variable _sceneView you’ll see it is instantiated and assigned in the initializeScene() method (this is the ‘it does / doesn’t need to interact with PBE’ bit). The SceneView class is one of the UI classes provided by PBE and it allows you to add objects to the SceneView instance (in this case _sceneView) the same way you would add items to the standard ActionScript DisplayList, so it is easy to create your game UIs completely separately to PBE and only wire them in where necessary (you can even leverage Flex for your UIs if you choose).

So How Does The Controller Work?
Without going over the ground the articles about virtual controllers have already covered, the controller does nothing more than dispatch key press events based on the movement of the actual ‘thumb’ of the thumbstick. By default, these are mapped to Up, Down, Left and Right. You will recall from one of the earlier articles how to add user input control to your ‘hero’ entity. Well, with a class called KeyboardController() mapped in to the initializeHero() method as one of the ‘hero’ components, whenever the user moves the thumbstick the relevant key press events are fired and the KeyboardController() class associated with the hero is triggered.

1
2
3
4
var _input	:KeyboardController = new KeyboardController();
_input.positionProperty = new PropertyReference("@Spatial.position");
 
_hero.addComponent(_input, "Controller");


I’ve put a version below, but this has limited functionality when it comes to testing virtual controls for a couple of reasons. Firstly, you’re running in a simulated environment – in the case of the example below it is mapping the controller’s movements to mouse events and not touch events. This is primarily because few people have touch screen computers (although if you look at this article on a Blackberry PlayBook or Android Tablet it should work as expected). Secondly, it isn’t your target platform for these types of controls so performance and functional testing ‘off device’ will only get you so far and are unlikely to give you an ideal representation of real world conditions.

[kml_flashembed publishmethod=”dynamic” fversion=”10.0.0″ replaceId=”virtualControl” movie=”http://blog.flashgen.com/swfs/pbe006-virtualcontrols.swf” width=”500″ height=”400″ targetclass=”flashmovie”]

Get Adobe Flash player

[/kml_flashembed]
Summary
In this article you’ve seen how you can easily go about adding in virtual controls to your games just by mapping them back in to existing controllers. And, you can easily add them to the display list of the SceneView class to create whatever additional UI elements you may require. We’ll be looking at more complex user interfaces in future articles so be sure to check back often.

Related Files
PBE006-VirtualControls.zip
PBE006-VirtualControlsWebDemo.zip

Leave a Reply

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