martedì 4 maggio 2010

Creare apps per iPhone con Flash CS5


Con il rilascio della nuova Creative Suite 5 sono stati aggiornati numerosi ambienti di sviluppo. Una delle migliorie più significative (eh, ahimè, presto inutili) è l'iPhone Packager, ossia un compiler in grado di convertire un sorgente ActionScript 3.0 in un eseguibile per iPhone.

Giusto per testare le effettive capacità del packager, ho provato a implemntare una banale app che reagisca all'inclinazione del telefono. Per farlo occorre utilizzare le nuove classi del package flash.sensor (implementate proprio in vista dei nuovi smartphone).

Vediamo nel dettaglio il codice

import flash.sensors.Accelerometer;
import flash.events.AccelerometerEvent;

stage.scaleMode = StageScaleMode.NO_SCALE;//blocca lo scale dello stage
stage.align = StageAlign.TOP_LEFT;//allinea lo stage in alto a sx (utile per posizionare oggetti al suo interno)
//stage.cacheAsSurface = true;//boh...

Innanzitutto importiamo i package che ci servono. In teoria questi import non servono se non quando si implementa una nuova classe, ma Flash CS5 le ha inserite non appena ho dichiarato gli oggetti, per cui...



var xSpeed:Number = 0;
var ySpeed:Number = 0;
const RADIUS = 20;


Inizializzo le variabili di cui ho bisogno:
  1. accelerometer contiene eventi e relative informazioni riguardo i sensori X,Y,Z dello smartphone.
  2. timer regolerà la frequenza di aggiornamento del movimento della pallina
  3. xSpeed/ySpeed sono le varibili Number della velocità della pallina nel piano
  4. RADIUS è una costante che dovrebbe indicare l'ingombro della pallina nello stage. Ovvio che è a vostra discrezione...

if (Accelerometer.isSupported)
{
    var accelerometer = new Accelerometer();
    accelerometer.addEventListener(AccelerometerEvent.UPDATE, accUpdateHandler);
    var timer = new Timer(40);
    timer.addEventListener(TimerEvent.TIMER, timerHandler);
    timer.start();
}

Il metodo statico isSupported della classe Accelerometer rileva la configurazione dello SP in modo da capire se ha o no i sensori di accelerazione e se sono abilitati dal suo O.S. E' utile per prevenire eventuali errori in caso di mancato funzionamento di questi ultimi.
  1. Istanzio quindi l'oggetto accelerometer
  2. Creo l'ascoltatore per l'ebento UPDATE, ossia l'evento scatenato al movimento dello SP
  3. Istanzio il timer. Questo oggetto scatena un evento Timer ad intevalli predefiniti specificato nel costruttore in millisec. Ho settato l'evento ogni 40 ms supponendo una framerate dell'iPhone di 25fps: 1000ms/25fps = 40ms, ossia una volta per frame. Un intervallo più basso sarebbe inutile in quanto non visualizzabile dallo SP
  4. Creo l'ascoltatore all'evento TIMER
  5. Faccio partire il timer

franco.x = stage.stageWidth / 2;
franco.y = stage.stageHeight / 2;
addChild(franco); 

Setto la posizione di partenza della pallina e la aggiungo allo stage.


function accUpdateHandler(event:AccelerometerEvent):void
{
xSpeed += event.accelerationX * 2;
ySpeed -= event.accelerationY * 2;
}

Questa funzione viene richiamata ad ogni evento di tipo AccelerometerEvent, ossia ogni volta che lo smartphone assume una posizione fuori asse. L'attributo accelerationX/Y contiene al suo interno un Number indicante l'accellerazione a cui lo SP è sottoposto (nota: qui sarebbe necessaria una distinzione tra Accellerometri e Giroscopi, che rimando a un post futuro): per la cronaca, l'unità di misura è metro/secondo^2, chi ha qualche riminescenza di meccanica classica capirà.

function movefranco():void
{
    var newX:Number = franco.x + xSpeed;
    var newY:Number = franco.y + ySpeed;
    if (newX < 20)
    {
        franco.x = RADIUS;
        xSpeed = 0;
    }
    else if (newX > stage.stageWidth - RADIUS)
    {
        franco.x = stage.stageWidth - RADIUS;
        xSpeed = 0;
    }
    else
    {
        franco.x +=  xSpeed;
    }

    if (newY < RADIUS)
    {
        franco.y = RADIUS;
        ySpeed = 0;
    }
    else if (newY > stage.stageHeight - RADIUS)
    {
        franco.y = stage.stageHeight - RADIUS;
        ySpeed = 0;
    }
    else
    {
        franco.y +=  ySpeed;
    }
}

Queste if altro non fanno che bloccare la pallina quando questa arriva a toccare i bordi. Senza entrare nel dettaglio (anche perchè credo sia tutto molto elementare) si considera l'ingombro determinato dal radius calcolando così quando la pallina deve smettere di muoversi.

function timerHandler(event:TimerEvent):void
{
    movefranco();
}

Questa funzione, richiamata dall'evento TimerEvent scatenato dall'oggetto timer si occupa di aggiornare la posizione della pallina in base alle possibile nuove inclinazioni dello SPhone.

Ecco il codice per esteso

import flash.sensors.Accelerometer;
import flash.events.AccelerometerEvent;
import flash.display.MovieClip;

stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
//stage.cacheAsSurface = true;

var accelerometer:Accelerometer;       
var timer:Timer;
var xSpeed:Number = 0;
var ySpeed:Number = 0;
const RADIUS = 20;

function accUpdateHandler(event:AccelerometerEvent):void
{
    xSpeed +=  event.accelerationX * 2;
    ySpeed -=  event.accelerationY * 2;
}

function movefranco():void
{
    var newX:Number = franco.x + xSpeed;
    var newY:Number = franco.y + ySpeed;
    if (newX < 20)
    {
        franco.x = RADIUS;
        xSpeed = 0;
    }
    else if (newX > stage.stageWidth - RADIUS)
    {
        franco.x = stage.stageWidth - RADIUS;
        xSpeed = 0;
    }
    else
    {
        franco.x +=  xSpeed;
    }

    if (newY < RADIUS)
    {
        franco.y = RADIUS;
        ySpeed = 0;
    }
    else if (newY > stage.stageHeight - RADIUS)
    {
        franco.y = stage.stageHeight - RADIUS;
        ySpeed = 0;
    }
    else
    {
        franco.y +=  ySpeed;
    }
}

function timerHandler(event:TimerEvent):void
{
    movefranco();
}
var ciccio: MovieClip = new MovieClip
//-----------------------------------------------------
if (Accelerometer.isSupported)
{
    accelerometer = new Accelerometer();
    accelerometer.addEventListener(AccelerometerEvent.UPDATE, accUpdateHandler);
    timer = new Timer(100);
    timer.addEventListener(TimerEvent.TIMER, timerHandler);
    timer.start();
}
franco.x = stage.stageWidth / 2;
franco.y = stage.stageHeight / 2;
addChild(franco);

Link: download

Nessun commento:

Posta un commento