Lo sviluppo di giochi in ambiente Android

 

Nel progredire del mondo mobile,  il settore   di  più  grande  impatto è  stato quello  videoludico.  Attualmente,  i  giochi  per  dispositivi  mobili rappresentano  il  33%  delle  applicazioni  scaricate  ed  il  66%  del  fatturato registrato sui marketplaces.

Il  mercato  videoludico  ha  fornito  in  questi  anni  un  contributo  rilevante  alla divulgazione  su  larga  scala  delle  tecnologie  dell’ informazione  e  della comunicazione.  Per  le  generazioni  più  giovani,  infatti,  il  videogioco rappresenta spesso il primo  modo per avvicinarsi all’informatica.

Lo  sviluppo  di  un  videogioco  è  caratterizzato  dall’utilizzo  massiccio  di  effetti grafici  e  sonori  ed  un  elevato  livello  di  interattività  con  l’utente,  al  fine  di catturare  parzialmente  o  completamente  l’attenzione  di  quest’ultimo  per  scopi ludici  e  di  divertimento.

Per  potersi  cimentare  in  questa  impresa  è  necessario conoscere  la piattaforma Android e dare uno sguardo alla sua architettura. Fatto ciò risulta molto utile gestire la creazione di un gioco con i game-engine  più comuni.

Un  game  engine  è  un  frame work software  progettato  specificamente  per  la  creazione  e  lo  sviluppo  di videogiochi.  Esso  è  il  cuore  del  gioco  e  la  scelta  del  game  engine  è  una  delle fasi  più  importanti  dello  sviluppo  di  un  videogame.

  

Dal  motore  di  gioco dipende  una  serie  di  caratteristiche  che  il  gioco  può  possedere  o  meno come, meccanismi  di  rendering  per  la  grafica  2D  o  3D,  meccanismi  per l’implementazione  della  fisica  di  gioco,  meccanismi  per  rilevare  le  collisioni fra  diversi  oggetti.  Alcuni  dei framework  più  utilizzati  fra  gli  sviluppatori  di  videogame sono:

  • jMonkeyEngine

  • AndEngine

  • Libgdx 

 


 

jMonkeyEngine  è  un  game  engine  open-source  utilizzato  per  la  realizzazione di  giochi  3D  in  linguaggio  Java.  Questo  motore grafico  fa  uso  delle  librerie  Java  LWJGL  (Lightweight  Java  Game  Library),  per  permettere  agli sviluppatori di accedere ad OpenGL (Open Graphics Library), OpenCL (OpenComputing Language) ed OpenAL (Open Audio Library).

Per  sfruttare  appieno  le  librerie  jMonkeyEngine  si  fa  uso  del  suo  ambiente  di sviluppo  ideale:  l’SDK  (Software  Development  Kit)  jMonkeyEngine.  Esso  è basato sulla piattaforma  NetBeans e  fornisce i plugin  unici per  la creazione  di contenuti  di  gioco.  Essendo  derivato  da  NetBeans  ha  accesso  a  tutti  gli strumenti di sviluppo di quest’ultimo.

Uno  degli  aspetti  più  interessanti  di  jMonkeyEngine  è  il  fatto  di  poter realizzare  applicazioni  non  soltanto  per  i  dispositivi  Android  ma  anche  per altre piattaforme come desktop e Web.

 

Come  jMonkeyEngine,  anche  AndEngine  è  un  game  engine  open-source utilizzato  per  la  realizzazione  di  giochi  ma,  a  differenza  del  primo,   esso consente  esclusivamente  la  grafica  2D.  La  libreria  AndEngine  permette  anche a  persone  inesperte  il  facile  apprendimento  nello  sviluppo  di  un  videogioco ma,  come  controparte,  le  API  non  offrono  ampie  possibilità  di personalizzazione come invece accade per altre librerie quali Libgdx.

AndEngine  supporta  le  seguenti  estensioni  che  forniscono  diverse funzionalità: 

  •  PhysicsBox2DExtension, che permette  l’uso della  fisica Box2D.
  •  TMXTiledMapExtension,  che  permette  la  lettura  dei  file  generati  in formato TMX per  la realizzazione di mappe. 
  •  MultiplayerExtension, supporta il  multiplayer.

 

A  differenza  dei  primi  due,  Libgdx  non  è  un  engine  bensì  è  un  frame work open-source  per  la  realizzazione  di  giochi  sia  2D  sia  3D  ed  una  delle  sue caratteristiche  principali  è  la  possibilità  di  sviluppare  giochi  per  diverse piattaforme  di  destinazione.  Attualmente  supporta  Windows,  Linux,  Mac  OSX, Android,  iOS e HTML5. Sostanzialmente è possibile scrivere  il codice  una sola  volta ed esportarlo sulle diverse piattaforme senza alcuna modifica. 

Libgdx  è  progettato  per  dare  allo  sviluppatore  libero  accesso  a  tutto  ciò  di  cui ha  bisogno:  file  system,  dispositivi  di  input,  dispositivi  audio  ed  OpenGL tramite  un’ interfaccia  OpenGL  ES  2.0  e  3.0.  Ha  un  set  di  API  che  aiutano nelle  comuni  attività  di  sviluppo  di  un  gioco:  rendering  di  sprite,  costruzione di  interfacce  utente, riproduzione di effetti sonori.

 

Nel  successivo paragrafo  si  effettuerà  un’analisi  più  dettagliata  di  Libgdx.

 


 

Libgdx  è  un  framework  open-source  per  lo  sviluppo  cross-platform  di  giochi su  tecnologia  Java.  In  realtà,  oltre  a  Java,  il  framework  fa  uso  anche  del linguaggio  C  sia  per  compiere  quei  compiti  che  sono  critici  per  le performance,  sia  per  incorporare  librerie  C  di  terze  parti  che  forniscono  tool di supporto.

Una  delle  caratteristiche  principali  di  Libgdx  è  la  possibilità  di  esportare  il proprio  progetto  su  diverse  piattaforme.  Per  fare  ciò  fornisce  un’API  comune che  astrae  completamente  i  dettagli  implementativi  delle  varie  piattaforme supportate  che  attualmente  sono:  Windows,  Linux,  Mac  OS  X,  Android,  iOS e HTML5.

Libgdx  non  è  un  game  engine.  I  game  engine  sono  composti,  generalmente, da  una  insieme  di  tool  che  vincolano  lo  sviluppatore.  In questo modo Libgdx  lascia  allo  sviluppatore  una  totale  libertà  sugli  strumenti  da  utilizzare ed  offre  la  possibilità  di  utilizzare  operazioni  di  basso  livello  qualora  fosse necessario.

Quando  si  crea  un’applicazione  con  Libgdx  si  vanno  ad  implementare  N progetti  di  cui  un  progetto core  che  sfrutta  l’API  fornita  e  che  contiene  gran parte  del  codice, ed  N-1  progetti,  uno  per  ogni  piattaforma  utilizzata,  che contengono  la  restante  parte  di  codice  utile  all’avvio  dell’applicazione  sulle diverse piattaforme.

Con  Libgdx  è  possibile  eseguire  e  debuggare  il  codice  su  desktop  come  una normale applicazione Java. Ciò  ha un duplice vantaggio:

  • Consente l’utilizzo  di  tutti  gli  strumenti  e  delle  funzionalità  supportate dalla Java Virtual Machine
  • Riduce sensibilmente i tempi di sviluppo e di debug.

Per  fare  in  modo  che  si  possa  scrivere  un unico  codice  di  base,  però,  è  necessario  che  tutti  i  progetti  abbiano  libero accesso  alle  risorse  che  dovranno  essere  utilizzate.  Abbiamo  anche  detto  che la  maggior  parte  del  codice  di  un’applicazione  Libgdx  è  scritta  nel  progetto core  e,  quindi,  si  potrebbe  pensare  di  avere  una  directory  interna  a  questo progetto  contenente  suoni,  immagini  e  quant’altro  possa  essere  condiviso  fra le  varie  piattaforme.  Tuttavia  Android  ha  delle  regole  molto  ferree  per  quanto riguarda  l’utilizzo  delle  risorse  e  per  tale  motivo  si  utilizza  la  cartella  assets del progetto Android per  la condivisione dei dati.

I  legami  fra  i  diversi  progetti  sono  gestiti  tramite Gradle. Gradle  è  un  sistema di  creazione  (build)  e  gestione  (management)  delle  dipendenze.  La  gestione delle  dipendenze  avviene  tramite  un  file  che  specifica  i  nomi  e  le  versioni delle  librerie  che  uno  sviluppatore  ha  bisogno  di  avere  nella  propria applicazione.  L’aggiunta,  la  rimozione  o  la  modifica  della  versione  di  una libreria  può  essere  ottenuta  semplicemente  modificando  alcune  righe  di questo  file.  Il  sistema  di  build  aiuta  con  la  creazione  della  propria applicazione  e  non  è  legato  al  particolare  IDE  (Integrated  DevelopmentEnvironment)  utilizzato.

Prima  di  Gradle  era  necessario  configurare  libgdx ogni  volta  che  si  creava  un  nuovo  progetto.   Tale  configurazione  consisteva  di una  serie  di  passi,  per  caricare  le  librerie  e  per  creare  le  dipendenze  fra  i diversi  progetti,  che  potevano  costituire  un  procedimento  abbastanza complesso  e  spesso  fonte  di  errori.  Il  sistema  di  build  di  Gradle  automatizza questo  procedimento  e  permette  a  tutte  le  piattaforme  di  condividere  la cartella assets del progetto Android.

 


 

Un’applicazione  in  Libgdx  ha  un  ciclo  di  vita  ben  definito  che  permette  allo sviluppatore  di  avere  un  controllo  totale  sugli  stati  dell’applicazione  stessa, quali:  creazione,  sospensione  e  riavvio,   raffigurazione  delle  immagini  e smaltimento  delle  risorse  utilizzate.  Tale  ciclo  di  vita  è  rappresentato  nella figura seguente:

Per  gestire  gli eventi che cambiano  lo stato  di  un’applicazione, lo sviluppatore non  deve  far  altro  che  creare  una  classe  Java  che  implementa  l’ interfaccia ApplicationListener  di  Libgdx.  Questa  contiene  tutti  i  metodi  necessari  allo scopo:

 

  • create(), viene  chiamato  una  sola  volta  quando  l’applicazione  è creata. Quando  ciò  accade  l’applicazione  carica  tutto  ciò  di  cui  ha bisogno  per  permettere  all’utente  di  giocare:  texture,  sprite, spritebatch, stage…
  • resize(int width,  int  height),  viene  chiamato  ogni  volta  che  lo schermo  del  gioco  viene  ridimensionato  ed  il  gioco  non  è  nello  stato di  pausa. Accetta  due  parametri,  width  ed  height,  che  rappresentano rispettivamente  i  nuovi  valori di  larghezza ed altezza dello schermo
  • render(), è  un  ciclo  infinito  che  viene  ripetutamente  chiamato dall’applicazione  durante  la  fase  di  gioco. Termina  solo  quando l’applicazione  stessa  termina.  Gli  aggiornamenti  logici,  come  la nuova  posizione  sullo  schermo  che  deve  assumere  un’immagine, vengono  inseriti  in questo metodo
  • pause(), è  un  metodo  che  serve  a  gestire  lo  stato  di  sospensione  del gioco  e  viene  invocato  in  modi  diversi  in  funzione  della  piattaforma di destinazione. In  Android,  viene  invocato  quando  è  premuto  il tasto  Home  o  se  è  in  arrivo  una  chiamata;  nelle  piattaforme  desktop, invece,  viene  invocato  prima  della  chiamata  al  metodo  dispose() ovvero quando  l’applicazione deve essere terminata
  • resume(), è  utilizzato  solo  nella  piattaforma  Android  e  permette  il riavvio  se  l’applicazione  si  trovava  precedentemente  nello  stato  di pausa
  • dispose(), viene  invocato  quando  l’applicazione  deve  terminare  e serve per  liberare memoria

 


 

Libgdx  è  composto  da  diversi  moduli  ognuno  dei  quali  fornisce  un  diverso servizio  per  ogni  step  di  una  tipica  architettura  di  gioco.  La  figura  seguente mostra questi moduli.

 

  • Input, fornisce  un  modello  per  la  gestione  dei  dispositivi  di  input  su tutte  le    Supporta  tastiera,  touchscreen,  accelerometro  e, dove disponibile, mouse.
  • Graphics, consente  il  disegno  delle  immagini  sullo  schermo  tramite OpenGL ES.
  • Files, consente l’accesso ai file su tutte  le piattaforme.
  • Audio, facilita  la  registrazione  e  la  riproduzione  di  suoni  su  tutte  le piattaforme.
  • Networking, fornisce  i  metodi  per  eseguire  operazioni  di  rete,  come  ad esempio  semplici  richieste  HTTP  o  comunicazione  client/server  con Socket TCP.

 

Le  diverse  piattaforme  di  destinazione  di  un  progetto  in  Libgdx  presentano diversi  dispositivi  di  input.  Sui  dispositivi  desktop  l’utente  invia  comandi tramite  tastiera  o  mouse;  sui  dispositivi  Android,  invece,  il  mouse  viene sostituito  da  un  touchscreen  capacitivo  e  la  tastiera  spesso  manca.  Inoltre,  i dispositivi  Android  spesso  dispongono  anche  di  un  accelerometro  e  di  un sensore di campo magnetico.

Libgdx  tratta  mouse  e  touchscreen  allo  stesso  modo  ed  a  seconda  del dispositivo  di  input  è  possibile  eseguire  un’ interrogazione  ciclica  dello  stato del  dispositivo  (polling)  oppure  registrare  un  listener  che  si  occuperà  di ricevere  gli  eventi  di  input  in  ordine  cronologico  (event  handling).  Il  primo metodo  è  sufficiente  alla  gestione  di  semplici  giochi  arcade;  il  secondo metodo,  invece,  è  necessario  quando  nel  videogioco  sono  coinvolti  element i dell’ interfaccia  utente  come  i  tasti,  poiché  questi  si  basano  su  sequenze  di eventi  come  tocco/rilascio  del  tasto.  La  gestione  di  tutti  i  dispositivi  di  input  è affidata all’ interfaccia di Input. 

 

L’ interfaccia  Graphics  fornisce  informazioni  riguardo  il  display  del dispositivo  o  la  finestra  dell’applicazione,  a  seconda  che  si  tratti  di piattaforma  Android  o  desktop  rispettivamente,  nonché  informazioni  e accesso  al  contesto  OpenGL  corrente.  Più  nello  specifico  fornisce informazioni  riguardo  la  dimensione  dello  schermo,  la  densità  dei  pixel  e  le proprietà  del  frame-buffer  come  la  profondità  di  colore  ovvero  la  quantità  di bit  necessari  per  rappresentare  un  colore  in  un  singolo  pixel  del  frame-buffer, appunto,  di  un  dispositivo  video.  Come  per  altri  comuni  moduli  di  Libgdx, l’accesso è fornito tramite  l’utilizzo di campi statici della classe Gdx.

Il  modulo  Graphics  permette  la  realizzazione  di  giochi  2D  o  3D.  In particolare,  per  il  2D  mette  a  disposizione  il  package  scene2d  che  consente un’agevole  costruzione  di  interfacce  GUI  grazie  ad  una  gerarchia  di  attori.

Tali  attori  sono  definiti  nella  classe  Actor  del  package  scene2d  ed  è  possibile impostare  posizione,  dimensione,  punto  di  origine,  scala,  rotazione  e  colore.

La  seconda  delle  tre  classi  che  compongono  il  cuore  di  scene2d  è  la  classe Group  che  a  sua  volta  è  un  attore  e  può  avere  attori  figli.  Quando  viene apportata  una  modifica  (rotazione,  scala…)  ad  un  oggetto  group  questa  si ripercuote  su  tutti  gli  oggetti  figli.  Infine,  la  classe  Stage  che  è  un InputProcessor  che  gestisce  il  disegno  degli  attori  e  quando  riceve  eventi  di input  li  invia  agli  attori  appropriati.  La  gestione  della  grafica  è  affidata all’ interfaccia Graphics.

 


 

Il  modulo  Files  in  libgdx  fornisce  i  metodi  per  leggere,  scrivere,  copiare, spostare  e  cancellare  file.  Ognuna  delle  piattaforme  di  destinazione  di  libgdx gestisce  i  file  in  modo  differente.  Su  un  sistema  operativo  di  una  piattaforma desktop  (Windows,  Linux,   Mac  OS  X)  i  file  possono  essere  riferiti  tramite percorsi  relativi  alla  directory  corrente  di  lavoro  o  tramite  percorsi  assoluti  e, generalmente,  possono  essere  letti  o  scritti  da  tutte  le  applicazioni.  In  Android la  situazione  è  un  po’  più  complessa:  ci  sono  tre  possibili  modi  per memorizzare  i  file:

  • all’ interno della cartella assets del progetto Android. In questo caso  i file sono delle risorse alle quali è possibile accedere in sola  lettura;
  • in una  directory  di  archiviazione  interna  all’applicazione  ed accessibile  solo  dall’applicazione.   In  questo  caso  i  file  sono accessibili  in  lettura e scrittura;
  • in una  memoria  esterna  (ad  esempio  una  scheda  SD).  Tale  memoria non è sempre disponibile e, di conseguenza, i file memorizzati al suo interno  devono  considerarsi  come    Se  si  utilizza  questo metodo  è  necessario  aggiungere  un  permesso  nel  file AndroidManifest.xml per poter accedere in scrittura.

Un  file  in  libgdx è rappresentato da  un’ istanza della classe  FileHandle. Questa classe  fornisce  un  tipo  (type)  che  definisce  dove  il  file  è  memorizzato.  I diversi  valori  che  può  assumere  questo  tipo  sono:  classpath,  internal,  local, external  e  absolute.  Tutte  le  piattaforme  di  destinazione  possono  far  uso  de i diversi  tipi  eccetto  HTML5  che  utilizza  esclusivamente  il  tipo  internal.  Il  tipo classpath  permette  di  memorizzare  file  in  sola  lettura  ma  non  viene  utilizzato spesso.  I  file  internal  e  local  sono  file  in  sola  lettura  memorizzati  nella directory  di  lavoro  delle  piattaforme  desktop  o  nella  cartella  assets  della piattaforma  Android.  Se  il  file  non  viene  trovato  fra  quelli  di  tipo  internal  o local  verrà  cercato  fra  quelli  di  tipo  classpath.  I  file  external  sono  relativi  alla scheda  SD  su  Android  o  alla  home  directory  sulle  piattaforme  desktop.  Infine i  file  absolute  specificano  i  loro  path  completi  ma,  per  motivi  di  portabilità, questi  file vengono  utilizzati solo quando strettamente  necessario.

I  tipi  di  archiviazione  descritti  potrebbero  non  essere  disponibili  per  alcune piattaforme  e  libgdx  fornisce  due  metodi  per  conoscere  la  disponibilità  o meno di memoria  interna o esterna:

boolean isExtAvailable = Gdx.files.isExternalStorageAvailable();

boolean isLocAvailable = Gdx.files.isLocalStorageAvailable();

 

La gestione dei  file è affidata all’ interfaccia Files.

Libgdx  fornisce  metodi  per  la  riproduzione  di  piccoli  effetti  sonori  (Sound)  o di  brani  musicali  (Music)  direttamente  dal  disco.  Tutti  gli  accessi  ai  serviz i audio  avvengono  tramite  l’ interfaccia  Audio  la  cui  istanza  è  ottenuta  con  la seguente  istruzione:

Audio audio = Gdx.audio;

 

I  Sound  sono  piccoli  file  audio,  generalmente  non  più  di  1MB  (qualche secondo)  di  dimensione,  che  vengono  riprodotti  per  specifici  eventi  di  gioco (per  esempio  il  salto  di  un  personaggio  o  lo  sparo  di  una  pistola).  Tali  effett i sonori  possono  essere  memorizzati  in  diversi  formati  e  libgdx  supporta  mp3, ogg  e  wav.  Nel  caso  in  cui  la  dimensione  del  file  è  maggiore  di  1MB  libgdx fornisce  un’istanza  della  classe  Music  che  permette  di  effettuare  lo  streaming del  file  direttamente  dal  disco  anziché  caricarlo  completamente  nella  RAM come  accade  per  i  Sound.  Le  istruzioni  seguenti  consentono  di  caricare  sound e music dalla memoria interna di  una piattaforma:

Sound sound = Gdx.audio.newSound(Gdx.files.internal("data/mysound.mp3"));

Music music = Gdx.audio.newMusic(Gdx.files.internal("data/mymusic.mp3"));

 

Una  volta  ottenuta  un’istanza  della  classe  Music  o  Sound  è  possibile riprodurre  il  brano  tramite  il  metodo  play(),  settarne  il  volume  tramite  il metodo  setVolume(float  volume),  ripetere  la   riproduzione  col  metodo setLooping(boolean   isLooping),  mettere  in  pausa  e  terminare  la  riproduzione tramite  i   metodi  pause() stop()  rispettivamente.  Al  termine  dell’esecuzione dell’applicazione  tutte  le  istanze  di  Music  e  Sound  devono  essere  eliminate per liberare memoria e ciò avviene tramite  il metodo dispose().

Infine, Libgdx  include  alcune  classi  per  le  operazioni  di  rete  cross-platform.  Le operazioni  fornite  dall’ interfaccia  Net  possono  essere  semplici  richieste  GET e  POST  http  o  operazioni  per  la  comunicazione  tramite  socket  TCP  in un’architettura  client/server.  L’interfaccia  Net  prevede  l’utilizzo  di  sei  classi Java:

  • java, è  un’ interfaccia  che  fornisce  stream  di  input  e  di  output per lavorare con  le socket;
  • java, è  una  classe  usata  per  configurare  le  socket  TCP lato client;
  • java, è  una  classe  usata  per  creare  le  socket  TCP  lato server,  essa  fornisce  il  metodo  standard  accept()  che  blocca  il  server in attesa che si colleghi  un client;
  • java, è  una  classe  usata  per  configurare  le  socie TCP  lato server;
  • java, è una classe che fornisce metodi per  vedere qual è  il codice di stato di  un tipico messaggio di risposta http;
  • java, è  una  classe  che  fornisce  metodi  utili  per le richieste  http.

La  creazione  di  socket  TCP  lato  client  e  lato  server  avviene  tramite  le seguenti  istruzioni:

Socket socket = Gdx.net.newClientSocket(Protocol p, String host, int port, SocketHints hints);

ServerSocket server = Gdx.net.newServerSocket(Protocol protocol, int port, ServerSocketHints hints);

 

per inviare richieste  http si  usa il seguente metodo dell’ interfaccia Net:

Gdx.net.sendHttpRequest(HttpRequest httpRequest, HttpResponseListener httpResponseListener);

 

Per maggiori dettagli riguardo l’ interfaccia Net è possibile visitare  la documentazione ufficiale.

 


 

Conclusioni

Un  aspetto  di  fondamentale  importanza  nell’uso di libgdx è la possibilità di esportare i proprio giochi anche  sulle  altre  piattaforme  supportate aumentando  la  visibilità  sul  mercato.  Questa  è  una  delle  ragioni  per  cui  si  è scelto di approfondire questo  framework.

Seguendo questo link, troverete un gioco sviluppato con libgdx per tutti gli manti della musica e per i geni dell’udito.

 

Ben tornato