martedì 17 gennaio 2012

XNA giochi localizzati impostare la regione

Riporto l'articolo scritto per il sito http://www.iprogrammatori.it/articoli/programmazione/art_xna-giochi-localizzati-impostare-la-regi_1129.aspx



Introduzione
In questo articolo, vedremo come creare un semplice gioco o meglio una semplice applicazione in XNA per la gestione delle lingue, ossia regioni diverse.
I videogames, a volte, possono avere lingue internazionali, l'articolo fornisce al lettore le conoscenze per rendere la propria applicazione multi lingua.



Creazione del progetto
Dopo aver creato un nuovo progetto, si aggiunge (tasto destro sulla soluzione in Esplora soluzioni) un progetto di tipo "Content Pipeline Extension Library", il tutto come mostrato in figura 1.





Figura 1



Nel progetto appena creato, si aggiunge una nuova classe di nome "RegioneFontDescrizione" in questo modo possiamo gestire il carattere (figura 2)





Figura 2
Aggiungiamo lo spazio dei nome "Microsoft.Xna.Framework.Content.Pipeline.Graphics" per gestire la classe del carattere, mentre lo spazio dei nomi "Microsoft.Xna.Framework.Content" per gestire alcuni aspetti della proprietà.
La classe deve ereditare da "FontDescription".
Il tutto come mostrato qui di seguito.



using System;



using System.Collections.Generic;



using System.Linq;



using System.Text;



//spazio di nomi per la gestione del testo



using Microsoft.Xna.Framework.Content.Pipeline.Graphics;



using Microsoft.Xna.Framework.Content;





namespace ContentPipelineExLocalizzato



{



class RegioneFontDescrizione : FontDescription



{



}



}





Si crea una proprietà che avrà il compito di gestire i file di risorse.
Qui di seguito il frammento di codice per tale proprietà



List<string> m_fileRisorsa = new List<string>();



//proprietà per la gestione dei file Risorse



[ContentSerializer(Optional = true, CollectionItemName = "Resx")]



public List<string> FileDiRisorse





{



get { return m_fileRisorsa; }



}





Riportiamo il codice completo di questa classe.




using System;



using System.Collections.Generic;



using System.Linq;



using System.Text;



//spazio di nomi per la gestione del testo



using Microsoft.Xna.Framework.Content.Pipeline.Graphics;



using Microsoft.Xna.Framework.Content;





namespace ContentPipelineExLocalizzato



{



class RegioneFontDescrizione : FontDescription



{



//costruttore



public RegioneFontDescrizione()



: base("Arial", 14, 0)



{



}





List<string> m_fileRisorsa = new List<string>();



//proprietà per la gestione dei file Risorse



[ContentSerializer(Optional = true, CollectionItemName = "Resx")]



public List<string> FileDiRisorse



{



get { return m_fileRisorsa; }



}







}



}





Ora dobbiamo creare una classe per gestire il carattere, dopo aver creato una classe (tasto destro sul nome del progetto, nuova classe) figura 3 impostiamolo che erediti da "ContentProcessor"





Figura 3



La nuova classe deriva dalla classe contentProcessor che accetta due argomenti, la classe precedente, quella relativa alla gestione della descrizione del carattere e la gestione del carattere font per la visualizzazione.



Aggiungiamo lo spazio dei nomi per gestire il content.



using Microsoft.Xna.Framework.Content.Pipeline;



using Microsoft.Xna.Framework.Content.Pipeline.Processors;





class RegioneFontProcessor : ContentProcessor<RegioneFontDescrizione, SpriteFontContent>



{



}







La classe avrà lo scopo di gestire i vari file di risorse.



Dobbiamo effettuare l'ovverride del metodo SprintFontContentProcess, gestendo il file risorse come un file xml.
Qui di seguito si riporta il codice completo della classe RegioneFontProcessor.




using System;



using System.Collections.Generic;



using System.Linq;



using System.Text;



//spazio dei nomi



using Microsoft.Xna.Framework.Content.Pipeline;



using Microsoft.Xna.Framework.Content.Pipeline.Processors;



using System.IO;



using System.Xml;





namespace ContentPipelineExLocalizzato



{



class RegioneFontProcessor : ContentProcessor<RegioneFontDescrizione, SpriteFontContent>



{



//faccio un ovverid del metodo process per gestire le informazioni



public override SpriteFontContent Process(RegioneFontDescrizione inputFont, ContentProcessorContext contextProces)



{



//verifico tutti i file di risorse per le vari voci



foreach (string resourceFile in inputFont.FileDiRisorse)



{



string percorso = Path.GetFullPath(resourceFile);





//se il file non esiste, genero un eccezione



if (!File.Exists(percorso))



{



throw new InvalidContentException("File non presente " + percorso);



}





//carico in un oggetto di tipo xml i dati del file risorse



XmlDocument xmlDocument = new XmlDocument();





xmlDocument.Load(percorso);







//esamino le varie chiavi e inserisco il valore del carattere trovato nella classe per la gestione del carattere



foreach (XmlNode xmlNode in xmlDocument.SelectNodes("root/data/value"))



{



string ValotreTrovato = xmlNode.InnerText;





//aggiungo alla classe di descrizione del carattere il valore trovato



foreach (char usedCharacter in ValotreTrovato)



{



inputFont.Characters.Add(usedCharacter);



}



}



//rigenero ogni volta il dato, quando viene modificato il file di risorsa



contextProces.AddDependency(percorso);



//generazione del tipo di carattere





}



return contextProces.Convert<RegioneFontDescrizione,



SpriteFontContent>(inputFont, "RegioneFontProcessor");





}



}





}





Terminata la creazione della classe, non ci resta che aggiungere nella sezione content, del progetto XNA, un oggetto di tipo SprintFont.



Nella sezione "Content" facciamo click con il tasto destro, selezioniamo dal menu di scelta rapida, aggiungi e successivamento elemento, selezioniamo tra i vari modelli quello relativo a sprintfont





Figura 4



Nel campo Name, lasciamo il nome così com’è.



Nel file sprintefont, modifichiamo



<Asset Type="Graphics:FontDescription">



in



<Asset Type="ContentPipelineExLocalizzato.RegioneFontDescrizione">



Dove il primo indica il nome del progetto, mentre il secondo è la descrizione..



Aggiungiamo un tag al file, il quale indica i nomi dei file di risorse, qui di seguit si riporta il frammento di codice.



<FileDiRisorse>



<Resx>..\Testo.resx</Resx>



<Resx>..\Testo.En.resx</Resx>



</FileDiRisorse>



Nella sezione "Content" aggiungiamo il riferimento al progetto "ContentPipelineExtension" creato precedentemente, il tutto come mostrato in figura 5.

Figura 5



Visualizzare le varie culture
Passiamo alla classe per la gestione del videgioco, in modo che scriviamo le varie funzioni per gestire il settaggio. Nella classe Game1, dichiariamo degli oggetti a livello di classe, il tutto come mostrato qui di seguito.



GraphicsDeviceManager graphics;



SpriteBatch spriteBatch;



SpriteFont font;



Nel caso che abbiamo il pc con la regione italiana, utilizziamo currentCulture, altrimenti tramite la parola chiave new, inizializziamo la proprietà culture con CultureInfo di tipo inglese.



//oggetto risorsa



Testo.Culture = CultureInfo.CurrentCulture;// new CultureInfo("en-US");



Nell’evento loadcontent inizializziamo il carattere, con il font appena aggiunto nel contento. Riportiamo il frammento di codice per l'evento LoadContent.



protected override void LoadContent()



{



// Create a new SpriteBatch, which can be used to draw textures.



spriteBatch = new SpriteBatch(GraphicsDevice);



//Carico il caraterre



font = Content.Load<SpriteFont>("SpriteFont1");



// TODO: use this.Content to load your game content here



}



Nell’evento Draw, visualizziamo a video le varie impostazoni. Qui di seguito si riporta il codice completo dell'evento Draw.



protected override void Draw(GameTime gameTime)



{



string TestoSaluto = Testo.benvenuto;



string TestoLivello = Testo.Livello;



string TestoFineGioco = Testo.FineGioco;



GraphicsDevice.Clear(Color.CornflowerBlue);



spriteBatch.Begin();



spriteBatch.DrawString(font, TestoSaluto, new Vector2(100, 100), Color.White);



spriteBatch.DrawString(font, TestoLivello, new Vector2(100, 150), Color.White);



spriteBatch.DrawString(font, TestoFineGioco, new Vector2(100, 200), Color.White);



spriteBatch.End ();





// TODO: Add your drawing code here





base.Draw(gameTime);



}





La stesura del codice è completata, si riporta il codice completo della classe Game1.




using System;



using System.Collections.Generic;



using System.Linq;



using Microsoft.Xna.Framework;



using Microsoft.Xna.Framework.Audio;



using Microsoft.Xna.Framework.Content;



using Microsoft.Xna.Framework.GamerServices;



using Microsoft.Xna.Framework.Graphics;



using Microsoft.Xna.Framework.Input;



using Microsoft.Xna.Framework.Media;



using System.Globalization;



using System.Collections;















namespace XNALocalizzato



{



/// <summary>



/// This is the main type for your game



/// </summary>



public class Game1 : Microsoft.Xna.Framework.Game



{



GraphicsDeviceManager graphics;



SpriteBatch spriteBatch;



SpriteFont font;



public Game1()



{



Content.RootDirectory = "Content";



graphics = new GraphicsDeviceManager(this);



//oggetto risorsa



Testo.Culture = CultureInfo.CurrentCulture;// new CultureInfo("en-US");



}





/// <summary>



/// Allows the game to perform any initialization it needs to before starting to run.



/// This is where it can query for any required services and load any non-graphic



/// related content. Calling base.Initialize will enumerate through any components



/// and initialize them as well.



/// </summary>



protected override void Initialize()



{



// TODO: Add your initialization logic here





base.Initialize();



}





/// <summary>



/// LoadContent will be called once per game and is the place to load



/// all of your content.



/// </summary>



protected override void LoadContent()



{



// Create a new SpriteBatch, which can be used to draw textures.



spriteBatch = new SpriteBatch(GraphicsDevice);



//Carico il caraterre



font = Content.Load<SpriteFont>("SpriteFont1");



// TODO: use this.Content to load your game content here



}





/// <summary>



/// UnloadContent will be called once per game and is the place to unload



/// all content.



/// </summary>



protected override void UnloadContent()



{



// TODO: Unload any non ContentManager content here



}





/// <summary>



/// Allows the game to run logic such as updating the world,



/// checking for collisions, gathering input, and playing audio.



/// </summary>



/// <param name="gameTime">Provides a snapshot of timing values.</param>



protected override void Update(GameTime gameTime)



{



// Allows the game to exit



if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)



this.Exit();



KeyboardState currentKeyboardState = Keyboard.GetState();



if (currentKeyboardState.IsKeyDown(Keys.Escape) )



{



Exit();



}



// TODO: Add your update logic here





base.Update(gameTime);



}





/// <summary>



/// This is called when the game should draw itself.



/// </summary>



/// <param name="gameTime">Provides a snapshot of timing values.</param>



protected override void Draw(GameTime gameTime)



{



string TestoSaluto = Testo.benvenuto;



string TestoLivello = Testo.Livello;



string TestoFineGioco = Testo.FineGioco;



GraphicsDevice.Clear(Color.CornflowerBlue);



spriteBatch.Begin();



spriteBatch.DrawString(font, TestoSaluto, new Vector2(100, 100), Color.White);



spriteBatch.DrawString(font, TestoLivello, new Vector2(100, 150), Color.White);



spriteBatch.DrawString(font, TestoFineGioco, new Vector2(100, 200), Color.White);



spriteBatch.End ();





// TODO: Add your drawing code here





base.Draw(gameTime);



}



}



}





Conclusioni
La localizzazione nei video giochi è molto considerata, visto che ad oggi i vari produttori di videogiochi, esportano il proprio video gioco in diversi paesi. Rendere il proprio gioco multi lingua, permetterebbe di ampliare il numero dei giocatori.

Nessun commento: