tag:blogger.com,1999:blog-68629363479491684662024-02-08T20:14:45.709+01:00Alessio AusilioOdinohttp://www.blogger.com/profile/05339005661503346027noreply@blogger.comBlogger83125tag:blogger.com,1999:blog-6862936347949168466.post-51086687566496307372012-08-06T16:19:00.001+02:002012-08-06T16:19:26.141+02:00Nuovo sitoComunicazione di servizio.<br />
<br />
Questo blog non verrà ulteriormente aggiornato.<br />
Ci sarà però un nuovo spazio dove verranno pubblicati altri contenuti e risorse, e questo spazio sarà<br />
<a href="www.indiegearlab.com">www.indiegearlab.com</a><br />
Il sito sarà aperto al pubblico tra pochi giorni.<br />
<br />
<br />
venite a trovarmi li ^^<br />
Un salutone a tutti.Odinohttp://www.blogger.com/profile/05339005661503346027noreply@blogger.com0tag:blogger.com,1999:blog-6862936347949168466.post-72266230120367688272012-02-15T21:16:00.001+01:002012-02-15T21:24:17.868+01:00Risorse grafiche per videogiochiDopo tanto un altro post.<br />
Ma questa volta non è un tutorial ma segnalo un modo per recuperare delle risorse grafiche per i vostri videogiochi.<br />
Una delle più grosse difficoltà che sto incontrando è quella di reperire delle risorse grafiche per fare delle prove.<br />
<br />
<span class="fullpost">Sto sviluppando in questo periodo un side-scrolling platform con XNA, e dopo aver sviluppato l'editor del gioco e parte del motore grafico mi sono trovato nella difficile situazione di trovare delle risorse grafiche adatte per fare le prime prove (nell'attesa di avere delle risorse grafiche proprietarie e fatte appositamente per me da utilizzare nel gioco).<br />
<br />
Ho perso delle ore cercando "free graphic resources", "free sprite sheet for indie games", "free graphic for side scrolling platform" e variazioni sul tema su google.<br />
Dopo estenuanti ricerche mi sono accorto che la maggior parte delle risorse sono per giochi in visuale isometrica, o per rpg maker, o altro, ma ho trovato pochissime (ed aiutatemi a dire pochissime) risorse di buona qualità per giochi con visuale perfettamente di lato (i vecchi side-scrolling vi dicono nulla)!<br />
Ci sono centinaia di sprite sheet con animazioni dei personaggi (tratti da dragon ball, i vari final fantasy, e chi più ne ha più ne metta!) ma pochissima roba per quanto riguarda tile-set per creare i livelli o le mappe di gioco, niente elementi decorativi... insomma non sono stato cane di trovar molto. Almeno fino ad oggi!<br />
Vi posso dire che è stata un'esperienza frustrante!<br />
So perfettamente che per il videogioco nella sua versione finale avrò bisogno di asset completamente miei e specifici, ma prima di buttarmi nella realizzazione della grafica volevo avere qualcosa da utilizzare per fare dele prove!<br />
<br />
Alla fine sono incappato in <b>BannedStory</b>. Non ho capito molto bene a cosa serva tale programmino, ma mi pare di aver intuito che serva per simulare e gestire l'aspetto del proprio personaggio (e non solo) relativamente al MMORPG Maple Story.<br />
Insomma... a noi sviluppatori di VG a cosa ci serve?<br />
Ho scoperto che è possibile, tramite BannedStory, recuperare gli sprite sheet delle animazioni, dei tile set, delle immagini per le mappe, di... TUTTO quello che volete, esportarli, e riutilizzarli poi nei vostri progetti.<br />
NOTARE CHE TUTTO CIO' E' MATERIALE PROTETTO DA DIRITTO D'AUTORE, QUINDI LE RISORSE GRAFICHE LE POTETE ANCHE SCARICARE E FARCI QUELLO CHE VOLETE IN LOCALE, MA NON POTETE RILASCIARE NULLA CHE LE UTILIZZI.<br />
Insomma, per le vostre prove si, per rilasciare qualcosa NO! Almeno questo è quello che ho capito io... insomma io non le userò di certo per rilasciare una demo o un tutorial sul web, figuriamoci per un gioco completo, ma per le mie prove personali in locale mi vanno più che bene...<br />
Comunque io non mi prendo responsabilità per quello che ne farete voi altri...<br />
<br />
Si procede come descritto di seguito:<br />
<ol><li>Andate su questo sito <a href="http://www.maplesimulator.com/programs/bannedstory">BannedStory</a></li>
<li>Cliccate su <b><i>Click to start BannedStory 4</i></b></li>
<li>Selezionate tutte le voci, e cliccate start</li>
<li>Quando il programma è avviato completamente cliccate su <b>Window -> Thumbnail Gallery</b> per aprire la finestra di gestione delle immagini</li>
<li>A me interessavano gli elementi della mappa, quindi sono andato sotto la voce <b>Map Items</b> e poi sotto <b>Tiles</b></li>
<li>A questo punto selezionate uno dei tile, ed aspettate che venga caricato nel canvas</li>
<li>Quando è stato caricato nel canvas assicuratevi di selezionarlo, poi premete CTRL+G per avviare l'esportazione</li>
<li>Cliccate su <i>Save</i> e salvate l'archivio .zip. All'interno di questo archivio troverete gli elementi che fanno parte del tile set da voi scelto.</li>
</ol>Ora le risorse le avete in locale e le potete riutilizzare come volete.<br />
Questa proceduta la potete utilizzare con ogni elemento che vi interessa.<br />
Come dice anche il sito di Maple Simulator al link che vi ho dato<br />
<blockquote>NOTICE: MapleStory-related materials used on this site are used with permission granted by Nexon America Inc. All unauthorized uses of said material are otherwise prohibited.</blockquote>quindi, come vi ho detto prima, tali risorse non le userò per rilasciare nulla che andrà a finire sul web, ma esclusivamente per le mie prove personali.<br />
Quindi utilizzateli <b>SOLO E SOLTANTO</b> per le vostre prove in locale, ma nulla di più. Questo è il mio consiglio.<br />
E già mi pare abbastanza non credete?<br />
Gli asset grafici costano cari, sia come lavoro che come tempo, ed avere a disposizione anche solo qualcosa per delle prove è già un aiuto enorme.<br />
<br />
Qua ecco il link della <a href="http://www.rpgrevolution.com/forums/index.php?showtopic=44675">FONTE</a> da cui ho scoperto tutto ciò.<br />
</span>Odinohttp://www.blogger.com/profile/05339005661503346027noreply@blogger.com0tag:blogger.com,1999:blog-6862936347949168466.post-7342726470776173382011-10-11T08:00:00.000+02:002011-10-11T08:00:10.655+02:00The Xna-Way: Tutorial 15: Utente collegato ed X-Box Live pt2 L'AvatarQuesta volta vi voglio parlare un poco degli Avatar degli utenti.<br />
Come sapete è possibile creare e personalizzare il proprio Avatar, sia attraverso la console, sia attraverso il sito di X-Box live.<br />
Voglio farvi vedere come si può, con poche righe di codice, renderizzare il proprio Avatar :)<br />
<br />
<b>NOTA:</b> il codice per la gestione degli Avatar può essere fatto girare anche sotto Windows 7 (e mi pare che per i Phone, ma non avendo un tale dispositivo non ne sono sicuro), solo che in tal caso i valori ritornati dalle varie funzioni non saranno validi, e quindi non verrà renderizzato nulla.<br />
In parole povere, <i><b>GLI AVATAR SONO ESCULISA DELLA CONSOLE!</b></i><br />
<br />
<span class="fullpost">In parte riutilizzerò il codice scritto nel precedente articolo.<br />
Nella classe del gioco aggiungiamo questi 3 campi:<br />
<div class="csharpcode"><pre class="alt"><span class="fullpost"><span class="lnum"> 1: </span> AvatarDescription avatarDescription;</span></pre><pre><span class="fullpost"><span class="lnum"> 2: </span> AvatarRenderer avatarRenderer; </span></pre><pre class="alt"><span class="fullpost"><span class="lnum"> 3: </span> AvatarAnimation avatarAnimation;</span></pre><pre><span class="fullpost"><span class="lnum"> 4: </span> AvatarRenderer avatarRenderer2;</span></pre><pre class="alt"><span class="fullpost"><span class="lnum"> 5: </span> AvatarDescription avatarDescription2;</span></pre></div>che rappresentano la descrizione di come è fatto il nostro Avatar (in parole povere la descrizione fisica), l'oggetto che utilizzeremo per renderizzare il nostro Avatar, l'animazione corrente che stiamo riproducendo, ed infine l'enumeratore che indica quale delle animazioni preimpostate vogliamo usare.<br />
Gli ultimi due oggetti, avatarRender2 ed avatarDescription2, serviranno per renderizzare e contenere un Avatar creato in modo random, in modo che alla fine del nostro esempio avremo a schermo il proprio Avatar ed un altro Avatar in più.<br />
Avremo naturalmente bisogno di mantenere i dati del giocatore attualmente loggato (rivedere articolo precedente).<br />
<br />
Nel LoadContent del game aggiungiamo questo:<br />
<div class="csharpcode"><pre class="alt"><span class="lnum"> 1: </span> avatarDescription2 = AvatarDescription.CreateRandom(AvatarBodyType.Female);</pre><pre><span class="lnum"> 2: </span> avatarRenderer2 = <span class="kwrd">new</span> AvatarRenderer(avatarDescription2);</pre><pre class="alt"><span class="lnum"> 3: </span> </pre><pre><span class="lnum"> 4: </span> avatarAnimation = <span class="kwrd">new</span> AvatarAnimation(preset);</pre></div>Le prime due righe creano un avatar casuale (femminile) ed un renderer basato sulla descrizione dell'Avatar appena creata.<br />
La terza riga imposta l'animazione con il preset definito come campo della classe.<br />
<br />
Ci servirà poi un metodo per il recupero in modo asincrono dei dati dell'Avatar, che può essere il seguente:<br />
<div class="csharpcode"><pre class="alt"><span class="lnum"> 1: </span> <span class="kwrd">void</span> LoadMyAvatar(IAsyncResult result)</pre><pre><span class="lnum"> 2: </span> {</pre><pre class="alt"><span class="lnum"> 3: </span> avatarDescription = AvatarDescription.EndGetFromGamer(result);</pre><pre><span class="lnum"> 4: </span> </pre><pre class="alt"><span class="lnum"> 5: </span> <span class="kwrd">if</span> (avatarDescription.IsValid)</pre><pre><span class="lnum"> 6: </span> avatarRenderer = <span class="kwrd">new</span> AvatarRenderer(avatarDescription);</pre><pre class="alt"><span class="lnum"> 7: </span> }</pre></div>Questo perchè per caricare la descrizione dell'Avatar dobbiamo chiamare il metodo <b>AvatarDescription.BeginGetFromGamer</b>, il quale lavora in metodo asincrono (quindi la sua esecuzione non si blocca in attesa del suo completamento) e può richiedere diverso tempo per essere completato. Quando il metodo avrò completato la sua esecuzione chiamerà il metodo da noi definito per completare le operazioni.<br />
Per mettere tutto assieme aggiungiamo alla fine del metoto LoadContent questo:<br />
<div class="csharpcode"><pre class="alt"><span class="lnum"> 1: </span> gamer = SignedInGamer.SignedInGamers[0];</pre><pre><span class="lnum"> 2: </span> <span class="kwrd">if</span> (gamer != <span class="kwrd">null</span>)</pre><pre class="alt"><span class="lnum"> 3: </span> AvatarDescription.BeginGetFromGamer(gamer, LoadMyAvatar, <span class="kwrd">null</span>);</pre></div>che non fa altro che provare a recuperare i dati del giocatore loggato, ed avvia il recupero dei dati dell'Avatar.<br />
<br />
Nel metodo update le uniche cose da mettere sono queste:<br />
<br />
Ci manca solo il Draw:<br />
<div class="csharpcode"><pre class="alt">GraphicsDevice.Clear(Color.CornflowerBlue);</pre><pre> </pre><pre class="alt"><span class="rem">//creo la matrix per la view</span></pre><pre>Matrix view = Matrix.CreateLookAt(<span class="kwrd">new</span> Vector3(0, 0.3f, -3), <span class="kwrd">new</span> Vector3(0, 0, 0), <span class="kwrd">new</span> Vector3(0, 1, 0));</pre><pre class="alt"><span class="rem">//creo la matrix per la projection</span></pre><pre>Matrix projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, GraphicsDevice.Viewport.AspectRatio, .01f, 40.0f);</pre><pre class="alt"> </pre><pre><span class="kwrd">if</span> (avatarRenderer != <span class="kwrd">null</span> && gamer != <span class="kwrd">null</span>)</pre><pre class="alt">{</pre><pre>avatarRenderer.View = view;</pre><pre class="alt">avatarRenderer.Projection = projection;</pre><pre>avatarRenderer.World = Matrix.CreateTranslation(-1, -1, 0);</pre><pre class="alt">avatarRenderer.Draw(avatarAnimation.BoneTransforms, avatarAnimation.Expression);</pre><pre>}</pre><pre class="alt"> </pre><pre><span class="kwrd">if</span> (avatarRenderer2 != <span class="kwrd">null</span> && avatarDescription2.IsValid)</pre><pre class="alt">{</pre><pre>avatarRenderer2.View = view;</pre><pre class="alt">avatarRenderer2.Projection = projection;</pre><pre>avatarRenderer2.World = Matrix.CreateTranslation(1, -1, 0);</pre><pre class="alt">avatarRenderer2.Draw(avatarAnimation.BoneTransforms, avatarAnimation.Expression);</pre><pre>}</pre><pre class="alt"> </pre><pre>spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend);</pre><pre class="alt"><span class="kwrd">if</span> (gamer != <span class="kwrd">null</span>)</pre><pre>{</pre><pre class="alt">spriteBatch.DrawString(myFont, gamer.Gamertag, Vector2.Zero, Color.Black);</pre><pre>spriteBatch.Draw(image, <span class="kwrd">new</span> Vector2(0, 30), Color.White);</pre><pre class="alt">spriteBatch.DrawString(myFont, String.Format(<span class="str">"Current Animation: {0}"</span>, preset.ToString()), <span class="kwrd">new</span> Vector2(0, 100),</pre><pre>Color.Black);</pre><pre class="alt">}</pre><pre>spriteBatch.End();</pre></div>Prima creiamo la view e la projection per il render, controlliamo che il giocatore loggato, il renderer e l'animazione siano validi, e poi renderiziamo il tutto.<br />
Poi ripetiamo anche per l'Avatar random.<br />
Alla fine, come nel precedente articolo, si visualizza il nome della nostra gamer tag, la nostra immagine e poi si stampa il nome dell'animazione che stiamo riproducendo.<br />
<br />
Ecco il codice completo sorgente del Game in questione:<br />
<h2 onclick="openclose("src15");" style="cursor: pointer;">Show∇</h2><div id="src15" style='display:none;'><div class="csharpcode"><pre class="alt">GraphicsDeviceManager graphics;</pre><pre>SpriteBatch spriteBatch;</pre><pre class="alt"> </pre><pre>SpriteFont myFont;</pre><pre class="alt"> </pre><pre>GamerServicesComponent gamerC;</pre><pre class="alt">SignedInGamer gamer;</pre><pre>Texture2D image;</pre><pre class="alt"> </pre><pre>InputDevice input;</pre><pre class="alt"> </pre><pre>AvatarDescription avatarDescription;</pre><pre class="alt">AvatarRenderer avatarRenderer; </pre><pre>AvatarAnimation avatarAnimation;</pre><pre class="alt">AvatarRenderer avatarRenderer2;</pre><pre>AvatarDescription avatarDescription2;</pre><pre class="alt"> </pre><pre>AvatarAnimationPreset preset = AvatarAnimationPreset.Celebrate;</pre><pre class="alt"> </pre><pre><span class="kwrd">public</span> Game1()</pre><pre class="alt">{</pre><pre>graphics = <span class="kwrd">new</span> GraphicsDeviceManager(<span class="kwrd">this</span>);</pre><pre class="alt">Content.RootDirectory = <span class="str">"Content"</span>;</pre><pre> </pre><pre class="alt">IsMouseVisible = <span class="kwrd">true</span>;</pre><pre> </pre><pre class="alt">Components.Add(<span class="kwrd">new</span> BasicLibrary.Components.FPSCounter(<span class="kwrd">this</span>, <span class="kwrd">false</span>));</pre><pre> </pre><pre class="alt">Components.Add((input = <span class="kwrd">new</span> InputDevice(<span class="kwrd">this</span>)));</pre><pre> </pre><pre class="alt"><span class="rem">//necessario per utilizzare la Guide</span></pre><pre>Components.Add((gamerC = <span class="kwrd">new</span> GamerServicesComponent(<span class="kwrd">this</span>)));</pre><pre class="alt"> </pre><pre>SignedInGamer.SignedIn += <span class="kwrd">new</span> EventHandler<SignedInEventArgs>(LoadGamer);</pre><pre class="alt">}</pre><pre> </pre><pre class="alt"><span class="kwrd">void</span> LoadGamer(<span class="kwrd">object</span> sender, SignedInEventArgs e)</pre><pre>{</pre><pre class="alt">gamer = e.Gamer;</pre><pre><span class="rem">//recupero lo stream per l'immagine</span></pre><pre class="alt">System.IO.Stream imgIO = gamer.GetProfile().GetGamerPicture();</pre><pre><span class="rem">//creo la texture2D a partire dallo stream</span></pre><pre class="alt">image = Texture2D.FromStream(GraphicsDevice, imgIO);</pre><pre> </pre><pre class="alt">AvatarDescription.BeginGetFromGamer(e.Gamer, LoadMyAvatar, <span class="kwrd">null</span>);</pre><pre>}</pre><pre class="alt"> </pre><pre><span class="kwrd">void</span> LoadMyAvatar(IAsyncResult result)</pre><pre class="alt">{</pre><pre>avatarDescription = AvatarDescription.EndGetFromGamer(result);</pre><pre class="alt"> </pre><pre><span class="kwrd">if</span> (avatarDescription.IsValid)</pre><pre class="alt">avatarRenderer = <span class="kwrd">new</span> AvatarRenderer(avatarDescription);</pre><pre>}</pre><pre class="alt"> </pre><pre><span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> Initialize()</pre><pre class="alt">{</pre><pre><span class="kwrd">base</span>.Initialize();</pre><pre class="alt">}</pre><pre> </pre><pre class="alt"><span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> LoadContent()</pre><pre>{</pre><pre class="alt">PresentationParameters pp = GraphicsDevice.PresentationParameters;</pre><pre>pp.BackBufferWidth = GraphicsDevice.DisplayMode.Width;</pre><pre class="alt">pp.BackBufferHeight = GraphicsDevice.DisplayMode.Height;</pre><pre> </pre><pre class="alt">avatarDescription2 = AvatarDescription.CreateRandom(AvatarBodyType.Female);</pre><pre>avatarRenderer2 = <span class="kwrd">new</span> AvatarRenderer(avatarDescription2);</pre><pre class="alt"> </pre><pre>spriteBatch = <span class="kwrd">new</span> SpriteBatch(GraphicsDevice);</pre><pre class="alt">myFont = Content.Load<SpriteFont>(<span class="str">"font"</span>);</pre><pre> </pre><pre class="alt">avatarAnimation = <span class="kwrd">new</span> AvatarAnimation(preset);</pre><pre>}</pre><pre class="alt"> </pre><pre><span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> Update(GameTime gameTime)</pre><pre class="alt">{</pre><pre><span class="kwrd">if</span> (input.wasPressed(Buttons.Y))</pre><pre class="alt">Guide.ShowSignIn(1, <span class="kwrd">false</span>);</pre><pre><span class="kwrd">if</span> (gamer != <span class="kwrd">null</span> && avatarRenderer != <span class="kwrd">null</span> && avatarAnimation != <span class="kwrd">null</span>)</pre><pre class="alt">{</pre><pre>avatarAnimation.Update(gameTime.ElapsedGameTime, <span class="kwrd">false</span>);</pre><pre class="alt"><span class="kwrd">if</span> (avatarAnimation.CurrentPosition == avatarAnimation.Length)</pre><pre>{</pre><pre class="alt"><span class="kwrd">if</span> ((<span class="kwrd">int</span>)preset >= 30)</pre><pre>preset = 0;</pre><pre class="alt">avatarAnimation = <span class="kwrd">new</span> AvatarAnimation(++preset);</pre><pre>}</pre><pre class="alt">}</pre><pre><span class="kwrd">base</span>.Update(gameTime);</pre><pre class="alt">}</pre><pre> </pre><pre class="alt"><span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> Draw(GameTime gameTime)</pre><pre>{</pre><pre class="alt">GraphicsDevice.Clear(Color.CornflowerBlue);</pre><pre> </pre><pre class="alt"><span class="rem">//creo la matrix per la view</span></pre><pre>Matrix view = Matrix.CreateLookAt(<span class="kwrd">new</span> Vector3(0, 0.3f, -3), <span class="kwrd">new</span> Vector3(0, 0, 0), <span class="kwrd">new</span> Vector3(0, 1, 0));</pre><pre class="alt"><span class="rem">//creo la matrix per la projection</span></pre><pre>Matrix projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, GraphicsDevice.Viewport.AspectRatio, .01f, 40.0f);</pre><pre class="alt"> </pre><pre><span class="kwrd">if</span> (avatarRenderer != <span class="kwrd">null</span> && gamer != <span class="kwrd">null</span>)</pre><pre class="alt">{</pre><pre>avatarRenderer.View = view;</pre><pre class="alt">avatarRenderer.Projection = projection;</pre><pre>avatarRenderer.World = Matrix.CreateTranslation(-1, -1, 0);</pre><pre class="alt">avatarRenderer.Draw(avatarAnimation.BoneTransforms, avatarAnimation.Expression);</pre><pre>}</pre><pre class="alt"> </pre><pre><span class="kwrd">if</span> (avatarRenderer2 != <span class="kwrd">null</span> && avatarDescription2.IsValid)</pre><pre class="alt">{</pre><pre>avatarRenderer2.View = view;</pre><pre class="alt">avatarRenderer2.Projection = projection;</pre><pre>avatarRenderer2.World = Matrix.CreateTranslation(1, -1, 0);</pre><pre class="alt">avatarRenderer2.Draw(avatarAnimation.BoneTransforms, avatarAnimation.Expression);</pre><pre>}</pre><pre class="alt"> </pre><pre>spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend);</pre><pre class="alt"><span class="kwrd">if</span> (gamer != <span class="kwrd">null</span>)</pre><pre>{</pre><pre class="alt">spriteBatch.DrawString(myFont, gamer.Gamertag, Vector2.Zero, Color.Black);</pre><pre>spriteBatch.Draw(image, <span class="kwrd">new</span> Vector2(0, 30), Color.White);</pre><pre class="alt">spriteBatch.DrawString(myFont, String.Format(<span class="str">"Current Animation: {0}"</span>, preset.ToString()), <span class="kwrd">new</span> Vector2(0, 100),</pre><pre>Color.Black);</pre><pre class="alt">}</pre><pre>spriteBatch.End();</pre><pre class="alt"> </pre><pre><span class="kwrd">base</span>.Draw(gameTime);</pre><pre class="alt">}</pre></div><h2 onclick="openclose("src15");" style="cursor: pointer;">HideΔ</h2></div><br />
Sinceramente pensavo che sarebbe stato molto più difficile fare una cosa del genere, invece ho trovato tutto molto ben strutturato e semplificato.<br />
Certo non ho ancora provato ad utilizzare le animazioni personalizzate per gli Avatart, o a fare il blend tra due animazioni... Ma quelle le vedrò in futuro!<br />
<br />
Intanto ecco a voi uno screen di quello che vedo utilizzando il mio profilo: l'Avatar sulla destra è il mio, quello sulla sinistra è quello generato casualmente!<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://farm7.static.flickr.com/6118/6227839998_f2520fe7f8_b.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"><img border="0" height="300" width="500" src="http://farm7.static.flickr.com/6118/6227839998_f2520fe7f8.jpg" /></a></div><br />
<br />
<br />
Alla prossima :)<br />
</span>Odinohttp://www.blogger.com/profile/05339005661503346027noreply@blogger.com0tag:blogger.com,1999:blog-6862936347949168466.post-28731381960410135412011-10-10T08:00:00.000+02:002011-10-10T08:00:03.720+02:00The Xna-Way: Tutorial 14: Utente collegato ed X-Box Live pt1 Dati di baseOggi voglio condividere alcune cose che ho provato riguardo alla gestione degli utenti XBox Live, come riconoscere se un utente ha fatto login, se ha fatto logout, chi è attualmente loggato, e le sue informazioni.<br />
<br />
Questa sarà la prima parte di considerazioni, dovuto al fatto che alcune funzionalità sono esclusive per X-Box 360, come al gestione degli Avatar.<br />
Riporto quindi qua solo quanto provato sotto piattaforma Windows.<br />
<br />
<span class="fullpost">Il metodo più semplice per recuperare le informazioni sull'untente attualmente collegato è tramite il seguente codice:<br />
</span><br />
<div class="csharpcode"><pre class="alt"><span class="fullpost"><span class="lnum"> 1: </span>SignedInGamer gamer1 = Gamer.SignedInGamers[PlayerIndex.One];</span></pre></div><span class="fullpost">Scrivendo questo, chiediamo di recuperare l'oggetto <b><a href="http://msdn.microsoft.com/it-it/library/microsoft.xna.framework.gamerservices.signedingamer.aspx">SignedInGamer</a></b> relativo al giocatore che sta utilizzando il gamepad numero 1 (cosa simile si può fare con gli altri gamepad, fino all'indice 4).<br />
Questa classe ci fornisce tutti metodi necessari per recuperare le informazioni del nostro giocatore.<br />
Il problema però sorge quando non c'è nessuno giocatore che ha fatto log-in. In questo caso il codice precedente ci fornirà un null.<br />
Sulla console questo si verifica quando lanciamo un gioco in modalità "anonima" possiamo dire, senza aver selezionato cioè il profilo che vogliamo usare.<br />
<br />
Ma come possiamo fare, su pc, ad poter fare una cosa simile?<br />
NOTA: per poter far funzionare correttamente il codice che segue, il LiveID che utilizzerete per fare log-in deve avere a disposizione un account Studente o superiore su App Hub, altrimenti andrete contro a delle spiacevoli eccezioni.<br />
<br />
La prima cosa da fare è di aggiungere un <a href="http://msdn.microsoft.com/en-us/library/bb975583.aspx"><b>GamerServicesComponent</b></a> al nostro gioco. Possiamo farlo all'interno del costruttore del nostro Game:<br />
</span><br />
<div class="csharpcode"><pre class="alt"><span class="fullpost"><span class="lnum"> 1: </span>Components.Add(<span class="kwrd">new</span> GamerServicesComponent(<span class="kwrd">this</span>));</span></pre></div><span class="fullpost"><br />
Il primo passo è fatto. Ora dobbiamo far si che quando si effettua il login di un account si deve recuperare i dati, tra cui per ora ci occuperemo del nome della GamerTag e dell'immagine associata.<br />
Aggiungiamo i seguenti campi alla nostra classe:<br />
</span><br />
<div class="csharpcode"><pre class="alt"><span class="fullpost"><span class="lnum"> 1: </span>SignedInGamer gamer;</span></pre><pre><span class="fullpost"><span class="lnum"> 2: </span>Texture2D image;</span></pre></div><span class="fullpost"> così facendo abbiamo definito dove andremo a memorizzare i dati recuperati.<br />
<br />
Abbiamo bisogno di registrare un EventHandler per recuperare i dati del profilo quando viene completata la fase di login. Ecco un esempio di come può essere fatto:<br />
</span><br />
<div class="csharpcode"><pre class="alt"><span class="fullpost"><span class="lnum"> 1: </span> <span class="kwrd">void</span> LoadGamer(<span class="kwrd">object</span> sender, SignedInEventArgs e)</span></pre><pre><span class="fullpost"><span class="lnum"> 2: </span> {</span></pre><pre class="alt"><span class="fullpost"><span class="lnum"> 3: </span> gamer = e.Gamer;</span></pre><pre><span class="fullpost"><span class="lnum"> 4: </span> <span class="rem">//recupero lo stream per l'immagine</span></span></pre><pre class="alt"><span class="fullpost"><span class="lnum"> 5: </span> System.IO.Stream imgIO = gamer.GetProfile().GetGamerPicture();</span></pre><pre><span class="fullpost"><span class="lnum"> 6: </span> <span class="rem">//creo la texture2D a partire dallo stream</span></span></pre><pre class="alt"><span class="fullpost"><span class="lnum"> 7: </span> image = Texture2D.FromStream(GraphicsDevice, imgIO);</span></pre><pre><span class="fullpost"><span class="lnum"> 8: </span> }</span></pre></div><span class="fullpost"> mentre nel costruttore, dopo la creazione del GamerServicesComponent, andiamo a registrare il nostro handler come segue:<br />
<div class="csharpcode"><pre class="alt"><span class="lnum"> 1: </span>SignedInGamer.SignedIn += <span class="kwrd">new</span> EventHandler<SignedInEventArgs>(LoadGamer); </pre></div><br />
Il nostro metodo Draw sarà semplicissimo!<br />
<div class="csharpcode"><pre class="alt"><span class="lnum"> 1: </span> <span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> Draw(GameTime gameTime)</pre><pre><span class="lnum"> 2: </span> {</pre><pre class="alt"><span class="lnum"> 3: </span> GraphicsDevice.Clear(Color.CornflowerBlue);</pre><pre><span class="lnum"> 4: </span> </pre><pre class="alt"><span class="lnum"> 5: </span> spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend);</pre><pre><span class="lnum"> 6: </span> <span class="kwrd">if</span> (gamer != <span class="kwrd">null</span>)</pre><pre class="alt"><span class="lnum"> 7: </span> {</pre><pre><span class="lnum"> 8: </span> spriteBatch.DrawString(myFont, gamer.Gamertag, Vector2.Zero, Color.Black);</pre><pre class="alt"><span class="lnum"> 9: </span> spriteBatch.Draw(image, <span class="kwrd">new</span> Vector2(0,30), Color.White);</pre><pre><span class="lnum"> 10: </span> }</pre><pre class="alt"><span class="lnum"> 11: </span> spriteBatch.End();</pre><pre><span class="lnum"> 12: </span> </pre><pre class="alt"><span class="lnum"> 13: </span> <span class="kwrd">base</span>.Draw(gameTime);</pre><pre><span class="lnum"> 14: </span> }</pre></div><br />
Ok vediamo di riassumere: creiamo il nostro EventHandler, il quale serve a recuperare i dati del Gamer che fa login (quindi la GamerTag, la sua immagine, i suoi Ack, la lista dei suoi amici, etc). Questo Handler viene chiamato quando il login viene completato con successo. E dopo di questo verrano visualizzate dal metodo Draw il nome della GamerTag e la sua immagine.<br />
<br />
Ecco ora a voi alcuni screenshot! (sono relativi alla versione che ho fatto girare sotto Windows 7, quindi sulla console potrebbero essere "leggermente" differenti)<br />
Una volta fatto partire il gioco premete il tastone centrale del vostro pad (o il tasto Home sulla tastiera). E quello che vedrete sarà più o meno questo:<div class="separator" style="clear: both; text-align: center;"><a href="http://farm7.static.flickr.com/6218/6214407993_742f8e8de3_b.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="188" src="http://farm7.static.flickr.com/6218/6214407993_742f8e8de3_m.jpg" width="240" /></a></div>Dopo che avrete accettato le condizioni d'uso, andate su "Accedi", dove avrete una schermata come la seguente:<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://farm7.static.flickr.com/6239/6214923586_b4179820fc_b.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="188" src="http://farm7.static.flickr.com/6239/6214923586_b4179820fc_m.jpg" width="240" /></a></div>Inserite i dati del vostro LiveID (che vi ricordo deve disporre di un account Studente o superiore su Abb Hup per essere provato con successo da chi scrive il codice), e avrete che inizierà la procedura di login (io ho anche spuntato l'opzione per fare in modo che ogni volta effettui l'accesso in automatico).<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://farm7.static.flickr.com/6177/6214923752_93a2635400_b.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="188" src="http://farm7.static.flickr.com/6177/6214923752_93a2635400_m.jpg" width="240" /></a></div>Quando il login sarà completo vi verrà notificato con un messaggio!<br />
Se fate come me, e avete messo il login automatico dell'account (in modo da non dover rifare la procedura a mano ogni volta), se riavviate l'applicazione ed aspettate qualche secondo, ecco cosa vedrete (salvo GamerTag diversa XD):<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://farm7.static.flickr.com/6234/6214408191_bcc73fd114_b.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="187" src="http://farm7.static.flickr.com/6234/6214408191_bcc73fd114_m.jpg" width="240" /></a></div><br />
Ora le basi ci sono! Potete sbizzarrirvi!<br />
<br />
Spero di esservi stato utile!<br />
A presto :)<br />
</span>Odinohttp://www.blogger.com/profile/05339005661503346027noreply@blogger.com0tag:blogger.com,1999:blog-6862936347949168466.post-13594719100388381842011-09-30T14:40:00.001+02:002011-09-30T14:40:21.906+02:00The Xna-Way: Tutorial 13: Semplice gestore audioOggi voglio proporvi una componente per gestire gli effetti sonori e le musiche del nostro gioco.<br />
Perchè diciamocelo, un gioco muto non ha proprio un bell'aspetto ed è anche poco accattivamente.<br />
<br />
<span class="fullpost">Quello che mi propongo è di mostrarvi un componente che si occupi di caricare gli effetti sonori e le canzoni che vogliamo utilizzare nel nostro progetto, per poi poterle richiamare ed utilizzare a nostro piacimento da qualsiasi punto del nostro progetto (a patto di poter accedere e riferire l'interfaccia definita per interagire con il nostro componente).<br />
<br />
Come prima cosa definiamoci l'interfaccia da utilizzare con il nostro audioManager:<br />
<h2 style='cursor:pointer;' onclick='openclose("myElm");'>Show∇</h2><div id="myElm" style='display:none;'><div class="csharpcode"><pre class="alt"><span class="lnum"> 1: </span> <span class="kwrd">public</span> <span class="kwrd">interface</span> AudioManagerI</pre><pre><span class="lnum"> 2: </span> {</pre><pre class="alt"><span class="lnum"> 3: </span> ContentManager ContentManager { get; }</pre><pre><span class="lnum"> 4: </span> <span class="kwrd">float</span> MusicVolume { get; set; }</pre><pre class="alt"><span class="lnum"> 5: </span> <span class="kwrd">float</span> SoundVolume { get; set; }</pre><pre><span class="lnum"> 6: </span> <span class="kwrd">void</span> LoadSong(<span class="kwrd">long</span> songID, <span class="kwrd">string</span> songName);</pre><pre class="alt"><span class="lnum"> 7: </span> <span class="kwrd">void</span> LoadSound(<span class="kwrd">long</span> soundID, <span class="kwrd">string</span> soundName);</pre><pre><span class="lnum"> 8: </span> <span class="kwrd">void</span> PlaySong(<span class="kwrd">long</span> idSong);</pre><pre class="alt"><span class="lnum"> 9: </span> <span class="kwrd">void</span> PauseSong();</pre><pre><span class="lnum"> 10: </span> <span class="kwrd">void</span> ResumeSong();</pre><pre class="alt"><span class="lnum"> 11: </span> <span class="kwrd">void</span> StopSong();</pre><pre><span class="lnum"> 12: </span> <span class="kwrd">void</span> PlaySound(<span class="kwrd">long</span> soundId);</pre><pre class="alt"><span class="lnum"> 13: </span> <span class="kwrd">void</span> StopAllSounds();</pre><pre><span class="lnum"> 14: </span> }</pre></div><h2 style='cursor:pointer;' onclick='openclose("myElm");'>HideΔ</h2></div>Molto intuitivamente diamo così la possibilità di agire sul volume dei suoni e delle musiche, permettiamo di caricare un singolo suono/canzone specificando anche l'ID da assegnargli, e che sarà utilizzato per recuperarlo e riprodurlo. Definiamo poi quei metodi che serviranno per riprodurre/fermare/riprendere una cazone e per riprodurre e fermare i suoni.<br />
Qualcuno mi potrà criticare il fatto che utilizzo degli anonimi e diffcili ID di tipo long per identifcare i suoni e le canzoni e non un nome. Io ragiono sul fatto che molto probabilmente la lista dei file audio da gestire mi arriverà da un qualche editor, che avrò usato per definire la lista di tutti i miei asset. Tali asset saranno riferiti da ogni luogo tramite i loro identificativi numeri, questo perchè il nome può essere cambiato per varie ragioni (preferenze, cambio di idee, diversa classificazione, etc) mentre un ID numerico rimarrà presumibilmente (a meno di persone poco sagge che vanno a mettere le manine nutellose dove non dovrebbero) lo stesso per tutto il tempo.<br />
Oltre al fatto che un numero occupa molto meno spazio di un stringa ^__^<br />
<br />
Continuiamo però nella nostra esposizione: dobbiamo ora implementare il tutto.<br />
<br />
<h2 style='cursor:pointer;' onclick='openclose("codeElm");'>Show∇</h2><br />
<div id="codeElm" style='display:none;'><div class="csharpcode"><pre class="alt"><span class="lnum"> 1: </span><span class="rem">/// <summary></span></pre><pre><span class="lnum"> 2: </span><span class="rem">/// Gestisce la musica di sottofondo ed i suoni che vengono riprodotti</span></pre><pre class="alt"><span class="lnum"> 3: </span><span class="rem">/// </summary></span></pre><pre><span class="lnum"> 4: </span><span class="kwrd">public</span> <span class="kwrd">class</span> AudioManager : GameComponent, AudioManagerI</pre><pre class="alt"><span class="lnum"> 5: </span>{</pre><pre><span class="lnum"> 6: </span> <span class="preproc">#region</span> Private fields</pre><pre class="alt"><span class="lnum"> 7: </span> <span class="kwrd">private</span> ContentManager content;</pre><pre><span class="lnum"> 8: </span> <span class="kwrd">public</span> ContentManager ContentManager { get { <span class="kwrd">return</span> content; } }</pre><pre class="alt"><span class="lnum"> 9: </span> </pre><pre><span class="lnum"> 10: </span> <span class="rem">//lista delle canzoni che vogliamo gestire</span></pre><pre class="alt"><span class="lnum"> 11: </span> <span class="kwrd">private</span> Dictionary<<span class="kwrd">long</span>, Song> songs = <span class="kwrd">new</span> Dictionary<<span class="kwrd">long</span>, Song>();</pre><pre><span class="lnum"> 12: </span> <span class="rem">//lista dei suoni che vogliamo gestire</span></pre><pre class="alt"><span class="lnum"> 13: </span> <span class="kwrd">private</span> Dictionary<<span class="kwrd">long</span>, SoundEffect> sounds = <span class="kwrd">new</span> Dictionary<<span class="kwrd">long</span>, SoundEffect>();</pre><pre><span class="lnum"> 14: </span> </pre><pre class="alt"><span class="lnum"> 15: </span> <span class="rem">//canzone corrente che stiamo riproducendo</span></pre><pre><span class="lnum"> 16: </span> <span class="kwrd">private</span> Song currentSong = <span class="kwrd">null</span>;</pre><pre class="alt"><span class="lnum"> 17: </span> <span class="rem">//lista dei suoni che stiamo correntemente riproducendo</span></pre><pre><span class="lnum"> 18: </span> <span class="kwrd">private</span> List<SoundEffectInstance> playingSounds;</pre><pre class="alt"><span class="lnum"> 19: </span> </pre><pre><span class="lnum"> 20: </span> <span class="rem">//sono in pausa?</span></pre><pre class="alt"><span class="lnum"> 21: </span> <span class="kwrd">private</span> <span class="kwrd">bool</span> isMusicPaused = <span class="kwrd">false</span>;</pre><pre><span class="lnum"> 22: </span> <span class="preproc">#endregion</span></pre><pre class="alt"><span class="lnum"> 23: </span> </pre><pre><span class="lnum"> 24: </span> <span class="rem">/// <summary></span></pre><pre class="alt"><span class="lnum"> 25: </span> <span class="rem">/// ID della canzone correntemente riprodotta</span></pre><pre><span class="lnum"> 26: </span> <span class="rem">/// </summary></span></pre><pre class="alt"><span class="lnum"> 27: </span> <span class="kwrd">public</span> <span class="kwrd">long</span> Current_IDSong { get; <span class="kwrd">private</span> set; }</pre><pre><span class="lnum"> 28: </span> </pre><pre class="alt"><span class="lnum"> 29: </span> <span class="rem">/// <summary></span></pre><pre><span class="lnum"> 30: </span> <span class="rem">/// Volume delle canzoni</span></pre><pre class="alt"><span class="lnum"> 31: </span> <span class="rem">/// </summary></span></pre><pre><span class="lnum"> 32: </span> <span class="kwrd">public</span> <span class="kwrd">float</span> MusicVolume</pre><pre class="alt"><span class="lnum"> 33: </span> {</pre><pre><span class="lnum"> 34: </span> get { <span class="kwrd">return</span> MediaPlayer.Volume; }</pre><pre class="alt"><span class="lnum"> 35: </span> set { MediaPlayer.Volume = <span class="kwrd">value</span>; }</pre><pre><span class="lnum"> 36: </span> }</pre><pre class="alt"><span class="lnum"> 37: </span> </pre><pre><span class="lnum"> 38: </span> <span class="rem">/// <summary></span></pre><pre class="alt"><span class="lnum"> 39: </span> <span class="rem">/// Volume per i suoni</span></pre><pre><span class="lnum"> 40: </span> <span class="rem">/// </summary></span></pre><pre class="alt"><span class="lnum"> 41: </span> <span class="kwrd">public</span> <span class="kwrd">float</span> SoundVolume</pre><pre><span class="lnum"> 42: </span> {</pre><pre class="alt"><span class="lnum"> 43: </span> get { <span class="kwrd">return</span> SoundEffect.MasterVolume; }</pre><pre><span class="lnum"> 44: </span> set { SoundEffect.MasterVolume = <span class="kwrd">value</span>; }</pre><pre class="alt"><span class="lnum"> 45: </span> }</pre><pre><span class="lnum"> 46: </span> </pre><pre class="alt"><span class="lnum"> 47: </span> <span class="rem">/// <summary></span></pre><pre><span class="lnum"> 48: </span> <span class="rem">/// True se la canzone corrente è in esecuzione o in pausa (!= stopped)</span></pre><pre class="alt"><span class="lnum"> 49: </span> <span class="rem">/// </summary></span></pre><pre><span class="lnum"> 50: </span> <span class="kwrd">public</span> <span class="kwrd">bool</span> IsSongActive { get { <span class="kwrd">return</span> currentSong != <span class="kwrd">null</span> && MediaPlayer.State != MediaState.Stopped; } }</pre><pre class="alt"><span class="lnum"> 51: </span> </pre><pre><span class="lnum"> 52: </span> <span class="rem">/// <summary></span></pre><pre class="alt"><span class="lnum"> 53: </span> <span class="rem">/// True se la canzone corrente è in pausa</span></pre><pre><span class="lnum"> 54: </span> <span class="rem">/// </summary></span></pre><pre class="alt"><span class="lnum"> 55: </span> <span class="kwrd">public</span> <span class="kwrd">bool</span> IsSongPaused { get { <span class="kwrd">return</span> currentSong != <span class="kwrd">null</span> && isMusicPaused; } }</pre><pre><span class="lnum"> 56: </span> </pre><pre class="alt"><span class="lnum"> 57: </span> <span class="kwrd">public</span> AudioManager(Game game)</pre><pre><span class="lnum"> 58: </span> : <span class="kwrd">this</span>(game, <span class="str">"Content"</span>)</pre><pre class="alt"><span class="lnum"> 59: </span> {</pre><pre><span class="lnum"> 60: </span> }</pre><pre class="alt"><span class="lnum"> 61: </span> </pre><pre><span class="lnum"> 62: </span> <span class="kwrd">public</span> AudioManager(Game game, <span class="kwrd">string</span> contentFolder)</pre><pre class="alt"><span class="lnum"> 63: </span> : <span class="kwrd">base</span>(game)</pre><pre><span class="lnum"> 64: </span> {</pre><pre class="alt"><span class="lnum"> 65: </span> Game.Services.AddService(<span class="kwrd">typeof</span>(AudioManagerI), <span class="kwrd">this</span>);</pre><pre><span class="lnum"> 66: </span> Current_IDSong = -1;</pre><pre class="alt"><span class="lnum"> 67: </span> content = <span class="kwrd">new</span> ContentManager(game.Content.ServiceProvider, contentFolder);</pre><pre><span class="lnum"> 68: </span> playingSounds = <span class="kwrd">new</span> List<SoundEffectInstance>();</pre><pre class="alt"><span class="lnum"> 69: </span> }</pre><pre><span class="lnum"> 70: </span> </pre><pre class="alt"><span class="lnum"> 71: </span> <span class="rem">/// <summary></span></pre><pre><span class="lnum"> 72: </span> <span class="rem">/// Carica una canzone.</span></pre><pre class="alt"><span class="lnum"> 73: </span> <span class="rem">/// </summary></span></pre><pre><span class="lnum"> 74: </span> <span class="rem">/// <param name="songID">Id da assegnare alla canzone da caricare</param></span></pre><pre class="alt"><span class="lnum"> 75: </span> <span class="rem">/// <param name="songName">Nome della canzone da caricare</param></span></pre><pre><span class="lnum"> 76: </span> <span class="kwrd">public</span> <span class="kwrd">void</span> LoadSong(<span class="kwrd">long</span> songID, <span class="kwrd">string</span> songName)</pre><pre class="alt"><span class="lnum"> 77: </span> {</pre><pre><span class="lnum"> 78: </span> songs.Add(songID, content.Load<Song>(songName));</pre><pre class="alt"><span class="lnum"> 79: </span> }</pre><pre><span class="lnum"> 80: </span> </pre><pre class="alt"><span class="lnum"> 81: </span> <span class="rem">/// <summary></span></pre><pre><span class="lnum"> 82: </span> <span class="rem">/// Carica un suono.</span></pre><pre class="alt"><span class="lnum"> 83: </span> <span class="rem">/// </summary></span></pre><pre><span class="lnum"> 84: </span> <span class="rem">/// <param name="sounID">Id da assegare al suono da caricare</param></span></pre><pre class="alt"><span class="lnum"> 85: </span> <span class="rem">/// <param name="soundName">Nome del suono da caricare</param></span></pre><pre><span class="lnum"> 86: </span> <span class="kwrd">public</span> <span class="kwrd">void</span> LoadSound(<span class="kwrd">long</span> soundID, <span class="kwrd">string</span> soundName)</pre><pre class="alt"><span class="lnum"> 87: </span> {</pre><pre><span class="lnum"> 88: </span> sounds.Add(soundID, content.Load<SoundEffect>(soundName));</pre><pre class="alt"><span class="lnum"> 89: </span> }</pre><pre><span class="lnum"> 90: </span> </pre><pre class="alt"><span class="lnum"> 91: </span> <span class="rem">/// <summary></span></pre><pre><span class="lnum"> 92: </span> <span class="rem">/// Libera la memoria da tutte le canzoni e suoni caricati</span></pre><pre class="alt"><span class="lnum"> 93: </span> <span class="rem">/// </summary></span></pre><pre><span class="lnum"> 94: </span> <span class="kwrd">public</span> <span class="kwrd">void</span> UnloadContent()</pre><pre class="alt"><span class="lnum"> 95: </span> {</pre><pre><span class="lnum"> 96: </span> content.Unload();</pre><pre class="alt"><span class="lnum"> 97: </span> }</pre><pre><span class="lnum"> 98: </span> </pre><pre class="alt"><span class="lnum"> 99: </span> <span class="rem">/// <summary></span></pre><pre><span class="lnum"> 100: </span> <span class="rem">/// Riproduce la canzone con id passato</span></pre><pre class="alt"><span class="lnum"> 101: </span> <span class="rem">/// </summary></span></pre><pre><span class="lnum"> 102: </span> <span class="rem">/// <param name="idSong">Id della canzone da riprodurre</param></span></pre><pre class="alt"><span class="lnum"> 103: </span> <span class="kwrd">public</span> <span class="kwrd">void</span> PlaySong(<span class="kwrd">long</span> idSong)</pre><pre><span class="lnum"> 104: </span> {</pre><pre class="alt"><span class="lnum"> 105: </span> <span class="rem">//controllo che la canzone che voglio riprodurre non sia quella che sto correntemente riproducendo</span></pre><pre><span class="lnum"> 106: </span> <span class="kwrd">if</span> (Current_IDSong != idSong) </pre><pre class="alt"><span class="lnum"> 107: </span> {</pre><pre><span class="lnum"> 108: </span> <span class="kwrd">if</span> (currentSong != <span class="kwrd">null</span>) <span class="rem">//fermo quella attuale</span></pre><pre class="alt"><span class="lnum"> 109: </span> {</pre><pre><span class="lnum"> 110: </span> MediaPlayer.Stop();</pre><pre class="alt"><span class="lnum"> 111: </span> }</pre><pre><span class="lnum"> 112: </span> </pre><pre class="alt"><span class="lnum"> 113: </span> <span class="kwrd">if</span> (songs.TryGetValue(idSong, <span class="kwrd">out</span> currentSong))</pre><pre><span class="lnum"> 114: </span> {</pre><pre class="alt"><span class="lnum"> 115: </span> Current_IDSong = idSong; <span class="rem">//aggiorno</span></pre><pre><span class="lnum"> 116: </span> </pre><pre class="alt"><span class="lnum"> 117: </span> isMusicPaused = <span class="kwrd">false</span>;</pre><pre><span class="lnum"> 118: </span> MediaPlayer.IsRepeating = <span class="kwrd">true</span>; <span class="rem">//metto in loop</span></pre><pre class="alt"><span class="lnum"> 119: </span> MediaPlayer.Play(currentSong); <span class="rem">//riproduco</span></pre><pre><span class="lnum"> 120: </span> </pre><pre class="alt"><span class="lnum"> 121: </span> <span class="kwrd">if</span> (!Enabled)</pre><pre><span class="lnum"> 122: </span> {</pre><pre class="alt"><span class="lnum"> 123: </span> MediaPlayer.Pause();</pre><pre><span class="lnum"> 124: </span> }</pre><pre class="alt"><span class="lnum"> 125: </span> }</pre><pre><span class="lnum"> 126: </span> }</pre><pre class="alt"><span class="lnum"> 127: </span> }</pre><pre><span class="lnum"> 128: </span> </pre><pre class="alt"><span class="lnum"> 129: </span> <span class="rem">/// <summary></span></pre><pre><span class="lnum"> 130: </span> <span class="rem">/// Mette in pausa la canzone corrente</span></pre><pre class="alt"><span class="lnum"> 131: </span> <span class="rem">/// </summary></span></pre><pre><span class="lnum"> 132: </span> <span class="kwrd">public</span> <span class="kwrd">void</span> PauseSong()</pre><pre class="alt"><span class="lnum"> 133: </span> {</pre><pre><span class="lnum"> 134: </span> <span class="kwrd">if</span> (currentSong != <span class="kwrd">null</span> && !isMusicPaused)</pre><pre class="alt"><span class="lnum"> 135: </span> {</pre><pre><span class="lnum"> 136: </span> <span class="kwrd">if</span> (Enabled) MediaPlayer.Pause();</pre><pre class="alt"><span class="lnum"> 137: </span> isMusicPaused = <span class="kwrd">true</span>;</pre><pre><span class="lnum"> 138: </span> }</pre><pre class="alt"><span class="lnum"> 139: </span> }</pre><pre><span class="lnum"> 140: </span> </pre><pre class="alt"><span class="lnum"> 141: </span> <span class="rem">/// <summary></span></pre><pre><span class="lnum"> 142: </span> <span class="rem">/// Fa ripartire la canzone corrente</span></pre><pre class="alt"><span class="lnum"> 143: </span> <span class="rem">/// </summary></span></pre><pre><span class="lnum"> 144: </span> <span class="kwrd">public</span> <span class="kwrd">void</span> ResumeSong()</pre><pre class="alt"><span class="lnum"> 145: </span> {</pre><pre><span class="lnum"> 146: </span> <span class="kwrd">if</span> (currentSong != <span class="kwrd">null</span> && isMusicPaused)</pre><pre class="alt"><span class="lnum"> 147: </span> {</pre><pre><span class="lnum"> 148: </span> <span class="kwrd">if</span> (Enabled) MediaPlayer.Resume();</pre><pre class="alt"><span class="lnum"> 149: </span> isMusicPaused = <span class="kwrd">false</span>;</pre><pre><span class="lnum"> 150: </span> }</pre><pre class="alt"><span class="lnum"> 151: </span> }</pre><pre><span class="lnum"> 152: </span> </pre><pre class="alt"><span class="lnum"> 153: </span> <span class="rem">/// <summary></span></pre><pre><span class="lnum"> 154: </span> <span class="rem">/// Ferma la cazone corrente</span></pre><pre class="alt"><span class="lnum"> 155: </span> <span class="rem">/// </summary></span></pre><pre><span class="lnum"> 156: </span> <span class="kwrd">public</span> <span class="kwrd">void</span> StopSong()</pre><pre class="alt"><span class="lnum"> 157: </span> {</pre><pre><span class="lnum"> 158: </span> <span class="kwrd">if</span> (currentSong != <span class="kwrd">null</span> && MediaPlayer.State != MediaState.Stopped)</pre><pre class="alt"><span class="lnum"> 159: </span> {</pre><pre><span class="lnum"> 160: </span> MediaPlayer.Stop();</pre><pre class="alt"><span class="lnum"> 161: </span> isMusicPaused = <span class="kwrd">false</span>;</pre><pre><span class="lnum"> 162: </span> }</pre><pre class="alt"><span class="lnum"> 163: </span> }</pre><pre><span class="lnum"> 164: </span> </pre><pre class="alt"><span class="lnum"> 165: </span> <span class="rem">/// <summary></span></pre><pre><span class="lnum"> 166: </span> <span class="rem">/// Riproduce il suono con id passato</span></pre><pre class="alt"><span class="lnum"> 167: </span> <span class="rem">/// </summary></span></pre><pre><span class="lnum"> 168: </span> <span class="rem">/// <param name="soundId">Id del suono da riprodurre</param></span></pre><pre class="alt"><span class="lnum"> 169: </span> <span class="kwrd">public</span> <span class="kwrd">void</span> PlaySound(<span class="kwrd">long</span> soundId)</pre><pre><span class="lnum"> 170: </span> {</pre><pre class="alt"><span class="lnum"> 171: </span> SoundEffect sound;</pre><pre><span class="lnum"> 172: </span> </pre><pre class="alt"><span class="lnum"> 173: </span> <span class="kwrd">if</span> (!sounds.TryGetValue(soundId, <span class="kwrd">out</span> sound))</pre><pre><span class="lnum"> 174: </span> {</pre><pre class="alt"><span class="lnum"> 175: </span> <span class="kwrd">throw</span> <span class="kwrd">new</span> ArgumentException(<span class="kwrd">string</span>.Format(<span class="str">"Sound '{0}' not found"</span>, soundId));</pre><pre><span class="lnum"> 176: </span> }</pre><pre class="alt"><span class="lnum"> 177: </span> </pre><pre><span class="lnum"> 178: </span> playingSounds.Add(sound.CreateInstance());</pre><pre class="alt"><span class="lnum"> 179: </span> <span class="kwrd">int</span> index = playingSounds.Count - 1;</pre><pre><span class="lnum"> 180: </span> </pre><pre class="alt"><span class="lnum"> 181: </span> playingSounds[index].Volume = SoundVolume;</pre><pre><span class="lnum"> 182: </span> playingSounds[index].Pitch = 0.0f;</pre><pre class="alt"><span class="lnum"> 183: </span> playingSounds[index].Pan = 0.0f;</pre><pre><span class="lnum"> 184: </span> playingSounds[index].Play();</pre><pre class="alt"><span class="lnum"> 185: </span> </pre><pre><span class="lnum"> 186: </span> <span class="kwrd">if</span> (!Enabled)</pre><pre class="alt"><span class="lnum"> 187: </span> {</pre><pre><span class="lnum"> 188: </span> playingSounds[index].Pause();</pre><pre class="alt"><span class="lnum"> 189: </span> }</pre><pre><span class="lnum"> 190: </span> }</pre><pre class="alt"><span class="lnum"> 191: </span> </pre><pre><span class="lnum"> 192: </span> <span class="rem">/// <summary></span></pre><pre class="alt"><span class="lnum"> 193: </span> <span class="rem">/// Fermat tutti i suoni correntemente riprodotti</span></pre><pre><span class="lnum"> 194: </span> <span class="rem">/// </summary></span></pre><pre class="alt"><span class="lnum"> 195: </span> <span class="kwrd">public</span> <span class="kwrd">void</span> StopAllSounds()</pre><pre><span class="lnum"> 196: </span> {</pre><pre class="alt"><span class="lnum"> 197: </span> <span class="kwrd">for</span> (<span class="kwrd">int</span> i = 0; i < playingSounds.Count; ++i)</pre><pre><span class="lnum"> 198: </span> {</pre><pre class="alt"><span class="lnum"> 199: </span> playingSounds[i].Stop();</pre><pre><span class="lnum"> 200: </span> playingSounds[i].Dispose();</pre><pre class="alt"><span class="lnum"> 201: </span> }</pre><pre><span class="lnum"> 202: </span> playingSounds.Clear();</pre><pre class="alt"><span class="lnum"> 203: </span> }</pre><pre><span class="lnum"> 204: </span> </pre><pre class="alt"><span class="lnum"> 205: </span> <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">void</span> Update(GameTime gameTime)</pre><pre><span class="lnum"> 206: </span> {</pre><pre class="alt"><span class="lnum"> 207: </span> <span class="kwrd">for</span> (<span class="kwrd">int</span> i = playingSounds.Count - 1; i >= 0; i--)</pre><pre><span class="lnum"> 208: </span> {</pre><pre class="alt"><span class="lnum"> 209: </span> <span class="rem">//rimuove i suoni che sono stati completati</span></pre><pre><span class="lnum"> 210: </span> <span class="kwrd">if</span> (playingSounds[i] != <span class="kwrd">null</span> && playingSounds[i].State == SoundState.Stopped)</pre><pre class="alt"><span class="lnum"> 211: </span> {</pre><pre><span class="lnum"> 212: </span> playingSounds[i].Dispose(); <span class="rem">//libero la memoria</span></pre><pre class="alt"><span class="lnum"> 213: </span> playingSounds.RemoveAt(i);</pre><pre><span class="lnum"> 214: </span> }</pre><pre class="alt"><span class="lnum"> 215: </span> }</pre><pre><span class="lnum"> 216: </span> </pre><pre class="alt"><span class="lnum"> 217: </span> <span class="rem">//se ho finito di riprodurre la canzone corrente stop</span></pre><pre><span class="lnum"> 218: </span> <span class="kwrd">if</span> (currentSong != <span class="kwrd">null</span> && MediaPlayer.State == MediaState.Stopped)</pre><pre class="alt"><span class="lnum"> 219: </span> {</pre><pre><span class="lnum"> 220: </span> currentSong = <span class="kwrd">null</span>;</pre><pre class="alt"><span class="lnum"> 221: </span> Current_IDSong = -1;</pre><pre><span class="lnum"> 222: </span> isMusicPaused = <span class="kwrd">false</span>;</pre><pre class="alt"><span class="lnum"> 223: </span> }</pre><pre><span class="lnum"> 224: </span> </pre><pre class="alt"><span class="lnum"> 225: </span> <span class="kwrd">base</span>.Update(gameTime);</pre><pre><span class="lnum"> 226: </span> }</pre><pre class="alt"><span class="lnum"> 227: </span> </pre><pre><span class="lnum"> 228: </span> <span class="rem">// Mette in pausa tutto se sospeso, altrimenti riprende tutto</span></pre><pre class="alt"><span class="lnum"> 229: </span> <span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> OnEnabledChanged(<span class="kwrd">object</span> sender, EventArgs args)</pre><pre><span class="lnum"> 230: </span> {</pre><pre class="alt"><span class="lnum"> 231: </span> <span class="kwrd">if</span> (Enabled)</pre><pre><span class="lnum"> 232: </span> {</pre><pre class="alt"><span class="lnum"> 233: </span> <span class="kwrd">for</span> (<span class="kwrd">int</span> i = 0; i < playingSounds.Count; i++)</pre><pre><span class="lnum"> 234: </span> {</pre><pre class="alt"><span class="lnum"> 235: </span> <span class="kwrd">if</span> (playingSounds[i] != <span class="kwrd">null</span> && playingSounds[i].State == SoundState.Paused)</pre><pre><span class="lnum"> 236: </span> {</pre><pre class="alt"><span class="lnum"> 237: </span> playingSounds[i].Resume();</pre><pre><span class="lnum"> 238: </span> }</pre><pre class="alt"><span class="lnum"> 239: </span> }</pre><pre><span class="lnum"> 240: </span> </pre><pre class="alt"><span class="lnum"> 241: </span> <span class="kwrd">if</span> (!isMusicPaused)</pre><pre><span class="lnum"> 242: </span> {</pre><pre class="alt"><span class="lnum"> 243: </span> MediaPlayer.Resume();</pre><pre><span class="lnum"> 244: </span> }</pre><pre class="alt"><span class="lnum"> 245: </span> }</pre><pre><span class="lnum"> 246: </span> <span class="kwrd">else</span></pre><pre class="alt"><span class="lnum"> 247: </span> {</pre><pre><span class="lnum"> 248: </span> <span class="kwrd">for</span> (<span class="kwrd">int</span> i = 0; i < playingSounds.Count; i++)</pre><pre class="alt"><span class="lnum"> 249: </span> {</pre><pre><span class="lnum"> 250: </span> <span class="kwrd">if</span> (playingSounds[i] != <span class="kwrd">null</span> && playingSounds[i].State == SoundState.Playing)</pre><pre class="alt"><span class="lnum"> 251: </span> {</pre><pre><span class="lnum"> 252: </span> playingSounds[i].Pause();</pre><pre class="alt"><span class="lnum"> 253: </span> }</pre><pre><span class="lnum"> 254: </span> }</pre><pre class="alt"><span class="lnum"> 255: </span> </pre><pre><span class="lnum"> 256: </span> MediaPlayer.Pause();</pre><pre class="alt"><span class="lnum"> 257: </span> }</pre><pre><span class="lnum"> 258: </span> </pre><pre class="alt"><span class="lnum"> 259: </span> <span class="kwrd">base</span>.OnEnabledChanged(sender, args);</pre><pre><span class="lnum"> 260: </span> }</pre><pre class="alt"><span class="lnum"> 261: </span>}</pre></div><h2 style='cursor:pointer;' onclick='openclose("codeElm");'>HideΔ</h2></div>Il codice mi pare che sia abbastanza autoesplicativo, se necessita di commenti non esitate a chiedermeli per email o nei commenti.<br />
Solo una minima spiegazione: un <b>SoundEffect</b> rappresenta una singola risorsa sonora caricata, ed è possibile riprodurla utilizzando il metodo play fornito da tale classe.<br />
Abbiamo invece che la <b>SoundEffectInstance</b> rappresenta una singola istanza di una risorsa sonora in fase di riproduzione (o sospesa o fermata). Questo vuol dire che con le SoundEffectInstance possiamo riprodurre più copie del nostro suono tranquillamente. Da fare attenzione al fatto che possiamo creare molte instance da un singolo SoundEffect, e nel caso liberiamo la memoria di quest'ultimo per poi provare a riprodurre una istanza ottenuta da questo... bè gli effetti saranno non piacevoli! Eccezioni su eccezioni!<br />
<br />
Forse c'è un punto che può essere in dubbio: come faccio a sapere che tutti i suoni che riproduco verrano riprodotti?<br />
Oppure possiamo mettere la questione nel senso di "quale è il numero massimo di suoni che posso riprodurre sulla mia console?"<br />
Come potete leggere a questa pagine di <a href="http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.audio.soundeffectinstance.aspx">MSDN</a> abbiamo che<br />
<blockquote>On Zune, a game can have a maximum of 16 total playing SoundEffectInstance instances at one time, combined across all loaded SoundEffect objects. The only limit to the total number of loaded SoundEffectInstance and SoundEffect objects is available memory. However, the user can play only 16 sound effects at one time. Attempts to play a SoundEffectInstance beyond this limit will fail. On Windows, there is no hard limit. Playing too many instances can lead to performance degradation. On Xbox 360, the limit is 300 sound effect instances loaded or playing. Dispose of old instances if you need more. </blockquote>quindi credo che 300 suoni contemporaneamente siano sufficienti per i nostri scopi.<br />
<br />
Spero di esservi stato un minimo utile.<br />
<br />
Se volete vedere un esempio più complesso di gestore audio, con una personalizzazione migliore di quello che potete fare, vi rimando alla <a href="http://www.xnawiki.com/index.php?title=Advanced_Sound_Manager_For_XNA_GS_3.1">XnaWiki</a>. Il loro esempio è quello a cui mi sono ispirato per creare il mio personale AudioManager, solo che come ho detto, non mi piacevano alcune cose riguardo all'identificazione degli asset, oltre al fatto che il numero dei suoni riproducibili tutti assieme era limitato a livello di codice.<br />
<br />
<br />
A presto!<br />
</span>Odinohttp://www.blogger.com/profile/05339005661503346027noreply@blogger.com0tag:blogger.com,1999:blog-6862936347949168466.post-24985115892845100492011-07-31T17:33:00.001+02:002011-10-07T14:39:24.937+02:00The Xna-Way: Tutorial 12: Performance & Ottimizzazioni pt1Vediamod i fare il punto su qualche considerazione che ho fatto relativamente allo sviluppo e deploy su PC vs quello su Xbox 360.<br />
<br />
Da quello che ricordo, nonostante si possa far girare i progetti XNA sia su pc che su console, i frameword utilizzati per far girare gli applicativi sono simili ma diversi sotto alcuni aspetti fondamentali. Primo tra tutti la gestione del garbage collector.<br />
<br />
<span class="fullpost">Su PC viene fatto girare il .NET framework completo, mentre sulla console viene utilizzato quello che si chiama .NET Compact Framework (che dovrebbe essere tra l'altro utilizzato anche per alcuni dispositivi portatili sempre di proprietà della Microsoft).<br /><br />Tale Compact Framework è alla fin fine un sottoinsieme di quello che gira su PC, ma questo implica che le funzioni che mette a disposizione sono minori.<br />Per quanto riguarda il Garbage Collector, il compact framework ha una versione che possiamo vedere come meno potente.<br />Con il Compact Framework si è costretti a controllare ogni oggetto presente in memoria per vedere se è ancora necessario o meno. Quindi attenzione all'allocazione di tanti oggetti e di oggeti di grosse dimenzioni.<br /><br /><br />Altro problema è il filtraggio degli oggetti di una collezione secondo una certa condizione.<br />Per un esempio: in una prova dovevo renderizzare gli oggetti che rientravano nella zona della vista del livello, e per fare questo nella versione WINDOWS del gioco avevo utilizzato il metodo <span style="font-weight: bold;">Where</span> di Enumerator, defidendomi delle lambda expression per definire il filtro. Sotto Windows funzionava tutto abbastanza bene.<br />Ma non appena ho eseguito il tutto sulla console le prestazioni sono precipitate vertiginosamente.<br />A quanto pare i metodi offerti da Enumerator, che accettano delle lambda expression, creano delle nuove liste/oggetti ogni volta che vengono invocati, e questo porta via tante risorse all'esecuzione.<br />Come risolvere e quindi ottimizzare il codice XNA?<br />Per risolvere il calo di prestazioni ho provato con il un classico for/foreach con un semplice if-then per l'esecuzione del codice. Ed il guadagno in frame per secondo è stato notevole (per farvi un esempio numerico: dai 26 fps che ottenevo inizialmente sono arrivato a 170 circa!).<br />Un'altra prova che ho fatto è stata con le query definite tramite LinQ. Il vantaggio di queste query è che permettono di esprimere in modo facile e naturale espressioni di filtraggio come se si scrivesse una query per un database relazionale.<br />La lettura di tale query è decisamente più semplice di un if-then-else che occupa diverse righe.<br />E per le prestazioni direte voi?<br />Da quello che ho visto (sempre con i dati numerici che ho riportato prima) da 170 fps sulla console sono sceso a circa 165.<br />5 fps per una maggiore leggibilità e manutenzione del codice... Accettabile secondo voi? Per ora secondo me si. Ma in caso si abbia bisogno di prestazioni estreme, e dove anche un solo fps guadagnato è un successo armatevi di calma e scrivetevi le vostre belle condizioni a manina!<br /><br />Da considerare perè che fino a quando il vostro progetto gira oltre i 60 fps potete stare tranquilli e occuparvi poco delle ottimizzazioni in generale. Il problema è quando scendete sotto i 60... <span style="font-weight: bold;">60 fps è la vostra line della morte.</span><br /><br />Ok...<br />queste sono solo delle mie considerazioni, dovute a prove che ho fatto e a qualche pagina di libro che ho letto.<br />In caso abbia sbagliato qualcosa siete pregati di farmelo notare.<br /><br />A presto.<br />Odino</span>Odinohttp://www.blogger.com/profile/05339005661503346027noreply@blogger.com0tag:blogger.com,1999:blog-6862936347949168466.post-11422026037330493212011-07-23T10:10:00.000+02:002011-07-23T10:12:18.400+02:00The Xna-Way: Special Tutorial: DreamSpark! Develop and deploy on the xBox 360Finalmente in questi giorni sono riuscito a decidermi a comprare una xBox 360. <br />Si sono stanto tanto stronzo che per tutti questi anni ho sviluppato con XNA solo su pc.<br /><br />Ma ora adesso che avevo la mia adorata console (piccolo momento di gloria: la slim è una cosa fantastica ^__^) dovevo trovare il modo di svilupparci sopra in modo appropriato.<br /><br />Il problema principale stava nel fatto che non avevo ora come ora la possibilithttp://www.blogger.com/img/blank.gifà di pagare l'abbonamento annuale di 75€ per l'XNA creator club. E sul sito MSDNAA della mia università non c'era nemmeno più la possibilità di richiedere l'abbonamento studenti.<br /><br />Ma per fortuna il WEB ci viene in aiuto. Può darsi che queste info siano ugualmente recuperabili da altre parti sul web, ma ho deciso lo stesso di condividerle tramite questo blog.<br /><br /><span class="fullpost">La Microsoft ha messo a disposizione di tutti gli studenti DEL MONDO (o perlomeno di moltissimi paesi) la possiblità di usufruire di molti http://www.blogger.com/img/blank.gifsuoi prodotti (certificati) in modo gratuito o scontato.<br />Il segreto di tutto questo è il progetto DreamSpark, a cui potete accedere tramite <a href="www.dreamspark.com">www.dreamspark.com</a>.<br /><br />Non voglio stare a farla tanto lunga: in parole povere questo permette a tutti gli stundenti universitari di qualsiasi facoltà (basta che sia registrata negli elenchi della Microsoft) di accedere ai loro prodotti.<br /><br />Ma vediamo come utilizzare tutto ciò per ottenere un account studente di 12 mesi per Xna creator Club (oramai di dovrebbe dire App Hub O_O).<br /><br /><span style="font-weight:bold;">Come presequisito è necessario essere studenti iscritti ad una qualche facoltà italiana!</span><br />La prima cosa da fare è accedere con il vostro LiveID (MI RACCOMANDO! DOVETE ACCEDERE CON IL LiveID A CUI E' COLLEGATA LA GAMERTAG CHE UTILIZZATE SULLA VOSTRA CONSOLE!) ed andare qua <a href="https://users.create.msdn.com/Register/">https://users.create.msdn.com/Register/</a> e selezionare la voce <span style="font-weight:bold;">Student</span> quando vi verrà richiesto.<br />Premendo next, al prossimo passo vi verrrà richiesta la certificazione tramite DreamSpark. Naturalmente si parte dal presesupposto che voi non l'abbiate, e quindi dovrete premere su <span style="font-style:italic;">Visit DreamSpark now to get verified</span>.<br />Fatto ciò verrete reindirizzati al sito di DreamSpark, il quale vi chiederà di inserire alcuni dati fondamentali.<br /><span style="font-weight:bold;">Step1</span><br />Vi chiederà di inserire il paese in cui risiedete, poi selezionate <span style="font-weight:bold;">Verify as a Student</span>, e nell'ultima voce <span style="font-weight:bold;">Get Verified through my School</span><br /><br /><span style="font-weight:bold;">Step2</span><br />Selezionate la vostra università nell'elenco di quelle disponibili per il vostro paese (se non è presente allora è un bel problema... ma non credo che ci dovrebbero essere atenei italiani mancanti).<br /><br /><span style="font-weight:bold;">Step3</span><br />Adesso dovete inserire la vostra mail da studente, quella data dal vostro dipartimento per intenderci. A questa mail sarà inviata una mail con il codice per poter completare la verifica su DreamSpark.<br />Voi potreste chiedere "Chi mi vieta di inserire una mail diversa?". Io non ho provato... ma non credo che sia molto complicato verificare al volo se la mail che inserite viene gestita dei server dell'università che avete scelto.<br />Quindi è bene inserire il vostro vero indirizzo e-mail di dipartimento.<br /><br /><span style="font-weight:bold;">Step4</span><br />Andate a leggere la mail che vi è arrivata. All'interno troverete il codice ed il link da visitare (dove appunto vi verrà richiesto di inserire il codice) per completare la registrazione.<br /><br /><span style="font-weight:bold;">Step5</span><br />Ok ora siete verificati su DreamSpark!<br />Tornate alla registrazione su App Hub, ripetere la procedura vista prima, selezionando sempre Student. Solo che questa volta mamma Microsoft si http://www.blogger.com/img/blank.gifaccorgerà della registrazione a DreamSpark e vi farà procedere.<br />Ora non dovete far altro che seguire tutti i passi, riempire tutti i campi (NOTA: le info che inserite du App Hub devono essere coerenti con quelle inserite sulla vostra gamerTag, se no il sistema si altera e vi chiede di modificare i dati), ed alla fine avrete il vostro account!<br /><br />Nota: per chi vuole anche delle immagini sono riuscito a trovare proprio ora questo topic!<br /><a href="http://forum.studentidia.org/index.php?showtopic=22821">Guida alla verifica su DreamSpark</a>.<br /><br />Ora non dovete far altro che accendere la vostra console, accedere con la gamerTag relativa all'indirizzo/LiveID con cui vi siete registrati su App Hub. <br />Nel market place, sotto la lettera X, troverete l'XNA Game Studio Connect (NOTA: il programmino è scaricabile anche da chi non si è registrato ad App Hub, solo che se l'account non soddisfa il tipo di registrazione il programma non parte -.-).<br /><br />Ora non ci resta che collegare la nostra console al pc.<br />Per fare questo dobbiamo fare alcuni altri passi.<br /><span style="font-weight:bold;">Connect xBox Step1</span><br />Dovete lanciare Xna Game Studio Connect. Quando sarà partito vedrete a schermo un codice. Segnatevelo da qualche parte perchè vi servirà.<br /><br /><span style="font-weight:bold;">Connect xBox Step2</span><br />Dal vostro pc dovete andare nel menù Tutti i programmi/Microsoft Xna Game Studio 4.0/ e selezionare la voce <span style="font-weight:bold;">XNA Game Studio Device Center</span>.<br />Qua dovrete selezionare la vostra console, dargli un nome, e quando richiesto inserire il codice che vi siete segnati prima.<br /><br />Ok tutto fatto!<br />Pc e console sono collegati.<br />Per provare qualcosa adesso dovete fare quando segue:<br />con Xna Game Studio Connect attivo sulla console ed in attesa di connessione dal vostro pc, dovete aprire Visual Studio (o Visual C#), aprire un progetto Xna (di tipo xBox360) e lanciarlo.<br />Il progetto verrà compilato e distribuito sulla console in automatico. E potrete provarlo direttamente li!<br /><br />Tanto per gradire: funziona anche il debug! Cioè potete mettere dei break point nel codice, e l'esecuzione del gioco sulla console si bloccherà al raggiungimento del break point. :))<br />Certo non potrete modificare al volo il codice come si fa in locale, ma una cosa pur sempre utile.<br /><br /><br />Spero di essere stato il più possibile chiaro.<br />In seguito pubblicherò altri articoli sulle prove e sulle performance ottenute eseguendo vari progetti sulla console.<br /><br />Per ogni chiarimento chiedete pure tramite mail o tramite commenti.<br />Saluti a tutti!<br />Odino<br /></span>Odinohttp://www.blogger.com/profile/05339005661503346027noreply@blogger.com1tag:blogger.com,1999:blog-6862936347949168466.post-87839714365305698102011-07-09T19:30:00.001+02:002011-07-09T19:32:22.854+02:00The Xna-Way: Tutorial 11: Spippolando con il gamePadHo recentemenete acquistato tramite Amazon.it il gamepad della xbox 360 con cavo usb, in modo da poterlo utilizzare su pc, e da poter provare direttamente su di esso le funzionalità del pad, che altrimenti sarebbero disponibili solo sulla console.<br /><br />Ho cominciato a giocarci, e questo è quanto ne ho ricavato fino ad ora.<br /><br /><span class="fullpost">Il pad in se per se è un ottimo prodotto. Ma questo già si sapeva :)<br /><br />Xna mette a dispozizione il <span style="font-weight:bold;">GamePadState </span>per poter interrogare lo stato del nostro pad. Come per tastiera e mouse, possiamo recuperare lo stato corrente del nostro pad tramite il metodo <span style="font-weight:bold;">GamePad.GetState(PlayerIndex)</span>, dove PlayerIndex indica il numero del giocatore/pad di cui vogliamo lo stato (il giocatore è identificato sul pad dal let acceso attorno al pulsante centrale, ed il valore di PlayerIndex varia tra 1 e 4).<br /><br />Tra i valori ed i metodi messi a disposizione da tale oggetto possiamo mettere in evidenza:<br /><span style="font-weight:bold;">ThumbStick</span>: ha due proprietà, Left e Right, che permettono di sapere la posizione dei due stick analogici del pad.<br />Left e Right sono dei Vector2, quindi a loro volta hanno i valori per X ed Y. I valori che possono assumere variano in [-1,+1] (estremi compresi), dove -1 significa che lo stick è completamente a sinistra/basso, 1 significa che lo stick è completamente a destra/alto. Lo 0 significa che lo stick non è stato mosso. Valori intermedi rappresentano posizione intermedie dello stick nelle varie direzioni.<br /><br /><span style="font-weight:bold;">Triggers</span>: i due grilletti posteriori del pad, oltre che come dei semplici bottoni (LeftTrigger e RightTrigger) che hanno stato rilasciato/premuto, possono essere identificati tramite questa proprietà, che contiene a sua volta due valori Left e Right, di tipo float. Questi due valori, varianti tra [0,1], estremi compresi, mi dicono quanto il grilletto è premuto, con 0 = rilasciato, 1 = completamente premuto, e valori intermedi, come prima, identificano posizioni intermedie.<br /><br /><span style="font-weight:bold;">Dpad</span>: identifica lo stato delle "frecce direzionali" del pad. Le direzioni possibili sono 4, ma possono essere combinate due a due. Tramite questo oggetto possiamo controllare quali delle direzioni sono premute.<br />Notate che il Dpad è completamente diverso dallo stick sinistro, quindi quando muovete lo stick sinistro non cambiate in nessun modo lo stato del Dpad (come era stato portato a credere inizialmente -.-), e viceversa.<br /><br />Spero che queste poche e brevi considerazioni personali sull'uso del gamepad possano tornare utili a qualcuno. Se avrò altro da aggiungere aggiornerò il post.<br /><br /><br />A presto.<br />Odino<br /></span>Odinohttp://www.blogger.com/profile/05339005661503346027noreply@blogger.com0tag:blogger.com,1999:blog-6862936347949168466.post-21152400644554371382011-04-16T22:37:00.006+02:002012-08-26T14:53:58.240+02:00The Xna-Way: Tutorial 10: Sprite Sheet & 2D AnimationVi siete mai imbattuti, mentre ricercavate risorse grafiche per i vostri giochi, negli sprite sheet? Immagini contenenti frame delle animazioni di personaggi, effetti speciali o altro?<br />
(Nota: molto belli sono quelli rippati dai vecchi giochi per il SNES, che potete trovare su alcuni siti, i cui link metterò alla fine del post).<br />
<br />
Vediamo un piccolo esempio su come possono essere utilizzati.<br />
<br />
<span class="fullpost"><br />
<br />
<span style="font-weight:bold;">Il codice sarà allegato alla fine del post!</span><br />
La strutturazione del codice per come l'ho pensata io è la seguente:<br />
- TextureCollection: un catalogo contenente tutte le texture2D caricate nel gioco, accedibili tramite un id unico<br />
- SpriteSheetCollection: un catalogo contenente gli SpriteSheet definiti per il gioco, anche questi accedibili tramite un id unico<br />
- AnimationDescCollection: un catalogo contenente la descrizione delle animazioni definite per il gioco, anche queste accedibili trami un id unico<br />
<br />
Le collezioni sopra definite sono definite come statiche, in modo che possano essere accedibili da ogni parte del codice.<br />
<br />
VI sono poi altre classi:<br />
- SpriteSheet: rappresenta un'immagine divisa in frame. Contiene l'identificatore della texture all'interno della TextureCollection, il numero di frame sull'asse X e sull'asse Y, oltre che un metodo per calcolare il rettangolo relativo al frammento di immagine che si vuole utilizzare.<br />
<br />
-AnimationDesc: contiene una collezione di frame che specificano l'animazione, oltre a dire se l'animazione deve essere ripetuta all'infinito o meno.<br />
- Frame: speficifica quale SpriteSheet utilizzare e quale è l'id del frammento da utilizzare (NOTA: I frammenti contentuni all'interno di uno spriteSheet sono numerati da 0 al numero massimo -1, partendo dall'angolo in alto a sinistra e procedendo da destra verso sinistra, e dall'alto verso il basso).<br />
<br />
- Animation: è l'oggetto che implementa l'animazione vera e propria. Contiene l'id della descrizione dell'animazione che si sta utilizzando, il frame corrente (cioè dove siamo arrivati a riprodurre l'animazione), il tempo passato dall'ultimo aggiornamento (in modo da poter avanzare il frame corrente al momento giusto), e la posizione dell'animazione nella vista del gioco.<br />
<br />
Infine arriviamo al componente principale:<br />
- AnimationManager: è il gameComponent che si preoccupa di gestire ed animare gli oggetti Animation che gli vengono dati in pasto.<br />
<br />
Ecco il codice per le classi principali:<br />
<h2 style='cursor:pointer;' onclick='openclose("myElm");'>Show∇</h2><br />
<div id="myElm"><br />
<div class="csharpcode"><br />
<pre><span class="lnum"> 1: </span> <span class="rem">/// <summary></span></pre><br />
<pre><span class="lnum"> 2: </span> <span class="rem">/// rappresenta un singolo frame dell'animazione</span></pre><br />
<pre><span class="lnum"> 3: </span> <span class="rem">/// Si caratterizza per l'id dello spriteSheet e per il frammento di immagine utilizzato dal frame</span></pre><br />
<pre><span class="lnum"> 4: </span> <span class="rem">/// </summary></span></pre><br />
<pre><span class="lnum"> 5: </span> <span class="kwrd">public</span> <span class="kwrd">class</span> Frame</pre><br />
<pre><span class="lnum"> 6: </span> {</pre><br />
<pre><span class="lnum"> 7: </span> <span class="rem">/// <summary></span></pre><br />
<pre><span class="lnum"> 8: </span> <span class="rem">/// Id dello spriteSheet che deve essere presente nella spriteSheetCollection</span></pre><br />
<pre><span class="lnum"> 9: </span> <span class="rem">/// </summary></span></pre><br />
<pre><span class="lnum"> 10: </span> <span class="kwrd">public</span> <span class="kwrd">long</span> IdSpriteSheet { get; <span class="kwrd">private</span> set; }</pre><br />
<pre><span class="lnum"> 11: </span> <span class="rem">/// <summary></span></pre><br />
<pre><span class="lnum"> 12: </span> <span class="rem">/// Id del frammento dell'immagine che si utilizza per il particolare frame</span></pre><br />
<pre><span class="lnum"> 13: </span> <span class="rem">/// </summary></span></pre><br />
<pre><span class="lnum"> 14: </span> <span class="kwrd">public</span> <span class="kwrd">int</span> IdFragment { get; <span class="kwrd">private</span> set; }</pre><br />
<pre><span class="lnum"> 15: </span> </pre><br />
<pre><span class="lnum"> 16: </span> <span class="rem">/// <summary></span></pre><br />
<pre><span class="lnum"> 17: </span> <span class="rem">/// Costruisce un frame per l'animazione</span></pre><br />
<pre><span class="lnum"> 18: </span> <span class="rem">/// </summary></span></pre><br />
<pre><span class="lnum"> 19: </span> <span class="rem">/// <param name="idSpriteSheet">Id di riferimento per lo spriteSheet che deve essere presente nella spriteSheetCollection</param></span></pre><br />
<pre><span class="lnum"> 20: </span> <span class="rem">/// <param name="idFragment">Id del frammento dell'immagine che si utilizza per il particolare frame</param></span></pre><br />
<pre><span class="lnum"> 21: </span> <span class="kwrd">public</span> Frame(<span class="kwrd">long</span> idSpriteSheet, <span class="kwrd">int</span> idFragment)</pre><br />
<pre><span class="lnum"> 22: </span> {</pre><br />
<pre><span class="lnum"> 23: </span> <span class="kwrd">this</span>.IdSpriteSheet = idSpriteSheet;</pre><br />
<pre><span class="lnum"> 24: </span> <span class="kwrd">this</span>.IdFragment = idFragment;</pre><br />
<pre><span class="lnum"> 25: </span> }</pre><br />
<pre><span class="lnum"> 26: </span> }</pre><br />
<pre><span class="lnum"> 27: </span> </pre><br />
<pre><span class="lnum"> 28: </span> <span class="rem">/// <summary></span></pre><br />
<pre><span class="lnum"> 29: </span> <span class="rem">/// Descrive come è fatta un'animazione</span></pre><br />
<pre><span class="lnum"> 30: </span> <span class="rem">/// </summary></span></pre><br />
<pre><span class="lnum"> 31: </span> <span class="kwrd">public</span> <span class="kwrd">class</span> AnimationDesc</pre><br />
<pre><span class="lnum"> 32: </span> {</pre><br />
<pre><span class="lnum"> 33: </span> <span class="rem">/// <summary></span></pre><br />
<pre><span class="lnum"> 34: </span> <span class="rem">/// Lista dei frame che compongono l'animazione</span></pre><br />
<pre><span class="lnum"> 35: </span> <span class="rem">/// </summary></span></pre><br />
<pre><span class="lnum"> 36: </span> <span class="kwrd">public</span> List<Frame> FrameList { get; set; }</pre><br />
<pre><span class="lnum"> 37: </span> </pre><br />
<pre><span class="lnum"> 38: </span> <span class="rem">/// <summary></span></pre><br />
<pre><span class="lnum"> 39: </span> <span class="rem">/// Vale true se l'animazione deve ripetersi</span></pre><br />
<pre><span class="lnum"> 40: </span> <span class="rem">/// False altrimenti</span></pre><br />
<pre><span class="lnum"> 41: </span> <span class="rem">/// </summary></span></pre><br />
<pre><span class="lnum"> 42: </span> <span class="kwrd">public</span> <span class="kwrd">bool</span> Loop { get; set; }</pre><br />
<pre><span class="lnum"> 43: </span> </pre><br />
<pre><span class="lnum"> 44: </span> <span class="rem">/// <summary></span></pre><br />
<pre><span class="lnum"> 45: </span> <span class="rem">/// Crea la descrizione di un'animazione che non si ripete dopo la fine</span></pre><br />
<pre><span class="lnum"> 46: </span> <span class="rem">/// </summary></span></pre><br />
<pre><span class="lnum"> 47: </span> <span class="kwrd">public</span> AnimationDesc()</pre><br />
<pre><span class="lnum"> 48: </span> : <span class="kwrd">this</span>(<span class="kwrd">false</span>)</pre><br />
<pre><span class="lnum"> 49: </span> {</pre><br />
<pre><span class="lnum"> 50: </span> }</pre><br />
<pre><span class="lnum"> 51: </span> </pre><br />
<pre><span class="lnum"> 52: </span> <span class="rem">/// <summary></span></pre><br />
<pre><span class="lnum"> 53: </span> <span class="rem">/// Crea la descrizione di un'animazione permettendo di configurare la ripetizione</span></pre><br />
<pre><span class="lnum"> 54: </span> <span class="rem">/// </summary></span></pre><br />
<pre><span class="lnum"> 55: </span> <span class="rem">/// <param name="loop">True se si vuol far ripetere l'animazione, false altrimenti</param></span></pre><br />
<pre><span class="lnum"> 56: </span> <span class="kwrd">public</span> AnimationDesc(<span class="kwrd">bool</span> loop)</pre><br />
<pre><span class="lnum"> 57: </span> {</pre><br />
<pre><span class="lnum"> 58: </span> FrameList = <span class="kwrd">new</span> List<Frame>();</pre><br />
<pre><span class="lnum"> 59: </span> Loop = loop;</pre><br />
<pre><span class="lnum"> 60: </span> }</pre><br />
<pre><span class="lnum"> 61: </span> }</pre><br />
<pre><span class="lnum"> 62: </span> </pre><br />
<pre><span class="lnum"> 63: </span> <span class="rem">/// <summary></span></pre><br />
<pre><span class="lnum"> 64: </span> <span class="rem">/// Definisce un'animazione da visualizzare a schermo dall'AnimationManager</span></pre><br />
<pre><span class="lnum"> 65: </span> <span class="rem">/// </summary></span></pre><br />
<pre><span class="lnum"> 66: </span> <span class="kwrd">public</span> <span class="kwrd">class</span> Animation</pre><br />
<pre><span class="lnum"> 67: </span> {</pre><br />
<pre><span class="lnum"> 68: </span> <span class="rem">/// <summary></span></pre><br />
<pre><span class="lnum"> 69: </span> <span class="rem">/// Posizione (nel range dello schermo) in cui viene visualizzata l'animazione</span></pre><br />
<pre><span class="lnum"> 70: </span> <span class="rem">/// </summary></span></pre><br />
<pre><span class="lnum"> 71: </span> <span class="kwrd">public</span> Vector2 Position { get; set; }</pre><br />
<pre><span class="lnum"> 72: </span> </pre><br />
<pre><span class="lnum"> 73: </span> <span class="rem">/// <summary></span></pre><br />
<pre><span class="lnum"> 74: </span> <span class="rem">/// Frame corrente dell'animazione</span></pre><br />
<pre><span class="lnum"> 75: </span> <span class="rem">/// </summary></span></pre><br />
<pre><span class="lnum"> 76: </span> <span class="kwrd">public</span> <span class="kwrd">int</span> CurrentFrame { get; set; }</pre><br />
<pre><span class="lnum"> 77: </span> </pre><br />
<pre><span class="lnum"> 78: </span> <span class="rem">/// <summary></span></pre><br />
<pre><span class="lnum"> 79: </span> <span class="rem">/// Id dell'AnimationDesc utilizzata</span></pre><br />
<pre><span class="lnum"> 80: </span> <span class="rem">/// </summary></span></pre><br />
<pre><span class="lnum"> 81: </span> <span class="kwrd">public</span> <span class="kwrd">long</span> IdAnimationDesc { get; <span class="kwrd">private</span> set; }</pre><br />
<pre><span class="lnum"> 82: </span> </pre><br />
<pre><span class="lnum"> 83: </span> <span class="rem">/// <summary></span></pre><br />
<pre><span class="lnum"> 84: </span> <span class="rem">/// Tempo passato dall'ultimo cambio di frame</span></pre><br />
<pre><span class="lnum"> 85: </span> <span class="rem">/// </summary></span></pre><br />
<pre><span class="lnum"> 86: </span> <span class="kwrd">public</span> <span class="kwrd">int</span> ElapsedTime { get; set; }</pre><br />
<pre><span class="lnum"> 87: </span> </pre><br />
<pre><span class="lnum"> 88: </span> <span class="rem">/// <summary></span></pre><br />
<pre><span class="lnum"> 89: </span> <span class="rem">/// Crea una nuova Animazione con riferimento all'AnimationDesc con id passato. Creata in posizione (0,0)</span></pre><br />
<pre><span class="lnum"> 90: </span> <span class="rem">/// </summary></span></pre><br />
<pre><span class="lnum"> 91: </span> <span class="rem">/// <param name="idAnimation">Id dell'AnimationDesc presente nella AnimationsDescCollection</param></span></pre><br />
<pre><span class="lnum"> 92: </span> <span class="kwrd">public</span> Animation(<span class="kwrd">long</span> idAnimationDesc)</pre><br />
<pre><span class="lnum"> 93: </span> : <span class="kwrd">this</span>(idAnimationDesc, Vector2.Zero)</pre><br />
<pre><span class="lnum"> 94: </span> {</pre><br />
<pre><span class="lnum"> 95: </span> }</pre><br />
<pre><span class="lnum"> 96: </span> </pre><br />
<pre><span class="lnum"> 97: </span> <span class="rem">/// <summary></span></pre><br />
<pre><span class="lnum"> 98: </span> <span class="rem">/// Crea una nuova Animazione con riferimento all'AnimationDesc con id passato.</span></pre><br />
<pre><span class="lnum"> 99: </span> <span class="rem">/// </summary></span></pre><br />
<pre><span class="lnum"> 100: </span> <span class="rem">/// <param name="idAnimation">Id dell'AnimationDesc presente nella AnimationsDescCollection</param></span></pre><br />
<pre><span class="lnum"> 101: </span> <span class="rem">/// <param name="position">Posizione dell'Animazione</param></span></pre><br />
<pre><span class="lnum"> 102: </span> <span class="kwrd">public</span> Animation(<span class="kwrd">long</span> idAnimationDesc, Vector2 position)</pre><br />
<pre><span class="lnum"> 103: </span> {</pre><br />
<pre><span class="lnum"> 104: </span> <span class="kwrd">this</span>.IdAnimationDesc = idAnimationDesc;</pre><br />
<pre><span class="lnum"> 105: </span> <span class="kwrd">this</span>.Position = position;</pre><br />
<pre><span class="lnum"> 106: </span> ElapsedTime = 0;</pre><br />
<pre><span class="lnum"> 107: </span> }</pre><br />
<pre><span class="lnum"> 108: </span> }</pre><br />
<pre><span class="lnum"> 109: </span> </pre><br />
<pre><span class="lnum"> 110: </span> <span class="rem">/// <summary></span></pre><br />
<pre><span class="lnum"> 111: </span> <span class="rem">/// Component per il rendering della Animation a schermo</span></pre><br />
<pre><span class="lnum"> 112: </span> <span class="rem">/// </summary></span></pre><br />
<pre><span class="lnum"> 113: </span> <span class="kwrd">public</span> <span class="kwrd">class</span> AnimationManager : Microsoft.Xna.Framework.DrawableGameComponent</pre><br />
<pre><span class="lnum"> 114: </span> {</pre><br />
<pre><span class="lnum"> 115: </span> <span class="rem">//spritebatch su cui disegnare</span></pre><br />
<pre><span class="lnum"> 116: </span> SpriteBatch spriteBatch = <span class="kwrd">null</span>;</pre><br />
<pre><span class="lnum"> 117: </span> </pre><br />
<pre><span class="lnum"> 118: </span> <span class="rem">/// <summary></span></pre><br />
<pre><span class="lnum"> 119: </span> <span class="rem">/// lista delle animazioni da eseguire. Un'animazione viene automaticamente rimossa al termine della sua animazione</span></pre><br />
<pre><span class="lnum"> 120: </span> <span class="rem">/// </summary></span></pre><br />
<pre><span class="lnum"> 121: </span> <span class="kwrd">public</span> List<Animation> AnimationList { get; set; }</pre><br />
<pre><span class="lnum"> 122: </span> </pre><br />
<pre><span class="lnum"> 123: </span> <span class="kwrd">public</span> AnimationManager(Game game)</pre><br />
<pre><span class="lnum"> 124: </span> : <span class="kwrd">base</span>(game)</pre><br />
<pre><span class="lnum"> 125: </span> {</pre><br />
<pre><span class="lnum"> 126: </span> AnimationList = <span class="kwrd">new</span> List<Animation>();</pre><br />
<pre><span class="lnum"> 127: </span> }</pre><br />
<pre><span class="lnum"> 128: </span> </pre><br />
<pre><span class="lnum"> 129: </span> </pre><br />
<pre><span class="lnum"> 130: </span> <span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> LoadContent()</pre><br />
<pre><span class="lnum"> 131: </span> {</pre><br />
<pre><span class="lnum"> 132: </span> spriteBatch = <span class="kwrd">new</span> SpriteBatch(Game.GraphicsDevice);</pre><br />
<pre><span class="lnum"> 133: </span> <span class="kwrd">base</span>.LoadContent();</pre><br />
<pre><span class="lnum"> 134: </span> }</pre><br />
<pre><span class="lnum"> 135: </span> </pre><br />
<pre><span class="lnum"> 136: </span> <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">void</span> Initialize()</pre><br />
<pre><span class="lnum"> 137: </span> {</pre><br />
<pre><span class="lnum"> 138: </span> <span class="kwrd">base</span>.Initialize();</pre><br />
<pre><span class="lnum"> 139: </span> }</pre><br />
<pre><span class="lnum"> 140: </span> </pre><br />
<pre><span class="lnum"> 141: </span> <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">void</span> Update(GameTime gameTime)</pre><br />
<pre><span class="lnum"> 142: </span> {</pre><br />
<pre><span class="lnum"> 143: </span> <span class="kwrd">int</span> delta = gameTime.ElapsedGameTime.Milliseconds;</pre><br />
<pre><span class="lnum"> 144: </span> </pre><br />
<pre><span class="lnum"> 145: </span> AnimationDesc desc = <span class="kwrd">null</span>;</pre><br />
<pre><span class="lnum"> 146: </span> <span class="kwrd">for</span> (<span class="kwrd">int</span> i = AnimationList.Count - 1; i >= 0; i--)</pre><br />
<pre><span class="lnum"> 147: </span> {</pre><br />
<pre><span class="lnum"> 148: </span> desc = AnimationsDescCollection.AnimationCollection[AnimationList[i].IdAnimationDesc];</pre><br />
<pre><span class="lnum"> 149: </span> <span class="kwrd">if</span> (!desc.Loop && AnimationList[i].CurrentFrame == desc.FrameList.Count - 1)</pre><br />
<pre><span class="lnum"> 150: </span> AnimationList.RemoveAt(i);</pre><br />
<pre><span class="lnum"> 151: </span> <span class="kwrd">else</span> <span class="kwrd">if</span> (desc.Loop && AnimationList[i].CurrentFrame == desc.FrameList.Count - 1)</pre><br />
<pre><span class="lnum"> 152: </span> AnimationList[i].CurrentFrame = 0;</pre><br />
<pre><span class="lnum"> 153: </span> }</pre><br />
<pre><span class="lnum"> 154: </span> </pre><br />
<pre><span class="lnum"> 155: </span> <span class="kwrd">for</span> (<span class="kwrd">int</span> i = 0; i < AnimationList.Count; i++)</pre><br />
<pre><span class="lnum"> 156: </span> {</pre><br />
<pre><span class="lnum"> 157: </span> desc = AnimationsDescCollection.AnimationCollection[AnimationList[i].IdAnimationDesc];</pre><br />
<pre><span class="lnum"> 158: </span> AnimationList[i].ElapsedTime += delta;</pre><br />
<pre><span class="lnum"> 159: </span> <span class="kwrd">if</span> (AnimationList[i].ElapsedTime >= 40)</pre><br />
<pre><span class="lnum"> 160: </span> {</pre><br />
<pre><span class="lnum"> 161: </span> AnimationList[i].ElapsedTime -= 40;</pre><br />
<pre><span class="lnum"> 162: </span> AnimationList[i].CurrentFrame++;</pre><br />
<pre><span class="lnum"> 163: </span> }</pre><br />
<pre><span class="lnum"> 164: </span> }</pre><br />
<pre><span class="lnum"> 165: </span> </pre><br />
<pre><span class="lnum"> 166: </span> <span class="kwrd">base</span>.Update(gameTime);</pre><br />
<pre><span class="lnum"> 167: </span> }</pre><br />
<pre><span class="lnum"> 168: </span> </pre><br />
<pre><span class="lnum"> 169: </span> <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">void</span> Draw(GameTime gameTime)</pre><br />
<pre><span class="lnum"> 170: </span> {</pre><br />
<pre><span class="lnum"> 171: </span> spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend);</pre><br />
<pre><span class="lnum"> 172: </span> AnimationDesc desc = <span class="kwrd">null</span>;</pre><br />
<pre><span class="lnum"> 173: </span> <span class="kwrd">for</span> (<span class="kwrd">int</span> i = 0; i < AnimationList.Count; i++)</pre><br />
<pre><span class="lnum"> 174: </span> {</pre><br />
<pre><span class="lnum"> 175: </span> desc = AnimationsDescCollection.AnimationCollection[AnimationList[i].IdAnimationDesc];</pre><br />
<pre><span class="lnum"> 176: </span> Frame current = desc.FrameList[AnimationList[i].CurrentFrame];</pre><br />
<pre><span class="lnum"> 177: </span> SpriteSheet spriteSheet = SpriteSheetCollection.SpritesSheetCollection[current.IdSpriteSheet];</pre><br />
<pre><span class="lnum"> 178: </span> </pre><br />
<pre><span class="lnum"> 179: </span> Texture2D img = TextColl.TextureCollection[spriteSheet.IdTexture];</pre><br />
<pre><span class="lnum"> 180: </span> Rectangle sRec = spriteSheet.GetRectangle(current.IdFragment);</pre><br />
<pre><span class="lnum"> 181: </span> spriteBatch.Draw(img, AnimationList[i].Position - <span class="kwrd">new</span> Vector2(sRec.Width / 2, sRec.Height / 2),</pre><br />
<pre><span class="lnum"> 182: </span> sRec, Color.White);</pre><br />
<pre><span class="lnum"> 183: </span> }</pre><br />
<pre><span class="lnum"> 184: </span> spriteBatch.End();</pre><br />
<pre><span class="lnum"> 185: </span> </pre><br />
<pre><span class="lnum"> 186: </span> <span class="kwrd">base</span>.Draw(gameTime);</pre><br />
<pre><span class="lnum"> 187: </span> }</pre><br />
<pre><span class="lnum"> 188: </span> }</pre><br />
</div><br />
<h2 style='cursor:pointer;' onclick='openclose("myElm");'>HideΔ</h2><br />
</div><br />
<br />
E questo è il codice per il Game:<br />
<h2 style='cursor:pointer;' onclick='openclose("myElm2");'>Show∇</h2><br />
<div id="myElm2"><br />
<div class="csharpcode"><br />
<pre><span class="lnum"> 1: </span> <span class="kwrd">public</span> <span class="kwrd">class</span> Game1 : Microsoft.Xna.Framework.Game</pre><br />
<pre><span class="lnum"> 2: </span> {</pre><br />
<pre><span class="lnum"> 3: </span> GraphicsDeviceManager graphics;</pre><br />
<pre><span class="lnum"> 4: </span> SpriteBatch spriteBatch;</pre><br />
<pre><span class="lnum"> 5: </span> </pre><br />
<pre><span class="lnum"> 6: </span> SpriteFont font;</pre><br />
<pre><span class="lnum"> 7: </span> </pre><br />
<pre><span class="lnum"> 8: </span> AnimationManager animMng;</pre><br />
<pre><span class="lnum"> 9: </span> </pre><br />
<pre><span class="lnum"> 10: </span> <span class="rem">//stato del mouse al ciclo precedente</span></pre><br />
<pre><span class="lnum"> 11: </span> MouseState lastMS;</pre><br />
<pre><span class="lnum"> 12: </span> </pre><br />
<pre><span class="lnum"> 13: </span> <span class="kwrd">public</span> Game1()</pre><br />
<pre><span class="lnum"> 14: </span> {</pre><br />
<pre><span class="lnum"> 15: </span> graphics = <span class="kwrd">new</span> GraphicsDeviceManager(<span class="kwrd">this</span>);</pre><br />
<pre><span class="lnum"> 16: </span> Content.RootDirectory = <span class="str">"Content"</span>;</pre><br />
<pre><span class="lnum"> 17: </span> </pre><br />
<pre><span class="lnum"> 18: </span> graphics.PreferredBackBufferWidth = 800;</pre><br />
<pre><span class="lnum"> 19: </span> graphics.PreferredBackBufferHeight = 600;</pre><br />
<pre><span class="lnum"> 20: </span> </pre><br />
<pre><span class="lnum"> 21: </span> TextColl.Initialize();</pre><br />
<pre><span class="lnum"> 22: </span> SpriteSheetCollection.Initialize();</pre><br />
<pre><span class="lnum"> 23: </span> AnimationsDescCollection.Initialize();</pre><br />
<pre><span class="lnum"> 24: </span> </pre><br />
<pre><span class="lnum"> 25: </span> Components.Add((animMng = <span class="kwrd">new</span> AnimationManager(<span class="kwrd">this</span>)));</pre><br />
<pre><span class="lnum"> 26: </span> </pre><br />
<pre><span class="lnum"> 27: </span> IsMouseVisible = <span class="kwrd">true</span>;</pre><br />
<pre><span class="lnum"> 28: </span> }</pre><br />
<pre><span class="lnum"> 29: </span> </pre><br />
<pre><span class="lnum"> 30: </span> <span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> Initialize()</pre><br />
<pre><span class="lnum"> 31: </span> {</pre><br />
<pre><span class="lnum"> 32: </span> <span class="kwrd">base</span>.Initialize();</pre><br />
<pre><span class="lnum"> 33: </span> }</pre><br />
<pre><span class="lnum"> 34: </span> </pre><br />
<pre><span class="lnum"> 35: </span> <span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> LoadContent()</pre><br />
<pre><span class="lnum"> 36: </span> {</pre><br />
<pre><span class="lnum"> 37: </span> spriteBatch = <span class="kwrd">new</span> SpriteBatch(GraphicsDevice);</pre><br />
<pre><span class="lnum"> 38: </span> </pre><br />
<pre><span class="lnum"> 39: </span> font = Content.Load<SpriteFont>(<span class="str">"font"</span>);</pre><br />
<pre><span class="lnum"> 40: </span> </pre><br />
<pre><span class="lnum"> 41: </span> TextColl.TextureCollection.Add(0, Content.Load<Texture2D>(<span class="str">"prova"</span>));</pre><br />
<pre><span class="lnum"> 42: </span> </pre><br />
<pre><span class="lnum"> 43: </span> SpriteSheet ss = <span class="kwrd">new</span> SpriteSheet(0, 5, 2);</pre><br />
<pre><span class="lnum"> 44: </span> SpriteSheetCollection.SpritesSheetCollection.Add(0, ss);</pre><br />
<pre><span class="lnum"> 45: </span> </pre><br />
<pre><span class="lnum"> 46: </span> AnimationDesc ad = <span class="kwrd">new</span> AnimationDesc();</pre><br />
<pre><span class="lnum"> 47: </span> ad.FrameList.Add(<span class="kwrd">new</span> Frame(0, 0));</pre><br />
<pre><span class="lnum"> 48: </span> ad.FrameList.Add(<span class="kwrd">new</span> Frame(0, 1));</pre><br />
<pre><span class="lnum"> 49: </span> ad.FrameList.Add(<span class="kwrd">new</span> Frame(0, 2));</pre><br />
<pre><span class="lnum"> 50: </span> ad.FrameList.Add(<span class="kwrd">new</span> Frame(0, 3));</pre><br />
<pre><span class="lnum"> 51: </span> ad.FrameList.Add(<span class="kwrd">new</span> Frame(0, 4));</pre><br />
<pre><span class="lnum"> 52: </span> AnimationsDescCollection.AnimationCollection.Add(0, ad);</pre><br />
<pre><span class="lnum"> 53: </span> </pre><br />
<pre><span class="lnum"> 54: </span> lastMS = Mouse.GetState();</pre><br />
<pre><span class="lnum"> 55: </span> }</pre><br />
<pre><span class="lnum"> 56: </span> </pre><br />
<pre><span class="lnum"> 57: </span> <span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> UnloadContent()</pre><br />
<pre><span class="lnum"> 58: </span> {</pre><br />
<pre><span class="lnum"> 59: </span> }</pre><br />
<pre><span class="lnum"> 60: </span> </pre><br />
<pre><span class="lnum"> 61: </span> <span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> Update(GameTime gameTime)</pre><br />
<pre><span class="lnum"> 62: </span> {</pre><br />
<pre><span class="lnum"> 63: </span> <span class="kwrd">if</span> (Keyboard.GetState().IsKeyDown(Keys.Escape))</pre><br />
<pre><span class="lnum"> 64: </span> <span class="kwrd">this</span>.Exit();</pre><br />
<pre><span class="lnum"> 65: </span> </pre><br />
<pre><span class="lnum"> 66: </span> <span class="kwrd">if</span> (lastMS.LeftButton == ButtonState.Released && Mouse.GetState().LeftButton == ButtonState.Pressed)</pre><br />
<pre><span class="lnum"> 67: </span> {</pre><br />
<pre><span class="lnum"> 68: </span> MouseState ms = Mouse.GetState();</pre><br />
<pre><span class="lnum"> 69: </span> Animation anim = <span class="kwrd">new</span> Animation(0, <span class="kwrd">new</span> Vector2(ms.X, ms.Y));</pre><br />
<pre><span class="lnum"> 70: </span> animMng.AnimationList.Add(anim);</pre><br />
<pre><span class="lnum"> 71: </span> }</pre><br />
<pre><span class="lnum"> 72: </span> lastMS = Mouse.GetState();</pre><br />
<pre><span class="lnum"> 73: </span> <span class="kwrd">base</span>.Update(gameTime);</pre><br />
<pre><span class="lnum"> 74: </span> }</pre><br />
<pre><span class="lnum"> 75: </span> </pre><br />
<pre><span class="lnum"> 76: </span> <span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> Draw(GameTime gameTime)</pre><br />
<pre><span class="lnum"> 77: </span> {</pre><br />
<pre><span class="lnum"> 78: </span> GraphicsDevice.Clear(Color.CornflowerBlue);</pre><br />
<pre><span class="lnum"> 79: </span> </pre><br />
<pre><span class="lnum"> 80: </span> <span class="kwrd">base</span>.Draw(gameTime);</pre><br />
<pre><span class="lnum"> 81: </span> }</pre><br />
<pre><span class="lnum"> 82: </span> }</pre><br />
</div><br />
<h2 style='cursor:pointer;' onclick='openclose("myElm2");'>HideΔ</h2><br />
</div><br />
<br />
Come potete vedere non è nulla di trascendentale o di così complicato come poteva sembrare.<br />
Vi allego anche la soluzione per Xna4 (se il link non funziona contattatemi):<br />
<a href="http://odino87.interfree.it/XNA/SpriteSheet.rar">Soluzione Visual Sutdio</a><br />
<br />
Ed ecco un buonissimo sito con tantissimi spriteSheet!<br />
<a href="http://sdb.drshnaps.com/system.php?sys=4">Sprite Database</a><br />
<br />
Alla prossima!<br />
Odino<br />
</span>Odinohttp://www.blogger.com/profile/05339005661503346027noreply@blogger.com0tag:blogger.com,1999:blog-6862936347949168466.post-70150517994396316312011-04-16T21:16:00.005+02:002011-04-16T21:31:33.500+02:00The Xna-Way: Tutorial 9 (Trick): Ordine dei DrawableGameComponent/GameComponentVi siete mai trovati a dover aggiungere diversi GameComponent al vostro progetto?<br />Bè credo di si, dato che sono il componente fondamentale su cui si basa XNA.<br /><br />E scommetto che molti si sono trovati nella situazione in cui un Component esegua il metodo Update prima di un altro, o che vengano eseguiti i metodi Draw in un ordine che non è quello desiderato... producendo in questo modo effetti del tutto errati.<br /><br />Ma c'è un semplicisso modo per ovviare a tutto questo.<br />La classe GameComponent espongono due proprietà interessanti:<br />- UpdateOrder: indica in quale ordine i componenti devono eseguire il loro metodo Update (questo se sono attivi). L'ordine è relativo agli altri componenti presenti nella stessa collezione. Naturalmente i GameComponent con valori più bassi verrano aggiornati prima.<br />- DrawOrder: indica in quale ordine verrano eseguiti i metodi Draw dei vari componenti.<br /><br />Queste due proprietà sono molto utili quando si lavora con componenti che si devono "passare" dai, o per i quali è necessario che lo stato (o la parte di stato) del gioco sui cui operano sia stata prima aggiornata da un altro componente.<br /><br />Lo stesso dicasi per l'ordine del rendering della scena. Ciò torna molto utile nel caso si abbia più DrawableGameComponent i quali operano su SpriteBatch differenti per esempio. Così potremmo delegare ai vari componenti il render di una parte della vista, per poi comporre il tutto assieme con pochissimo sforzo.<br /><br />Spero vi sia utile (a me lo è stato^^).<br />Per qualsiasi dubbio contattatemi pure.<br />A presto.<br /><br />Odino<br /><span class="fullpost"></span>Odinohttp://www.blogger.com/profile/05339005661503346027noreply@blogger.com0tag:blogger.com,1999:blog-6862936347949168466.post-49590637832838240462011-04-05T13:35:00.002+02:002011-04-05T13:38:26.907+02:00X-RPG Builder 2D - aggiornamento 8Lo sviluppo del progetto è attualmente sospeso causa studi universitari, che mi portano via la maggior parte del tempo, e nel tempo che mi rimane mi sono messo a sviluppare un altro proggetto, che spero porterà alla nascita di un Indie Game da poter poi inserire nel Market Place della Microsft.<br /><br />Per qualsiasi domanda sul progetto X-Rpg Builder 2D (quando riprenderà, come funzionano certi particolari, come sono state realizzate le strutture dati, etc) contattatemi via e-email. <br /><br />A presto.<br />Odino<br /><span class="fullpost">E questo è il resto.</span>Odinohttp://www.blogger.com/profile/05339005661503346027noreply@blogger.com0tag:blogger.com,1999:blog-6862936347949168466.post-62286536953244956252011-03-13T10:14:00.005+01:002011-03-13T10:21:44.253+01:00X-RPG Builder 2D - aggiornamento 7E' passato un bel di tempo dall'ultimo aggiornamento.<br />Cosa è successo nel frattempo?<br /><br /><span class="fullpost">Tante cose. Tanti intoppi, altre faccende da sbrigare che mi hanno tenuto lontano dallo sviluppo.<br />Solo da poco ho ripreso a mettere mano al codice.<br />Sto ora lavorando alla parte game del progetto, sviluppando i components e le classi che dovranno mandare effettivamente avanti il gioco.<br />Ho sviluppato parte del sistema di generazione e gestione delle azioni (e del corrispettivo codice da eseguire) scatenate dagli eventi di gioco.<br />Per esempio adesso sto lavorando sulla parte del menù di interazione con l'untente, e questo è l'effetto per ora ottenuto.<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://farm6.static.flickr.com/5019/5521680617_1fe0c5df07_b.jpg"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 240px; height: 187px;" src="http://farm6.static.flickr.com/5019/5521680617_1fe0c5df07_m.jpg" border="0" alt="" /></a><br /><br />C'è ancora molto da fare.<br />E con il ricominciare delle lezioni può darsi che il tempo che passerò a sviluppare il tutto diminuirà drasticamente. Ma piano piano si porterà tutto a compimento.<br /><br />Alla prossima!<br /></span>Odinohttp://www.blogger.com/profile/05339005661503346027noreply@blogger.com0tag:blogger.com,1999:blog-6862936347949168466.post-56422079143718096102011-01-06T19:30:00.003+01:002011-01-06T19:38:42.685+01:00X-RPG Builder 2D - aggiornamento 6Piccolo aggiornamento sull'editor ed in parte sul game Engine.<br /><br /><span class="fullpost">Ho dovuto separare in modo drastico la libreria base per l'Rpg dal resto della logica dell'applicazione, in modo da avere un ottimo riutilizzo del codice tra editor e motore del gioco.<br /><br />Adesso l'engine e l'editor specializzano solo le classi necessarie alla gestione delle immagini, mentre la parte di caricamento è rimasta la solita.<br />Quindi ho dovuto riscrivere buona parte dell'engine, e ho cominciato a strutturare i vari gameComponents che dovranno girare in background nel gioco.<br /><br />Per quanto riguarda l'editor adesso sto strutturando la gestione e la personalizzazione degli eventi, compreso il codice degli eventi. Il codice degli eventi potrà anche portare all'esecuzione di codice C# personale.<br />Quello che voglio fare è ottenere, dalla struttura del codice degli eventi, la produzione di codice C# che dopo dovrà essere compilato ed eseguito: cioè voglio che durante la fase di esportazione del progetto mi venga generato il codice C# relativo allo pseudo codice degli eventi. In questo modo non dovrò costruirmi un interprete personalizzato per il codice.<br /><br />Eccovi un'immagine di come si presenta in questo momento l'editor degli eventi:<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://farm6.static.flickr.com/5044/5330322805_72028215f3_b.jpg"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 500px; height: 266px;" src="http://farm6.static.flickr.com/5044/5330322805_72028215f3.jpg" border="0" alt="" /></a><br /><br />Vi saluto.<br />A presto con altri aggiornamenti :)<br />Ciau<br /></span>Odinohttp://www.blogger.com/profile/05339005661503346027noreply@blogger.com0tag:blogger.com,1999:blog-6862936347949168466.post-51483243516585564632010-12-05T21:51:00.003+01:002010-12-05T21:55:51.440+01:00X-RPG Builder 2D - aggiornamento 5Questo non è un vero e proprio aggiornamento, ma solo una comunicazione.<br /><br />Dato che sto seguendo le lezioni dei corsi universitari adesso ho poco tempo (come poche energie) da dedicare a questo progetto, che sta quindi procedendo molto a rilento.<br />In questo periodo mi sono concentrato sull'editor (e non sul motore del gioco) in modo da poter produrre tutti i dati di cui la mia applicazione finale potrà aver bisogno.<br />Sono state aggiunte diverse funzioanlità all'editor, ma ancora manca molto da fare.<br /><br />Una della perti più importanti da fare (da progettare e da implementare), e che sarà un po' il cuore di tutto è la gestione degli eventi. Questa parte (a cui piano piano sto pensando) rappresenterà il nucleo primario del funzionamento del gioco. <br />Quindi è fondamentale ponderare bene la sua costruzione, pena una grossa fila di eresie.<br /><br />Spero a presto con dei veri aggiornamenti.<br />Odino<br /><span class="fullpost"></span>Odinohttp://www.blogger.com/profile/05339005661503346027noreply@blogger.com0tag:blogger.com,1999:blog-6862936347949168466.post-28766450420478452502010-10-08T13:45:00.003+02:002010-10-12T15:16:37.432+02:00X-RPG Builder 2D - aggiornamento 4Aggiunta la gestione della creazione e modifica della animazioni per le skill.<br />Queste animazioni potranno essere utilizzate anche al di fuori delle battaglie, quindi potranno essere utilizzate come "effetti" speciali nell'esplorazione della mappa. <br /><br /><span class="fullpost">L'ultima versione di Rpg-maker permetteva l'utilizzo di sole due immagini (se ricordo bene) come fonte per i frame da utilizzare per definire le animazioni.<br />Ho invece deciso che nel mio editor non ci siano limiti al numero di immagini che è possibile utilizzare come fonte per i frame.<br />Non ci sono ne limiti al numero di immagini che possono comporre un frame, ne al numero di frame che è possibile aggiungere all'immagine. Si possono creare animazioni lunghe a piacimento.<br /><br />Certo manca ancora tutta la gestione degli effetti sonori e di altri effetti grafici.<br />Ma ora come ora sto mirando a produrre più roba possibile ed avere un qualcosa di funzionante.<br />Per fare questo ho anche cominciato a definire le altre strutture dati di cui avrò bisogno per far funzionare il tutto, tra cui ci sono gli Status che si possono subire (sia per i nemici che per gli alleati), gli elementi (fuoco, acqua, etc) che sono presenti nel gioco e che determineranno l'efficacia delle abilità.<br />Ora c'è da definire le abilità/magie, gli equipaggiamenti, gli oggetti dell'inventario. Insomma il lavoro non manca.<br />Quello che mi "spaventa" un po' di più è la creazione di formule bilanciate per il calcolo dei danni che verranno inferti dai/verso i mob.<br />Quella sarà una parte bella complessa mi sa...<br />Ma ci arriverò piano piano.<br /><br />Alla prossima.<br />Sperando di riuscire ad uppare anche un video della gestione delle animazioni.<br /><br />A presto!<br />Odino<br /></span>Odinohttp://www.blogger.com/profile/05339005661503346027noreply@blogger.com0tag:blogger.com,1999:blog-6862936347949168466.post-56580060038862744862010-09-22T11:18:00.002+02:002010-09-22T11:21:20.397+02:00X-RPG Builder 2D - aggiornamento 3Altro aggiornamento su questo piccolo (almeno per ora) editor.<br /><br /><span class="fullpost">Credo di aver ormai completato la gestione dei tileset, e di aver implementato anche la gestione dei "livelli" dei tileset di tipo B (quelli che su RPG-Maker erano dedicati a tetti e muri).<br />Ecco un'immagine di come vengono gestiti nel gioco (e nell'editor di mappe naturalmente).<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://farm5.static.flickr.com/4087/5012015776_0410945211_b.jpg"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 240px; height: 171px;" src="http://farm5.static.flickr.com/4087/5012015776_0410945211_m.jpg" border="0" alt="" /></a><br />Direi che come risultato può andare più che bene.<br />Non mi pare di vedere difetti nel render o nella continuità dei tileset.<br />Se ne notate perfavore ditelo! ^_^<br /><br />Alla prossima!<br />Odino<br /> </span>Odinohttp://www.blogger.com/profile/05339005661503346027noreply@blogger.com1tag:blogger.com,1999:blog-6862936347949168466.post-30358552070318405362010-09-18T10:56:00.002+02:002010-09-18T11:04:39.722+02:00X-RPG Builder 2D - aggiornamento 2Eccomi con un altro aggiornamento su X-RPG Builder 2D.<br />Sembra che più sia stressato, più abbia mal di testa e meglio riesca a lavorare...<br />vabbè andiamo avanti.<br /><br /><span class="fullpost">Ho aggiunto la gestione degli altri 2 tile set utilizzati da RPG Maker VX, e cioè il tile set per le montagne e le foreste/erba (sempre di 2 celle orizzontali per 3 celle verticali) e quello per i muri/tetto (di 2 celle per 2 celle).<br />Questo è uno screen preso dal mio editor:<br /><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 317px; height: 296px;" src="http://farm5.static.flickr.com/4111/4997769275_e69855a15d.jpg" border="0" alt="" /><br />come si può vedere il risultato non è male, cioè almeno io ne sono abbastanza soddisfatto (c'è ancora da gestire qualcosa ma per ora può bastare, i dettagli li puntualizzerò più avanti).<br /><br />Questo invece è il gioco in esecuzione nel progetto XNA <br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://farm5.static.flickr.com/4127/5000855246_068faa19f6_b.jpg"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 240px; height: 179px;" src="http://farm5.static.flickr.com/4127/5000855246_068faa19f6_m.jpg" border="0" alt="" /></a><br />Gli npc in automatico sono solo come prova per il controllo delle collisioni.<br />Quella parte va ancora completata.<br /><br />Lo sviluppo di X-RPG Builder (il mio rpg maker su xna) continua!<br /><br />Alla prossima con altri aggiornamenti ^_^<br /><br />Ciao<br />Odino<br /><br /><a href="http://alessioausilio.blogspot.com/p/x-rpg-builder.html"><span style="font-weight:bold; font-size:15pt;">Pagina</span></a> con il riassunto di quanto fatto fino ad ora (contiene tutti i post riguardanti questo progetto).<br /><br /></span>Odinohttp://www.blogger.com/profile/05339005661503346027noreply@blogger.com0tag:blogger.com,1999:blog-6862936347949168466.post-2726081127856107502010-09-07T22:21:00.005+02:002010-09-07T22:24:41.416+02:00X-RPG Builder 2D - aggiornamento 1Dopo molto aggiorno questa pagina.<br />Tutta colpa della preparazione della tesi, che mi porta via sempre tanto tempo.<br />Comunque è stata aggiunta qualche piccola funzione:<br />- sono state aggiunte le varibili (contentitori per valori) che possono essere a livello di mappa (visibili ed utilizzabili solo all'interno della mappa in cui sono definite) o a livello di progetto (visibili da ogni parte). Non sono ancora utilizzate<br />- è possibile impostare il party iniziale<br />- è possibile aggiungere e definire delle armi<br />- adesso quando si effettua l'esportazione del progetto vengono salvati nella directory principale tutti i file necessari e vengonoa aggiunti in automatico al progetto XNA<br />- vengono salvati ed aggiunti al content project del gioco XNA tutte le immagini necessarie al funzionamento del gioco<br /><br />Sto ora lavorando per poter definire gli altri oggetti utilizzabili durante il gioco (equipaggiamenti, oggetti dell'inventario, oggetti per delle quest, etc), in modo da poter avere una base su cui cominciare a programmare la gestione degli eventi, dalla loro creazione nell'editor al loro utilizzo all'interno del gioco.<br /><br /><a href="http://alessioausilio.blogspot.com/p/x-rpg-builder.html"><span style="font-weight:bold; font-size:15pt;">Pagina</span></a> con il riassunto di quanto fatto fino ad ora (contiene tutti i post riguardanti questo progetto).Odinohttp://www.blogger.com/profile/05339005661503346027noreply@blogger.com0tag:blogger.com,1999:blog-6862936347949168466.post-18825330712075032252010-08-11T13:19:00.002+02:002010-08-11T13:22:51.851+02:00Mage Masher (o Tritamago) WIP 2Dopo un po' di lavoro ecco a voi il rendering della versione finale (almeno credo) della tritamago di Gidan.<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://fc02.deviantart.net/fs70/i/2010/222/3/9/Magemasher___TritaMago_by_Odino87.jpg"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;max-width: 350px;" src="http://fc02.deviantart.net/fs70/i/2010/222/3/9/Magemasher___TritaMago_by_Odino87.jpg" border="0" alt="" /></a><br /><br />Per la versione a piena risoluzione (4800x2600) dovete scaricarla da qua:<br /><a href="http://odino87.deviantart.com/#/d2w2hjo">DeviantArt</a><br /><br />Spero vi piaccia.<br /><br />A presto :)<br />Odino<br /><span class="fullpost"></span>Odinohttp://www.blogger.com/profile/05339005661503346027noreply@blogger.com3tag:blogger.com,1999:blog-6862936347949168466.post-2605146010298020352010-08-10T09:15:00.004+02:002010-08-10T09:24:27.127+02:00Mage Masher (o Tritamago) WIP 1Dopo tanto mi sono deciso a rimettermi a lavorare un po' con il 3D.<br />Tanto per riprendere un po' la mano.<br />Devo dire che mi trovo un po' arrugginito (anche se non del tutto corroso XD).<br /><br />Comunque vediamo di spiegare quello che si vuol tentare di fare ^^<br /><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 1px; height: 1px;" src="http://images1.wikia.nocookie.net/__cb21710/common/skins/common/blank.gif" border="0" alt="" /><br /><br /><span class="fullpost">Molti avranno giocato a Final Fantasy IX (gioco che in questo periodo mi vorrei proprio rigiocare :D, anche se quella è un'altra storia xD), e il personaggio principale Gidan (Zidane) Tribal come molti usanno utilizzava delle daghe.<br />Questa è la sua daga più famosa, tanto che se ricordo bene anche nei vari artwork è rappresentato con questa, la ormai famosa tritamago.<br />Dato che molto tempo addietro mi ero cimentato nella realizzazione dei Gunblade di Squall e Seifer (cosa che mi è piaciuta tantissimo) ho deciso ora invece di mettermi a realizzare nuovamente le armi dei personaggi dei vari Final Fantasy.<br />Ed ecco a voi il risultato (della sola modellazione) della Tritamago, per la quale ho impiegato più o meno un'oretta.<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://farm5.static.flickr.com/4102/4876725532_b863a35fff_z.jpg"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 613px; height: 620px;" src="http://farm5.static.flickr.com/4102/4876725532_b863a35fff_z.jpg" border="0" alt="" /></a><br />Appena avrò tempo e voglia mi cimenterò con il rendering, anche se ancora devo fare delle modifiche alla mesh ed al modello (voglio aggiungere più particolari).<br /><br />Se poi avrò modo posterò anche delle immagini progresstive dei vari lavori in modo che si possa avere un'idea del come è stato realizzata la modellazione.<br />Se qualcuno è interessato ai modelli mi contatti e vediamo se glieli mando ^^<br /><br />A presto :)<br />Odino<br /></span>Odinohttp://www.blogger.com/profile/05339005661503346027noreply@blogger.com0tag:blogger.com,1999:blog-6862936347949168466.post-20915418846929021672010-08-08T21:20:00.003+02:002010-08-08T21:22:46.166+02:00Apertura nuova paginaAnnuncio l'apertura della pagina relativa ad un mio nuovo progetto, che piano piano sto portando avanti.<br /><br />A questo link<br /><a href="http://alessioausilio.blogspot.com/p/x-rpg-builder.html">X-RPG Builder 2D</a><br />potrete trovare di volta in volta informazioni più approfondite a riguardo di questo progetto.<br /><br />Spero a presto con altre notizie ^^<br />Ciau!Odinohttp://www.blogger.com/profile/05339005661503346027noreply@blogger.com0tag:blogger.com,1999:blog-6862936347949168466.post-78537465502866184602010-07-06T10:08:00.011+02:002010-07-06T15:55:20.954+02:00Piccolo editor di terreni freeApprofitto dopo tanto di un momento di pace per scrivere e postare qualcosa che spero possa interessare a molti.<br />Rendo infatti disponibile il codice sorgente di questa mia applicazione, un piccolo terrain editor che ho realizzato per un esame universitario.<br />Il perchè di questa mia scelta: primo perchè credo che nonostante le grandi imprecisioni, gli errori e i bug che ci possono essere, può essere di interesse per qualcuno, sia per i concetti applicati sia come punto di partenza per altro.<br />Secondo perchè lo considero io stesso un progetto ormai superato, che però mi ha fatto imparare tanto.<br />Infatti lo userò come base teorica per realizzare ben altro. <br /><br /><span class="fullpost">Cominciamo con una piccola spiegazione:<br />l'interfaccia dell'applicazione è questa:<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://farm5.static.flickr.com/4136/4767582066_470a0c9c3c_b.jpg"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 240px; height: 128px;" src="http://farm5.static.flickr.com/4136/4767582066_470a0c9c3c_m_d.jpg" border="0" alt="" /></a><br />Per un riassunto veloce dei comandi e delle funzioni basta che andate sulla voce "comandi" sotto "?" nel menù in alto.<br /><br />La prima cosa che dovete fare è creare un nuovo livello. Dopo potete o agire direttamente con i mouse sul terreno o caricare una Height Map (tramite il bottone nella colonna di destra). Ecco cosa viene realizzato caricando una delle HM che ho inserito come prova.<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://farm5.static.flickr.com/4114/4767582386_4660ae19a4_b.jpg"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 240px; height: 128px;" src="http://farm5.static.flickr.com/4114/4767582386_4660ae19a4_m_d.jpg" border="0" alt="" /></a><br />La modalità di editing è modale: se vedete bene in alto a sinistra c'è un gruppo di radio button che vi dicono attualmente cosa state andando a modificare nel livello, se il terreno, le texture o i modelli. Quando siete in una modalità agite solo su quella parte.<br />Potete cambiare la modalità cliccando sul radio button relativo o premendo 'T'.<br />Potete texturizzare il terreno a vostro piacere utilizzando le 4 texture in alto a destra. Per cambiare la texture da usare basta farci click sopra, mentre se proprio volete caricare un'altra immagine al suo posto dovete farci doppio click.<br /><br />Per inserire i modelli nella scena dovete prima caricarli: andate sotto la scheda Objects e cliccate su "Load Model". Selezionate il modello da caricare e date l'ok. Il modello verrà "compilato" al volo nel formato compatibile con XNA e potrete poi utilizzarlo nel livello. Se ci cliccate sopra nel riquadro sottostante vedrete anche l'anteprima del modello in questione.<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://farm5.static.flickr.com/4116/4767582432_8d90082f16_b.jpg"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 240px; height: 128px;" src="http://farm5.static.flickr.com/4116/4767582432_8d90082f16_m.jpg" border="0" alt="" /></a><br /><br />Provatelo poi ditemi.<br /><br />Immagiamo di aver salvato questo livello:<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://farm5.static.flickr.com/4123/4767606542_5f845734b3_b.jpg"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 240px; height: 128px;" src="http://farm5.static.flickr.com/4123/4767606542_5f845734b3_m.jpg" border="0" alt="" /></a><br />Per caricarlo all'interno di un progetto XNA game dovete seguire alcuni passi:<br />1) dovete aggiungere il file *.map che viene generato quando salvate la mappa al progetto XNA e impostare le sue proprietà in modo che venga copiato nella directory finale del progetto durante la compilazione<br />2) Dovete copiare la bitmap del livello, che ha lo stesso nome del file *.map, e le texture usate per texturizzare il terrain sotto la directory "Content\Textures" del vostro gioco XNA<br />3) dovete copiare i modelli che avete utilizzato nel livello sotto la directory "Content\Models"<br />4) dovete copiare le texture usate dai vostri modelli nel gioco XNA mantenendo lo stesso percorso relativo rispetto ai file di origine<br />NOTA: Naturalmente tutte queste risorse vanno aggiunte al progetto Content del gioco XNA per permettergli di elaborarle.<br />A questo punto tutto è fatto. Basta che lanciate il il programma e vi ritroverete con il vostro livello caricato e pronto all'uso.<br />Ecco un'immagine dell'esempio allegato:<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://farm5.static.flickr.com/4122/4767623856_e46ac47ed8_b.jpg"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 240px; height: 189px;" src="http://farm5.static.flickr.com/4122/4767623856_e46ac47ed8_m.jpg" border="0" alt="" /></a><br /><br />Vi allego di seguito la soluzione per Visual Studio 2008.<br />Per far girare il programma è necessario aver installato XNA 3.1 e il .Net Framework 3.5.<br />Per qualsiasi cosa, consigli, problemi, lamentele, critiche commentate il pure, o mandate un'email.<br />Per favore, se scaricate e provate il codice commentate, almeno mi lasciate un feedback sul mio lavoro ^^<br /><br /><a href="http://odino87.interfree.it/XNA/TerrainEditor.rar"><b>Codice sorgente</b></a><br /><br />Alla prossima :)<br />Alessio (Odino)<br /><br /></span>Odinohttp://www.blogger.com/profile/05339005661503346027noreply@blogger.com1tag:blogger.com,1999:blog-6862936347949168466.post-35984394263416914442010-06-13T20:30:00.003+02:002010-06-13T20:34:27.187+02:00Apertura nuovo blogCome preannunciato tempo fa, ho aperto dopo tanto il nuovo blog destinato a raccogliere quei post che non erano attinenti all'informatica, oltre a contenere i nuovi post di tal genere che pubblicherò.<br /><br />Il link è: <a href="http://asgardwalls.blogspot.com/">AsgardWalls</a><br />Chi vuole darci un'occhiata faccia pure (se siete tanto coraggioni o incoscienti).<br />In un'epoca dove tutti possono dire quello che vogliono ho pensato che era il caso di fare lo stesso. Almeno ci si sfoga un pochino.<br /><br />Alla prossima!<br /><span class="fullpost"></span>Odinohttp://www.blogger.com/profile/05339005661503346027noreply@blogger.com1tag:blogger.com,1999:blog-6862936347949168466.post-91613167497989541192010-05-31T09:01:00.003+02:002010-05-31T10:02:55.798+02:00AvvisoComunicazione di servizio:<br />per esigenze particolari dettate dalla mia mente contorta, forse qualcuno potrà notare che una trentina di post sono scomparsi dal blog.<br />Questo perchè ho deciso di ripulire il blog, lasciando questo solo per gli articoli riguardanti la programmazione.<br />Gli altri articoli/post andranno a finire in un altro blog, che vedrò di aprire il prima possibile, dove andrò a mettere tutta quella roba che non riguarda il mondo della programmazione (quindi recensioni, riflessioni, lamentazioni, bestemmioni vari).<br />Abbiate un po' di calma che ora come ora di tempo ne ho poco quindi la cosa andrà a rilento.<br /><br />Saluti dal vostro amichevole Odino di quartiere (non mi uccidete per questa citazione storpiata XD)Odinohttp://www.blogger.com/profile/05339005661503346027noreply@blogger.com4tag:blogger.com,1999:blog-6862936347949168466.post-11721303651186829232010-04-17T11:23:00.002+02:002010-04-17T11:28:20.927+02:00Tanti auguri a me!No, non sono impazzito...<br />Era ormai il lontano 06/04/2009 quando veniva pubblicato su questo blog il primo post, il primo post dopo il Ragnarok.<br />Tante cose sono accadute da allora, alcune buone ma la maggior parte mica tanto...<br /><br />Tra una disavventura e l'altra siamo andati avanti, si è pubblicato un po' di roba (non tanta, ma ci si è provato).<br /><br />L'intenzione di continuare, nonostante il poco tempo, c'è sempre.<br />Dovuta anche al fatto che bene o male un po' di visite ci sono sempre, per quanto questo sia un blog un po' strano...<br /><br />Quindi faccio gli auguri a questo blog! Che possa continuare a prosperare!<br />E che la luce di Odino lo protegga!<span class="fullpost"></span>Odinohttp://www.blogger.com/profile/05339005661503346027noreply@blogger.com1