A5. Gestire le collisioni - Parte II
La mazza c'è, la palla c'è, lo sfondo anche, le collisioni sono impostate ottimamente, ma... mancano i blocchi da rompere. Metteremo diversi blocchetti sparsi per lo schermo, che dovranno essere tutti colpiti e frantumati con la palla per completare il livello. I più fragili saranno da colpire una sola volta, mentre quelli più resistenti più volte. Per questo scopo, abbiamo bisogno di una nuova classe, Block, che rappresenti il blocchetto e la sua "vita". Tale classe andrà scritta nel file GameObjects.vb, insieme alla classe GameObject:
Dato che ci saranno molti blocchi sullo schermo, non è necessario un solo oggetto per rappresentarlo, ma una lista:Public Class Block 'Il blocco è pur sempre un oggetto del gioco, quindi 'eredita da GameObject Inherits GameObject '"Vita" del blocco, ossia il numero di colpi necessari 'a romperlo. Default = 1 Private _LifeAs Int16 = 1 'Nome del blocco. Servirà più tardi Private _NameAs String Public Property Life()As Int16Get Return _LifeEnd Get Set (ByVal valueAs Int16) _Life = valueEnd Set End Property Public Property Name()As String Get Return _NameEnd Get Set (ByVal valueAs String ) _Name = valueEnd Set End Property Sub New ()My Base.new()End 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
'Ed ecco gli sprite che useremo per i blocchi:Lista di tutti i blocchi sullo schermo Private BlocksAs New List(Of Block)
Block01
Block02
Block03
Block04
Block05
Le immagini sono chiamate in modo che si possa dedurre la resistenza del blocco dal numero che lo segue: Block03 necessiterà di 3 colpi per essere tolto di mezzo.
Modifichiamo il codice di CollisionCheck in modo che operi anche sui blocchi:
Per fare una prova, aggiungiamo manualmente qualche blocco in LoadContent:Private Sub CollisionCheck()Dim BallRectAs Rectangle = GetBounds(Ball)Dim BatRectAs Rectangle = GetBounds(Bat) 'Questa variabile booleana determina se la pallina ha 'sbattuto contro un blocco. In questo modo, sbattendo 'contro due blocchi contemporaneamente, i rimbalzi 'non si annulleranno a vicenda Dim BouncedAs Boolean = FalseIf BallRect.Intersects(BatRect)Then CalculateBallVelocity(Bat)End If If ((Ball.Position.X < 5)Or _ (Ball.Position.X >Me .GraphicsDevice.Viewport.Width - 5)) _And (Ball.Position.Y <Me .GraphicsDevice.Viewport.Height - 5)Then Ball.Velocity = _New Vector2(-Ball.Velocity.X, Ball.Velocity.Y)End If If Ball.Position.Y < 5Then Ball.Velocity = _New Vector2(Ball.Velocity.X, -Ball.Velocity.Y)End If If Ball.Position.Y >Me .Graphics.GraphicsDevice.Viewport.HeightThen End If 'Questa lista contiene tutti i blocchi distrutti Dim HitBlocksAs New List(Of Block)For Each BlockAs BlockIn Blocks 'Costruisce il rettangolo che contiene il blocco Dim BlockRectAs Rectangle = GetBounds(Block) 'Se la palla lo ha colpito e non ha già 'rimbalzato, procede If BallRect.Intersects(BlockRect)And (Not Bounced)Then 'Inverte la componente Y della velocità Ball.Velocity = _New Vector2(Ball.Velocity.X, -Ball.Velocity.Y) 'Imposta Bounced=True Bounced = True 'Toglie un punto vita al blocco Block.Life -= 1If Block.Life = 0Then 'Se il blocco non ha più vita, lo disabilita 'e lo aggiunge alla lista dei blocchi distrutti Block.Enabled = False HitBlocks.Add(Block)Else 'Altrimenti, cambia il suo sprite, mettendo al 'posto di quello attuale, la texture del blocco di 'livello minore. Ad esempio, se il blocco giallo 'è colpito, diventerà bianco. Block.Sprite = GetTexture("Block" & _ Block.Life.ToString.PadLeft(2, "0") & ".png") 'La funzione PadLeft fa in modo che il numero 'riempia due posti: 1 diventerà 01 End If End If Next 'Rimuove i blocchi distrutti For Each BlockAs BlockIn HitBlocks Blocks.Remove(Block)Next End Sub
E non dimentichiamoci di disegnarli:Protected Overrides Sub LoadContent()My Base.LoadContent() Background =New GameObject(GetTexture("Background.png")) Background.Position = Background.CenterDim SizeAs New Viewport Size.Width = Background.Sprite.Width Size.Height = Background.Sprite.Height Size.X = 0 Size.Y = 0Me .Graphics.GraphicsDevice.Viewport = SizeMe .Graphics.PreferredBackBufferHeight = Size.HeightMe .Graphics.PreferredBackBufferWidth = Size.WidthMe .Graphics.ApplyChanges() Bat =New GameObject(GetTexture("Bat.png")) Bat.Position =New Vector2( _Me .Graphics.GraphicsDevice.Viewport.Width / 2, _Me .Graphics.GraphicsDevice.Viewport.Height - 40) Ball =New GameObject(GetTexture("Ball.png")) Ball.Position =New Vector2( _Me .Graphics.GraphicsDevice.Viewport.Width / 2, _Me .Graphics.GraphicsDevice.Viewport.Height / 2) Ball.Velocity =New Vector2(0, BallSpeed)Dim BAs Block B =New Block(GetTexture("Block01.png")) B.Name = "Block01" B.Position =New Vector2(150, 150) Blocks.Add(B) B =New Block(GetTexture("Block02.png")) B.Name = "Block02" B.Life = 2 B.Position =New Vector2(400, 300) Blocks.Add(B)End Sub
E il risultato è questo.Protected Overrides Sub Draw(ByVal gameTimeAs GameTime)Me .Graphics.GraphicsDevice.Clear(Color.White) Batch.Begin() Background.Draw(Batch) Bat.Draw(Batch) Ball.Draw(Batch) 'Disegna tutti i blocchi For Each BlockAs GameObjectIn Blocks Block.Draw(Batch)Next Batch.End()My Base.Draw(gameTime)End Sub
The Totem's Lair - Copyright (C) 2009
È vietata la riproduzione sia totale che parziale del sito.



