Archive for the ‘as3’ Category
Fast 2D Arrays/Vectors (and the Game Of Life)
Introduction
I was recently looking at an implementation of Conway’s Game Of Life, and was struck by the way in which the developer had constructed his grid. The Game of Life requires that you construct a two-dimensional array, but Flash does not support 2D arrays natively, so work arounds have to be found. There are slow workarounds, fast workarounds, and very fast workarounds. Of course, for very fast workarounds, we use Vector and target the Flash Player 10.
An example of Conway’s Game Of Life can be found below.
I should point out at the start that in these I am using for (var x:int = 0; x < 100; x++) loops. Using while (x--) or even while(--x > -1) may well be quicker, but here I am trying to highlight the relative speeds of the data structures that are being looped around, not the loops themselves.
Slow
public function generate():void
{
grid = [];
for (var x:int = 0; x < 100; x++)
{
grid[x] = [];
for (var y:int = 0; y < 100; y++)
{
grid[x][y] = Math.random() < 0.5;
}
}
}
public function retrieve(x:int, y:int):Boolean
{
return grid[x][y];
}
This is the slowest good method around. It's undoubtedly good, in that it is readable and concise. It's not so good in terms of speed though, because of the double Array reference that is required to get to the relevant reference. Array lookups are slow, and should be avoided in performance-critical areas.
Fast
public function generate():void
{
grid = [];
for (var x:int = 0; x < 100; x++)
{
for (var y:int = 0; y < 100; y++)
{
grid[x * 100 + y] = Math.random() < 0.5;
}
}
}
public function retrieve(x:int, y:int):Boolean
{
return grid[x * 100 + y];
}
Instead of putting your 2D grid in a nested array, we can just use a one-dimensional array, and use an expression x * 100 + y within the lookup to differentiate between cells.
If you're targetting the version 9 player still, then this is probably the fastest mechanism you're going to get. (there is probably no need to, the latest Flash player penetration statistics suggests about 95% adoption in the western hemisphere, and above 90% adoption elsewhere)
Fast (again, but with Vector)
public function generate():void
{
grid = new Vector.<Boolean>(10000, true);
for (var x:int = 0; x < 100; x++)
{
for (var y:int = 0; y < 100; y++)
{
grid[x * 100 + y] = Math.random() < 0.5;
}
}
}
public function retrieve(x:int, y:int):Boolean
{
return grid[x * 100 + y];
}
Moving to use the FP10 Vector class gives you some great benefits. The Flash Player can be told up-front how big the array is going to be, and it knows the type of element. It is all-round quicker to do it this way. However, this is not the quickest structure we can use!
Faster
public function generate():void
{
shift = 7;
grid = new Vector.<Boolean>(100 << shift, true);
for (var x:int = 0; x < 100; x++)
{
for (var y:int = 0; y < 100; y++)
{
grid[(x << shift) | y] = Math.random() < 0.5;
}
}
}
public function retrieve(x:int, y:int):Boolean
{
return grid[(x << shift) | y];
}
By referencing the cell using [x * 100 + y] we get the computer to do a multiplication and an addition. That's pretty quick, but while we consider these two of the most primitive mathematical operations, they are not two primitive calculations for a computer! Instead, we can use [(x << shift) | y] which replaces the multiplication and addition with a bit-shift and a bitwise disjunction. They are about as simple calculations as a computer can make, and the time it gains us is small, but significant if we are working with big grids.
I do not intend to go into the details of bitwise operations here, but for further reading, try this Wikipedia article.
Interestingly, if you try this approach with Array, it does not run as quickly as the example labelled 'Fast'. This is because, as Jackson Dunstan and JP Auclair noted, it will leave 'gaps' in the Array (for example no values will be entered in the above Vector for values, 100 - 127. For a Vector of a known size, that is not a performance problem, but Arrays work differently.
Results Summary

The results on the horizontal access are milliseconds that it took to iterate through the grid 1000 times. The difference in speed by adopting Vector and the bitwise-shift approach is to cut the calculation time by nearly a quarter. The bigger the grid is, the more this technique becomes useful.
After-Thought - Game Of Life
The Game Of Life is a grid structure, in which each cell is a Boolean switch; either 'on' or 'off'. Iteratively, the grid changes, according to a very simple instruction set:
- Each grid cell's value is determined by the values of the eight adjacent grid cells;
- For each cell, If exactly three of those adjacent cells are 'on', then in the next iteration, that cell will be 'on';
- For each cell, if two adjacent cells are 'on' then in the next iteration that cell will remain in it's current state;
- Otherwise, that cell's value in the next iteration will be set to 'off'.
At the edges, either those cells just have fewer neighbours, or the neighbours are thought to 'wrap around' the 2D space, so that the cells' universe resembles a torus in 3D space.
The result of these simple rules is an interesting pattern which is very interesting for a great number of reasons. The example below should show you what I mean. It will run only when the mouse is over the application. Click on it to break the iteration cycle and populate the cells with random data.
Introducing RacetrackStats v.0.0.1
Introduction
RacetrackStats is an in-Flash performance profiler that gives real-time feedback about how the code it is contained within is performing. It can be found at GitHub:
http://github.com/alecmce/RacetrackStats
RacetrackStats is inspired by and seeks to move forward from Mr Doob’s Stats package (http://code.google.com/p/mrdoob/wiki/stats)
In Action
Below is the first alpha of RacetrackStats in action.
The Flash plugin is required to view this object.
source: http://github.com/alecmce/RacetrackStats/blob/master/test/demo/RacetrackStatsDemo.as
The SWF comprises three small animations (from left to right):
- A mixture of computation and rendering: A simple BitmapData-driven particle system attempting to model smoke using 100000 pixels and a heavy glow filter and blur filter;
- Heavy computation: A prime-factorisation algorithm, which computes 24 * 100 prime factor decompositions per frame. As it continues to run, the numbers get larger which leads to heavier calculation cycles;
- Extremely heavy rendering: A cycadelic circle pattern that has hundreds of semi-transparent circular sprites moving around and overlapping with each other.
The ‘Elastic Racetrack’
RacetrackStats attempts to go beyond Mr Doob’s Stats by measuring how the elastic racetrack is being stretched. The Elastic Racetrack was a phrase coined to describe how the original AVM1 Flash Player segmented each second into frames and attempted to balance the requirements of code, refreshing the screen and doing work like garbage collection. The AVM2 player’s model is sufficiently similar, that the name remains appropriate.
Code Execution
It does this by hooking into the Event.ENTER_FRAME and Event.RENDER events to record when portions of the code start and end. By recording when the ENTER_FRAME starts and when the RENDER starts, the intervening time is taken to be code execution.
Pre-Render Code Execution
Commonly this part of the code cycle is almost unused. If you exploit stage.invalidate and Event.RENDER in order for your classes to execute code after the main code execution has completed, then it will be captured here, between the top-priority Event.RENDER and the bottom-priority Event.RENDER calls.
Rendering
A problem is, the time between the RENDER ending and the ENTER_FRAME starting is used to draw the screen but if time is left over in which the Flash Player has nothing to do, it will idle during this time also. To counteract this, RacetrackStats attempts to throttle the FlashPlayer so that the application is always running as fast as it can, minimising, or even eliminating that idle time. I call this the “render” portion – the “Event.RENDER” event is badly named – screen rendering happens after the RENDER event has finished.
Work To Do
As soon as you add weight like this to an application, the speed at which it runs changes. By measuring the speed, you change the speed. It is the classic scientific paradox. It is mitigated by shrinking down the weight of the stats package as far as possible. At the moment, functionality rather than size is the chief concern, though I have tried to minimize the package by avoiding embedding fonts, and so forth.
I would love to hear what you think about the package, whether positive or negative. I’d also really appreciate it if you use it in your applications. If you have any problems, questions, queries or comments, please leave a comment below, or open an issue on GitHub.
Gotcha – transform.matrix and scaleX/Y
I came across this gotcha for the first time today. Praise-be to ASUnit, without which this could have been extremely difficult to unearth:
// given two sprites called "a" and "b"... a.transform.matrix = new Matrix(-.5, 0, 0, -.5, a.x, a.y); b.scaleX = b.scaleY = -.5; trace(a.scaleX, a.scaleY, b.scaleX, b.scaleY); // outputs: 0.5, 0.5, -0.5, -0.5
Both clips have been scaled by -0.5, but because the transform was used to produce the scale for a, the scaleX/Y variables do not reflect the object’s true scale.
Now, just to confuse yourself, add a third sprite to the stage:
// given another sprite called "c"... c.transform.matrix = new Matrix(-.5, 0, 0, -.5, c.x, c.y); c.scaleX = c.scaleY = -.5;
Curiouser and curiouser! This needed a more complete experimentation…
The Flash plugin is required to view this object.
The source for this experiment can be found here: scaleAndTransform. The buttons call the following methods:
function onGo(event:Event):void
{
a.transform.matrix = new Matrix(-.5, 0, 0, -.5, a.x, a.y);
b.scaleX = b.scaleY = -.5;
c.transform.matrix = new Matrix(-.5, 0, 0, -.5, c.x, c.y);
c.scaleX = c.scaleY = -.5;
}
function onResetScale(event:Event):void
{
a.scaleX = a.scaleY = 1;
b.scaleX = b.scaleY = 1;
c.scaleX = c.scaleY = 1;
}
function onResetTransform(event:Event):void
{
a.transform.matrix = new Matrix(1, 0, 0, 1, a.x, a.y);
b.transform.matrix = new Matrix(1, 0, 0, 1, b.x, b.y);
c.transform.matrix = new Matrix(1, 0, 0, 1, c.x, c.y);
}
What Is Going On?
If you apply a transformation matrix then a scale, the magnitude of the scale is applied, but the direction is determined by the product of the transformation and the scalar… which is to say that:
a.realScaleX = (a.transform.matrix.a * a.scaleX > 0 ? 1 : -1) * a.scaleX;
If however you apply a scale then a transformation, the scale is defined by the transformation only!
a.realScaleX = a.transform.matrix.a;
Bug?
Does this qualify as a bug? I haven’t thought about this for long enough. The conditions in which a transformation matrix rotates and skews the MovieClip confuse me; how would I define scaleX and scaleY in that scenario? I need to give this some thought; perhaps you the community can give me some help! I am reluctant to call anything a bug immediately now, after my experience with my The Problem With Vector.<T> post, where I was just plain wrong!
A similar bug exists in Adobe JIRA: UIComponent.scaleX, scaleY differ from transform.matrix.a,d. You’ll need an account to look at this – it’s free, and once you’ve got it you can pester Adobe with your bugs too.
When is a sub-class appropriate?
My colleague Anatoly and I regularly need to create dialogs which pop-up in front of our application. Anatoly has created a class which allows the dialog to be configured by a packet of data which contains header, any text or images, button labels, footers, and information about how the buttons are processed, like this:
public class Dialog extends Sprite
{
public function Dialog(data:DialogData)
{
... composes the dialog according to the data that is passed into it ...
}
}
Anatoly – Dialog Composition
Let’s say that Anatoly wants to create a dialog in a particular view class (please ignore any other architectural considerations – I say “view class” broadly, hoping not to rile anyone who might shout “mediator”, which is beside the point in this case):
public class SomeClassWhereDialogsAreShown
{
...
public function onActionWhichTriggersExampleDialog():void
{
// this is a simplified structure to avoid complicating the point
var header:String = "This is Header";
var body:String = "This is body";
var buttons:Array = ["OK","Cancel"];
var data:DialogData = new DialogData(header, body, buttons);
var dialog:Dialog = new Dialog(data);
showDialog(dialog);
}
// this is one of many dialogs defined here...
public function onActionWhichTriggersADifferentDialog():void { ... }
public function onActionWhichTriggersAThirdDialog():void { ... }
public function onActionWhichTriggersAFourth():void { ... }
public function onActionWhichTriggersAFifthDialog():void { ... }
}
It is important to note that I have massively over-simplified the DialogData. It could be dozens of lines long, contain nested arguments, and so on. This point becomes part of the discussion later on.
Me – Dialog Inheritance
In contrast, I want to create a dialog sub-class and package away the dialog data:
public class ExampleDialog extends Dialog
{
public function ExampleDialog()
{
// this is a simplified structure to avoid complicating the point
var header:String = "This is Header";
var body:String = "This is body";
var buttons:Array = ["OK","Cancel"];
var data:DialogData = new DialogData(header, body, buttons);
super(data);
}
}
public class SomeClassWhereDialogsAreShown
{
public function onActionWhichTriggersExampleDialog():void
{
showDialog(new ExampleDialog());
}
}
This approach allows me to encapsulate the ExampleDialog very neatly, though it requires more lines of code than the composition approach. ActionScript is verbose enough without actively seeking to add more lines of code.
Single Responsibility Principle
If the dialog needs to be changed, the inheritance approach ensures that the only place that code editing need take place is in the code which relates to the particular dialog. This conforms to the Single Responsibility Principle, based on the principle of cohesion: the degree to which lines of code form a single unit of functionality is the extent to which they should be in their own class.
I would argue that creating a particular dialog is a functional unit, especially in user-interface code. Anatoly makes the point that all our dialogs are functionally equivalent (more of which below). I suppose he thinks of functionality in terms of the developer, and I the interface.
OOP Design principles are not inviolate, but they point us towards ways of writing code which lead to more robust code. This principle points towards the dialog configuration data not being defined in the SomeClassWhereDialogsAreShown class. (which is different from saying it supports the inheritance approach!)
Liskov Substitution Princple
Creating inheritance chains can be problematic. It might be considered reasonable to create a Square class as a subclass of the Rectangle, like this:
public class Rectangle
{
...
public function set width(value:Number):void
{
_width = value;
}
public function set height(value:Number):void
{
_height = value;
}
public function get area():Number
{
return _width * _height;
}
}
public class Square extends Rectangle
{
override public function set width(value:Number):void
{
_width = _height = value;
}
override public function set height(value:Number):void
{
_height = _width = value;
}
}
However, this can cause problems. Imagine, during your code that you utilise Rectangle like this:
public class SomeOtherClass
{
public function doubleRectangleArea(rectangle:Rectangle):void
{
rectangle.width *= 2;
}
}
The doubleRectangleArea method presupposes that the Rectangle’s width and height properties are independent. Polymorphism allows a Square to be passed into the doubleRectangleArea method, but as configured this would quadruple the square’s area. The functionality of the doubleRectangleArea method is broken because the Square-Rectangle relationship breaks Liskov Substitution Principle (LSP).
This principle serves as a general warning against inappropriate inheritance. Anatoly invoked it in our discussion as a reason to be cautious about inheritance, but I remain unconvinced – surely not all inheritance is bad, and I am pretty sure that as things stand, no particular thing about our dialogs violate LSP?
Function and Configuration
Let’s suppose you want to model two cars: A Honda Jazz and a Lotus Exige. The following class structure may be appropriate:
public class Car { ... }
public class HondaJazz extends Car { ... }
public class LotusExige extends Car { ... }
If, on the other hand, you have two colours of Honda Jazz, the following structure makes little sense:
public class HondaJazz extends Car { ... }
public class BlueHondaJazz extends HondaJazz { ... }
public class WhiteHondaJazz extends HondaJazz { ... }
More sensible would be:
public class HondaJazz extends Car
{
public function HondaJazz(color:uint) { ... }
}
In the case of the two types of car there are clear functional differences: acceleration, top-speed, fuel efficiency, to name a few. In the case of the two jazzes, there are no functional differences, merely different configurations.
Anatoly argues that different dialogs are essentially like different configurations, rather than different functionalities. Therefore, they should all be the same class, but the Dialog should be configured through parameters in its constructor.
Discussion
So what is the right approach? The Single Responsibility Principle (SRP) definitely points away from the composition approach, if the class in which the composition is made has many other responsibilities. Anatoly has offered to meet me half-way having conceded this point, instead storing the various configurations in static methods of Dialog, or elsewhere, rather than create a subclass.
To me, this still feels wrong. The Function and Configuration argument is a good one, and points towards no sub-class being created. However, I still feel that the sheer quantity of configuration that some dialogs require start to make the act of configuration feel inappropriate.
Furthermore, if all we are really doing is is configuring the same dialog over and over, then I do not think that the Liskov Substitution Principle (LSP) is a concern. If all dialogs really are functionally equivalent, then how can they violate LSP?
Aesthetically, the inheritance approach feels right to me, but it is important to respect that Anatoly comes from a very different tradition and has been coding a lot longer than me! The discussion was an interesting (and pleasant) one. If any of you can add to it, then I would be delighted to hear your points of view.
Mr Tayto Website
Just before I left for San Francisco, I was asked to work on the Mr Tayto website for Yomego. During my time at Yomego, I was mostly working on big projects, some of which never really saw the light of day. This was a bit of light relief.
The website was well received, Creative News attributing some of the success of the book to the website and the surrounding social media campaign.
The site itself was assembled in under two weeks by myself and Colin McKinney. The page turning mechanism was built from scratch in that time in order to guarantee integration with the initial animation sequence, the bookmark turn effects. More polish could have been applied with a longer time-frame, but this was not a bad effort, in the circumstances.
Events and Signals – Performance Tests
The new as3signals library devised by Robert Penner offers a replacement to the native AS3 event model. One benefit is that signals are more lightweight, and therefore faster. Grant Skinner’s Performance Harness is a widely accepted library for comparing the speeds of code execution.
I found the following results on Mac OS X, Flash Player 10.0.42.34, with a release build.
When an event (signal) is dispatched but nothing is listening for it:

When an event (signal) is dispatched and handled by one method listener:

The source code for my test methods follows:
If you browse these tests, you will notice that more tests were run than I have displayed above. The graphs above reference results from running the dataEventOptimised and dataSignal methods in each context.
These tests are not scientific. No attempt has been to control for player version, computer version, computer specifications, so on and so forth. You are invited to download and run these tests for yourself. If you do, remember that testing on a release build not a debug build is appropriate, and then please post your results as a comment, particularly if your results differ from my own.
Updates
For a comparison with good old fashioned callbacks, please put on your sarcasm snorkel and visit va.lent.in’s follow up post.
From the as3signals Google Group there was a suggestion that the Flash Player 10.1 might produce different results. Here are my results; they appear to corroborate the earlier results:
–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––– performancetests.EventsTest (5 iterations) Player version: MAC 10,1,51,66 (regular) –––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––– method...................................................ttl ms...avg ms dataEvent 2344 468.80 dataEventOptimised 2270 454.00 dataSignal 313 62.60 simpleEvent 2755 551.00 simpleEventOptimised 2285 457.00 simpleSignal 174 34.80 –––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––– –––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––– performancetests.CapturedEventsTest (5 iterations) Player version: MAC 10,1,51,66 (regular) –––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––– method...................................................ttl ms...avg ms dataEvent 2708 541.60 dataEventOptimised 2703 540.60 dataSignal 1182 236.40 simpleEvent 2724 544.80 simpleEventOptimised 2717 543.40 simpleSignal 1042 208.40 ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
RobotLegsPong Part 1 – Overview
Introduction
RobotLegsPong attempts to combine RobotLegs application framework with the as3signals event model and a Frame-Ticker (as well as a pinch of ASUnit unit-testing) to create a ‘game’.
It is an open-source project, available on GitHub as an example of using RobotLegs together with these other technologies.
Source Code: github/alecmce/RobotLegsPong
RobotLegsPong is not a very good game; it is playable only in the loosest sense. Bats require to be dragged in order to move (and there is no computer-logic to play against), so you could not really play against an opponent. The purpose of the exercise was to see what structure a game like Pong would take within the RobotLegs framework.
The purpose of this article is to describe the particulars of the technologies and why I chose them. In a follow-up article, I will look in more detail how RobotLegsPong is wired up.
Why I Chose These Technologies
RobotLegs
The RobotLegs framework is a lightweight, flexible application framework that allows coders to spend less time wiring up their application, and more time working on its functionality.
Frameworks are often criticised because they force developers to write code in a particular way, which might be inappropriate for a particular context. I have used Cairngorm, Pure MVC, as well as some proprietary frameworks, and have found that all of them do some things well, and do other things clumsily. So far I have not found this problem with RobotLegs, because most of the time it gets out of the way and lets you code; in fact, it does more than that: it reduces the amount of code you have to write.
as3signals
RobotLegs comes with an application event bus, but I have decided to circumvent that and use as3signals instead. as3signals allows you to define an object which acts as an event dispatcher within an application.
I like as3signals because describing an event as a Signal object allows my event model to be described through interfaces. as3signals is supposed to be fast too. Then again, interfaces are slow. The relative speeds of the approaches is interesting, but not a significant factor in my decision making process.
Frame-Ticker
The frame-ticker is a simple idea: rather than creating multiple enter-frame event listeners, each creating event objects, create one enter-frame listener and a main game loop iterating through those methods that need to be called per-iteration.
This implementation came out of a discussion on Twitter that I was involved in on the fringes; I wrote about it in a previous blog post.
ASUnit
Unit testing enables developers to test portions of their code in isolation, so that they can be confident that every method works exactly as the developer intended. They also represent a secondary form of documentation-in-code; if you want to know how I meant a method to work, reading the unit test will tell you almost everything you need to know (including, if a good test is missing, what I didn’t consider).
That said, I have not unit tested every method; in this example I have only unit-tested the geometric logic for the bats. This is bad practice, however under time constraints I think that it is most important to unit test what is complex, mathematical or ambiguous, since this is where behaviour is most likely to fall down.
[Inject]
The ‘trick’ to using RobotLegs is that you do not need to inject dependent objects into classes when you contruct them; this is done automatically. This code:
public class Dependee {}
public class MyExample
{
public var dependee:Dependee;
public function MyExample(dependee:Dependee)
{
this.dependee = dependee;
}
}
becomes this code:
public class Dependee {}
public class MyExample
{
[Inject]
public var dependee:Dependee;
}
The metadata tag [Inject] has the effect of automatically injecting the dependee into the class when it is constructed. This isn’t much on the face of it, but it is enough. It feels to me as though a quarter of my code is actually just wiring up classes so that they each have access to the classes that they need to function, or passing objects around methods. The [Inject] tag lets me shift all of that wiring into the RobotLegs framework.
Context
There is a little more to the RobotLegs story however; how should RobotLegs react when it comes across an [Inject] tag? It could construct a new Dependee object, or it could be that I want only one Dependee object to be injected wherever the [Inject] tag is found. This is where the Context class becomes meaningful.
In the PongContext, different classes are wired up in different ways. Their definitions are defined by adding injector mappings and the mediatorMap mappings in the startup method.
public class PongContext extends Context
{
override public function startup():void
{
...
injector.mapSingleton(DragMechanism);
injector.mapSingletonOf(Geometry, GeometryModel);
injector.mapClass(BatGeometry, BatGeometryModel);
...
}
}
injector.mapSingleton
injector.mapSingleton(DragMechanism)
mapSingleton indicates that only one instance of the class entered should be constructed. In this case, just one DragMechanism will be created, and injected whenever this is found:
[Inject] public var mechanism:DragMechanism;
injector.mapSingletonOf
injector.mapSingletonOf(Geometry, GeometryModel);
mapSingletonOf extends the mapSingleton idea to interfaces and their implementing classes. In this case the Geometry interface is mapped to the GeometryModel class. The injection is called as follows:
[Inject] public var model:Geometry;
No reference to the GeometryModel is needed in any class other than the PongContext. This allows a very pure use of interfaces across the application.
injector.mapClass
injector.mapClass(BatGeometry, BatGeometryModel)
injector.mapClass works a little differently; whenever a BatGeometry interface is flagged to be injected, a new instance of BatGeometryModel is constructed and injected into the class, so the following code is used to create the injection:
Each BatMediator needs its own BatGeometry object. By using the mapClass method, multiple BatGeometryModel objects will be constructed, one for each time the following code is found:
[Inject] public var model:BatGeometry;
Mediators and Components
public class PongContext extends Context
{
override public function startup():void
{
...
mediatorMap.mapView(Background, BackgroundMediator);
addChild(new Background());
}
}
mediatorMap references a slightly different aspect of the application: your view objects. The mediatorMap allows users to define associations between display objects and Mediators. These two parts comprise the View aspect of the standard MVC pattern.
The DisplayObject – in this case Background – is the asset that you want to be visible on the stage. In my pong example this is essentially just a Sprite, though it might just as well have been imported as a graphical asset in a SWC.
The Mediator is associated with the DisplayObject so that when an instance of the DisplayObject is created, the corresponding Mediator is also constructed. The BackgroundMediator looks something like this:
public class BackgroundMediator extends Mediator
{
[Inject]
public var view:Background;
override public function onRegister():void
{
...
}
}
The DisplayObject Background is injected into the BackgroundMediator when it is constructed. The DisplayObject can then be manipulated. It is an elegant solution that separates display object from UI logic.
addChild(new Background());
is all that is needed to wire the entire DisplayObject/Mediator combination.
RobotLegs & Tickers
The RobotLegs structure is particularly useful for wiring up a Ticker-based application because one ticker can be mapped as a singleton, and injected to all those methods that need to iterate every frame:
public class PongContext extends Context
{
override public function startup():void
{
...
injector.mapSingletonOf(Ticker, EnterFrameTicker);
...
}
}
RobotLegs with as3signals
I really like the style of event dispatching that as3signals provides, but my implementation demands that if one class requires another class then it must flag it to be injected, and then the signal wired up in a method flagged as [PostConstruct] (see GeometryModel). This doesn’t feel like the right solution.
Integrating as3signals with RobotLegs is beyond the scope of this article. It looks like Joel Hooks and Robert Penner are making inroads into this problem through as3signals’ Google Group. I look forward to seeing what they come up with.
Circle Segments
I’ve added circle segments to the as3geometry library. The two examples below demonstrate the definition of a segment by two vertices constrained to the circle radius and by a line and circle:
Circle Segment By Vertices
The Flash plugin is required to view this object.
view source | click-and-drag the red points to interact
Circle Segment By Line And Circle
The Flash plugin is required to view this object.
view source | click-and-drag the red points to interact
The library update also includes some preliminary work on the intersection of two polygons, but I haven’t yet sorted out the mutability yet, because it’s pretty complicated, and because I’m furiously busy this December preparing to move from the UK to the USA! Expect more udpates from late January onwards, once I’m settled in.
The Problem With Vector.<T>
I thought I’d found a bug with respect to Adobe’s new Vector class. I logged it in JIRA, but the answer came back that it is Not A Bug. Respectfully, I disagree. Here’s why.
UPDATE: I may be wrong about this. My brother has written a response: http://bit.ly/9OotIS. For further discussion, please also see the comments below.
The Problem
// create an interface and implementing class
public interface Fruit {}
public class Apple implements Fruit {}
// create a vector of Apple objects and try to cast it to a vector of Fruit objects
public class TheProblemWithVectors
{
public var fruits:Vector.<Fruit>;
public function TheProblemWithVectors()
{
var apples:Vector.<Apple> = new Vector.<Apple>();
apples.push(new Apple());
// THIS THROWS AN ERROR!
fruits = apples as Vector.<Fruit>;
}
}
The following is indisputable:
- All (elements in)
applesmust be anApple; - All
Apples areFruits; - Therefore, (elements in)
applesareFruit.
In which case, why can’t apples be cast as fruits? The Flash player does not accept that a Vector of Fruit could be described as a Vector of Apple. To me this feels like a bug. Does it to you?
Not A Bug?
To Adobe it is Not A Bug:
http://bugs.adobe.com/jira/browse/ASC-3836
According to Chris Peyer who works at Adobe:
This is the expected behavior. Vector.
and Vector. are unrelated types no matter what the relation is between Example and ExampleA.
It seems to me that this argument can only stem from the idea that if one object is composed of Fruits and another composed of Apples, that does not mean that the two objects are themselves related:
public class MarketStall
{
public var forSale:Apple;
}
public class Supermarket
{
public var forSale:Fruit;
}
There is no relationship between MarketStall and Supermarket in this code.
Surely though the relationship between two Vectors defined by a generic is much stronger than that? The Vector is nothing more than an indexed plurality of the objects that compose it. We know it doesn’t have other unrelated functionality. We can do this:
var fruits:Vector.<Fruit> = new Vector.<Fruit>(); for each (var apple:Apple in apples) fruits.push(apple);
without problem, but not this:
var fruits:Vector.<Fruit> = apples as Vector.<Fruit>;
Most importantly however, can’t the Adobe engineers see how damned useful it would be if we could cast Vectors like this? Languages should not get in the way of what is intuitively right. You should not have to struggle with the language like this, or find workarounds. Flash developers are almost always looking for improvements in speed and memory, but here you the language makes you waste memory and take time. Or, use the other workaround and avoid Vector and use Array instead. That’s what I did; what a triumph, Adobe!
Please Vote On This Bug
I’ve been here before! My former Colleague Vizio360 rediscovered this bug about buttonMode=true preventing unloading of SWF files, but it too was resolved by being called Not A Bug. The clamour for it to be reopened has so-far fallen on deaf ears, but the only way anyone will ever take any notice is if you vote and comment.
Currently Adobe consider this issue closed. Pehaps if you comment on the post they will give it second thoughts. (this is edited text after it was pointed out to me that you can’t vote for closed bugs)
as3geometry – line & circle intersection
Addition to my as3geometry library, the intersection between a line and a circle
The Flash plugin is required to view this object.
view source | click-and-drag the red points to interact


