Animazioni e giochi in Visual Basic Il gioco del Pimball - 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 Pimball, 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 Introduzione all’animazione e ai giochi in Visual Basic Matteo Temperoni 4ATP – prof.Claudio Maccherani – ITC “Vittorio Emanuele II” di Perugia - a.s.2005/06 pag.1 / 9 L’Evento MauseMove ha due variabili di default utili al nostro scopo: nome descrizione variabile restituisce la posizione del Puntatore del Mouse dal margine sinistro della FORM x restituisce la posizione del Puntatore del Mouse dalla cima della FORM y y x form shape 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 form left y shape Perciò basterà eguagliare nell’Evento MauseMove della FORM la proprietà left di shape 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 = shabar.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 sarà Overflow. Introduzione all’animazione e ai giochi in Visual Basic Matteo Temperoni 4ATP – prof.Claudio Maccherani – ITC “Vittorio Emanuele II” di Perugia - a.s.2005/06 pag.2 / 9 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 deve tornare nella direzione da dove è venuta. Per fare ciò saranno utili le proprietà delle Shape: Top e Height Quando la pallina tocca la parte superiore della barra significa che: shabar.Top = 0 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 = -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 della variabile di incremento sarà molto utile più avanti, in quanto risparmiera di scrivere molte righe di comando. Introduzione all’animazione e ai giochi in Visual Basic Matteo Temperoni 4ATP – prof.Claudio Maccherani – ITC “Vittorio Emanuele II” di Perugia - a.s.2005/06 pag.3 / 9 5) Dare altre direzioni alla pallina Finora abbiamo lavorato solo nel movimento verticale, Ma per un gioco del pimball 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 (altobasso). Perciò oltre che incrementare o decrementare la top bisognerà fare lo stesso anche con la Left della shaball, Ma 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 avere 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: 1/5 1/5 1/5 1/5 1/5 width 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 Introduzione all’animazione e ai giochi in Visual Basic Matteo Temperoni 4ATP – prof.Claudio Maccherani – ITC “Vittorio Emanuele II” di Perugia - a.s.2005/06 pag.4 / 9 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 è = 0, quando tocca la parete sinistra la sua left è = alla width della form left = 0 left = form.width 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à. Introduzione all’animazione e ai giochi in Visual Basic Matteo Temperoni 4ATP – prof.Claudio Maccherani – ITC “Vittorio Emanuele II” di Perugia - a.s.2005/06 pag.5 / 9 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 Introduzione all’animazione e ai giochi in Visual Basic Matteo Temperoni 4ATP – prof.Claudio Maccherani – ITC “Vittorio Emanuele II” di Perugia - a.s.2005/06 pag.6 / 9 Animazioni e giochi in Visual Basic Il gioco del Pimball - versione B prof. Claudio Maccherani Il gioco consiste nell’abbattere tutti i mattoncini colpendoli con la pallina. La pallina rimbalza sui bordi laterali, sul bordo superiore, dopo aver colpito un mattoncino e sulla barra che 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 barra mossa dal giocatore con il mouse, tocca il bordo inferiore. ShaX(i) [ Shape ] mattoncino ShaP [ Shape ] pallina ShaB [ Shape ] barra cmbVel [ Combo box ] velocità ! " % # $ & Introduzione all’animazione e ai giochi in Visual Basic Matteo Temperoni 4ATP – prof.Claudio Maccherani – ITC “Vittorio Emanuele II” di Perugia - a.s.2005/06 pag.7 / 9 ' 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 Introduzione all’animazione e ai giochi in Visual Basic Matteo Temperoni 4ATP – prof.Claudio Maccherani – ITC “Vittorio Emanuele II” di Perugia - a.s.2005/06 pag.8 / 9 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 Introduzione all’animazione e ai giochi in Visual Basic Matteo Temperoni 4ATP – prof.Claudio Maccherani – ITC “Vittorio Emanuele II” di Perugia - a.s.2005/06 pag.9 / 9