Problem nie nowy, ale wciąż spotykany. Otóż próba komunikacji aplikacji flashowej z serwerem w bezpiecznym połączeniu HTTPS, w przeglądarce Internet Explorer 6 oraz 7 ma spore szanse zakończyć się niepowodzeniem:
Tego typu błąd otrzymamy w aplikacji napisanej w ActionScript3. W starszej wersji 2 języka problem może być jeszcze bardziej irytujący, gdyż nie otrzymamy żadnego widocznego komunikatu o błędzie, ale nasz program też nie będzie działać.
Błąd występuje niezależnie od wersji flash playera. Odporny na ten przypadek jest Internet Explorer dopiero w wersji 8. Lekarstwem na bolączkę jest wysłanie w zasadzie dowolnej nieprawidłowej wartości dla nagłówka Pragma, np.:
header (”Pragma: internet-explorer-is-my-life”);
Co ciekawe, wysłanie nagłówka “Pragma: no-cache”, nie dosyć że powoduje opisany wyżej problem, to wcale nie zapobiega cachowaniu zawartości podczas połączenia bez szyfrowania SSL.
W toku jakże intensywnych prac nad efektami specjalnymi we flashu, przez przypadek stworzyłem maziageneratora – program, który także tobie pozwoli poczuć się prawdziwym impresjonistą.
Tak się kończą zabawy z Bitmap.draw, BlendMode.OVERLAY i krzywymi lissajou:
Kolejny sympatyczny efekt, wykorzystywany bardzo często w produkcjach demosceny to tunel. W milionach różnych wersji, wyewoluował od całkiem prostej realizacji rysowanych okręgów do hiper-super-triple teksturowanego tunelu z dynamicznym oświetleniem, cieniami i bajerami.
Realizacja tego efektu we flashu jest jak najbardziej możliwa. Sprawa wygląda prosto:
Od pewnego czasu wracam wspomnieniami do czasów demosceny, a od kilku dni odświeżam stare umiejętności i przekładam to, co kiedyś robiło się w assemblerze, na Flasha i Actionscript. Jednym z wynalazków koderów z demosceny, był efekt plazmy.
Opisowo efekt ten polegał na uzyskaniu interesujących graficznie animacji “rozlewających” się kolorów. Ponieważ jednak ówczesne komputery były zbyt wolne na obliczanie co ramke wartości każdego pixela na ekranie, koderzy użyli jednej ze swoich sztuczek: tylko raz na starcie rysowało się obraz pixeli na ekranie, a potem podmieniano jedynie paletę kolorów używaną przez układ graficzny. W ten sposób nawet ZX-Spectrum dawało radę:
W takim razie, skoro ZX-Spectrum ze swoim Zilogiem Z80 dawało radę, jak poradzi sobie flash na procesorach taktowanych gigaherzami? :) Nie możemy niestety operować bezpośrednio na palecie ( zabawa z ColorTransform również odpada), więc jednak musimy za każdym razem odrysować wszystkie pixele na ekranie. Spróbujmy:
package {import flash.display.Sprite;
import flash.display.StageScaleMode;
import flash.display.StageAlign;
import flash.events.Event;
import flash.display.BitmapData;
[SWF(width="300", height="300", backgroundColor="0x000000")]publicclass PlasmaEffect extends Sprite
{privatevar w:int = 150;
privatevar h:int = 150;
privatevar colors:Array = newArray();
privatevar plasma:Array = [w];
privatevar paletteShift:int;
publicfunction PlasmaEffect(){this.stage.scaleMode = StageScaleMode.NO_SCALE;
this.stage.align = StageAlign.TOP_LEFT;
this.stage.frameRate = 10;
this.stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);
generatePalette();
generatePlasma();
}privatefunction draw():void{this.graphics.clear();
for(var x:int = 0; x < w; x++)for(var y:int = 0; y < h; y++){this.graphics.lineStyle(1, colors[(plasma[x][y] + paletteShift)%256]);
this.graphics.moveTo(x *2, y *2);
this.graphics.lineTo(x *2, y *2 + 1);
}}privatefunction generatePlasma():void{var colorIndex:int;
for(var x:int = 0; x < w; x++){
plasma[x] = [h];
for(var y:int = 0; y < h; y++){
colorIndex =
(128.0 + (128.0*Math.sin(x /16.0))
+ 128.0 + (128.0*Math.sin(y /32.0))
+ 128.0 + (128.0*Math.sin(Math.sqrt(((x - w /2.0)*(x - w /2.0) + (y - h /2.0)*(y - h /2.0)))/8.0))
+ 128.0 + (128.0*Math.sin(Math.sqrt((x * x + y * y))/8.0)))/4;
plasma[x][y] = colorIndex;
}}}privatefunction generatePalette():void{var r:int;
var g:int;
var b:int;
for(var x:int = 0; x <256; x++){
r = 128.0 + 128*Math.sin(3.1415* x /16.0);
g = 128.0 + 128*Math.sin(3.1415* x /128.0);
b = 0;
colors.push(r *256*256 + g *256 + b);
}}privatefunctiononEnterFrame(e:Event):void{
draw();
paletteShift += 1;
}}}
No cóż, na moim, całkiem współczesnym komputerze nie daje rady – ledwo 5 klatek na sekundę, i macierz pixeli o rozmiarach 150×150. Winowajcą jest metoda lineTo – zbyt wolna jak na nasze potrzeby.
Ale, drobna zmiana kodu, zastąpienie rysowanie poprzez graphics.lineTo na bezpośrednie ustawianie pixelów bitmapy:
package {import flash.display.Sprite;
import flash.display.StageScaleMode;
import flash.display.StageAlign;
import flash.events.Event;
import flash.display.BitmapData;
import flash.display.Bitmap;
[SWF(width="300", height="300", backgroundColor="0x000000")]publicclass PlasmaEffect extends Sprite
{privatevar w:int = 300;
privatevar h:int = 300;
privatevar colors:Array = newArray();
privatevar plasma:Array = [w];
privatevar paletteShift:int;
privatevar bitmap:BitmapData = new BitmapData(w, h, false);
publicfunction PlasmaEffect(){this.stage.scaleMode = StageScaleMode.NO_SCALE;
this.stage.align = StageAlign.TOP_LEFT;
this.stage.frameRate = 20;
this.stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);
this.addChild(new Bitmap(bitmap));
generatePalette();
generatePlasma();
}privatefunction draw():void{this.graphics.clear();
for(var x:int = 0; x < w; x++)for(var y:int = 0; y < h; y++){
bitmap.setPixel(x, y, colors[(plasma[x][y] + paletteShift)%256]);
//this.graphics.lineStyle(1, colors[(plasma[x][y] + paletteShift) % 256]);//this.graphics.moveTo(x * 2, y * 2);//this.graphics.lineTo(x * 2, y * 2 + 1); }}privatefunction generatePlasma():void{var colorIndex:int;
for(var x:int = 0; x < w; x++){
plasma[x] = [h];
for(var y:int = 0; y < h; y++){
colorIndex =
(128.0 + (128.0*Math.sin(x /16.0))
+ 128.0 + (128.0*Math.sin(y /32.0))
+ 128.0 + (128.0*Math.sin(Math.sqrt(((x - w /2.0)*(x - w /2.0) + (y - h /2.0)*(y - h /2.0)))/8.0))
+ 128.0 + (128.0*Math.sin(Math.sqrt((x * x + y * y))/8.0)))/4;
plasma[x][y] = colorIndex;
}}}privatefunction generatePalette():void{var r:int;
var g:int;
var b:int;
for(var x:int = 0; x <256; x++){
r = 128.0 + 128*Math.sin(3.1415* x /16.0);
g = 128.0 + 128*Math.sin(3.1415* x /128.0);
b = 0;
colors.push(r *256*256 + g *256 + b);
}}privatefunctiononEnterFrame(e:Event):void{
draw();
paletteShift += 1;
}}}
i… sukces! :) Tym razem macierz 300×300 i 20 klatek na sekundę:
Do większego projektu, potrzebowałem napisać program obliczający położenie (wysokość i azymut) słońca na nieboskłonie. O tym “większym” projekcie mam nadzieję, że napiszę niebawem, a na razie oddaję do dyspozycji gotowy kalkulator położenia słońca – parametry wejściowe to lokalizacja, data i godzina; wynik – azymut i wysokość. Program napisany w Adobe Flex.
Kilka dni temu szukałem malutkiego mp3 playera, który wyświetlał by jedynie ikonkę z przyciskiem play i odgrywał wskazany dźwięk mp3. Poszukiwania w googlu dały kilka rezultatów, ale każdy z nich albo był “za bardzo”, albo miał złą licencję. Zamiast tracić dalej czas napisałem te kilkanaście linijek kodu i stworzyłem swój własny FemtoPlayer – Femto to brzmi dumnie ;)
Parametry:
file = pathToMP3 //ścieżka do pliku mp3
autoplay = true|false //czy automatycznie odgrywać dźwięk po wczytaniu
Andy Zupko, współautor Papervision3D, napisał klasę dzięki której dostajemy możliwość rzucania cieni przez dowolne obiekty na naszej scenie 3D. Muszę przyznać, że działa to znakomicie – oraz dużo szybciej od pierwszej wersji, którą zaprezentował w ubiegłym roku. Klasa ShadowCaster nie została na razie dodana do pakietu z Papervision3D, ale można pobrać jej źródło bezpośrednio ze strony Andiego – tam też znajdziecie demo i przykład wykorzystania.
Problem: Plik swf utworzony w actionscript2 będzie osadzony w innym pliku swf utworzonym w actionscript3. W jaki sposób z jednego pliku swf wywołać metodę w drugim?
Rozwiązaniem jest użycie klasy LocalConnection. Oto przykładowy kod:
Prywatnie - mąż i ojciec, miłośnik dobrej książki i świętego spokoju.
Zawodowo - konsultant i programista. Wyznaje zasadę: proste jest piękne, a mniej znaczy więcej!