Mapping coordinates from one range to another in ActionScript 3.0

I am very fond of Processing, and the way it easily makes it possible to experiment with design ideas. One of the powerful features are it’s map() function, that takes a value and remaps it from one range to another. I haven’t seen a similar function in the ActionScript 3.0 reference, so I decided to make one to my own utils-library, because it is something the can come in handy in many situations. First I looked at using the Point() class, and interpolation to describe the ratios, but actually found it easier to just do it with regular math.

I haven’t looked at performance yet, and there is possibly a lot of ways to optimize this code – this article can be a start for further fine tuning. The helper function looks like this:

function map(val:Number, inMin:Number, inMax:Number, outMin:Number, outMax:Number, decimals:uint=0):Number
{
var returnVal:Number;
 
// Sets the total range for both in and out
var inRange:Number = inMax - inMin;
var outRange:Number = outMax - outMin;
 
//calculates the ratio for the value in relation to the in range
var ratio:Number = (val - inMin)/inRange;
//makes sure that the value is within range
val = Math.max(inMin, val);
val = Math.min(inMax, val);
//Finds the same ratio in the out range and shift it into place
returnVal = (outRange * ratio) + outMin;
 
//rounding of the decimals
var factor:int = Math.pow(10,decimals);
returnVal = Math.round(returnVal*factor)/factor;
 
return returnVal;
}

The function takes the the following arguments:

  • val: the number to be remapped
  • inMin and inMax: The original range, in which the value is measures in relation to.
  • outMin and outMax: The destination range, that the value will be re-mapped to
  • decimals: sets the precision in decimals (optional)
First it calculates the ranges with
var inRange:Number = inMax - inMin;
var outRange:Number = outMax - outMin;
These variables are defining the total range for both the incoming number, and the range of number is eventually will be placed within.
val = Math.max(inMin, val);
val = Math.min(inMax, val);
In this function I have decided to make sure, that the value is within the boundaries of the inRange. If i took the value 4, and sets the range of number to be within 10 and 100, I would get some unexpected results. You could treat this differently, or even make it possible by omitting these lines.
var ratio:Number = (val - inMin)/inRange;
ratio holds a number between 0 and 1 that defines where in the original range it is located. The closer to zero it gets, the lower the value – closer to one goes towards inMax.
returnVal = (outRange * ratio) + outMin;
Then the number is multiplied to the outRange to find the same relative point in the target range, and finally shifted into place by adding the outMin value. Negative values are treated fine in these ranges – when you add -200 to something, it is actually subtracted from the number.
var factor:int = Math.pow(10,decimals);
returnVal = Math.round(returnVal*factor)/factor;
The last part of the function is meant to round of the values. For performance, this could easily be removed, but it may be useful in some cases to have odd long numbers rounded and presented with only a few digits precition. First, the variable factor holds the value to be used in the rounding proces. For 1 digit it should be “10″, 2 digits is “100″, 3 is “1000″ and so forth. That value is used in the line below, where it first multiplies the final value by the factor and then rounds it to an integer. Then it divides with the factor again. It goes something like this:
  1. factor is 1000 (3 digits)
  2. value is 134.744637
  3. Multiplication results in 134744.637
  4. Rounding returns 134745
  5. divided by 1000 gives the result 134.745
Finally the value is returned as a Number.

Optimization

There are a lot of code shortening, that can produce a speed improvement. You could also work with int or uint exclusively to gain some performance i suppose. Finally, you can remove the decimals and the lines that check if the number is in range. I have left the to show what functionality that could come in handy.

An example

As a practical example of the map() function you can  copy the following code into a Flash document. Here the map() fuction is directly inside the main code, but you could start building your own utils-library with the helper functions as public static function for easier access.
The code draws two squares with different sizes. When the mouse moves over the small square, it draw lines in the larger square, while maintaining the relative coordinates inside the squares.
import flash.display.Sprite;
import flash.events.MouseEvent;
 
//make the small square and color it dark grey
var inArea:Sprite = new Sprite();
inArea.graphics.beginFill(0x333333);
inArea.graphics.drawRect(0,0,100, 100);
inArea.graphics.endFill();
addChild(inArea);
 
//make the large square and color it black
var outArea:Sprite = new Sprite();
outArea.graphics.beginFill(0x000000);
outArea.graphics.drawRect(0,0,400,400);
outArea.graphics.endFill();
outArea.graphics.lineStyle(1, 0xFFFFFF, 0.3);
addChild(outArea);
outArea.x = inArea.width;
 
//adds a listener for the small square, that listens for mouse movement
inArea.addEventListener(MouseEvent.MOUSE_MOVE, updateDrawing, false, 0, true);
function updateDrawing(event:MouseEvent):void
{
	//Map the local coordinates from the mouse movement to the size of the large square
	var targetX:int = map(event.localX, 0, event.target.width, 0, outArea.width);
	var targetY:int = map(event.localY, 0, event.target.height, 0, outArea.height);
 
	//Draws the line in the large square.
	outArea.graphics.lineTo(targetX, targetY);
}
 
//Helper function
function map(val:Number, inMin:Number, inMax:Number, outMin:Number, outMax:Number, decimals:uint=0):Number
{
	var returnVal:Number;
	// Sets the total range for both in and out
	var inRange:Number = inMax - inMin;
	var outRange:Number = outMax - outMin;
 
	//makes sure that the value is within range
	val = Math.max(inMin,val);
	val = Math.min(inMax,val);
 
	//calculates the ratio for the value in relation to the in range
	var ratio:Number = (val - inMin) / inRange;
 
	//Finds the same ratio in the out range and shift it into place
	returnVal = (outRange * ratio) + outMin;
 
	//rounding of the decimals
	var factor:int = Math.pow(10,decimals);
	returnVal = Math.round(returnVal*factor)/factor;
 
	return returnVal;
}

Calling a function dynamically in ActionScript 3.0

Have you ever wondered, how you could use a String to decide, which function to be called. You could go so far to let the user enter the function name in an input field and call a function by that name, if it exists.

I have made a short article with an example on how that is done in Flash and ActionScript 3.0. You can read the article at http://www.hjaelpmignu.dk/content/dynamic-call-functions

HTML5 canvas with JavaScript and Flash Player performance

This post is an examination of the performance provided by JavaScript and the canvas HTML element, and its role on mobile platforms in the future. The inspiration for this post came when I stumpled on Water Ripple Canvas by Almer Thies. It was running without problems (with Canvas: 20fps and Water: 30 fps) on my computer but was frighteningly slow with a max of 0.5 fps on my iPhone 4 (yep. A half frame per second!). I therefore found it relevant to produce a comparable piece of code that could run on the canvas element and easily port to Flash, so I could get an idea of how well each technology performed.
It is not a secret that I’m fond of the Adobe Flash Player, and have always believed that Apples excommunication of the player due performance issues had no standing ground, in light of the present alternatives. But HTML5 is a promising technology, that takes the job as website maker seriously again, and that may result in Flash being able to focus on it plug-in nature again, and help lift sites up above the tomorrows standard sites. The most important topic to discuss is: what should happen when our mobile visits a website in the month/years to come. Not distinguishing  between mobile and desktop would lead to sluggish performance on mobiles when canvas gets integrated in eager designers creative solutions – a future that I predict as the “big dip”, in the worst cases.

Study 1

The test case is the famous snowflake that are loved or hated by everyone. The effect is exclusively produced by code and can be scaled easily to increase the load on the processor. I found an example at http://blog.webreakstuff.com/2010/11/building-a-canvas-snowglobe/ by Pedro Freitas. The code can be found on GitHub via https://gist.github.com/716215. I would also use an FPS counter, which could easily be ported to ActionScript and chose snippet from http://stackoverflow.com/questions/4787431/check-fps-in-js
I need it to produce a working example of the FPS counter that can be found at http://eksempler.hjaelpmignu.dk/flash/actionscript/snowflake/snowcanvas.html. I have come to the following data (max is set to 100 FPS):
  • Desktop PC: 99.9 FPS (Firefox)
  • MacBook Pro: 97 - 98 FPS (Safari)
  • iPad (iOS 4.3): 19 - 20 FPS (updated 17/3 – 2011)
  • HTC Desire HD (2.2): 15.5 - 16.5 FPS
  • Inspire 4G (2.3): ~ 14 FPS (updated 17/3 – 2011)
  • HTC Desire (2.2): 14.4 - 14.7 FPS
  • iPad 1 (iOS 4.3): 13 – 13.5 FPS (updated 17/3 – 2011)
  • iPad 1 (iOS 4.2): 12.4 - 13.3 FPS
  • iPhone 4 (iOS 4.3): 9.9 - 10.5 FPS (updated 17/3 – 2011)
  • iPhone 4 (iOS 4.2): 9.9 - 10.3 FPS
  • iPhone 3GS (iOS 4.2): 9.9 - 10.3 FPS
  • HTC Legend: 7.5 - 8.9 FPS
Thanks to @seb_ly and @leebrimelow for additional test results
When I dropped the restriction the PC actually easily spun on over 200 FPS, but the intention here is not to benchmark in the high end, but find a relationship in the “low end” and a relative measurement to a standard machine. PC as well as Mac differ so much on hardware as well as range of browsers, it will not contribute anything positive to uncover all facets.

Conclusion 1

It is evident that both computers frame rates hits the ceiling. The portable Mac has thrown a frame or two in the test, but will probably do 100 FPS in a another run, or with another browser. Of course it cannot run from a Quadro graphics card, but it’s clearly capable of running the test. iOS machines (iPad 1, iPhone 3GS and iPhone 4) has a hard time, to produce frames for the canvas element. On average, they just over 10 FPS.
Desire HD is a bit higher. Not much, but still enough that it should be designated as a better settlement. Lowest is the HTC Legend, with around 8 fps.

Study 2

The second test was made to compare performance between javascripts work on the canvas, and Flash Player’s work with the BitmapData class. The technique used for both are very similar and it will give the best basis for comparison, and minimal editing of the code. You can see an example at http://eksempler.hjaelpmignu.dk/flash/actionscript/snowflake/snowFLA.html
The following changes have been made from the original code:
  • Snow flakes was made as a separate class (Flake.as)
  • Updated variables, etc so they are strictly typed
  • Minor changes in variable names
  • Used Flash Player’s flash.sensors.Accelerometer to handle motion

Flake.as

 

package 
{ 
import flash.display.Sprite; 
import flash.display.BitmapData; 

public class Flake extends Sprite 
{ 
private var canvasWidth; 
private var canvasHeight; 
private var speed: Number; 
private var alpha: Number; 
private var size: Number; 
private var amp: Number; 
private var shift: Number; 
private var range: Number; 

public function Flake (w, h, a, s) 
{ 
this.canvasWidth = w; 
this.canvasHeight = h; 
this.x = 200; 
this.y = Math.random () * -1 * h; 
this.alfa = Math.random () * 0.5 + a; 
this.speed = Math.random (); 
this.size = s - this.speed - this.alfa; 
this.amp = Math.random () * 2; 
this.shift = Math.random () * 25 + 25; 
if (Math.random ()> 0.5) 
{ 
this.shift *= -1; 
} 
this.drift = Math.random () - 0.5; 
draw (); 
} 
public function draw (canvas: BitmapData = null): void 
{ 
this.graphics.beginFill (0xFFFFFF, this.alfa); 
this.graphics.drawCircle (0.0, this.size); 
this.graphics.endFill (); 
} 
public function move (f, wind): void 
{ 
this.y + = this.speed; 
this.x + = Math.cos (f / this.shift) * this.amp + + this.drift wind; 
if (this.y> this.canvasHeight) 
{ 
this.restart (); 
} 
} 
public function restart (): void 
{ 
this.y = -20; 
this.shift = Math.random () * 25 + 25; 
this.x = 200; 
} 
} 
}

 

 

MainApp.as

package
{ 
import flash.display.Sprite; 
import flash.display.Bitmap; 
import flash.display.BitmapData; 
import flash.utils.Timer; 
import flash.events.TimerEvent; 
import flash.geom.Rectangle; 
import flash.geom.Matrix; 
import flashx.textLayout.elements.InlineGraphicElement; 
import flash.sensors.Accelerometer; 
import flash.events.AccelerometerEvent; 
import flash.text.TextField; 

public class MainApp extends Sprite 
{ 
private var bgflakes: Array = new Array (); 
private var fgflakes: Array = new Array (); 
private var bgFlakeCount: int = 200; 
private var fgFlakeCount: int = 50; 
private var frame count: int = 0; 
private var wind: int = 0; 
private var dWidth: int; 
private var dHeight: int; 
private var orientX: int = 1; 

private var bgBitmapData: BitmapData; 
private var bgCanvas: Bitmap; 
private var fgBitmapData: BitmapData; 
private var fgCanvas: Bitmap; 
private var timer: Timer; 
private var orientation: Boolean = false; 
private var myAcc: Accelerometer; 

private var filter Strength: int = 20; 
private var frame hours: int = 0; 
private var loading loop: Date = new Date (); 
private var this loop: Date = new Date (); 

private var fps: TextField; 

public function MainApp () 
{ 
init (); 
} 

private function init () 
{ 
dWidth = this.stage.stageWidth; 
dHeight = this.stage.stageHeight; 
bgBitmapData = new BitmapData (dWidth, dHeight, false, 0x000000); 
bgCanvas = new Bitmap (bgBitmapData); 
fgBitmapData = new BitmapData (dWidth, dHeight, true, 0xFF0000); 
fgCanvas = new Bitmap (fgBitmapData); 
addChild (bgCanvas); 
addChild (fgCanvas); 

fps = new TextField (); 
addChild (fps); 
fps.textColor = 0xFFFFFF; 

was i = 0; 
for (i = 0; i { 
bgflakes.push (New Flake (bgCanvas.width, bgCanvas.height, 0,3)); 
} 
for (i = 0; i { 
fgflakes.push (New Flake (fgCanvas.width, fgCanvas.height, 0.2,4)); 
} 
hours = new Timer (10); 
timer.addEventListener (TimerEvent.TIMER, draw); 
timer.start (); 

if (Accelerometer.isSupported) 
{ 
orientation = true; 
myAcc = new Accelerometer (); 
myAcc.addEventListener (AccelerometerEvent.UPDATE, onAccUpdate); 
} 
} 

private function onAccUpdate (e: AccelerometerEvent): void 
{ 
orientX = e.accelerationX; 
} 

private function setWind () 
{ 
if (! orientation) 
{ 
was mx: Number = mouseX - dWidth / 2; 
wind = (mx / dWidth) * 3; 
} 
lodging 
{ 
Wind = Number (orientX) * 3; 
} 
if (! wind) 
{ 
wind = 0; 
} 
} 

private function draw (e: Event hours) 
{ 
frame count + = 1; 

bgBitmapData.fillRect (new Rectangle (0.0, dWidth, dHeight), 0x000000); 
fgBitmapData = new BitmapData (dWidth, dHeight, true, 0xFF0000); 
setWind (); 
was: int = 0; 
for (i = 0; i { 
bgflakes [i]. move (frame count, wind); 

bgBitmapData.draw (bgflakes [i], new Matrix (1,0,0,1, bgflakes [i]. x, bgflakes [i]. y)); 
} 
for (i = 0; i { 
fgflakes [i]. move (frame count, wind); 

fgBitmapData.draw (bgflakes [i]); 
} 

was this frame hours: int = (Number (this loop = new Date ())) - Number (last loop); 
Frame hour + = (this frame - time frame hours) / filter strength; 
load loop = this loop; 
fps.text = (1000/frameTime). toFixed (1) + "fps"; 
} 
} 
}

 

Comments on Code
I have kept the draw () inside the Flake class and draw the flakes with graphics.drawCircle () to keep the code across the examples as similar as possible. The transfer of values on canvas size, etc. are also retained in the Flash version is also preserved. Finally, I used Bitmap () and BitmapData () to simulate the properties used on the canvas element.

Results 2

With mobile units, that is capable of running Flash Player 10.1 and canvas, I try to measure them against each other. Not as a battle, favoring one technology, for the future (I think) belongs to them both. It’s more an attempt to find out how bad Flash performs and supporters of the canvas as a “Flash Killer” has some back support. I’ll update as I stumple on different phones/tablets on my way:
  • Dersire HD (2.2): Canvas ~ 16.5 FPS and Flash 10.1 ~ 24.2 FPS
  • Inspire 4G (2.3): Canvas ~ 14 FPS and Flash 10.1 ~ 22 FPS (updated 17/3 – 2011)
  • HTC Desire (2.2): Canvas ~ 14.5 FPS and Flash 10.1 21.7 to 23.5 FPS
You are welcome to submit own measurements

Conclusion

I get a relatively higher frame rate when running the test in Flash Player on Android than if I the canvas version. I wasn’t able to turn the relationship between the numbers on my phone, not even leveling the difference in frame rate. I therefore think that the user will have a better experience of this experiment in a flash player, than with a canvas version. It is important to remember that the canvas element’s ability to deliver, do not need to inflict on the general view on HTML5 and CSS3. My feeling is that CSS3 has a fairly good performance on the mobile devices, perhaps because of their predictable nature, but I haven’t investigated that topic yet.
Finally, I have not taken installed software on the devices into account. It may be relevant in a recount to look at parameters such as:
  • How long the phone has been switched on.
  • Is it connected to the charger.
  • Programs running in the background.
  • Video documentation of test
My point here is to get some numbers up in the air, and a comparison of material playd on mobile devices. Please reply with the results of your own measurements for computer, tablet and mobile.
Links to tests:
Links to documents

HTML5 canvas med JavaScript og Flash Player performance

Dette indlæg er en undersøgelse af den performance som præsteres af henholdsvis JavaScript og Canvas elementet og dets rolle på mobile platforme i fremtiden. Inspirationen fik jeg da jeg kom forbi Almer Thies Water Ripple Canvas der kørte uden problemer (med Canvas: 20fps og Water:30 fps) på min computer men skræmte mig fra vid og sans med et maks på 0.5 fps på min iPhone (yep. En halv frame i sekundet!!). Jeg fik derfor en idé om at finde et sammenligneligt stykke kode, der kunne afvikles fra canvas og nemt porteres til Flash, så jeg kunne danne mig et overblik over hvor godt de hver i sær præsterede.
Selv er jeg tilhænger af Adobe Flash Player og har altid ment at iOS bandlysning af den på grund af performance ikke havde nogen gang på jord, set i lyset af alternativerne. At vi så grundlæggende skal tage os en grundig snak om, hvad der skal ske, når vores mobile enheder besøger en hjemmeside i årene der kommer, er en helt anden snak – en fremtid, som jeg spår som “det store dyk”, i værste tilfælde.

Forsøg 1

Valget faldt på de berømte snefnug, som er elsket/hadet af alle. Effekten bliver udelukkende produceret med kode, og kan skaleres nemt for at øge belastningen. Jeg fandt et eksempel på http://blog.webreakstuff.com/2010/11/building-a-canvas-snowglobe/ af Pedro Freitas. Koden kan findes på Github via https://gist.github.com/716215. Jeg skulle også bruge en FPS-counter, der nemt kunne porteres til ActionScript og valget faldt på kodestumpen fra http://stackoverflow.com/questions/4787431/check-fps-in-js
Jeg har brug det til at producere et virkende eksempel med FPS-counter, der kan findes på http://eksempler.hjaelpmignu.dk/flash/actionscript/snowflake/snowcanvas.html. Jeg er kommet frem til følgende data (max er sat til 100 FPS):
  • Desktop PC: 99.9 FPS (Firefox)
  • MacBook Pro: 97 - 98 FPS (Safari)
  • iPad (iOS 4.3): 19 - 20 FPS (opdateret 17/3 – 2011)
  • HTC Desire HD (2.2): 15.5 - 16.5 FPS
  • Inspire 4G (2.3): ~ 14 FPS (opdateret 17/3 – 2011)
  • HTC Desire (2.2): 14.4 - 14.7 FPS
  • iPad 1 (iOS 4.3): 13 – 13.5 FPS (opdateret 17/3 – 2011)
  • iPad 1 (iOS 4.2): 12.4 - 13.3 FPS
  • iPhone 4 (iOS 4.3): 9.9 - 10.5 FPS (opdateret 17/3 – 2011)
  • iPhone 4 (iOS 4.2): 9.9 - 10.3 FPS
  • iPhone 3GS (iOS 4.2): 9.9 - 10.3 FPS
  • HTC Legend: 7.5 - 8.9 FPS
Tak til @seb_ly og @leebrimelow for yderligere testresultater
Jeg droppede begrænsningen og så at PC’eren faktisk nemt snurrede den over 200 FPS, men meningen her er ikke at benchmarke i den høje ende, men finde et forhold i “den lave ende” og en relativ måling til en standard maskine. PC såvel som Mac varierer så meget på hardware samt udvalg af browsere, at det ikke vil bidrage til noget positivt at afdække alle facetter.

Konklusion

  • Det er klart at fornemme at begge computere rammer toppen. Den bærbare Mac har smidt en frame eller to i testen, men vil sikkert ramme 100 FPS i en anden. Selvfølgelig kan den ikke løbe fra et Quadro grafikkort, men klart er det at der er rigelig overskud til at løse opgaven.
  • iOS maskinerne (iPad 1 og iPhone 4) har en hård tid, med at producere frames til canvas elementet. I gennemsnit ligger de på lidt over 10 FPS.
  • Desire HD ligger en smule højere. Ikke meget, men alligevel nok til at det må betegnes som en bedre afvikling.

Forsøg 2

Forsøg nummer to var lavet for at sammenligne performance mellem JavaScripts arbejde på canvas, samt Flash Playerens arbejde med BitmapData klassen. Teknikken der bruges til begge er meget ens, og det vil give det bedste sammenligningsgrundlag, og mindst mulig redigering i koden. Du kan se et eksempel på http://eksempler.hjaelpmignu.dk/flash/actionscript/snowflake/snowFLA.html
Følgende ændringer er blevet foretaget fra originalkoden:
  • Snefnug lavet som en selvstændig klasse (Flake.as)
  • Har opdateret variabler osv så de er strict typed
  • Mindre ændringer i variabel navne
  • Brugt Flash Playerens flash.sensors.Accelerometer til at håndtere bevægelse
Flake.as

package
{
import flash.display.Sprite;
import flash.display.BitmapData;

public class Flake extends Sprite
{
private var canvasWidth;
private var canvasHeight;
private var speed:Number;
private var alfa:Number;
private var size:Number;
private var amp:Number;
private var shift:Number;
private var drift:Number;

public function Flake(w,h,a,s)
{
this.canvasWidth = w;
this.canvasHeight = h;
this.x = 200;
this.y = Math.random() * -1 * h;
this.alfa = Math.random() * 0.5 + a;
this.speed = Math.random();
this.size = s - this.speed - this.alfa;
this.amp = Math.random() * 2;
this.shift = Math.random() * 25 + 25;
if (Math.random() > 0.5)
{
this.shift *=  -1;
}
this.drift = Math.random() - 0.5;
draw();
}
public function draw(canvas:BitmapData = null):void
{
this.graphics.beginFill(0xFFFFFF,this.alfa);
this.graphics.drawCircle(0,0,this.size);
this.graphics.endFill();
}
public function move(f,wind):void
{
this.y +=  this.speed;
this.x +=  Math.cos(f / this.shift) * this.amp + this.drift + wind;
if (this.y > this.canvasHeight)
{
this.restart();
}
}
public function restart():void
{
this.y = -20;
this.shift = Math.random() * 25 + 25;
this.x = 200;
}
}
}

 

MainApp.as
 

package
{
import flash.display.Sprite;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.geom.Rectangle;
import flash.geom.Matrix;
import flashx.textLayout.elements.InlineGraphicElement;
import flash.sensors.Accelerometer;
import flash.events.AccelerometerEvent;
import flash.text.TextField;

public class MainApp extends Sprite
{
private var bgflakes:Array = new Array();
private var fgflakes:Array = new Array();
private var bgFlakeCount:int = 200;
private var fgFlakeCount:int = 50;
private var frameCount:int = 0;
private var wind:int = 0;
private var dWidth:int;
private var dHeight:int;
private var orientX:int = 1;

private var bgBitmapData:BitmapData;
private var bgCanvas:Bitmap;
private var fgBitmapData:BitmapData;
private var fgCanvas:Bitmap;
private var timer:Timer;
private var orientation:Boolean = false;
private var myAcc:Accelerometer;

private var filterStrength:int = 20;
private var frameTime:int = 0;
private var lastLoop:Date = new Date();
private var thisLoop:Date = new Date();

private var fps:TextField;

public function MainApp()
{
init();
}

private function init()
{
dWidth = this.stage.stageWidth;
dHeight = this.stage.stageHeight;
bgBitmapData = new BitmapData(dWidth,dHeight,false,0x000000);
bgCanvas = new Bitmap(bgBitmapData);
fgBitmapData = new BitmapData(dWidth,dHeight,true,0xFF0000);
fgCanvas = new Bitmap(fgBitmapData);
addChild(bgCanvas);
addChild(fgCanvas);

fps = new TextField();
addChild(fps);
fps.textColor = 0xFFFFFF;

var i = 0;
for (i=0; i 			{
bgflakes.push(new Flake(bgCanvas.width, bgCanvas.height,0,3));
}
for (i=0; i 			{
fgflakes.push(new Flake(fgCanvas.width, fgCanvas.height,0.2,4));
}
timer = new Timer(10);
timer.addEventListener(TimerEvent.TIMER, draw);
timer.start();

if (Accelerometer.isSupported)
{
orientation = true;
myAcc = new Accelerometer();
myAcc.addEventListener(AccelerometerEvent.UPDATE, onAccUpdate);
}
}

private function onAccUpdate(e:AccelerometerEvent):void
{
orientX = e.accelerationX;
}

private function setWind()
{
if (! orientation)
{
var mx:Number = mouseX - dWidth / 2;
wind = (mx/dWidth)*3;
}
else
{
wind = Number(orientX) * 3;
}
if (! wind)
{
wind = 0;
}
}

private function draw(e:TimerEvent)
{
frameCount +=  1;

bgBitmapData.fillRect(new Rectangle(0,0,dWidth, dHeight),0x000000);
fgBitmapData = new BitmapData(dWidth,dHeight,true,0xFF0000);
setWind();
var i:int = 0;
for (i=0; i 			{
bgflakes[i].move(frameCount, wind);

bgBitmapData.draw(bgflakes[i], new Matrix(1,0,0,1,bgflakes[i].x, bgflakes[i].y));
}
for (i=0; i 			{
fgflakes[i].move(frameCount, wind);

fgBitmapData.draw(bgflakes[i]);
}

var thisFrameTime:int = (Number(thisLoop=new Date())) - Number(lastLoop);
frameTime+= (thisFrameTime - frameTime) / filterStrength;
lastLoop = thisLoop;
fps.text = (1000/frameTime).toFixed(1) + " fps";
}
}
}

 

Kommentarer til koden
Jeg har beholdt draw() inde i Flake klassen og tegner den fysisk op med graphics.drawCircle() for at beholde koden på tværs af eksemplerne. Overførsel af værdier om canvas-størrelse osv. er også bevaret i Flash eksemplet er også bevaret. Endelig er der brugt Bitmap() og BitmapData() til at simulere de egenskaber som bruges på canvas elementet.

Resultat 2

På modeller, hvor der både kan køres Flash Player 10.1 og canvas vil jeg prøve at teste dem op mod hinanden. Ikke så meget en kamp mellem det ene og det andet, for fremtiden (tror jeg) tilhører dem begge, men mere et forsøg på at finde ud af, hvor dårlig Flash præsterer og om tilhængere af canvas, som “Flash Killer” har noget at have det i. Jeg vil opdatere efterhånden som jeg rammer flere forskellige telefoner på min vej:
  • Dersire HD (2.2): Canvas ~ 16.5 FPS og Flash 10.1 ~ 24.2 FPS
  • Inspire 4G (2.3): Canvas ~ 14 FPS og Flash 10.1 ~ 14 FPS (opdateret 17/3 – 2011)
  • HTC Desire (2.2): Canvas ~ 14.5 FPS og Flash 10.1 21.7 to 23.5 FPS
I er velkommen til at indsende oprigtige målinger

Konklusion

Jeg ser en relativ højere frame rate når jeg afvikler i Flash Player på Android, end hvis jeg udfører tilsvarende med canvas elementet. Det er ikke lykkedes mig at vende forholdet mellem tallene på min telefon, end ikke få dem til at nærme sig hinanden, mærkbart. Jeg vil derfor mene at brugeren vil have en bedre oplevelse af dette eksperiment i en Flash Player, end ved en canvas-løsning. Det er vigtigt at huske på, at canvas elementets evne til at præstere, ikke behøver at gå ud over den generelle opfattelse af HTML5 og CSS3. Min fornemmelse er, at CSS3 har en ok afvikling på de mobile enheder, måske på grund af deres forudsigelige natur, men det har jeg stadig tilbage at undersøge.
Endelig har jeg ikke forholdt mig til, hvad der er installeret på enhederne. Det kan være relevant i en fintælling at se på parametre som:
  • Hvor lang tid telefonen har været tændt.
  • Er den tilsluttet oplader.
  • Kører der programmer i baggrunden.
  • Videodokumentation af test
Mit ønske her er at få nogle tal i luften, og et forhold til den relativt ringe afvikling af materiale på mobile enheder.
Meld gerne tilbage med resultater af jeres egne målinger på computer, tablet og mobil.
Links til tests:
Links til dokumenter

Video tutorial om at sende data fra Flash til mail via PHP

Jeg har fået gang i gode gamle Camtasia og snedkereret en tutorial der viser, hvordan en række input felter, samlet i en formular, kan sendes fra en Flash-film, via et php-script og hen til din mail boks. Det er som svar på forum indlæget Contact Form

Vejledningen tager dels udgangspunkt i det link til en tutorial på Flashforum, der blev nævnt, og dels en gammel video tutorial af Lee Brimelow.

Se den på www.hjaelpmignu.dk

Adobe Flash Professional CS5 beta (Signup)

Det rykker tættere og tættere på. Adobe Flash CS5 (Viper) blev præsenteret på MAX og det er nu kendt at den kommer i en offentlig beta senere i år. Tag et kig på http://labs.adobe.com/technologies/flashcs5/ og skriv dig op, så du får en mail når den er klar til at blive hentet.

De nye muligheder i programmet og den bedre integration med Flash Builder gør den til noget af det mest interessante i 2010.

Hvis du ikke har set programmet i aktion, så besøg http://max.adobe.com/online/ og se den “hemmelige session” på http://max.adobe.com/online/session/381

Iiiiiiiiih, altså!! :-)

Learning ActionScript 3.0 – A Beginner’s Guide : Boganmeldelse

Learning ActionScript 3.0 - A Beginner's Guide

Titel: Learning ActionScript 3.0 – A Beginner’s Guide

Sider: 363

Forfatter: Rich Shupe, Zevan Rosser

Udgiver: O’Reilly

Genre: ActionScript 3.0

ISBN:
ISBN-10: 0-596-52787-X
ISBN-13: 978-0-596-52787-7

Introduktion

Jeg har læst mange bøger om ActionScript 3.0, men det er sjældent at jeg er blevet så fanget af en bog som jeg er blevet af Learning ActionScript 3.0 – A Beginner’s Guide. Der er flere grunde til at jeg har lyst til at fremhæve den, og give den topkarakter.

Farver og linjer

Jeps, En ActionScript bog i farver. Jeg har egentlig aldrig rigtig tænkt over, hvor meget det forbedrer læsevenligheden – det er ret vildt. Al koden er skrevet i farver som du genkender fra Flash. Derudover er linjerne nummereret, hvilket gør det uhyre nemt at overskue længere kodestumper. De steder i bogen hvor koden bygges op lidt ad gangen er det også nemt at orientere sig i forhold til de brudstykker der bliver pillet ud og forklaret.

For børn i alle aldre

Du må ikke lade dig narre af titlen: “A Beginner’s Guide” for der er sandelig rigtig meget at komme efter for en trænet udvikler. Der er nok af små fif i de senere kapitler, og måder forfatterne forklarer det på, til at alle føler der er gods i bogen. Nogen vil måske mene at der er så meget i bogen at begyndere bliver hægtet af til sidst.

Sproget er vigtigt

Bogen er uhyre velskrevet. Der bliver brugt lange afsnit på forklaringer om begreber, metoder og egenskaber. Hvor mange andre ActionScript bøger fokuserer meget på at vise en masse kode, kan der her nemt tages et opslag eller to fra, til at forklare om principperne i det som koden udfører.

Billeder, Illustrationer osv

Der er rigtig mange illustrationer. Ikke kun skærmdumps af Flash, eller resultatet af din kode, men også gedigen infografik, der viser principperne i noget af den matematik e. lign. du skal arbejde med.

Indhold

Hvad skriver de så om, i bogen? De dækker faktisk et meget bredt område. Uden at gå for meget i kapitel tilstand kan jeg dele det lidt op i faser:

Overblik

Den starter med et dybdegående overblik over Flash Platformen, hvad det betyder og hvilke programmer der leverer til den. Den gennemgår derefter forskellene i procedural- og Object-Orientered programming. Når alt det indledende er på plads løber den en 40 sider igennem med variabler, funktioner, klasser osv – der er fart på, så hvis man er helt ny er det vigtigt at man “tygger maden godt her” og prøver de ting der er beskrevet.

Display List

Ingen ActionScript-bog uden en god gennemgang af display listen – et problem de fleste ridligere bruger bøvler med. Her gennemgås hvordan man tilføjer- eller fjerner objekter, bytter rundt på dem osv. Der kommer også et OOP afsnit, der fortæller om Classes, Inheritance, Composition og et par andre relevante Design Patterns.

Bevægelse og tegning

Efter man har læst de første 100 sider, skulle man allerede være ret habil i forhold til sproget. Nu begynder nogle af koncepterne at udfolde sig i programmeret bevægelse og partikelsystemer. Endelig bliver Graphics-klassen gennemgået og du bliver præsenteret for nogle meget tunge emner som matricer og trigonometri (Arrgh) :-)

Der er også afsat god plads til at forstå hvordan Flash arbejder med pixels. Du gennemgår BitmapData, Blend Modes, filtre og Color Effects, og her (200 sider inde) burde din hjerne sprudle af idéer til, hvordan den nyvundne viden kan udnyttes i praksis.

Tekst

I en særskilt sektion bliver teksten behandlet. Bogen går godt i dybden med forklaringerne når det kommer til at oprette tekstfelter, redigere dem, indlejre fonte og tilknytte CSS. Der bliver også taget fat på, hvordan HTML arbejder inde i flash og hvilke muligheder du har for at kalde ActionScript fra HTML.

Lyd og video

Næsten til slut, tages der hul på behandlingen af video og lyd. Du lærer at hente ID3 data fra musik. Visualisere waveforms, arbejde med webcam og mikrofon, streame lyd og video osv. osv. Her skal du virkelig have ørene ind til hovedet for at følge med.

Input/Output

Til allersidst tages der hul på mulighederne for at hente data ind i flash. Det har været gennemgået sporadisk tidligere, men nu bliver der taget fat om nældens rod og du bliver trukket godt rundt til de forskellige emner der normalt hentes (text, video, billede, swf og lyd). Derefter er et helt kapitel tilegnet XML og E4X. For en Flashudvikler, -designer er det et must at kunne håndtere XML, og dette kapitel ruster dig rigtig godt til at løfte opgaven.

Ressourcer

Sidst i bogen er der en beskrivelse af nogle metoder til at gribe et flash-projekt an på og en række referencer til ressourcer, blogs osv.

Afslutning

Slap af, Karsten. Du får penge for det. Niks – ikke i dette tilfælde i hvertfald. Jeg synes denne her bog er så god at jeg vil sige det til alle der gider at høre på det. Den gennemgår så mange teknikker (mange som jeg ikke kendte) og forklarer det på en måde som jeg i hvertfald synes gør den let fordøjelig.

Held og lykke med den, hvis I anskaffer jer den. Skriv gerne kommentarer hvis i har læst den, eller vil høre om den tager bestemte emner op.

Med venlig hilsen
Karsten Vestergaard (ockley)

Adobe Flash Catalyst og Adobe Flash Builder 4

Så er ventetiden ovre! Et tidspunkt jeg har set frem til, kom her i weekenden. Du har nu mulighed for at prøve kræfter med Adobe Flash Catalyst, som ligger i offentlig beta på labs.adobe.com. Det gør den sammen med Adobe Flash Builder 4 der er det sidste skud på stammen i den produktserie der tidligere var kendt som Flex Builder. Først og fremmest lige nogle link til softwaren:

Adobe Flash Catalyst: http://labs.adobe.com/technologies/flashcatalyst/
Adobe Flash Builder 4: http://labs.adobe.com/technologies/flashbuilder4/

Hvad kan programmerne?

Adobe Flash Catalyst

Dette program er ment til at binde designere af RIA tættere til den interaktive platform. Hvor de fleste designere bruger Illustrator, Photoshop og Fireworks til at udvikle skærme og elementer til brugergrænseflader, har udvikleren ofte alt for megen kode i vejen når der skal dannes et overblik over den visuelle stil.

Det resulterer i at der bliver indgået en masse kompromier, når der skal pustes liv i layoutet. Med Flash Catalyst er følelsen og muligheden for at levere et “kodeklart” resultat rykket tættere på. Du kan nu med Flash Catalyst, tage dit layout fra Illustrator, Photoshop eller Fireworks og definere de interaktive elementer. Du kan vise overgange imellem states (tilstande) og præcist bestemme hvordan grafiske objekter i dit design skal optræde i den endelige applikation.

Resultatet bliver et køreklart projekt til Adobe Flash Builder 4, som udvikleren så bruger til at gøre applikationen færdig.

Adobe Flash Builder 4

Fra at være et program for super nørder, har Adobe Flash Builder vendt sig mere og mere til den “mindre øvede udvilker”. Har du erfaring med Adobe Flash CS4 og ActionScript 3.0 vil du helt sikkert få meget ud af Adobe Flash Builder 4. Programmet er baseret på Flex framework’et og levere Rich Internet Applications til Flash Platformen. Den er født med en bunke indbyggede effekter og klasser, der gør det hurtigt at lave applikationer der kan afvikles på Flash Platformen.

Hvor Adobe Flash CS4 bruger sin timeline og library til at levere unikke animationer og oplevelser, kan Flash Builder bygge robuste og appelerende applikationer til interenettet eller din desktop (via AIR)

Med direkte understøttelse af projekter eksporteret fra Flash Catalyst er det blivet endnu nemmere at overskue designet af Flash Builder projekter – en ting som folk, vant til Flash Professionel, har sukket efter.

Kom i gang, nu!

For at komme igang med programmerne er her en lille liste af relevante links:

Adobe Flash Catalyst

Adobe Flash Builder 4

Derudover er der en række demonstrationer af Flash Platformen på http://labs.adobe.com/technologies/flash/videos/

Held og lykke. Jeg glæder mig til at se, hvor langt i kan trække programmerne :-)

/ockley

Mit håndikon er væk!! – husk det nu

OK. Her kommer et indlæg til jer, som ligeså meget er for min egen skyld. Jeg sad i aftes og brændte rigtig mange unødvendige arbejdstimer af på noget jeg havde løst før. Nu skriver jeg det her på blog’en, så jeg selv og I aldrig falder ned i det frustrationshul igen :-)

Problemet er følgende:
Når jeg opretter et movie clip og vil have det skal opføre sig som en knap, kommer hånden ikke frem, når musen bevæger sig hen over det.

Umiddelbar løsning er:
Husk at sætte buttonMode til true. Når du gør det, kan du bruge useHandCursor til at bestemme om hånden skal vises eller ej. Prøv følgende:

//Opret en sprite. Placer den på din stage i position (50,50)
var knap:Sprite = new Sprite();
addChild(knap);
knap.x = knap.y = 50;

//Tegn en grøn kasse inde i knappen
var kg:Graphics = knap.graphics;
kg.beginFill(0x55CC55);
kg.drawRect(0,0,90,25);
kg.endFill();

//Aktiver knaptilstand for spriten
knap.buttonMode = true;

Den sidste linje får spriten (eller movie clippet) til at opføre sig som en mus. Nu kommer problemet. Hvis du skriver følgende efter:


//Opret et tekstfelt, hvor teksten ikke kan markeres
//og placer den inde i knappen
var tekst:TextField = new TextField();
tekst.autoSize = TextFieldAutoSize.LEFT;
tekst.selectable = false;
tekst.text = "Nu er der tekst i";
tekst.x = tekst.y = 5;
knap.addChild(tekst);

Når du tester filmen, vil du se at tekstfeltet fjerner musehånden fra knappen. Hvis du flytter markøren helt ud til et af hjørnerne vil du se, at den stadig er aktiv – det er tekstfeltet, der er skyld i misæren.

Der er to måder at løse det på. Begge bunder i at det ikke skal være muligt for objekter inde i symbolet at reagere på musens gestus. Hvis du vil forhindre tekstfeltet i at forholde sig til musen kan det gøre således:

tekst.mouseEnabled = false;

Dette vil påvirke den enkelte knap og skrives tit samtidig med oprettelsen af tekstfeltet (når man husker det) :-)

Den anden metode fjerner muligheden for alle objekter inde i knappen. Det er yderst praktisk, hvis knappen er bygget op af mange delobjekter, som du med sikkerhed kan sige, ikke skal bruge musen til noget. Med andre ord: Hvis det kun er knappen som helhed, der skal reagere. Det ser således ud:


knap.mouseChildren = false;

Den sidste er værd at huske på. Men grundlæggende virker det forkert at musehånden ikke virker, når bare teksten ikke er markerbar. Må dette indlæg spare dig for noget bøvl, hvis projektet skulle dreje sig i den retning :-)

/ockley

Adobe Flash Catalyst rykker tættere på

Der er mere og mere, der rør sig, når det gælder det nye designværktøj til Flash platformen, nemlig Flash Catalyst. Med dette program er det muligt at layoute dine komplette montager i Photoshop og Illustrator. Disse kan du så importere til Adobe Flash Catalyst, som der omdanner al grafik og vektor til “symboler”. Det er også muligt at vælge hvad der skal være knapper og skydekontroller. Når det gøres vil Flash Catalyst automatisk omdanne dem til komponeneter, med det udseende, som du har layoutet. Du kan redigere dem med et enkelt dobbeltklik (kan man sige det?) og tilføje de forskellige tilstande.

Det smukke ved alt dette er, at Adobe Flash Catalyst arbejder med ActionScript 3.0 og MXML under motorhjelmen. Resultatet af dit arbejde vil umiddelbart kunne exporteres som en fxp-fil, der er kompatibel med den næste version af Flex kaldet “Gumbo” (Adobe Flex Builder 4).

Det er faktisk ret fantastisk at se Flash Catalyst i aktion, og Ryan Steward har netop oprettet et screencast, der viser en gennemgang af programmet. Han har også en skrevet udgave af tutorial’en og en psd-fil med øvelsesfilen, hvis du er så heldig at være med i den private beta :-)

Der er ingen information om, hvornår Flash Catalyst kommer i offentlig beta, men du kan læse mere om programmet på adressen http://www.adobe.com/go/flashcatalyst/ hvor du også kan skrive dig op til info om frigivelse.

Uhhh, det bliver SÅ spændende :-)

/ockley

Adobe Flash CS4 Professional online dokumentation

Halløj igen.

Jeg troede faktisk ikke denne måtte blive offentliggjort, men når du Lee Brimelow gør det, så er den vel ude i det åbne :-) Der er nemlig også en hulens masse dokumentation til Adobe Flash CS3 Professional. Følgende tre er nok de mest interessante:

Online hjælp til FLash CS4
http://help.adobe.com/en_US/Flash/10.0_Welcome/

Stedet hvor du kan læse om ahvordan selv IDE’en kommer til at virke. Det umiddelbare startpunkt vil være Using Flash hvor du kan kigge i underkategorierne.

Reference til ActionScript 3.0 Language and Components
http://help.adobe.com/en_US/AS3LCR/Flash_10.0/index.htm

Den gode gamle ven, som giver dig svar på alle klasserne og hvilke muligheder de giver. Opdateret til Flash Player 10

Programming ActionScript 3.0
http://help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3/

Her er den nye bibel til folk der vil lære at programmere ActionScript 3.0. Den er ikke nem for begyndere, men folk med erfaring med programmering vil synes godt om den. De fleste vil nok dykke lige ned i kapitlet Working in three dimensions (3D) :-)

God fornøjelse

/ockley