Pagine    Articoli    Prodotti    Forum    Cerca  
Nickname

Password


Non sei registrato?
Registrati a GPI qui!

Puoi anche attivare un vecchio utente GPI e chiedere una nuova password.
I Team

Mappa Team
I nostri utenti

Mappa Utenti
  Programmare un videogame in FLASH e Starling #2
Pubblicato da Andrea Venturi il 2012-07-18 20:31:21

"cameriere mi porti il menù"

In questo secondo tutorial iniziamo a scrivere un pò di codice, ma prima i compiti per casa.

 

Come si poteva intuire lo scopo di oggi è realizzare il menù del nostro gioco, quindi andiamo a creare una cartella (anche sul desktop) e nominiamola media, al suo interno ne creiamo un'altra dal nome graphics al cui interno, finalmente, andiamo a inserire i file creati, nominandoli:

  1. BGMENU.png
    BG 
  2. LOGO.png
     logo
  3. PLAY.png
    Play 
  4. ABOUT.png
    About 
  5. TITOLO.png
    Titolo 

(nel mio esempio sono tutti file .png come potete intuire)

 

Per fare quanto serve, bisogna aprire FD, clickare con il tasto destro sulla cartella src quindi selezioniamo la voce Explore, a questo punto saliamo di una cartella e qui andiamo a posizionare la cartella precedentemente creata media.

 

Ora saremmo pronti per partire, ma prima una piccola parte di teoria, giusto due concetti per capire meglio cosa stiamo utilizzando.

 

Ricordo che questo framework (Starling) serve per migliorare l'efficenza dei vostri giochi 2D utilizzando le nuove API di Stage 3D, in maniera molto intuitiva per chi già è pratico della programmazione AS3, in quanto riutilizza gli stessi concetti come: DisplayList, il modello di eventi, MovieClip, Sprite e TextField; tutto questo senza andare a conoscere concetti di pipile di rendering, matrici prospettiche,vertex o fragment program.

 

Per riassumere Starling non fa altro che prendere il vostro contesto 2D e trasformalo in un contesto 3D per poi demandare la GPU (su pc tramite DirectX o OpenGL, su device OpenGL ES2) il disegno, senza impegnare la CPU.

 

 

Partiamo

Andiamo ad aprire l'unico file .as presente nel progetto Main.as.

Per prima cosa andiamo ad importare il nostro framwork, per essere inizializzato.

 

Quindi tra gli import andiamo ad aggiungere:


import starling.core.Starling;

poi andiamo a creare un attributo privato della classe di tipo Starling:

private var _starling:Starling;

 

A questo punto creiamo un metodo privato per inizializzare Starling

private function init():void
{
  _starling = new Starling(Game, stage);
  _starling.start();
}

 

Come potete notare il costruttore prende due parametri, il primo è un tipo Class che è la classe del nostro gioco (che chiameremo Game) e il secondo è il riferimento allo stage.

 

A questo putno bisogna andare a creare la classe Game, andiamo col mouse sopra la cartella src, click destro e Add->New Class.

 

Nominiamola Game (se volete cambiarlo ricordatevi di andarlo a sostituire nella chiamata al costruttore nel file Main.as).

 

La classe deve estendere il tipo Sprite, ma non quella di Flash ma quella di Starling, quindi andremo a importare il tipo Sprite giusto

import starling.display.Sprite;
import starling.events.Event;

 

Visto che ci siamo andiamo pure ad importare gli eventi, così possiamo andare a gestire l'evento di aggiunta allo stage.

 

Quindi nel costruttore andiamo a scrivere

super();
this.addEventListener(Event.ADDED_TO_STAGE, onAddToStage);

Ovviamente con super() andiamo a richiamare il costruttore della classe che stiamo estendendo e aggiungiamo un listener per ascoltare l’evento di aggiunta allo stage e lo gestiamo

private function onAddToStage(e:Event):void
{
  removeEventListener(Event.ADDED_TO_STAGE, onAddToStage);
  //...
}

 

A questop putno siamo pronti, ma prima di procedere meglio introdurre un paio di concetti fondamentali su questo framework.

 

Ancora teoria

Come già detto prima Starling trasforma il un contesto 2D in 3D, ma come avviene la trasformazione?

 

Magia? mmmh quasi...

 

Immaginate di avere un'immagine e di averla in uno Sprite, questo framework va a creare un quadrato in 3D e applica l'immagine nello sprite come Texture del quadrato, ed ecco come avviene la magia.

 

Per capire meglio immaginatevi il quadrato formato da due triangoli attaccati e complanari, prende l'immagine e la applica al modello formato tramite texture mapping.

 

Quindi come oggetto base per le immagini, come si poteva già immaginare,  abbiamo il tipo Texture, da cui andiamo a creare un oggetto di tipo Image (o altro) per essere visualizzato.

Per capire meglio, facciamo un raffronto con Flash: la texture sta ad una BitmapData come un oggetto di tipo Image sta ad una Bitmap.

 

Ora ci serve una classe per gestire le Texture create dalle immagini caricate, quindi andiamo a creare una classe e diamole nome Asset, questa classe avrà il comportamento di un object pool, molto utile per risparmiare risorse.

 

Dopo la dichiarazione di classe andiamo a inserire il riferimento alle immagini create per questo tutorial (se avete fatto i compiti per casa) e “embeddiamole” nel codice

[Embed ("../media/graphics/BGMENU.png")]
public static const BGMENU:Class;

La prima riga indica al compilatore che deve includere nel compilato quella risorsa, mentre la seconda riga indica al compilatore che la risorsa incorporata viene riferita come un oggetto di tipo BGMENU; in pratica andiamo a creare una classe che identifica la risorsa incorporata.

 

Ovviamente dovete inserire il path corretto alle vostre risorse.

Incorporiamo anche le altre immagini

[Embed ("../media/graphics/LOGO.png")]
public static const LOGO:Class;
[Embed ("../media/graphics/TITOLO.png")]
public static const TITOLO:Class;
[Embed ("../media/graphics/PLAY.png")]
public static const PLAY:Class;
[Embed ("../media/graphics/ABOUT.png")]
public static const ABOUT:Class;

 

A questo punto andiamo a creare una variabile di tipo Dictionary per memorizzare le immagini caricate e poterle prendere quando ne abbiamo bisogno.

 

Andiamo a dichiarare la variabile subito sotto il codice appena scritto

private static var gameTexture:Dictionary = new Dictionary();

Notate l'uso dell'attributo static, in questo caso è corretto in quanto si deve poterreperire questa informazione ovunque, soprattutto vengono caricate una sola volta.

 

Per facilitare il reperimento delle immagini e la loro trasformazione in Texture, andiamo a creare una funzione atta a questo scopo

public static function getTexture(name:String):Texture
{
  if (gameTexture[name] == undefined)
  {
    var bitmap:Bitmap = new Assets[name]();
    gameTexture[name] = Texture.fromBitmap(bitmap);
  }
  return gameTexture[name];
} 

Anche questa funzione ha l'attributo static per lo stesso motivo della variabile.

 

In pratica la funzione ritorna una Texture di nome passato tramite il parametro name, che viene prelevata nel Dictionary, nel quale viene caricata in caso non sia presente.

 

A questo punto andiamo a creare una nuova cartella dal nome screens, sempre sotto src, dove andremo a mettere le scermate del gioco.

 

Andiamo a creare la classe Menu, che estenderà Sprite di Starling, in quanto qui si disegna.

Quindi andiamo a importare Event, Sprite e Image, ovviamente non le classiche di Flash ma di Starling.

import starling.display.Image;
import starling.display.Sprite;
import starling.events.Event;

Andiamo a creare i nostri attributi privati per lo sfondo, il titolo e il logo, tanto per iniziare.

Il tipo Image è il tipo che crea la magia detta in precedenza, che trasforma da 2D a 3D.

private var bg:Image;
private var title:Image;
private var logo:Image;

Come visto in precedenza nel costruttore andremo a richiamare il costruttore della classe che estendiamo e gestiamo l'evento ADDED_TO_STAGE

super();
this.addEventListener(Event.ADDED_TO_STAGE, onAddToStage);

Quindi la funzione che gestisce l’evento, che oltre a rimuovere il listener richiamerà la funzione drawScreen per disegnare le nostro menù

private function onAddToStage(e:Event):void
{
  removeEventListener(Event.ADDED_TO_STAGE, onAddToStage);
  drawScreen();
}

 

La funzione drawScreen che andiamo a creare serve e posizionare i nostri elementi grafici, iniziamo con lo sfondo.

private function drawScreen():void
{
  bg = new Image(Assets.getTexture("BGMENU"));
  addChild(bg);
  title = new Image(Assets.getTexture("TITOLO"));
  title.x = 140;
  title.y = 20;
  addChild(title);
  logo = new Image(Assets.getTexture("LOGO"));
  logo.x = 500;
  logo.y = 150;
  addChild(logo);
}

 

 

Ritorniamo sulla classe Game e aggingiamo l'import alla classe Menu

import screens.Menu;

creiamo un membro di questo tipo

private var screenMenu:Menu;

e nella funzione addToStage lo inizializzeremo e aggiungiamo allo stage

screenMenu = new Menu();
addChild(screenMenu);

E ora? andiamo a vedere le posizioni, quindi:

Compilate! ed errori a parte, comparirà una prima bozza del vostro menù.

Ma prima di procedere...

 

Un pizzico di teoria teoria per insaporire

Introduciamo i tipi Button.

In Starling i tipi button sono oggetti particolari, necessitano di una texture e una stringa, poichè nativamete possono andare a creare un textfield con il testo passato come etichetta del bottone, e altre particolarità che vedremo nel prossimo appuntamento.

 

Quindi torniamo nella classe Menu e andiamo ad importare il tipo Button

import starling.display.Button;

Andiamo ad aggiungere due membri privati per i nostri due bottoni: play e about

private var play:Button;
private var about:Button;

E andiamo ad istanziarli nella funzione drawScene

play = new Button(Assets.getTexture("PLAY"));
about = new Button(Assets.getTexture("ABOUT"));

Posizioniamoli e aggiungiamoli al nodo per essere disegnati

play.x = 200;
play.y = 260;
about.x = 220;
about.y = 380;
addChild(play);
addChild(about);

Compilate e guardate il risultato.

 

 

Il piatto del vicino è sempre più buono.

A questo punto se compiliamo il risultato è un menù praticamente completo, ma un po' statico, quindi per animarlo un pochino ho preso spunto da uno degli esempi presenti sul sito di Starling.

 

L'idea e' andare ad animare il logo facendolo comparire dopo che il menù si è caricato, quindi per prima cosa andiamo a modificare la posizione di partenza del logo

logo.x = 800+logo.width;

Per spostarlo vado ad utilizzare una libreria che ho già usato in passato, ma se volete potete usare pure il sistema di tweening fornito da starling, ma secondo me è un pò troppo verboso.

 

Andate a scaricare TweenLite dal sito della GreenSock, copiate il file swc nella cartella src del progetto e da FD con il tasto destro andate ad aggiungerlo in libreria (Add to Library).

 

Sempre nella classe Menu andiamo ad importare la classe tweenlite

import com.greensock.TweenLite;

 

andiamo a creare una nuova funzione, pubblica, dal nome inizialize e andiamo a riposizionare il nostro logo e lanciamo l'animazione.

public function initialize():void
{
  visible = true;
  logo.x = 800+logo.width;
  logo.y = 150;
  TweenLite.to(logo, 2, { x: 480 } );
  addEventListener(Event.ENTER_FRAME, logoAnimation);
}

 

L'aggiunta del visible = true serve per essere sicuri che sia visibile la nostra scena, ma approfondiremo avanti.

 

La chiamata TweenLite.to definisce e fa partire l'animazione, prende come parametri: l'oggetto da muovere, la durata dell'animazione e un oggetto contenente le caratteristiche a cui deve arrivare al fine animazione.

 

Per dargli un ulteriore movimento andiamo ad aggiungere un listener all'evento ENTER_FRAME  e lo andiamo a gestire

private function logoAnimation(e:Event):void
{
  var currentDate:Date = new Date();
  logo.y = 150 + (Math.cos(currentDate.getTime() * 0.002) * 25);
}

 

Spieghiamola un attimo, ad ogni frame creo una variabile di tipo Date e la inizializzo, serve per avere un valore per valore che si incrementa.

Subito sotto associo alla y del logo il risultato di un piccolo conto matematico.

Il coseno è una funzione periodica che restituisce un valore tra -1 e +1.

Con 0.002 indico il fattore moltipolicativo (ovvero la velocita' di spostamento verticale), tutto lo moltiplico per 25, che indica la metà dell’ ampieza dell'oscillazione, infine sommo 150 che il punto centrale in cui deve avvenire.

 

Ovviamente come ultima cosa ritornarte nella classe Game nella funzione onAddToStage e dopo tutto andiamo a chiamare inizialize.

 

private function onAddToStage(e:Event):void 
{
  removeEventListener(Event.ADDED_TO_STAGE, onAddToStage);
  screenMenu = new Menu();
  addChild(screenMenu);
  screenMenu.initialize();
}

 

 

Mi dimenticavo i sorgenti :)

Campagne crowfunding

Just One Line
Siamo presenti su

     
Copyright ©2016 - Manifesto - Privacy - Termini di Servizio - Community - Collaboratori - Contattaci