Problema con gli SPRITE in vb.net

sabato 14 gennaio 2012 - 07.09
Tag Elenco Tags  VB.NET  |  .NET 4.0  |  Windows 7  |  Visual Studio 2010

xyzsurf Profilo | Newbie

Ho un problema come sempre:
vorrei muovere una pallina ... immaginiamo una palla da biliardo, quando questa riceve un colpo. Una cosa semplice solo per creare un effetto visivo.
Ho provato sia con THREAD che con il timer ... manipolando la visualizzazione di una picturebox. Ovviamente tutto procede a scatti, per nulla fluido il tutto.

C'è sicuramente qualcosa che non conosco. MI RIFIUTO DI CREDERE che in vb.net siamo impossibile animare degli sprite.

Per l'animazione, devo riposizionare il controllo sugli assi x e y con un cilo for-next ... MI SEMBRA TUTTO COSI' PRIMITIVO.

grazie a chi mi apre la mente!
ciao

luigidibiasi Profilo | Guru

in realtà sbagli approccio... (ma non è una questione di vb.net bensì di tutto .net in genere)
se tu riposizioni il controllo, ad ogni step devi gestire l'intera coda di messaggi di windows...

Per fare quello che vuoi hai 3 strade ovvero usare uno tra i tre:

1) GDI
2) DirectX
3) OpenGL

dato che stai usando vb.net per evitare di installare sdk e cose varie puoi sfruttare gdi

1) metti la picturebox che farà da monitor
2) ti prendi l'handle gdi della image della picturebox (es: dim toDraw as graphics = graphics.fromImage(picturebox1.image))
3) ad ogni step fai il refresh dell'image ridisegnado la pallina nella posizione corretta
4) effettui il refresh della picturebox



Luigi Di Biasi


http://www.dibiasi.it/
http://netsell.dibiasi.it - ecomm software -
http://blogs.dotnethell.it/luigidibiasi/
http://yadamp.unisa.it/ - YADAMP CMS -

xyzsurf Profilo | Newbie

interessante ... sapresti dirmi come fare il refresh della picturebox?

luigidibiasi Profilo | Guru

c'è il metodo invalidate da richiamare quando è necessario ridisegnare il controllo (se ci passa un'altra finestra da sopra o perde il focus)

http://www.google.it/#sclient=psy-ab&hl=it&safe=off&site=&source=hp&q=picturebox+invalidate&pbx=1&oq=picturebox+invalidate&aq=f&aqi=g-L1&aql=&gs_sm=e&gs_upl=71l2158l0l2193l21l9l0l5l5l1l172l1205l1.8l10l0&bav=on.2,or.r_gc.r_pw.r_cp.,cf.osb&fp=f23b58a1cb65471c&biw=1366&bih=681

Luigi Di Biasi


http://www.dibiasi.it/
http://netsell.dibiasi.it - ecomm software -
http://blogs.dotnethell.it/luigidibiasi/
http://yadamp.unisa.it/ - YADAMP CMS -

xyzsurf Profilo | Newbie

visto che sei molto gentile e preparato ti mostro la mia deficenza:

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click

Dim Rotola As Int16
For Rotola = 100 To 700 Step 5
Thread.Sleep(1)
PictureBox1.Location = New Point(Rotola, 42)
Next

End Sub

IL TUO SUGGERIMENTO: Dim toDraw As Graphics = Graphics.FromImage(PictureBox1.Image)
non so dove collecolarlo ne tantomeno come fare il refresh.

Mi rendo conto di quanto sia stupida la cosa, ma non ho mai lavorato con le immagini !
CIAO!

MarKonE Profilo | Guru

CIAO !

XNA potrebbe fare per te :)

http://code.msdn.microsoft.com/windowsdesktop/Visual-Basic-XNA-29cd4963
http://totemslair.org/guide/viewchapter.php?guida=xna&id=1

CIAO !

My Blog... http://blogs.dotnethell.it/Mark/

luigidibiasi Profilo | Guru

>visto che sei molto gentile e preparato ti mostro la mia deficenza:
che brutta frase che è questa... deficienza non si addice a chi chiede consiglio su qualcosa

>
>Private Sub Button2_Click(ByVal sender As System.Object, ByVal
>e As System.EventArgs) Handles Button2.Click
>
> Dim Rotola As Int16
> For Rotola = 100 To 700 Step 5
> Thread.Sleep(1)
> PictureBox1.Location = New Point(Rotola, 42)
> Next
>
>End Sub

allora il problema nasce dal fatto che vuoi modificare la location della picturebox... ora... io non so che immagine ci sta dentro ma ti faccio l'esempio con un'immagine presa a caso... lo posto nel post successivo a questo


>
>IL TUO SUGGERIMENTO: Dim toDraw As Graphics = Graphics.FromImage(PictureBox1.Image)
>non so dove collecolarlo ne tantomeno come fare il refresh.
>
>Mi rendo conto di quanto sia stupida la cosa, ma non ho mai lavorato
>con le immagini !
>CIAO!

Luigi Di Biasi


http://www.dibiasi.it/
http://netsell.dibiasi.it - ecomm software -
http://blogs.dotnethell.it/luigidibiasi/
http://yadamp.unisa.it/ - YADAMP CMS -

luigidibiasi Profilo | Guru

ecco il file di esempio... la logica quando utilizzi le animazioni è un po' diversa però credo sia abbastanza chiara come l'ho scritta

se hai altri problemi dimmi pure

p.S: vale sempre la regola di buttarsi su directx o xna come ti hanno suggerito sopra perché anche GDI ha i suoi limiti (non può farci un videogioco in 3d ad esempio ne puoi usarlo per avere un alto framerate)

Luigi Di Biasi


http://www.dibiasi.it/
http://netsell.dibiasi.it - ecomm software -
http://blogs.dotnethell.it/luigidibiasi/
http://yadamp.unisa.it/ - YADAMP CMS -

luigidibiasi Profilo | Guru

mi sono dimenticato di dirti che devi gestire "il passare del tempo" altrimenti i frame vengono aggiornati in base a come decide windows...
quindi su pc più veloci andrà tutta l'animazione più veloce...


un abbozzo di gestione del tempo

Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra


Luigi Di Biasi


http://www.dibiasi.it/
http://netsell.dibiasi.it - ecomm software -
http://blogs.dotnethell.it/luigidibiasi/
http://yadamp.unisa.it/ - YADAMP CMS -

zirobyte75 Profilo | Newbie

Ciao: il tuo problema è molto semplice da risolvere. Inserisci un TIMER, imposta INTERVAL su 25 e ENABLED su TRUE.
in questo esempio basterà che installi un componente aggiuntivo di pochi mb della microsoft(http://msdn.microsoft.com/en-us/vstudio/bb735936.aspx)


e poi gestisci l'evento tick del timer e dichiara 2 variabili boleana.
ti allego il codice:

Public Class Form1
Dim MuoviDestra As Boolean 'Variabile per controllare il movimento sull'asse orizontale(Sx/Dx)
Dim MuoviSu As Boolean 'Variabile per controllare il movimento sull'asse verticale(Su/Giù)

Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
'ad ogni evento Tick del Timer1, muove la palla e ne verifica la posizione impostando la direzione
If MuoviDestra = True Then
'sposta a dx
OvalShape1.Left += 10
Else
'sposta a sx
OvalShape1.Left -= 10
End If
If MuoviSu = True Then
'sposta giù
OvalShape1.Top -= 10
Else
'sposta su
OvalShape1.Top += 10
End If
'VERIFICA CONDIZIONE: se supera margine sx, cambia direzione
If OvalShape1.Left <= Me.ClientRectangle.Left Then
MuoviDestra = True
End If
'VERIFICA CONDIZIONE: se supera margine dx, cambia direzione
If OvalShape1.Left + OvalShape1.Width >= Me.ClientRectangle.Right Then
MuoviDestra = False
End If
'VERIFICA CONDIZIONE: se supera il margine superiore, cambia direzione
If OvalShape1.Top <= Me.ClientRectangle.Top Then
MuoviSu = False
End If
'VERIFICA CONDIZIONE: se supera il margine inferiore, cambia direzione
If OvalShape1.Top + OvalShape1.Height >= Me.ClientRectangle.Bottom Then
MuoviSu = True
End If
End Sub
End Class

ricorda che di solito basic.net ha problemi per il codice copia incola nella gestione degli eventi, quindi la sub del Private Sub Timer1_Tick ti conviene rigenerarla cliccando due volte sul controllo.

SE HAI DUBBI, GUARDA UN MIO VIDEO SULL'ARGOMENTO: ecco il link
http://www.youtube.com/watch?v=Sdx95hNweXM&feature=plcp&context=C3d04438UDOEgsToPDskKp3Sux3AaHh-IhZ41bMksI

ciao
se riesci a pensarlo puoi anche realizzarlo!
http://www.youtube.com/user/zirobyte75

Vinsent Profilo | Senior Member

Ciao, il codice di seguito è parte di una serie di giochini che stavo facendo e non più finito...
In pratica c' è un button (target) dentro un panel che si muove con movimenti diciamo "casuali" e lo scopo è cliccarlo nel limite di tempo, con il trascorrere del tempo il movimento del button rallenta, se si passa con il mouse sul button_target la sua direzione cambia.
Ci vuole una form con tre timer, un panel con dentro un button (target), due button (start e stop), un CheckBox (pausa) con apparence=button.
Il codice:
Public Class Form1 Dim contatore As Integer Dim limite_tempo As Integer Dim limite_basso As Integer Dim limite_destro As Integer Dim su_giu As String Dim des_sin As String Dim rnd As New Random Dim x As Integer Dim y As Integer Dim reset_timer1 As Integer Private Sub Form1_Load() Handles Me.Load reset_timer1 = 5 Button_target.Hide() su_giu = "giu" des_sin = "sin" Timer1.Interval = reset_timer1 Timer2.Interval = 200 Timer3.Interval = 1000 limite_tempo = 20 End Sub Private Sub Timer1_tick() Handles Timer1.Tick If Button_target.Top <= 0 Then su_giu = "giu" x = rnd.Next(3, 10) y = rnd.Next(3, 10) End If If Button_target.Top >= limite_basso Then su_giu = "su" x = rnd.Next(3, 10) y = rnd.Next(3, 10) End If If Button_target.Left <= 0 Then des_sin = "des" x = rnd.Next(3, 10) y = rnd.Next(3, 10) End If If Button_target.Left >= limite_destro Then des_sin = "sin" x = rnd.Next(3, 10) y = rnd.Next(3, 10) End If If su_giu = "giu" Then Button_target.Top = Button_target.Top + x End If If su_giu = "su" Then Button_target.Top = Button_target.Top - x End If If des_sin = "des" Then Button_target.Left = Button_target.Left + y End If If des_sin = "sin" Then Button_target.Left = Button_target.Left - y End If End Sub Private Sub Timer2_Tick() Handles Timer2.Tick x = rnd.Next(3, 10) y = rnd.Next(3, 10) End Sub Private Sub Timer3_Tick() Handles Timer3.Tick contatore = contatore + 1 If contatore = limite_tempo Then Button_target.Hide() Timer1.Stop() Timer2.Stop() Timer3.Stop() MsgBox("you fail") Else Timer1.Interval = Timer1.Interval + 3 End If End Sub Private Sub Button_start_Click() Handles Button_start.Click x = rnd.Next(0, 10) y = rnd.Next(0, 10) Timer1.Interval = reset_timer1 contatore = 0 limite_basso = Panel1.Height - Button_target.Height limite_destro = Panel1.Width - Button_target.Width Timer1.Start() Timer2.Start() Timer3.Start() Button_target.Show() End Sub Private Sub Button_stop_Click() Handles Button_stop.Click Button_target.Hide() Timer1.Stop() Timer2.Stop() Timer3.Stop() End Sub Private Sub CheckBox_pausa_CheckedChanged() Handles CheckBox_pausa.CheckedChanged If CheckBox_pausa.Checked = True Then Button_target.Hide() Timer1.Stop() Timer2.Stop() Timer3.Stop() End If If CheckBox_pausa.Checked = False Then Button_target.Show() Timer1.Start() Timer2.Start() Timer3.Start() End If End Sub Private Sub Button_target_Click() Handles Button_target.Click Timer1.Stop() Timer2.Stop() Timer3.Stop() Button_target.Hide() MsgBox("bravo, tempo impiegato: " & contatore & " secondi.") End Sub Private Sub Button_target_MouseEnter() Handles Button_target.MouseEnter x = 20 y = 20 End Sub End Class

Vedi tu se può esserti utile....
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2017
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5