Strona wykorzystuje ciasteczka by usprawnić komfort z jej korzystania. Korzystając ze strony akceptujesz naszą Politykę Ciasteczek. X

5 powodów dla których ActionScript2 jest wciąż przydatny

ActionScript3 jest bez wątpienia bardziej zaawansowanym językiem niż ActionScript2 i już większość programistów Flash z niego korzysta, jednak to nie oznacza, że AS2 nie ma swojego prawa bytu - w końcu, musi być jakiś powód dla którego Adobe jeszcze go nie uśmierciło. Oto 5 powód dla których ActionScript2 jest wciąż przydatny:

5. Łatwiejszy w nauce.
Dla osób które zaczynają przygodę z Flash'em i dopiero zastanawiają się który język wybrać, AS2 będzie przyjemniejszym wprowadzeniem do programowania. Nie tylko pozwala pominąć trudniejsze koncepty programowania (choćby nadawanie typów), sam również idzie użytkownikowi na rękę robiąc wszystko byle tylko nie zatrzymać całej aplikacji w działaniu.

4. Skoncentrowane działanie.
ActionScript3 jest w stanie zrobić o wiele więcej niż ActionScript2, aczkolwiek w zamian może wymagać większego zaangażowania od strony programisty, czasem nawet wymagając wiedzy z poza standardowej dokumentacji (komunikacja na Socket'ach, akceleracja sprzętowa, grafika 3D). ActionScript2 potrafi mniej, ale to często wystarczy.

3. W prostych zastosowaniach prędkość nie jest problemem.
To chyba jeden z najczęściej przytaczanych argumentów wyższości AS3 nad AS2, jednak prawda jest taka, że szybszym sposobem na obciążenie procesora jest stosowanie nadmiernej ilości grafiki, niż starszego kodu. Generalnie jeśli nie wiesz czy szybszy kod Ci się przyda, to prawdopodobnie go nie potrzebujesz.

2. Stworzenie podstawowych elementów wymaga mniej czasu.
Powiedzmy, że chcemy stworzyć przycisk który przeniesie użytkownika na jakąś stronę WWW.
W ActionScript2 tyle w zupełności wystarcza:
on(press) {
	getURL("http://4as.pl");
}
Podczas gdy ActionScript3 wymaga już trochę więcej:
import flash.events.MouseEvent;
import flash.net.navigateToURL;
import flash.net.URLRequest;
buttonMode = true;
addEventListener(MouseEvent.CLICK,onMouseClick);
function onMouseClick(e:MouseEvent):void {
	navigateToURL(new URLRequest("http://4as.pl"));
}
Nie wspominając już o takich rzeczach jak duplikowanie MovieClip’ów

1. Większa kompatybilność ze starszymi urządzeniami
Czasem łatwo zapomnieć, że Flash nie jest dostępny tylko na komputerach - Z ActionScript2 łatwiej trafić do szerszego grona użytkowników, w tym posiadaczy telefonów komórkowych na których korzystanie z nowszych wersji Flash Player'a może być... kłopotliwe.

Ostatecznie jednak należy pamiętać, że mimo wszystko ActionScript3 jest lepszym językiem, którego warto się nauczyć jeśli mamy zamiar poważnie programować we Flash'u, szczególnie przy większych projektach, jak na przykład tworzeniu gier.

Komunikacja pomiędzy AS2 i AS3 [podstawowy]

Jak tylko ActionScript3 po raz pierwszy ujrzał światło dzienne Adobe od razu stwierdziło, że stoi za nim zupełnie inna wirtualna maszyna niż ta w AS2, a co za tym idzie nie jest możliwa bezpośrednia komunikacja między tymi dwoma językami. W tym momencie za pewne każdy by pomyślał, że w takim razie nie ma co próbować, skoro nie mogą się komunikować to temat jest zamknięty. Ale chwila moment, brak bezpośredniego połączenia to nie jest jednoznaczne z brakiem jakiegokolwiek połączenia. Ujmę to tak: weźmy na przykład MySQL, Flash sam z siebie nie ma żadnego sposobu by połączyć się z nim bezpośrednio, ale to nas nie powstrzymuje by i tak z niego korzystaj przez PHP (lub inne metody). I tu dochodzimy do sedna sprawy: pośrednie połączenie. W przypadku AS3 i AS2 jest to nawet jeszcze prostsze niż korzystanie z PHP, bo oby dwa języki mają wbudowaną klasę do komunikacji między lokalnymi plikami SWF - mowa tutaj o LocalConnection.
LocalConnection w głównym założeniu ma pozwalać na komunikację między aplikacjami Flash uruchomionymi na tym samym komputerze , jednak ponieważ implementacja tej klasy w ogolę się nie zmieniła po przejść do AS3, nic nie stoi na przeszkodzie by wykorzystać ją do wymiany informacji między AS2 i AS3.
Utworzenie LocalConnection w obydwóch przypadkach jest bardzo łatwe i będzie wyglądać prawie identycznie. Dla ActionScript2 będzie to:
var connectionAS2:LocalConnection = new LocalConnection();
connectionAS2.connect("LocalConnectionTestAS2");
A dla ActionScript3:
var connectionAS3:LocalConnection = new LocalConnection();
connectionAS3.client = this;
connectionAS3.connect("LocalConnectionTestAS3");
connectionAS3.addEventListener(StatusEvent.STATUS,onStatus);
function onStatus(e:Event):void { }
O ile wersja dla AS2 jest trywialna, to AS3 już wymaga paru słów wyjaśnienia. Przede wszystkim linijka connectionAS3.client = this;, która służy do wyznaczenia obiektu odpowiedzialnego za wykonywanie funkcji wywoływanych z drugiej strony połączenia, jest bardzo ważna i bez niej aplikacja zwyczajnie nie będzie działać. StatusEvent jest dodany do LocalConnection tylko po to by Flash nie wyrzucał żadnych błędów przed nawiązaniem połączenia.
A i nazwy w funkcji connect() są różne by pozwolić na dwustronną komunikację.
W porządku, teraz gdy już AS2 i AS3 są gotowe do przyjmowania komend od siebie nawzajem, czas stworzyć funkcje które będą mogli wywołać. By cały proces lepiej zobrazować wykorzystamy TextField'y do pokazania danych otrzymanych z zewnątrz. Dla ActionScript3 będzie to:
var tf:TextField = new TextField();
tf.text = "No Messages";
addChild(tf);

function messageFromAS2(msg:String,nx:Number,ny:Number):void {
	tf.text = msg+" "+nx+" "+ny;
	tf.x = nx;
	tf.y = ny;
}
A dla ActionScript2:
this.createTextField("textMsg",this.getNextHighestDepth(),0,0,200,25);
var tf:TextField = this.textMsg;
tf.text = "No Messages";

connectionAS2.messageFromAS3 = function(msg:String,nx:Number,ny:Number):Void {
	tf.text = msg+" "+nx+" "+ny;
	tf._x = nx;
	tf._y = ny;
}
Teraz już tylko pozostało jakoś wywołać te funkcje, np. za pomocą myszki. W ActionScript3:
stage.addEventListener(MouseEvent.MOUSE_MOVE,onMove);
function onMove(e:MouseEvent):void {
	try {
		connectionAS3.send("LocalConnectionTestAS2","messageFromAS3","AS3 MouseEvent",e.stageX,e.stageY);
	} catch(e:Error) {
		return;
	}
}
W ActionScript2:
this.onMouseMove = function():Void {
	try {
		connectionAS2.send("LocalConnectionTestAS3","messageFromAS2","AS2 Mouse Event",_root._xmouse,_root._ymouse);
	} catch(e) {
		return;
	}
}
W obydwóch przypadkach potrzebny jest try-catch by zapobiec wszelkim błędom przed nawiązaniem przez Flash połączenia.
W akcji całość będzie wyglądać tak:
Kod źródłowy: localcon.zip

Przy okazji, w sytuacji w której musielibyśmy coś odczytać z pliku AS2 a który nie obsługuje LocalConnection i którego już nie możemy modyfikować, sugerował bym stworzyć osobny plik SWF w ActionScript2, wczytać (funkcja loadMovie()) w nim nasz docelowy plik, następnie wyciągnąć wszystkie potrzebne informacje i przesłać je dalej za pomocą LocalConnection.

Od AS2 do AS3: duplicateMovieClip() w ActionScript 3 [zaawansowany]

Programiści którzy postanowią przejść na AS3 z AS2 prędzej czy później na pewno zauważą kompletny brak odpowiednika funkcji duplicateMovieClip() w najnowszej iteracji ActionScript'a. Może wydawać się to nieco dziwne, w końcu trudno sobie wyobrazić by Adobe nie było wstanie zaimplementować takiej funkcji - powodem ten decyzji jest prawdopodobnie chęć zabicia złych nawyków w użytkownikach AS3. W każdym razie, czasem po prostu trzeba zduplikować jakiś MovieClip dlatego poniżej prezentuje listę możliwych rozwiązań:

1. Własna klasa.
Myślę, że około 90% ludzi którzy szukają alternatywy dla duplicateMovieClip() powinni być zadowoleni z tego rozwiązania. W skrócie chodzi tutaj o stworzenie klasy podrzędnej MovieClip'a i powiązanie jej z grafiką którą chcemy powielić. Dla przykłady powiedzmy, że tworzymy aplikacje która w tle będzie miała spadające gwiazdy i oczywiście by uzyskać ten efekt stworzymy MovieClip jednej gwiazdy a następnie zaczniemy ją kopiować tyle razy ile jest to potrzebne. W tym celu należy udać się do właściwości MovieClip'a owej gwiazdy i zaawansowanych opcjach zaznaczyć "Eksportuj dla ActionScript".
Eksporotwanie dla ActionScript
Od teraz klasa "Star" zawiera grafikę gwiazdy i można ją duplikować do woli pisząc:

var mc:MovieClip = new Star();
addChild(mc);
I tyle.

2. Skorzystanie z funkcji loadBytes() w klasie Loader.
Więc metoda #1 jest całkiem przyjemna ale co jeśli chcemy zduplikować plik wczytany z zewnętrznego źródła? Zobaczmy jak może w takim wypadku wyglądać ładowanie grafiki:

import flash.display.Loader;
import flash.events.Event;
import flash.net.URLRequest;

lLoad = new Loader();
lLoad.contentLoaderInfo.addEventListener(Event.COMPLETE,onLoaded);
lLoad.load(new URLRequest("your_file.swf"));

function onLoaded(e:Event):void {
	addChild(lLoad.content);
}
Cóż, klasa Loader nie ma zbyt wielu funkcji i po załadowaniu pliku SWF możemy go praktycznie tylko dodać na scenę albo załadować inną grafikę. Oczywiście ponowne wczytanie grafiki z serwera odpada (aczkolwiek jeśli użytkownik ma włączone przechowywanie obiektów w pamięci podręcznej Flash skorzysta właśnie z niej zamiast nawiązywać połączenie jeszcze raz) dlatego duplikacji dokonamy wykorzystując loadBytes(). Trik polega na tym, że loadBytes() jest w stanie wczytać dowolny, obsługiwany przez load(), obiekt zapisany w ByteArray. Pytanie tylko jak uzyskać ByteArray wczytanego MovieClip'a? Okazuje się, że rozwiązanie jest bardzo proste:
function onLoaded(e:Event):void {
	addChild(lLoad.content);
	lLoad.loadBytes(lLoad.content.loaderInfo.bytes);
}
Wartość lLoad.content.loaderInfo.bytes przechowuje wczytaną animację jako ByteArray, więc wystarczy ją wrzucić do funkcji loadBytes by ponownie wywołać zdarzenie onLoaded i dostać kolejny MovieClip bez nawiązywania jakichkolwiek dodatkowych zewnętrznych połączeń.
Jest tylko jeden problem, zdarzenie onLoaded nie zostanie wywołane natychmiast... co oznacza, że wczytany MovieClip zostanie zduplikowany dopiero po kilku lub kilkunastu milisekundach (zależnie od wartości FPS).

3. Skorzystanie z wartości constructor w obiekcie wczytam przez Loader.
Alternatywnym rozwiązaniem do duplikowania SWF wczytanych z zewnątrz jest wykorzystanie wartości constructor dostępnej we wszystkich klasach Flash'a. Bez owijania w bawełnę korzysta się z niej w następujący sposób:

function onLoaded(e:Event):void {
	var d:DisplayObject = new lLoad.content["constructor"]();
	addChild(d);
}
(Zmienna constructor jest dynamiczna więc to jedyny sposób by się do niej dostać. Ponadto nie zapomnij o słowie kluczowym new!)
Niestety, nie jest to idealne rozwiązanie. Kod zdziała tylko wtedy gdy wczytana animacja będzie miała niestandardową "Klasę Dokumentu" (może to być cokolwiek, byle tylko pole "Klasa Dokumentu" nie było puste), co w praktyce oznacza, że to ty musisz być twórcą wczytywanego pliku.

By zaoszczędzić trochę na pracy zaimplementowałem te rozwiązania w jedną klasę - powinna być w stanie zduplikować każdy MovieClip (i nie tylko): foras_clone.zip
A korzysta się z niej w następujący sposób:

import foras.utils.ForCloner;
import flash.display.DisplayObject;
if(stage==null) return;
var fas_Clone:ForCloner = new ForCloner();
var d:DisplayObject = fas_Clone.cloneMovie(my_mc,onClone);
if(d!=null) {
	d.x = stage.stageWidth*Math.random();
	d.y = stage.stageHeight*Math.random();
	addChild(d);
}

function onClone(d:DisplayObject):void {
	d.x = stage.stageWidth*Math.random();
	d.y = stage.stageHeight*Math.random();
	addChild(d);
}
Ponieważ klasa ForCloner również korzysta z metody loadBytes() (o której pisałem w punkcie 2) potrzebna jest funkcja która zajmie się zdarzeniem wczytania pliku i właśnie dlatego cloneMovie() jej wymaga. Oczywiście może się zdarzyć, że wcale nie będzie potrzebna i cloneMovie() natychmiast zwróci zduplikowany MovieClip. Najczęściej jednak będzie to null i wtedy kopia animacji trafi do wybranej funkcji (w tym przykładzie onClone).
Jeszcze jedna uwaga na koniec, linijka if(stage==null) return; zatrzymuje kod przed ponowny wywołaniem - jeśli wszystko inne zawiedzie zduplikowana zostanie cała aplikacja, a to oznacza wczytanie również kodu drugi raz (z całości zostanie wyciągnięty tylko docelowy MovieClip, a reszta zostanie usunięta).

Od AS2 do AS3: odpowiednik _global w AS3 [podstawowy]

Pewnego razu zostałem zapytany czy istnieje sposób by odczytać zmienne utworzone na _root albo _global. W AS3 problemem są bardzo rygorystyczne wymagania - w AS2 można po prostu napisać _global.myVar = 5 by mieć dostęp do tej zmiennej z każdego miejsca w projekcie, ale niestety AS3 po prostu nie toleruje dynamicznych zmiennych (no i nie obsługuje słowa kluczowego _global).
Można to obejść na dwa sposoby:

1. Użyć składni przewidzianej do dynamicznych zmiennych.

root["myVar"] = 5;
To właściwie to samo co w AS2, ale używanie dynamicznych zmiennych może tragicznie spowolnić działanie aplikacje (przy częstym używaniu). W takim wypadku lepiej zainteresować się drugą opcją.

2. Użyć słowa kluczowego static.
To prawdopodobnie najlepsze podejście do całej sprawy, ale wymaga nieco dodatkowej pracy. Przed zrobieniem czegokolwiek należy utworzyć "Klasę Dokumentu" na zakładce właściwości.

Wybraną nazwę klasy (np. "MyClass") należy potwierdzić enter'em (w tym momencie wyskoczy okienko informujące, że taka klasa nie istnieje - śmiało można to zignorować) a następnie kliknąć na ikonkę ołówka obok.
Jeśli wszystko przebiegło pomyślnie zawartość naszej nowej klasy zostanie wyświetlona w osobnym okienku:

package  {
	import flash.display.MovieClip;
	
	public class MyClass extends MovieClip {
		
		public function MyClass() {
			// constructor code
		}
	}
	
}
Teraz jeszcze przed linijką public function MyClass() pozostało napisać:
public static var myVar:Number = 5;
To w zasadzie wszystko. Od teraz z każdego miejsca w projekcie możemy dostać się do naszej zmiennej pisząc:
import MyClass;
trace(MyClass.myVar);
Ponadto skoro klasa dokumentu jest obiektem nadrzędnym całego projektu, możemy się do niej dostać przez pole root w każdym MovieClip'ie. Trzeba go tylko rzutować na naszą klasę:
import MyClass;
trace((root as MyClass).myVar);