Tile-Based Game Development in Flex
I’ve started work on a tile-base gaming engine in Flex. The hope is to post tutorials based on my work, but until then you can check out the current demo here: http://game.morrise.com and the source for the project is freely downloadable from here: http://code.google.com/p/gameengineas3/.
Flex Bulletin Board
Some time ago I started work on a Bulletin Board application that I built using Flash technology. It’s probably been over a year since I did anything major with it. Last week, while I was moving files from one server to another I realized that there were several places linking to that Bulletin Board and the links would be dead. While I was at work I got on opportunity to prototype some functionality that was very similar to the work I had done on the Flash version on the Bulletin Board, but this time I got to build it in Flex. Once I discovered that my prototyping could be done in the context of the Bulletin Board I decided to whip up an application that is essentially a duplicate of what I’d already created visually, but behind the scenes I’ve made some vast improvements. The previous version was saving all the data about the Bulletin Board in a database and was being recalled using PHP. I’ve not change the functionality so that the Bulletin Board definition is stored in an XML document. I’ve also made the Bulletin Board flexible enough to allow notes that contain something other than text. I’m now able to add notes that are image based, as well as videos. The demo that I have up now is not enabled for text or video, but maybe someday I’ll put that in.
Also, for those interested, you can download the source for this project here.
Calling Flex Methods From JavaScript
If you want to call methods inside of your Flex application from javascript all you have to do is a couple of simple steps. First you have to add the external interface to you flex application:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="creationComplete()">
<mx:Script>
<![CDATA[
import mx.controls.Alert;
private function creationComplete():void
{
ExternalInterface.addCallback("doCall", myCall);
}
private function myCall(message:String):void
{
Alert.show("Did Call: " + message);
}
]]>
</mx:Script>
</mx:Application>
Then, from JavaScript you need to access the movie and then call the method that was created as an external interface. You can even pass in parameters:
function getMovie(movieName)
{
if (navigator.appName.indexOf("Microsoft") != -1) {
return window[movieName];
} else {
return document[movieName];
}
}
function doCall() {
getMovie("[Your Movie Name Here]").doCall("Hello World!");
}
Setting TextInput Focus on Load
For those who have tried, you’ve probably noticed that your Flex applications can set focus on TextInput elements when it loads. The reason behind this is that the Flash player doesn’t get focus unless you click on it or tell it to get focus from JavaScript. There is a solution that seems to work well with most browsers for getting focus on the Flash player:
function getFlashMovieObject(movieName) {
if (window.document[movieName]) {
return window.document[movieName];
}
if (navigator.appName.indexOf("Microsoft Internet")==-1) {
if (document.embeds && document.embeds[movieName]) {
return document.embeds[movieName];
}
} else {
return document.getElementById(movieName);
}
}
function setBrowserFocus() {
getFlashMovieObject('${application}').focus();
}
You must also add the onload attribute to the body so it will call the setBrowserFocus method like this:
<body onload="setBrowserFocus()">
Once you’ve done this all you have to do is create a handler that will set the focus on a TextInput like so:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute"
creationComplete="creationCompleteHandler()">
<mx:Script>
<![CDATA[
private function creationCompleteHandler():void
{
focusManager.setFocus(textInput);
}
]]>
</mx:Script>
<mx:TextInput id="textInput" />
</mx:Application>
Custom Flex Preloader
Flex has a built in preloader that isn’t very stylish, so it stands to reason that you might want to create your own. The process for this isn’t very well documented, but it’s not very difficult if you know what you’re doing.
To get your custom preloader to work you have to add the preloader attribute to the Application tag. I’ve also put the preloader in the same directory as the Application mxml, but you could put it in any directory as long as you give the preloader attribute the full package path.
<?xml version="1.0" ?>
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
width="100%"
height="100%"
layout="absolute"
preloader="CustomPreloader">
<!-- Your Code Here -->
</mx:Application>
Your custom loader class must extend the DownloadProgressBar class. I’ve drawn the progress bar programmatically, but you are free to try what you want.
package
{
import flash.display.GradientType;
import flash.display.InterpolationMethod;
import flash.display.MovieClip;
import flash.display.SpreadMethod;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.ProgressEvent;
import flash.filters.DropShadowFilter;
import flash.geom.Matrix;
import mx.events.FlexEvent;
import mx.preloaders.DownloadProgressBar;
public class CustomPreloader extends DownloadProgressBar
{
public var progress:Sprite;
public var progressTotal:Sprite;
public static var PROGRESS_WIDTH:Number = 274;
public static var PROGRESS_HEIGHT:Number = 6;
public function CustomPreloader():void
{
super();
progressTotal = new Sprite();
addChild(progressTotal);
var type:String = GradientType.LINEAR;
var colors:Array = [0x545454, 0x8A8A8A];
var alphas:Array = [1, 1];
var ratios:Array = [0, 255];
var spreadMethod:String = SpreadMethod.PAD;
var interp:String = InterpolationMethod.LINEAR_RGB;
var focalPtRatio:Number = 0;
var matrix:Matrix = new Matrix();
var boxWidth:Number = PROGRESS_WIDTH;
var boxHeight:Number = PROGRESS_HEIGHT;
var boxRotation:Number = Math.PI/2; // 90˚
var tx:Number = 0;
var ty:Number = 0;
matrix.createGradientBox(boxWidth, boxHeight, boxRotation, tx, ty);
progressTotal.graphics.beginGradientFill(type,
colors,
alphas,
ratios,
matrix,
spreadMethod,
interp,
focalPtRatio);
progressTotal.graphics.lineStyle(1, 0x000000);
progressTotal.graphics.drawRoundRect(0, 0, PROGRESS_WIDTH, PROGRESS_HEIGHT, PROGRESS_HEIGHT);
progressTotal.graphics.endFill();
progress = new Sprite();
addChild(progress);
var dropShadowFilter:DropShadowFilter = new DropShadowFilter;
dropShadowFilter.blurX = 10;
dropShadowFilter.blurY = 10;
dropShadowFilter.distance = 0;
dropShadowFilter.color = 0x90d955;
progress.filters = [dropShadowFilter];
}
public function drawProgress(percentage:Number):void
{
progress.graphics.clear();
var type:String = GradientType.LINEAR;
var colors:Array = [0x99DE62, 0x7AC142];
var alphas:Array = [1, 1];
var ratios:Array = [0, 255];
var spreadMethod:String = SpreadMethod.PAD;
var interp:String = InterpolationMethod.LINEAR_RGB;
var focalPtRatio:Number = 0;
var matrix:Matrix = new Matrix();
var boxWidth:Number = PROGRESS_WIDTH*percentage;
var boxHeight:Number = PROGRESS_HEIGHT;
var boxRotation:Number = Math.PI/2; // 90˚
var tx:Number = 0;
var ty:Number = 0;
matrix.createGradientBox(boxWidth, boxHeight, boxRotation, tx, ty);
progress.graphics.beginGradientFill(type,
colors,
alphas,
ratios,
matrix,
spreadMethod,
interp,
focalPtRatio);
progress.graphics.drawRoundRect(0, 0, PROGRESS_WIDTH*percentage, PROGRESS_HEIGHT, PROGRESS_HEIGHT);
progress.graphics.endFill();
}
public override function set preloader(preloader:Sprite):void
{
preloader.addEventListener(ProgressEvent.PROGRESS, onSWFDownloadProgress);
preloader.addEventListener(Event.COMPLETE, onSWFDownloadComplete);
preloader.addEventListener(FlexEvent.INIT_PROGRESS, onFlexInitProgress);
preloader.addEventListener(FlexEvent.INIT_COMPLETE, onFlexInitComplete);
progressTotal.x = stage.stageWidth/2 - PROGRESS_WIDTH/2;
progressTotal.y = stage.stageHeight/2;
progress.x = stage.stageWidth/2 - PROGRESS_WIDTH/2;
progress.y = stage.stageHeight/2;
}
private function onSWFDownloadProgress(event:ProgressEvent):void
{
drawProgress(event.bytesLoaded/event.bytesTotal);
}
private function onSWFDownloadComplete(event:Event):void
{
//onSWFDownloadComplete
}
private function onFlexInitProgress(event:FlexEvent):void
{
//onFlexInitProgress
}
private function onFlexInitComplete(event:FlexEvent):void
{
dispatchEvent( new Event(Event.COMPLETE));
}
}
}
Inverse Mask
Here’s how to do an inverse mask in Flex:
<mx:Canvas width="100%" height="100%" blendMode="{BlendMode.LAYER}" backgroundColor="#FFFFFF" alpha=".75"
horizontalScrollPolicy="off" verticalScrollPolicy="off">
<mx:Canvas id="crop" width="100" height="100" backgroundColor="#000000"
blendMode="{BlendMode.ERASE}" horizontalCenter="0" verticalCenter="0"/>
</mx:Canvas>
This will punch a 100×100 hole in a shape with a 75% opacity.
Flex Coding Conventions
While recently looking for a definitive list of coding conventions in Flex I discovered this document on adobe’s website: Flex SDK coding conventions and best practices. This document, while useful, is not complete. There are many things that are not complete in this document, so I decided to add some of the missing pieces.
Component IDs
When creating a new component in mxml use an identifier for the function of the button postfixed with the object type.
Do this:
<mx:Button id="addItemButton" label="Add Item" />
Not this:
<mx:Button id="add" label="Add Item" />
Or this:
<mx:Button id="addItem" label="Add Item" />
Custom PopUps
Where building a component that will be used for a popup, postfix the component definition with PopUp
ex: AddItemPopUp.mxml
GalleryBuilder Working Demo
I’ve put a working demo of the GalleryBuilder software here: http://bit.ly/3yFUV2. Check it out.
Username: test
Password: test
Cairngorm Project
One of the best ways I’ve found to learn something is by looking at a working example. The Gallery Builder project is built using the Cairngorm Framework. Feel free to download the source and check it out. Once again the url for the project: http://code.google.com/p/gallerybuilder/
Click + Drag Multi-Select in Flex TileList
While working on the Flex Gallery Builder project, I’m using a TileList component to display the images for each gallery. As I built this, one piece of functionality that I found to be missing is the ability to click and drag a selection box to select the elements in the TileList. I have therefore come up with a solution; I’ve built a custom component based on the TileList component that includes the ability to click and drag. Since I’m unable to post the code here effectively, Check out the code at http://code.google.com/p/gallerybuilder/ and look for the GalleryList.mxml file.
Edit: Here is a link to the file itself - GalleryList.mxml

Recent Comments