Archive for the ‘Flex’ Category

Exile Issue 1 Released

Tuesday, April 27th, 2010

Exile Issue 1 Cover

The game I’ve been working on at my day job has been released. The first issue of Exile is available today, and if you order now for $8 you get the remaining 3 issues delivered digitally when they are released.

Exile is unlike most games and most graphic novels, in that it offers first rate art and story with a compelling interface including interactivity, a soundtrack, and sound effects. We’ve also put a lot of effort into making the game as immersive as possible by providing unlockable elements within the game that give players a look at concept art, character sketches, and even minigames set in the Exile universe. The end result is a unique experience and the game succeeds in blurring the line between graphic novels and video games.

I’ve been lucky to work with a great team of artists and writers on this game, and I couldn’t be happier with the way this has turned out.

Flixel Pixel Perfect Collisions

Sunday, January 31st, 2010

I haven’t found a decent source of information about this on the interwebs so I thought I’d share my findings. Flixel doesn’t have any built in pixel perfect collision support, it just assumes that you are using square (or at least rectangle) sprites and don’t use any rotation. Well, that’s not entirely a real world assumption so some of us will have to dig around and implement something ourselves. Hence, the below class.

The class I developed is a simple override of the base FlxSprite class with some modifications to its collision detection system. It takes advantage of the fact that each sprite has its own set of BitmapData in its own coordinate space, which the framework uses to blit to the main screen BitmapData. BitmapData objects in Flash provide us with a native implementation (in the Player AFAIK) of per pixel collision detection, using the hitTest method.

The hitTest method takes 5 parameters, but we only really care about the first 4. The first parameter we pass it defines where the calling BitmapData object is in screen space, i.e. the sprite’s (x,y) coordinates. We then pass it a threshold alpha value, 0 being transparent and 255 being opaque. If you want semi-transparent regions of your sprite to collide then set this to something lower than 255 (0xFF is the hexadecimal representation of decimal 255). The third parameter is the colliding sprite’s BitmapData object. And the fourth is the colliding sprite’s (x,y) coordinates in screen space.

I have abstracted this into the class’s structure, so the overridden functions handle everything. You can use another alpha threshold by setting the sprite’s alphaThreshold value to something valid, as explained above. You can also disable this pixel perfect collision detection method per technique by either setting doPerfectCollide or doPerfectOverlap to false. Because there are two methods Flixel uses to detect collisions, the class implements enhanced versions of both, and allows you to disable either independently.

Note that, in order for the collision detection to be pixel perfect, either a) both colliding objects must subclass PPlxSprite or b) the sprite calling overlaps or collide must sublcass PPlxSprite and the colliding sprite must have a single frame. This is due to fact that the original FlxSprite class does not expose the _framePixels BitmapData object which is needed to collide the objects with the frame that is currently displayed. When a FlxSprite is collided with a PPlxSprite and the perfect collision is enabled, the exposed _pixels BitmapData is used, which contains the entire sprite sheet, so collisions are detected against all frames, not just the frame displayed. However, changing existing sprite’s to use this class is easy enough so as not to cause problems.

Note also that we only call the hitTest method when we know there is already a bounding box collision, so as not to waste CPU cycles. The native hitTest method is fast but probably not fast enough to call every frame, which would be wasteful in any case.

Below is the PPlxSprite class which override the collision methods to provide pixel perfect collisions.

import flash.display.BitmapData;
import flash.geom.Point;

import org.flixel.FlxCore;
import org.flixel.FlxSprite;

public class PPlxSprite extends FlxSprite {

    public var alphaThreshold:uint = 0xFF;
    public var doPerfectOverlap:Boolean = true;
    public var doPerfectCollide:Boolean = true;

    protected var _corePos:Point = new Point();
    protected var _thisPos:Point = new Point();

    public function PPlxSprite(X:int=0, Y:int=0, SimpleGraphic:Class=null) {
        super(X, Y, SimpleGraphic);
    }

    public function get framePixels():BitmapData { return this._framePixels; }

    override public function overlaps(Core:FlxCore):Boolean {
        var doesOverlap:Boolean = super.overlaps(Core);
        if (doesOverlap && this.doPerfectOverlap && Core is FlxSprite) {
            doesOverlap = this.perfectCollision(FlxSprite(Core));
        }
        return doesOverlap;
    }

    public function perfectCollision(Sprite:FlxSprite):Boolean {
        this._corePos = Sprite.getScreenXY(this._corePos);
        this._thisPos = this.getScreenXY(this._thisPos);

        var corePixels:BitmapData;
        if (Sprite is PPlxSprite) {
            corePixels = PPlxSprite(Sprite).framePixels;
        } else {
            // i guess other standard FlxSprites are boned if they are animted
            corePixels = Sprite.pixels;
        }

        return this._framePixels.hitTest(this._thisPos, this.alphaThreshold, corePixels, this._corePos);
    }

    override public function hitWall(Contact:FlxCore=null):Boolean { return this.hitSomething(Contact); }
    override public function hitFloor(Contact:FlxCore=null):Boolean { return this.hitSomething(Contact); }
    override public function hitCeiling(Contact:FlxCore=null):Boolean { return this.hitSomething(Contact); }

    public function hitSomething(Contact:FlxCore):Boolean {
        var didHit:Boolean = true;
        if (this.doPerfectCollide && Contact is FlxSprite) {
            didHit = this.perfectCollision(FlxSprite(Contact));
        }

        return didHit;
    }
}

 
Here I have overriden the core FlxSprite methods that are responsible for collision detection, those methods being overlaps and the hit family of methods. Overlaps gets called when you explicitly issue a sprite.overlaps(otherSprite); This is a simple override that adds functionality to the super overlaps method, namely, calling the pixel perfect detection method and returning its results.

The hit family of methods are called after calling the collide family of methods, including collideArray and the like. The collide methods, when they have detecting a bounding box collision, call the hit family of methods, depending on the location of the collision, which return a boolean. If the called hit method implemented by the sprite returns false, the collide method aborts and reports that it didn’t collide after all. This is the behavior on which the above hit methods rely, and return false when it detects that while a bounding box collision may have occurred, the pixels in either sprite have not collided.

A short usage class follows.

public class SomeSprite extends PPlxSprite {

    // Embed sprite image.

    public function SomeSprite(X:Number, Y:Number):void {
        super(X, Y);
        // Load sprite image, and other sprite stuff
    }

    override public function hitWall(Contact:FlxCore):Boolean {
        if (super.hitWall(Contact)) {
            this.hurt(1);
            return true;
        }
        return false;
    }
}

 
Here, all we do is simply extend the PPlxSprite class from above, and do what we normally do for sprites. We also decide to do something special when a character hits a wall, namely, get hut. To do this we override the hitWall method, call the super hitWall (which would be the PPlxSprite hitWall) method, and depending on its return value, we either get hurt or do nothing. We don’t need to do anything special for calling the overlaps method, as this will simply call PPlxSprite overlaps method.

So, hopefully this is helpful for someone looking to do this, or at least someone can find the ideas listed here useful. Let me know if you used it and if you find any bugs, improvements, or have any other suggestions.

Flixel Puddles and Oil Slicks

Monday, January 18th, 2010

I’ve been using the super cool Flixel framework to make a game and it’s quite handy for most things. The game I’m working on is basically a top down…ehh, well let’s just say it’s top down. :) I can post more details when the game is actually released.

As a category, top down and platformer games in general usually have some type of movement modification obstacles. These obstacles allow the player to pass through them, so they don’t stop the player from moving, but they somehow alter the player’s course by speeding up, slowing down, or sending the player in a different direction. In my case, these obstacles are oil slicks and water puddles, which speed up and slow down the player in whatever direction they are traveling. Here I will cover how I solved speeding up and slowing down the player when he crosses over such an obstacle.

Below is a skeleton of my main player class:

 package sprites {
	import org.flixel.FlxG;
	import org.flixel.FlxSprite;

	public class Player extends FlxSprite {

		[Embed(source="player.png")] private var Img:Class;

		protected var _runSpeed:Number = 100;

		public var velocityFactor:Number = 1;

		public function Girl(X:int=0, Y:int=0) {
			super(Img, X, Y, true, false, 58, 58);

			drag.x = this._runSpeed * 8;
			drag.y = this._runSpeed * 8;

			maxVelocity.x = this._runSpeed;
			maxVelocity.y = this._runSpeed;

			...
		}

		override public function update():void {
			// MOVEMENT
			acceleration.x = acceleration.y = 0;
			this.maxVelocity.x = this._runSpeed * this.velocityFactor;
			this.maxVelocity.y = this._runSpeed * this.velocityFactor;
			if (FlxG.keys.UP) {
				acceleration.y -= drag.y;
			}
			// And similarly for all 4 key directions
			...

			super.update();
		}
	}
}

Using this player class, we can see that by modifying the velocityFactor instance variable, we can effectively control how fast the player can move around the screen. By setting velocityFactor equal to a value less than one, we decrease the player speed, and by setting it equal to a value greater than one we increase the player speed. So what we need now is a way to modify this value externally in response to player interaction with the world, namely, the player stepping onto a puddle or an oil slick. We also need sprites that define how they should change the player movement when they are stepped over.

Below is a skeleton of one of my obstacle classes:

package sprites.obstacles {
	import org.flixel.FlxG;
	import org.flixel.FlxSprite;

	public class SpawnerObstacle extends FlxSprite {

		public function get playerVelocityFactor():Number { return 2; }

		[Embed(source="spawner.png")] private var SpawnerImg:Class;

		public function SpawnerObstacle(X:int=0, Y:int=0) {
			super(SpawnerImg, X, Y, true, false, 24, 24);

			this.fixed = true;
		}

	}
}

Here is just a simple implementation of a FlxSprite class where we define that this sprite, when stepped over, speeds up the player by a factor of 2.

Below are the relevant parts of the update() method in my main PlayState class.

this._player.velocityFactor = 1;
for each (sprite in this._obstacles) {
	if (this._player.overlaps(sprite)) {
		trace('modifying player velocity');
		this._player.velocityFactor = obstacle.playerVelocityFactor;
		break;
	}
}

Here we loop over the obstacle sprites in the _obstacles array. This array would be created whenever you initialize the obstacles for the game. The obstacles themselves, in this case, are instances like the above SpawnerObstacle class, which have a playerVelocityFactor getter attached. In the beginning, we make sure that we set the player’s velocityFactor to 1 so that the player moves at the default speed in the case that they are not on top of an obstacle sprite. We also break out of the loop when we collide with a single obstacle sprite to avoid any extra complexity. We could make it so that we average the velocity factors when multiple obstacle sprites are encountered, but I don’t have this use case so it would be unnecessary.

When all these parts are in place and working in conjunction, we have a game that satisfies our original goal. When the player collides with one of our obstacles sprites, he is either sped up or slowed down, depending on the velocity factor defined by the colliding sprite. If I get any less lazy (highly unlikely) I’ll post an example swf with source code.

Flash Draw Transparent BitmapData

Tuesday, January 12th, 2010

Recently ran into an issue where I thought I should have been drawing a transparent BitmapData object, but the resulting object had a white background. The original incorrect code was the following:

var bd:BitmapData = new BitmapData(w, h, true);

 
The third boolean argument to the function is a transparency flag, and here it is set to true. However, when creating a Bitmap object from this BitmapData object and adding it to the display list, it clearly has a white background instead of being transparent.
 
To remedy this, the solution is to pass along to the function a 32bit color value where the alpha value is zero. The following code illustrates this solution:

var bd:BitmapData = new BitmapData(w, h, true, 0x00000000);

 
This will create a totally transparent BitmapData object on which you can draw whatever you desire. In practice I use this to determine the alpha values of a given pixel in a given display object. The following function implements this technique:

public static function getAlphaAt(d:DisplayObject, x:Number, y:Number):Number {
	// Even though we set transparent to true, we still need to use a transparent color.
	// This is easily done by setting alpha to 0; the RGB octects after that don't matter.
	var bd:BitmapData = new BitmapData(d.width, d.height, true, 0x00000000);
	bd.draw(d);
	return (bd.getPixel32(x, y) >> 24 & 0xFF)/255;
}

Flex Scale Image to Max Dimension

Monday, January 11th, 2010

Recently had a problem where I needed to display images as large as possible within given bounds. So I made a handy little function that computes the scaling needed so that the image, if it is larger than any of the bounds, is scaled so that its largest dimension becomes equal to the given maximum. This function scales the image proportionally so it won’t skew it.

public function scaleImageToMaxDimension(img:Image, maxWidth:Number, maxHeight:Number):void {
	var scaleH:Number=1, scaleV:Number=1;
	if (img.content.height > maxHeight) {
		scaleV = maxHeight / img.content.height;
	}
	if (img.content.width > maxWidth) {
		scaleH = maxWidth / img.width;
	}
	img.scaleX = img.scaleY = Math.min(scaleH, scaleV);
}

 
Flex doesn’t do a terribly good job of resizing images, however, but it works for images that just need to be tweaked to fit. If you have control over your images and your display size, it is always best to resize them as needed to save space/bandwidth and preserve quality. This approach works best when you have little or no control over either.

In application this code would be used after the image has finished loading. So for example I might do something like the following:

import flash.events.Event;
import mx.controls.Image;

public class Test {
	public var image:Image;

	// pretend scale function is here

	public function Test {
		image = new Image();
		image.addEventListener(Event.COMPLETE, imageComplete, false, 0, true);
		image.load('http://www.google.com/intl/en_ALL/images/logo.gif')
	}

	private function imageComplete(event:Event):void {
		scaleImageToMaxDimension(image, 100, 100);
	}
}

Flash 10 Valid Vector Elements

Wednesday, August 19th, 2009

Finally got around to learning about the new collection class available in Flash 10. To be honest, I’m not terribly excited about many things in Flash 10, hence my slowness to adapt.

But, the vector class does interest me somewhat. It promises faster iteration over a strongly typed collection. Doesn’t seem to add any other handy features however, like Flex’s robust ArrayCollection methods including removeItem. But alas. As for it being faster, I have heard talk around the internets of the vector class only being significantly faster with simple types, but I’m way too lazy to any informal benchmarks of my own, so I’ll just read someone else’s results.

One specific question I had that I didn’t see answered anywhere, however, was the type of objects you could stick in a vector once the template class had been set. It was my suspicion that you could put any subclass of the template class in the vector, just like C++ templated vetors, but I hadn’t read it confirmed anywhere, so I fired up my shiny new Flash CS4 and gave it a try. And indeed, my suspicion was correct. The following simple code below validates my hypothesis.

var test:Vector.<Sprite> = new Vector.<Sprite>();
test.push(new Sprite(), new MovieClip());

// should output something like "[object Sprite],[object MovieClip]"
trace(test);

Copying a Flash MovieClip, or The Flash Holy Grail

Friday, May 15th, 2009

Ran into a nice solution for copying arbitrary MovieClips at runtime today. I am designing a spot the difference game akin to 6 Differences with the requirement that, upon finding a difference, the scene should go to the “correct” state depending on which difference was defined as master, among a few other criterion. This required that I somehow duplicate, as much as is possible, the state of the “master” difference, when appropriate.

At any rate, the solution comes from Danny Burbol’s blog, which apparently came from a Experts Exchange thread (damn people charging for information). I modified the solution a bit to fit my needs, but not by a whole lot. Sometimes I only need to copy the instance and I can reconstitute the MovieClip from there but other times I will need to get the whole shebang. It’s pretty handy in general. So my version follows (as a bonus I include my handy-dandy clearAllChildren function):

package com.bmm.utils {
  import flash.display.DisplayObject;
  import flash.display.DisplayObjectContainer;
  import flash.geom.Rectangle;

  /**
   * ...
   * @author BenS
   */
  public class UIUtils {

    public static function clearAllChildren(c:DisplayObjectContainer):void {
      if (c == null || c.numChildren == 0) return;

      var i:int = 0, n:int = c.numChildren;
      for (i = 0; i < n; i++) {
        c.removeChildAt(0);
      }
    }

    public static function simpleDisplayObjectClone(source:DisplayObject):DisplayObject {
      var cc:Class = Object(source).constructor;
      return new cc();
    }

    public static function displayObjectClone(source:DisplayObject):DisplayObject {
      var copy:DisplayObject = UIUtils.simpleDisplayObjectClone(source);

      copy.transform = source.transform;
      copy.filters = source.filters;
      copy.cacheAsBitmap = source.cacheAsBitmap;
      copy.opaqueBackground = source.opaqueBackground;
      if (source.scale9Grid) {
        var r:Rectangle = source.scale9Grid;
        copy.scale9Grid = r;
      }

      return copy;
    }
  }
}

Flexunit Asyncrhonous Setups

Thursday, February 12th, 2009

If you ever need to load some external data before running a test, or need to wait for a component’s creation complete event, then you know the inadequacies of the Flexunit framework when it comes to asynchronous operations. One approach you might think of is to load the XML data, for example, in the setUp() method and attach a handler to the loader to wait for the complete event which would then call runMiddle() so the actual test body runs. You would need to override the runMiddle() method in your test case, and call super.runMiddle() in your complete handler. However, while this will cause the tests to run properly after the data has become available, Flexunit will not hang around long enough to catch the passed/failed asserts in your test body. You will instead get a runtime error box telling you which asserts failed, and a green bar from the Flexunit UI. This is not desirable.

What we need then is to somehow write a test case that begins loading the data, and somehow specifies which method to run that contains the actual asserts for the test method. Essentially if you wanted to do really simply you would just load the data with a Loader object, attach a complete handler to the loader wrapped with the addAsync method of the TestCase to delay test execution, and write the complete handler so that it accepts the complete event and does what it will with the event.currentTarget. I would rather have a general asynchronous setup method that takes as parameters the URL of the data to load, the test handler with all the asserts, and the class of the data that should be loaded. Instead of a jumble of words explaining this it would probably help more to just paste the code at this point.

package {
	import flash.events.Event;
	import flash.net.URLLoader;
	import flash.net.URLRequest;

	import flexunit.framework.TestCase;

	public class AsyncSetupTestCase extends TestCase {

		public var data:*;
		public var returnType:Class;

		public function setupAsync(target:String, test:Function, returnType:Class):void {
			this.returnType = returnType;
			var helper:Function = this.addAsync(this.completeHandler, 1000, test);
			var loader:URLLoader = new URLLoader();
			loader.addEventListener(Event.COMPLETE, helper);
			loader.load(new URLRequest(target));
		}

		private function completeHandler(event:Event, test:Function):void {
			trace('async load complete');
			this.data = event.currentTarget.data as this.returnType;
			test.call(this);
		}

	}
}



As the previous code demonstrates, I have simply extended Flexunit’s TestCase class and added a few methods to help with asynchronous setups. Essentially all a test case that needs to load external data must do then is to call the setupAsync method with the desired information, and AsyncSetupTestCase will handle running the test once the load is complete. All the designated handler in the test needs to do differently from other tests is to a) not be prefixed with test and b) use the data property to access the loaded data from the setup. An example test case demonstrating this follows:

public function testMethod():void {
	this.setupAsync('something.xml', this.doTestMethod, XML);
}
public function doTestMethod():void {
	// do what we will with this.data, it shall be an XML instance
	assertTrue(this.data is XML);
}

Flex MenuItem Actions

Friday, January 30th, 2009

So, gonna write this here because I will forget how to do it. Essentially, this approach eliminates the need to conditionally branch on menu item properties. Before we would do something like:

private function menuHandler(event:MouseEvent):void {
    if (event.item.@label == 'Save') {
        f = File.destopDirectory;
        f.browseForSave('Save');
        f.addEventListener(Event.SELECT, this.selectSaveFolderHandler);
    } else if (event.item.@label == 'Open') {
        // etc
    }
}

As you can see, this is an awfully coupled solution. Whenever we want to change the name of a menu item, we also need to change the logic in the handler. This can be somewhat alleviated by using an @id property instead of the display text, but its still coupled. The better solution is to allow the menu item itself designate what action it should trigger when clicked. This is the method that Buttons use, but for menu items it’s a little different because the menu is simply XML data.

What we need then is a way to store a method name in the menu item XML definition, have that parameter read by the menu handler method, and the appropriate method called. For simplicity we limit the specified method to whichever class contains the actual menu, and that the method has no required arguments. The magic here is the use of the flash.utils.getDefinitionByName() function to return a Function definition rather than a Class, and using the Function.call() method to actually call the returned Function. So our revised menu item XML would look something like:

<!-- menu items -->
<mx:XMLList>
    <menuitem label="Save" action="saveMenuHandler"/>
    <menuitem label="Open" action="openMenuHandler"/>
</mx:XMLList>

And our handler would look like:

// AS handler
private function menuHandler(event:MouseEvent):void {
    var method:String = String(event.item.@action);
    try {
        var methodRef:Function = Function(flash.utils.getDefinitionByName(method));
        methodRef.call(this);
    } catch (e:ReferenceError) {
        trace(e.message);
    }
}

I haven’t tested this idea so no idea if it works or not, so YMMV. But it should work, and if I ever get around to refactoring some old code I will certainly be including this.