Animazioni e giochi in Visual Basic Il gioco del Brick - versione A
Matteo Temperoni
4 A Programmatori, ITC "Vittorio Emanuele II", Perugia, a.s. 2005/2006
Obbiettivi:
Fornire le conoscenze di base per creare un semplice gioco, tipo Brick (mattone), in Visual Basic.
Conoscenze
Per realizzare il gioco bisogna avere delle conoscenze generali sui seguenti oggetti e proprietà:
• Timer;
• Shape;
• Top, Left, Height, Width;
1) Creazione e movimento della barra
Dopo aver creato una semplice FORM inseriamo una SHAPE della Barra degli Strumenti .
Ora bisogna muoverla dentro la FORM con il MOUSE. Per farlo utilizzeremo l’Evento MouseMove
L’Evento MouseMove ha due variabili di default utili al nostro scopo:
nome descrizione variabile
x restituisce la posizione del Puntatore del Mouse dal margine sinistro della FORM y restituisce la posizione del Puntatore del Mouse dalla cima della FORM
Analogamente la shape ha due proprietà (comuni a tutti gli oggetti, tranne le FORM):
nome Descrizione
left restituisce la posizione della SHAPE dal bordo sinistro della FORM top restituisce la posizione della SHAPE dalla cima della FORM
Perciò basterà eguagliare nell’Evento MauseMove della FORM la proprietà left di shabar alla x.
Private Sub Form_MouseMove(Button As Integer, Shift As Integer, x As Single, y As Single) shabar.Left = x
End Sub
2) Movimento della pallina
Per muovere la pallina avremo bisogno dell’oggetto TIMER reperibile dalla Barra degli Strumenti.
Per questo programma sarà necessario conoscere l’unico evento dell’oggetto e una sua proprietà.
L’evento si chiama come l’oggetto Timer è viene eseguito ogni tot di tempo. Questo tot deve essere inserito nella proprietà Interval dell’oggetto Timer. Il valore di Interval è espresso in millisecondi.
Per muovere la pallina sarà necessario spostare le coordinate Left e Top della pallina ogni tot di tempo.
Private Sub Form_Load() Timer.Interval = 1 End Sub
Private Sub Timer_Timer() shaball.Top = shaball.Top + 40 End Sub
Con questo codice otterremo un risultato un po’ deludente. La pallina si muoverà verso il basso e non si fermerà finche il valore della Top non darà errore di Overflow.
x y form
shape
left y
form
shape
3) Far rimbalzare la pallina a contatto con la barra
Quando la pallina tocca la barra deve rimbalzare, tornare da dove è venuta.
Per fare ciò saranno utili le proprietà delle Shape: Left, Top e Width
Quando la pallina si trova nella scia immaginaria che crea la barra (quella colorata di celeste) e alla sua altezza (riga tratteggiata rossa) bisognerà semplicemente trasformare l’addendo della shabar.top in un sottraendo nell’evento Timer. (Vedremo l’esempio con il prossimo passo)
4) Far rimbalzare la pallina a contatto con la parete superiore
Quando la pallina tocca la parete superiore (cioè il suo Top è minore o uguale a zero) deve tornare nella direzione da dove è venuta. Per fare ciò saranno utili le proprietà delle Shape: Top e Height
Quando la parte inferiore della pallina (il suo Top + la sua altezza Height) tocca la parte superiore della barra (Top della barra) la pallina deve rimbalzare. Per questo, una volta controllato che essa è arrivata all’altezza della barra, occorre controllare anche che si trovi effettivamente tra il margine sinistro e il margine destro della barra.
Private Sub Timer_Timer()
If shaball.Top + shaball.Height >= shabar.Top Then
If shaball.Left >= shabar.Left And shaball.Left <= shabar.Left + shabar.Width Then Incremento_verticale = -40
shaball.Top = shaball.Top + Incremento_verticale Else
MsgBox "Game Over"
End End If Else
If shaball.Top <= 0 Then Incremento_verticale = 40
shaball.Top = shaball.Top + Incremento_verticale Else
shaball.Top = shaball.Top + Incremento_verticale End If
End If End Sub
N.B. Al posto di incrementare direttamente la top di shabar ho usato una variabile di incremento. L’uso
5) Dare altre direzioni alla pallina
Finora abbiamo lavorato solo sul movimento verticale, Ma per un gioco del brick che si rispetti ci deve essere anche un movimento orizzontale.
Per fare ciò saranno utili:
• le proprietà delle Shape: Left e Width
• le proprietà Form: Width
• il costrutto Select Case
Quando la pallina tocca una parete laterale deve cambiare direzione (destra-sinistra) ma non verso (alto- basso), cioè l’incremento orizzontale della sua Left dovrà cambiare di segno.
Quando la pallina tocca la barra, oltre che decrementare la top, bisognerà fare lo stesso anche con la Left.
Ma di quanto? A seconda del punto d’impatto della pallina sulla barra questa avrà un’angolazione diversa.
N.B. Se si incrementa sia la Top che la Left della pallina si avrà come risultato un movimento diagonale (come nel disegno), che potrà essere più o meno angolato in funzione della differenza tra l’incremento della top e della left.
Ora è essenziale conoscere il punto d’impatto. A tal fine si può frazionare la barra in più parti:
A seconda di dove la shaball toccherà ci sarà un diverso incremento della left di shaball.
Select Case shaball.Left
Case Is <= shabar.Left + shabar.Width * 1 / 5 Incremento_orizzontale = -50
shaball.Left = shaball.Left + Incremento_orizzontale Case Is <= shabar.Left + shabar.Width * 2 / 5
Incremento_orizzontale = -20
shaball.Left = shaball.Left + Incremento_orizzontale Case Is <= shabar.Left + shabar.Width * 3 / 5
Incremento_orizzontale = 0
shaball.Left = shaball.Left + Incremento_orizzontale Case Is <= shabar.Left + shabar.Width * 4 / 5
Incremento_orizzontale = 20
shaball.Left = shaball.Left + Incremento_orizzontale Case Is <= shabar.Left + shabar.Width
Incremento_orizzontale = 50
shaball.Left = shaball.Left + Incremento_orizzontale End Select
width
1 / 5 1 / 5 1 / 5 1 / 5 1 / 5
6) Sesto Passo – Far rimbalzare la pallina sulle pareti laterali
Questo passaggio, simile al terzo e quarto passo, consiste nel far rimbalzare la palla a contatto con i lati della form.
Per fare ciò saranno utili:
• le proprietà delle Shape: Left
• le proprietà Form: Width
Quando la shaball tocca la parete sinistra significa che la sua left è uguale a 0, quando tocca la parete destra la sua left è uguale alla width della form
A questo punto basterà creare un a variabile che gestisce il movimento orizzontale e, ogni qual volta la pallina tocchi una parete, cambiargli segno. Se la pallina si muove verso destra significa che la sua left sta aumentando, viceversa se si muove verso sinistra la sua left diminuisce, di conseguenza l’incrementatore aumenterà o diminuirà.
left = 0 left = form.width
Prototipo del programma
Option Explicit
Dim Incremento_verticale As Integer, Incremento_orizzontale As Integer Private Sub Form_Load()
Incremento_verticale = 40 Timer.Interval = 1
End Sub
Private Sub Form_MouseMove(Button As Integer, Shift As Integer, x As Single, y As Single) shabar.Left = x
End Sub
Private Sub Timer_Timer()
If shaball.Top >= shabar.Top Then
If shaball.Left >= shabar.Left And shaball.Left <= shabar.Left + shabar.Width Then Incremento_verticale = 0 - Incremento_verticale
Select Case shaball.Left
Case Is <= shabar.Left + shabar.Width * 1 / 5 Incremento_orizzontale = -40
Case Is <= shabar.Left + shabar.Width * 2 / 5 Incremento_orizzontale = -20
Case Is <= shabar.Left + shabar.Width * 3 / 5 Incremento_orizzontale = 0
Case Is <= shabar.Left + shabar.Width * 4 / 5 Incremento_orizzontale = 20
Case Is <= shabar.Left + shabar.Width Incremento_orizzontale = 40
End Select Else
MsgBox "Game Over"
End End If Else
If shaball.Top <= 0 Then
Incremento_verticale = 0 - Incremento_verticale Else
If shaball.Left <= 0 Or shaball.Left >= Form1.Width Then Incremento_orizzontale = 0 - Incremento_orizzontale End If
End If End If
shaball.Top = shaball.Top + Incremento_verticale
shaball.Left = shaball.Left + Incremento_orizzontale
End Sub
Animazioni e giochi in Visual Basic Il gioco del Brick - versione B
prof. Claudio Maccherani
Il gioco consiste nell’abbattere tutti i
mattoncinicolpendoli con la
pallina. La
pallinarimbalza sui bordi laterali, sul bordo superiore, dopo aver colpito un
mattoncinoe sulla
barrache il giocatore sposta orizzontalmente con il mouse.
I
mattoncini, quando colpiti, spariscono ed aumentano di uno il punteggio del giocatore.
La partita termina con la vittoria del giocatore - quando abbatte l’ultimo
mattoncino– o con la sua sconfitta – quando la
pallina, non intercettata dalla
barramossa dal giocatore con il mouse, tocca il bordo inferiore.
! " # $
% &
ShaX(i) [ Shape ] mattoncino
ShaP [ Shape ]
pallina
ShaB [ Shape ]
barra
cmbVel [ Combo box ]
velocità frame [ Frame ]
' frmSpace.frm - esempio di animazione in Visual Basic - prof.Claudio Maccherani Option Explicit
Dim Kv As Integer ' fattore di spostamento verticale Dim Ko As Integer ' fattore di spostamento orizzontale
Dim It As Integer ' intervallo di tempo del timer (più è grande, più è lenta la pallina) Dim Ms As Integer ' coordinata x del mouse
Dim Pt As Integer ' contatore punti
--- Private Sub Form_Load()
Dim i As Integer: Kv = 60: Ko = 0: Ms = 0: Pt = 0: lblPunti = ""
It = 1: Timer.Interval = It ' intervallo del timer in millesimi di secondo For i = 1 To 10: cmbVel.AddItem i * 20: Next i: cmbVel.Text = Kv
End Sub
--- Private Sub Form_Activate()
Dim i As Integer ' crea i mattoncini (a partire dall'unico "scaX(0)" esistente
For i = 1 To 11: Load shaX(i): shaX(i).Left = shaX(i - 1).Left + shaX(i - 1).Width + 50:
shaX(i).Visible = True: Next i
Load shaX(i): shaX(i).Left = s1haX(0).Left + shaX(0).Width / 2 + 50: shaX(i).Top = shaX(0).Top + shaX(0).Height + 50: shaX(i).Visible = True
For i = 13 To 22: Load shaX(i): shaX(i).Left = shaX(i - 1).Left + shaX(i - 1).Width + 50:
shaX(i).Top = shaX(i - 1).Top: shaX(i).Visible = True: Next i
Load shaX(i): shaX(i).Left = shaX(12).Left + shaX(12).Width / 2 + 50: shaX(i).Top = shaX(12).Top + shaX(12).Height + 50: shaX(i).Visible = True
For i = 24 To 32: Load shaX(i): shaX(i).Left = shaX(i - 1).Left + shaX(i - 1).Width + 50:
shaX(i).Top = shaX(i - 1).Top: shaX(i).Visible = True: Next i
Load shaX(i): shaX(i).Left = shaX(23).Left + shaX(23).Width / 2 + 50: shaX(i).Top = shaX(23).Top + shaX(23).Height + 50: shaX(i).Visible = True
For i = 34 To 41: Load shaX(i): shaX(i).Left = shaX(i - 1).Left + shaX(i - 1).Width + 50:
shaX(i).Top = shaX(i - 1).Top: shaX(i).Visible = True: Next i
Load shaX(i): shaX(i).Left = shaX(33).Left + shaX(33).Width / 2 + 50: shaX(i).Top = shaX(33).Top + shaX(33).Height + 50: shaX(i).Visible = True
For i = 43 To 49: Load shaX(i): shaX(i).Left = shaX(i - 1).Left + shaX(i - 1).Width + 50:
shaX(i).Top = shaX(i - 1).Top: shaX(i).Visible = True: Next i
Load shaX(i): shaX(i).Left = shaX(42).Left + shaX(42).Width / 2 + 50: shaX(i).Top = shaX(42).Top + shaX(42).Height + 50: shaX(i).Visible = True
For i = 51 To 56: Load shaX(i): shaX(i).Left = shaX(i - 1).Left + shaX(i - 1).Width + 50:
shaX(i).Top = shaX(i - 1).Top: shaX(i).Visible = True: Next i End Sub
--- Private Sub cmdFine_Click(): End: End Sub
--- Private Sub frame_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single) If Button = 1 Then
With shaB
If (.Top + .Height) >= Y And Y >= (.Top) And (.Left + .Width) >= X And X >= (.Left) Then Ms = X ' coordinata x del mouse quando lo si clicca sopra la barra
End If End With End If End Sub
--- Private Sub frame_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) Dim k As Integer
If Button = 1 And Ms > 0 Then ' controlla se muovere la barra With shaB
If (.Top + .Height) >= Y And Y >= (.Top) And (.Left + .Width) >= X And X >= (.Left) Then ' calcola lo spostamento positivo o negativo del mouse rispetto alla sua precedente posizione k = X – Ms
If (k > 0 And .Left + .Width + k < frame.Width) Or (k < 0 And .Left + k > 0) Then .Left = .Left + k ' muove la barra
Ms = X ' salva la nuova posizione del mouse End If
End If End With End If End Sub
--- Private Sub frame_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
If Button = 1 And Ms > 0 Then With shaB
If (.Top + .Height) >= Y And Y >= (.Top) And (.Left + .Width) >= X And X >= (.Left) Then Ms = 0
End If End With End If End Sub
--- Private Sub Timer_Timer()
Call Muovi_Pallina ' controlla il movimento della pallina End Sub
--- Private Sub Muovi_Pallina() ' controlla il movimento della pallina
Dim Px As Integer: Px = shaP.Left + shaP.Width / 2 ' centro pallina
Dim b0 As Integer: b0 = shaB.Left ' +---+---+---+
Dim b1 As Integer: b1 = b0 + shaB.Width / 3 ' | | | | Dim b2 As Integer: b2 = b1 + shaB.Width / 3 ' +---+---+---+
Dim b3 As Integer: b3 = b2 + shaB.Width / 3 ' b0 b1 b2 b3
If shaP.Top + shaP.Height >= shaB.Top And shaP.Top + shaP.Height <= shaB.Top + shaB.Height Then ' all'altezza della barra
If shaB.Left <= shaP.Left + shaP.Width / 2 And shaP.Left + shaP.Width / 2 <= shaB.Left + shaB.Width Then ' pallina intercettata
Kv = -Kv ' rimbalzo verticale (la pallina colpisce la barra) Select Case Px
Case b0 To b1: Ko = -30 ' colpisce a sinistra, rimbalza a sinistra Case b1 To b2: Ko = 0 ' colpisce al centro, rimbalza verticale Case b2 To b3: Ko = 30 ' colpisce a destra, rimbalza a destra End Select
End If
ElseIf shaP.Top + shaP.Height / 2 >= frame.Height Then ' pallina passata, partita finita male MsgBox "Game Over !": End
ElseIf shaP.Left <= 0 Then ' la pallina colpisce il bordo sinistro Ko = 30 ' rimbalza a destra
ElseIf shaP.Left + shaP.Width >= frame.Width Then ' la pallina colpisce il bordo destro Ko = -30 ' rimbalza a sinistra
ElseIf shaP.Top <= 0 Then ' la pallina colpisce il bordo superiore Kv = -Kv ' rimbalzo verticale (inverte la direzione)
Ko = Ko ' rimbalzo orizzontale Else
Call Abbatti_Birilli ' controlla se la pallina abbatte un "birillo"
End If
shaP.Top = shaP.Top + Kv: shaP.Left = shaP.Left + Ko End Sub
--- Private Sub cmbVel_Click(): Dim v: v = Val(cmbVel.Text): Kv = IIf(Kv > 0, v, -v): End Sub
--- Private Sub Abbatti_Birilli() ' controlla se la pallina abbatte un "birillo"
Dim x0 As Integer, x1 As Integer, i As Integer
Dim pp0 As Integer: pp0 = shaP.Left ' inizio pallina (bordo sinistro) Dim pp1 As Integer: pp1 = shaP.Left + shaP.Width ' fine pallina (bordo destro) For i = 0 To shaX.Count - 1 ' controlla ciascun "birillo" rimasto (ancora visibile) If shaX(i).Visible Then ' solo se è visibile è ancora in gioco
x0 = shaX(i).Left: x1 = shaX(i).Left + shaX(i).Width
If (x0 <= pp0 And pp0 <= x1) Or (x0 <= pp1 And pp1 <= x1) Then ' in orizzontale è nella traiettoria della pallina
If Kv > 0 Then ' pallina discendente
If shaP.Top + shaP.Height >= shaX(i).Top And _
shaP.Top + shaP.Height <= shaX(i).Top + shaX(i).Height Then ' "birillo" colpito dall'alto, viene disattivato (reso invisibile) Kv = -Kv: Pt = Pt + 1: lblPunti = Pt: shaX(i).Visible = False: Exit Sub End If
Else ' pallina ascendente
If shaP.Top <= shaX(i).Top + shaX(i).Height And _
shaP.Top >= shaX(i).Top Then ' "birillo" colpito dal basso, diviene invisibile Kv = -Kv: Pt = Pt + 1: lblPunti = Pt: shaX(i).Visible = False: Exit Sub
End If End If End If End If Next i End Sub