A2. Gli oggetti di gioco
Ricordiamoci sempre che stiamo scrivendo in .Net, un insieme di linguaggi orientati agli oggetti. Sulla base di questo, potrete facilmente capire perchè servirà una classe per ogni oggetto presente sulla scena. Tuttavia, non sarà necessaria una classe diversa per ogni entità e, anzi, in molti casi ne basterà solo una. Questa classe si chiama GameObject e rappresenta un generico oggetto nel gioco: ha molte proprietà, che ne determinano tutte le caratteristiche, e un metodo Draw che lo disegna sullo schermo tenendo conto di tutte le variabili in gioco.
Prima di descriverne le proprietà vorrei far notare tre particolari:Imports Microsoft.Xna.FrameworkImports Microsoft.Xna.Framework.GraphicsPublic Class GameObjectProtected _PositionAs Vector2Protected _VelocityAs Vector2Protected _RotationAs Single Protected _CenterAs Vector2Protected _SpriteAs Texture2DProtected _ColorAs ColorProtected _ScaleAs Single Protected _EnabledAs Boolean = TruePublic Overridable Property Position()As Vector2Get Return _PositionEnd Get Set (ByVal ValueAs Vector2) _Position = ValueEnd Set End Property Public Overridable Property Velocity()As Vector2Get Return _VelocityEnd Get Set (ByVal ValueAs Vector2) _Velocity = ValueEnd Set End Property Public Overridable Property Rotation()As Single Get Return _RotationEnd Get Set (ByVal ValueAs Single ) _Rotation = ValueEnd Set End Property Public Overridable Property Center()As Vector2Get Return _CenterEnd Get Set (ByVal ValueAs Vector2) _Center = ValueEnd Set End Property Public Overridable Property Sprite()As Texture2DGet Return _SpriteEnd Get Set (ByVal valueAs Texture2D) _Sprite = valueEnd Set End Property Public Overridable Property Color()As ColorGet Return _ColorEnd Get Set (ByVal valueAs Color) _Color = valueEnd Set End Property Public Overridable Property Scale()As Single Get Return _ScaleEnd Get Set (ByVal valueAs Single ) _Scale = valueEnd Set End Property Public Overridable Property Enabled()As Boolean Get Return _EnabledEnd Get Set (ByVal valueAs Boolean ) _Enabled = valueEnd Set End Property Public Overridable Sub Draw(ByVal BatchAs SpriteBatch)If Me .EnabledThen Batch.Draw(Me .Sprite,Me .Position, Nothing,Me .Color, _Me .Rotation,Me .Center,Me .Scale, SpriteEffects.None, 0)End If End Sub Sub New ()Me .Color = Graphics.Color.WhiteMe .Position = Vector2.ZeroMe .Rotation = 0Me .Scale = 1.0Me .Velocity = Vector2.ZeroEnd Sub Sub New (ByVal SpriteAs Texture2D)Me .New()Me .Sprite = SpriteMe .Center =Me .Position +New Vector2( _Me .Sprite.Width *Me .Scale / 2,Me .Sprite.Height * Me.Scale / 2)End Sub End Class
- Tutte le proprietà che indicano un singolo punto non sono di tipo Point, ma di tipo Vector2. È questa la classe che si usa in XNA per determinare una posizione sullo schermo. Inoltre, è anche più precisa, poiché le coordinate possono essere espresse come numeri decimali Single
- L'immagine dell'oggetto è rappresentata da un oggetto Texture2D. Allo stesso modo, in XNA le immagini non sono rappresentate dalle classi Image o Bitmap, ma da questa Texture2D
- Anche se non si nota, la struttura Color non è quella a cui siamo abituati, perchè si tratta di Xna.Framework.Graphics.Color e non della solita Drawing.Color. Nonostante ciò essa mantiene comunque tutte le sue proprietà statiche
- Position : la posizione dell'oggetto nel piano
- Velocity : la velocità dell'oggetto, rappresentata come un vettore
- Rotation : l'angolo di rotazione dell'oggetto, espresso in radianti
- Center : il centro dell'oggetto. Serve per calcolare correttamente la rotazione. Il codice che trova il centro dell'oggetto l'ho già scritto io
- Sprite : l'immagine dell'oggetto. Qualsiasi immagine, in XNA ma in generale nell'ambito della scrittura di videogiochi, si chiama sprite
- Color : la variazione di colore dell'immagine
- Scale : fattore di zoom
- Enabled : determina se l'oggetto sia visibile
- Draw(B As SpriteBatch) : disegna l'oggetto sullo schermo usando i parametri impostati
Scale = 1
Scale = 2
Color = Color.Green
Rotation = -π/4 (-45�)
Ora iniziamo, ad esempio, a dichiarare un nuovo GameObject che costituirà la mazza del giocatore. Nella classe Game dichiariamo una nuova variabile privata:
E la inizializziamo in LoadContent. Useremo il secondo overload di New, quello che un solo parametro di tipo Texture2D, ma ci manca l'immagine della mazza. Frugando nelle mie cartelle ho trovato questa, presa da Game Maker 6:Private BatAs GameObject
Bat: la mazza
Scaricate questa immagine e salvatela nella cartella bin\Debug del vostro progetto:
Facendo correre il programma vedrete una finestra dallo sfondo bianco e l'immagine della mazza in basso al centro. Niente di più.Imports Microsoft.Xna.FrameworkImports Microsoft.Xna.Framework.InputImports Microsoft.Xna.Framework.GraphicsPublic Class GameInherits Microsoft.Xna.Framework.GamePrivate GraphicsAs GraphicsDeviceManagerPrivate BatchAs SpriteBatch 'Bat rappresenta la mazza del giocatore Private BatAs GameObject 'Questa funzione carica un'immagine dalla cartella del programma. 'La definisco perchè in seguito sarà molto utile per 'rendere più leggibile il codice Private Function GetTexture(ByVal NameAs String )As Texture2DReturn Texture2D.FromFile(Me .Graphics.GraphicsDevice, _My .Application.Info.DirectoryPath & "\" & Name)End Function Sub New ()Me .Graphics =New GraphicsDeviceManager(Me )Me .Content.RootDirectory = "Content"End Sub Protected Overrides Sub Initialize() Batch =New SpriteBatch(Me .Graphics.GraphicsDevice)My Base.Initialize()End Sub Protected Overrides Sub LoadContent()My Base.LoadContent() 'Carica l'oggetto Bat con l'immagine della mazza Bat =New GameObject(GetTexture("Bat.png")) 'Imposta la posizione della mazza. 'Me.Graphics.GraphicsDevice.Viewport è una proprietà di 'tipo Rectangle, ma, ancora una volta, non si tratta di Drawing.Rectangle, 'ma di Xna.Framework.Graphics.Rectangle, una struttura ricca di 'nuovi e utili metodi, ancora migliore del vecchio Rectangle. 'Con questo codice, la mazza si trova esattamente nel centro del 'piano di gioco, e 40 pixel sopra il margine inferiore. Bat.Position =New Vector2( _Me .Graphics.GraphicsDevice.Viewport.Width / 2, _Me .Graphics.GraphicsDevice.Viewport.Height - 40)End Sub Protected Overrides Sub UnloadContent()My Base.UnloadContent()End Sub Protected Overrides Sub Update(ByVal GameTimeAs GameTime) 'Questo lo potete anche cancellare 'Dal prossimo capitolo non ci sarà più, poiché non stiamo 'usando il joypad, ma la tastiera If GamePad.GetState(PlayerIndex.One).Buttons.Back = _ ButtonState.PressedThen Me .Exit()End If My Base.Update(GameTime)End Sub Protected Overrides Sub Draw(ByVal gameTimeAs GameTime) 'Tinge lo schermo di bianco Me .Graphics.GraphicsDevice.Clear(Color.White) 'Tutte le chiamate a Draw devono essere comprese tra 'Batch.Begin, che inizializza il disegno... Batch.Begin() Bat.Draw(Batch) '... e Batch.End, che lo termina Batch.End()My Base.Draw(gameTime)End Sub End Class
Bat persa nel bianco
Un'ultima osservazione su questo codice:
Bat.Position =Come ho detto e scritto in tutti i capitoli della guida e in tutti i miei articoli sulla grafica, la posizione di un oggetto (spesso espressa dalla proprietà Location) determina il punto superiore sinistro dell'immagine. In XNA, invece, la proprietà Position indica il centro dell'immagine: posizionare un oggetto alle coordinate 50;50 signifca che il suo centro viene posto a quelle coordinate:New Vector2( _Me .Graphics.GraphicsDevice.Viewport.Width / 2, _Me .Graphics.GraphicsDevice.Viewport.Height - 40)
Location / Position
The Totem's Lair - Copyright (C) 2009
È vietata la riproduzione sia totale che parziale del sito.



