Facebook aplikationer og Flash - navigateToUrl drilleri

Kategori: Tips og tricks | Kommentarer (2)
Gemt: 2009-01-29 12:03


Vi er i øjeblikket i fuld gang med at lave en Facebook aplikation der i høj grad benytter sig af Flash (mere om den senere), og i den forbindelse er jeg stødt på et par mindre besværligheder.

Den første og største var, at Facebook når man bruger FBML (fb:swf) automatisk sætter alle Flash-objekter til at kører med allowScriptAccess=never.

Det er en sikkerhedsbegrænsning de har sat på, for at alle vi udviklere ikke uhæmmet skal kunne kalde en masse javascript-funktioner og dermed få adgang til data som vi ikke skal have adgang til.
Problemet med det er så, at det også sætter en række begrænsninger for funktioner som man ikke nødvendigvis ved bruger javascript, eksempelvis navigateToUrl, som pludselig er begrænset til kun at kunne bruge _blank, og det er jo helt umuligt at lave en lækker aplikation i Flash, hvis alle sider åbner i nye vinduer.

Det ved Facebook også godt og derfor er der en metode til at komme uden om problemet, nemlig ved at bruge en Flash-fil som Facebook har lavet som en bro.
Lyder det indviklet? Det er det også lidt og det tog mig noget tid at lure, så derfor kommer opskriften her.

Før skal man indsætte den Facebook-bro som man senere skal tilgå via LocalConnection:

<fb:fbjs-bridge/>
<fb:swf swfbgcolor="FFFFFF"
	swfsrc='http://www.dinurl.dk/din.swf'
	width='760'
	height='600'
	/>
<script> <!-- --></script>

Dernæst, så skal man bruge en funktion som tilgår broen og som kan bruges som erstatning for navigateToUrl, selv lavede jeg denne lille klasse, men det kan gøres på mange måder:

import flash.net.LocalConnection;
import flash.display.LoaderInfo;

public class FacebookUtil {
	private var connection:LocalConnection;
	private var connectionName:String;
	private var baseUrl:String = "http://apps.facebook.com/dinaplikation/";

	public function init(_loaderInfo:LoaderInfo):void {
		connection = new LocalConnection();
		connectionName = _loaderInfo.parameters.fb_local_connection;
	}

	function go(_url:String):void {
		if (connectionName) {
			connection.send(connectionName,
			"callFBJS",
			"document.setLocation",
			[baseUrl + _url]
			);
		} else {
			trace("FacebookUtil.go: No connection");
		}
	}
}

Som du kan se, så har den en init funktion, og det er fordi at Facebook som standard sender nogle værdier med til alle fb:swf objekter, og nogle af dem har vi brug for, så derfor skal klassen klargøres inden man kan kalde funktionen go, som det hele drejer sig om:

var Facebook:FacebookUtil = new FacebookUtil();

Facebook.init(LoaderInfo(this.root.loaderInfo));

Facebook.go("minside.php");

I den klasse jeg lige har lavet er der ikke mulighed for at sætte target, da jeg kun havde brug for _self, men det kan den sagtens udvides med.

Håber det kan gøre vejen til din første Facebook aplikation i Flash lidt nemmere :-)


ActionScript 3: Picture klasse med indbygget load, brightness, contrast, saturation og hue

Kategori: Tips og tricks | Kommentarer (3)
Gemt: 2008-08-27 13:35


Det fede ved at alle deler med alle, er at man har mulighed for at “stå på andres skuldre” som det så populært hedder, og det er netop grundlaget for min nyeste klasse: Picture.

For ikke så lang tid siden havde jeg en post om hvordan man nemt kan konvertere et billede til sort/hvid.
I den post kom der en kommentar fra Thonbo som viste en anden måde at gøre det på, nemlig ved hjælp af ColorMatrixFilter, som jeg hidtil har afholdt mig fra at bruge, da det er en anelse tungt at sætte sig ind.

Men, det fik mig til at søge lidt rundt, hvorefter jeg fandt en ColorMatrix klasse fra Grant Skinner, hvor man kan inputte de normale værdier for brightness, contrast, saturation og hue, som man kender dem fra f.eks. filtrene i selve Flash, såvel som Photoshop.

Stadigvæk synes jeg dog at det var lidt bøvlet at man skulle hen og lave et nyt objekt hver gang man skulle stille på en enkelt værdi, og derudover gør den fremgansmåde det særdeles svært at tweene værdierne.
Så, for at gøre det endnu nemmere, i hvert fald i forhold til der hvor jeg skulle bruge funktionen, så har jeg wrappet den klasse i min egen, nemlig Picture klassen.

Den nye klasse har to funktioner:
load(url:String)
setColors(brightness:int, contrast:int, saturation:int, hue:int)

Og 4 properties man kan stille på:
- brightness
- contrast
- saturation
- hue

Og nogle properties som man kan aflæse:
- bytesLoaded
- bytesTotal
- bytes Percent
- loadingComplete

Samt 2 events man kan lytte på:
- Event.COMPLETE
- ProgressEvent.PROGRESS

Ønsker man kun at ændre en enkelt ting ved billedet, så er det nemmest blot at opdate den specifikke property, men skal man ændre mange ting på en gang, så er det smartere (og mindre performance krævende) at kalde funktionen setColors.

Et ekstremt simpelt eksempel kunne se sådan her ud:

var picture:Picture = new Picture();
picture.addEventListener(Event.COMPLETE, loadCompleted);
picture.load("test.jpg");
addChild(picture);

function loadCompleted(_e:Event):void {
	picture.saturation = -100;
}

Download
For at gøre det nemt at komme igang, så er alt det nødvendige, inklusive en CS3 fla-fil med et simpelt eksempel, samlet til download her:
Download picture.zip

Forslag til forbedringer eller nye funktioner modtages som altid gerne :-)


ActionScript 3: Tiles på den nemme måde

Kategori: Tips og tricks | Kommentarer (0)
Gemt: 2008-08-20 10:13


Nogen gange har man brug for at tile (gentage det samme stykke grafik mange gange) for eksempelvis at fylde en baggrund ud.
En oplagt måde er at lave et loop, som kopierer og placerer det stykke grafik der skal tiles, men der findes en meget, meget nemmere måde, nemlig funktionen beginBitmapFill.

Først skal vi bruge det stykke grafik som skal tiles, så i dette eksempel har jeg importeret en png ind i mit library og efterfølgende sat den til at blive eksporteret til ActionScript som klassen Tile:

ActionScript 3 Tile

Og herefter er det såre simpelt:

var tile:BitmapData = new Tile(0, 0);
var background:Sprite = new Sprite();
background.graphics.beginBitmapFill(tile, null, true, false);
background.graphics.drawRect(0, 0, 500, 500);
background.graphics.endFill();
addChild(background);

Voila, en baggrund på 500×500 pixels.

En ting der er værd at bemærke er, at hvis man har brug for efterfølgende at ændre størrelsen på baggrunden, så er det ikke nok bare at sætte en ny højde og bredde, da det vil strække tilen, fremfor at kopiere den.

I stedet skal man bruge graphics.clear() og tegne et nyt område:

background.graphics.clear()
background.graphics.beginBitmapFill(tile, null, true, false);
background.graphics.drawRect(0, 0, 2000, 2000);
background.graphics.endFill();

Dynamisk load
I det første eksempel har jeg brugt et stykke grafik fra mit library, men det kan naturligvis også gøres med en jpg eller lignende som man loader dynamisk:

var url:String = "tile.jpg";
var loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, tileLoadComplete);
loader.load(new URLRequest(url));

function tileLoadComplete(_e:Event):void {
	var tile:Bitmap = Bitmap(_e.target.loader.content);
	var background:Sprite = new Sprite();
	background.graphics.beginBitmapFill(tile.bitmapData, null, true, false);
	background.graphics.drawRect(0, 0, 500, 500);
	background.graphics.endFill();
	addChild(background);
}

Så nu er der ingen undskyld for ikke at tile på livet løs, men please, ingen hjerter eller killinger!


ActionScript 3: Konverter farvebilleder til sort/hvid

Kategori: Tips og tricks | Kommentarer (3)
Gemt: 2008-08-14 16:58


Nogen gange har man brug for det samme billede både i farver og i sort/hvid, men hvorfor bruge tid på at konvertere dem manuelt og ikke mindst, spilde båndbredde på at loade dobbelt så mange billeder, når man kan konvertere dem fra farver til sort/hvid automatisk i ActionScript 3?

Funktion:

function convertToBW(_image:Bitmap):Bitmap {
	var _image_bw:Bitmap = new Bitmap(_image.bitmapData);
	var _r:Rectangle = new Rectangle(0, 0, _image_bw.width, _image_bw.height);
	var _p:Point = new Point(0,0);
	_image_bw.bitmapData.copyChannel(_image_bw.bitmapData, _r, _p, 2, 1);
	_image_bw.bitmapData.copyChannel(_image_bw.bitmapData, _r, _p, 2, 2);
	_image_bw.bitmapData.copyChannel(_image_bw.bitmapData, _r, _p, 2, 4);
	return _image_bw;
}


ActionScript 3 tips og tricks fra Grant Skinner

Kategori: Diverse | Kommentarer (0)
Gemt: 2008-06-5 11:00


Grant Skinner har netop offentliggjort sine slides fra en workshop han holdt i slutningen af 2007, og selvom det er et stykke tid siden, så er der stadig en del godt at hente.

Den kommer glimrende ind på forskellene mellem AS2 og AS3, og han kommer generelt rigtig langt omkring på de 167(!) slides, så der skulle både være noget at hente for de fleste:
ActionScript 3 Workshop


Actionscript 3 performance optimering

Kategori: Diverse | Kommentarer (2)
Gemt: 2008-05-30 12:49


En af de mest hardcore Flashkodere Joa Ebart har lavet et lille dokument med alle de tips og tricks til at optimere performance i ActionScript, som han selv er stødt på, og der er absolut et par guldkorn imellem.

De to som gør den allerstørste forskel er:

Genbrug objekter
Langsom:
for (;i<n;i++)
p = new Point(i, i);

Hurtig:
for (;i<n;i++)
{
p.x = i;
p.y = i;
}

Her er det cirka 40 gange hurtigere at genbruge objektet.

Undgå såvidt muligt try and catch
Langsom:
var o: Sprite;
for (;i<n;i++)
{
try
{
o.blendMode = BlendMode.ADD;
}
catch ( error: Error ) {}
}

Hurtig:
var o: Sprite;
for (;i<n;i++)
if ( o != null )
o.blendMode = BlendMode.ADD;

Her er det cirka 1000 gange hurtigere at teste på null.

Disse to og mange flere tips finder du i dette dokument:
ActionScript 3 optimization techniques by Joe Ebert

Og hvis du er i humør til lidt nørdgloser og teknisk snak, så vil jeg anbefale dig at kigge på hans egen blogpost om emnet, hvor særligt kommentarer bliver særdeles nørdede:
ActionScript 3 optimization techniques


God tutorial om avanceret tweening

Kategori: Diverse | Kommentarer (1)
Gemt: 2008-05-7 10:19


Flash & Math har netop lavet en rigtig god tutorial som kigger nærmere på hvordan man laver avancerede tweens i ActionScript.
Normalt når man tweener, så er det jo linært, flyt object x fra a til b, men hvad nu hvis bevægelsen skal være en cirkel eller måske et s?

Det giver denne tutorial et par bud på:
Tween Tricks in ActionScript 3 and Flash CS3


Nemmere debugging: Runtime errors med linienummer

Kategori: Tips og tricks | Kommentarer (6)
Gemt: 2008-04-29 9:59


Er der noget mere irriterende end at få en runtime i ActionScript 3, som bare lister at der gik noget galt i en funktion?
Eksempelvis at en unavngiven variabel ikke var defineret?

Hvis man har en stor funktion og fejlen ikke lige springer en i øjnene med det samme, så er det nemlig rent et spørgsmål om trial-and-error for at få fundet stedet hvor det går galt.
Eller, det vil sige, det er det faktisk ikke!

Man kan lige i “Publish settings” sætte et flueben i “Permit debugging”, hvilket gør at man får den fejlbesked man hele tiden har fået PLUS det præcise linienummer hvor fejlen er opstået.
Så bliver det ikke meget nemmere!

Permit debugging

Skal ikke kunne sige om det er almen viden for alle andre, men jeg havde i hvert fald ikke lige luret det.

Fundet via denne blog.


currentFrame og totalFrames i ActionScript 3

Kategori: Tips og tricks | Kommentarer (0)
Gemt: 2008-04-21 15:59


Et lille hurtigt tip:
I ActionScript 3 findes værdierne currentFrame og totalFrames kun på MovieClips, ikke på stagen, og derfor er det ikke umiddelbart lige til at finde ud af hvor mange frames der er i stagen.

Men, man kan heldigvis få ActionScript 3 til at behandle stagen som om den var et MovieClip, og voila, så findes værdierne:

MovieClip(root).currentFrame


ActionScript 3 performance tip: Slå mouseEnabled og mouseChildren fra

Kategori: Tips og tricks | Kommentarer (2)
Gemt: 2008-03-27 11:09


Jeg kan ikke tage æren for dette ActionScript 3 tip, men det skal ikke udelukke mig fra at bringe det:
Hvis du har mange objekter på scenen, så kan man ofte halvere CPU forbruget ved at sætte mouseEnabled = false og mouseChildren = false på de objekter som rent faktisk ikke skal interagere med musen.

Så, tak til NateJC for at dokumentere det:
mouseEnabled and mouseChildren Affect CPU Load

Og til Ryan Taylor for at påpege det (se den første kommentar):
Does this code make my Flash look fat?