Katsoin jo tarpeelliseksi tehdä uuden Strite-esimerkin.
Tässä esimerkissä spritejä on 6 kpl. 5 nelötä ja yksi olio
Tässä tehdään myös törmäys tarkistukset.
Tarvitset yhden formin nimi PL
Picturebox-kontrooleja:
Pkuva,Buffer1,Buffer2 laita mäihin sama peli-kuva. esim 320*240
pSprite(0 - 5) 0-4 neliöt (32*32), 5 = olio (37*37)
pVanha(0 - 5) 0-4 nelöt (32*32), 5 = olio (37*37)
pMask(0 - 1) 0 neliöt (32*32), 1 = olio (37*37)
Timer1
Tekniikkana on käyttää kahta puskuria, Buffer1 on paikka jonne kaikki piirretään, Buffer2 on paikka jossa on koko ajan "alkuperäinen kuva", tarvitaan vain jos, liikkuvia kuvaelementtejä on muitakin kuin nämä, ja halutaan että gfafiikka ei laahaudu, spritejen mennessä päällekkäin.
Buffer1:n kuva kopioidaan pKuvaan.
Esimerkki ei ole törmäyksen osalta täydellinen, varsinkin kun kaikki sulloutuvat samaan nurkkaan, mutta täytyyhän ihmisille jättää vähän paranneltavaakin...
Esimerkin Zip-Versio: http://koti.mbnet.fi/joresoft/Download/Esim/SpriteEsim2.zip
Moduliin
Option Explicit
'Muuttujat
Public Declare Function BitBlt Lib "gdi32" (ByVal hDestDC As Long, ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long
Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Type SpriteType 'Pelinapin yms. Muuttuja määrittely
Value As Integer ' Arvo
On As Boolean ' On/Off
X As Integer ' X-paikka ruudulla
Y As Integer ' Y-paikka
Z As Integer ' Z-paikka
VX As Integer ' Vanha X
VY As Integer ' Vanha Y
VZ As Integer ' Vanha Z
SX As Integer ' Lisäyslaskuri
SY As Integer
Temp As Integer ' Väliaikainen tieto
'Kuvankäsittelyyn liittyvät muuttujat
Old As Integer ' Mikä spitren vanha kuva käytössä
Mask As Integer ' Mikä Spriten Maski käytössä
ScaleX As Integer ' Spriten X-koko
ScaleY As Integer ' Spriten Y-koko
End Type
Global Sprite(0 To 5) As SpriteType
Global zz&
Function Rand(R As Integer)
Randomize Timer
Rand = Int(Rnd(1) * R)
DoEvents
End Function
Sub PalautaVanha(I As SpriteType, X As Integer)
If I.On Then
'Palautetaan
zz = BitBlt(PL!pBuffer1.hDC, I.VX, I.VY, I.ScaleX, I.ScaleY, PL!pVanha(X).hDC, 0, 0, vbSrcCopy)
End If
End Sub
Sub OtaKuvatalteen(I As SpriteType, X%)
If I.On Then
If I.VX <> -100 Then
'otetaan kuva talteen (Nappi)
zz = BitBlt(PL!pVanha(X).hDC, 0, 0, I.ScaleX, I.ScaleY, PL!pBuffer1.hDC, I.X, I.Y, vbSrcCopy)
Else
'Haetaan ensimmäinen Kuva puuhtaalta pelipöydältä
zz = BitBlt(PL!pVanha(X).hDC, 0, 0, I.ScaleX, I.ScaleY, PL!pBuffer2.hDC, I.X, I.Y, vbSrcCopy)
End If
PL!pVanha(X).Refresh
End If
End Sub
Sub PiirräSprite(I As SpriteType, X%, Y%)
Dim J%
If I.On Then
If I.VX <> -100 Then
'Piirretään
zz = BitBlt(PL!pBuffer1.hDC, I.X, I.Y, I.ScaleX, I.ScaleY, PL!pMask(Y).hDC, 0, 0, vbSrcAnd)
zz = BitBlt(PL!pBuffer1.hDC, I.X, I.Y, I.ScaleX, I.ScaleY, PL!pSprite(X).hDC, 0, 0, vbSrcInvert)
End If
I.VX = I.X: I.VY = I.Y
End If
End Sub
Function OnkoTörmäys(X1%, Y1%, X2%, Y2%, SX%, SY%) As Boolean
If X1 + SX > X2 Then
If X1 < X2 + SX Then
If Y1 + SY > Y2 Then
If Y1 < Y2 + SY Then
OnkoTörmäys = True
End If
End If
End If
End If
End FunctionFormiin
Option Explicit
Private Sub Form_Load()
Dim I%, J%, T As Boolean
For I = 0 To 5
If I < 5 Then
Sprite(I).X = Rand(pKuva.Width)
Sprite(I).Y = Rand(pKuva.Height)
End If
Do
Sprite(I).SX = (Rand(2) - 1) * Rand(3)
Sprite(I).SY = (Rand(2) - 1) * Rand(3)
Loop Until Sprite(I).SX <> 0 And Sprite(I).SY <> 0
Sprite(I).Z = 1
Sprite(I).On = True
Sprite(I).Value = I
Sprite(I).Mask = 0
Sprite(I).Old = I
Sprite(I).VX = -100
Sprite(I).ScaleX = pSprite(I).ScaleWidth
Sprite(I).ScaleY = pSprite(I).ScaleHeight
Next I
'Asetetaan olio
Sprite(5).Mask = 1
Sprite(5).SX = Rand(2) - 1
Sprite(5).SY = Rand(2) - 1
Do
Sprite(5).X = Rand(pKuva.Width)
Sprite(5).Y = Rand(pKuva.Height)
For J = 0 To 4 'Jos törmäys sijoitetaan olio uudestaan
T = OnkoTörmäys(Sprite(5).X, Sprite(5).Y, Sprite(J).X, Sprite(J).Y, Sprite(5).ScaleX, Sprite(5).ScaleY)
If T Then Exit For
Next J
Loop Until Not T
Timer1.Enabled = True
End Sub
Private Sub Form_Unload(Cancel As Integer)
End
End Sub
Private Sub Timer1_Timer()
Dim I%, J%
Timer1.Enabled = False
For I = 0 To 5 'Palautetaan kaikki vanhat
PalautaVanha Sprite(I), Sprite(I).Old
Next I
For I = 0 To 5
Sprite(I).X = Sprite(I).X + Sprite(I).SX
For J = 0 To 5
If I <> J Then
If OnkoTörmäys(Sprite(J).X, Sprite(J).Y, Sprite(I).X, Sprite(I).Y, Sprite(J).ScaleX, Sprite(J).ScaleY) Then
Sprite(I).SX = -Sprite(I).SX
Sprite(I).X = Sprite(I).X + Sprite(I).SX
End If
End If
Next J
If Sprite(I).X + Sprite(I).ScaleX > pKuva.Width Then Sprite(I).SX = -1: Sprite(I).X = Sprite(I).X - 1
If Sprite(I).X < 0 Then Sprite(I).SX = 1: Sprite(I).X = Sprite(I).X + 1
Sprite(I).Y = Sprite(I).Y + Sprite(I).SY
'Onko spritet tärmänneet toisiinsa?
For J = 0 To 5
If J <> I Then
If OnkoTörmäys(Sprite(J).X, Sprite(J).Y, Sprite(I).X, Sprite(I).Y, Sprite(J).ScaleX, Sprite(J).ScaleY) Then
Sprite(I).SY = -Sprite(I).SY
Sprite(I).Y = Sprite(I).Y + Sprite(I).SY
End If
End If
Next J
If Sprite(I).Y + Sprite(I).ScaleY > pKuva.Height Then Sprite(I).SY = -1: Sprite(I).Y = Sprite(I).Y - 1
If Sprite(I).Y < 0 Then Sprite(I).SY = 1: Sprite(I).Y = Sprite(I).Y + 1
Next I
For I = 0 To 5 'Annetaan kaikille "puhdas" kuva (Ilman toisia spritejä)
OtaKuvatalteen Sprite(I), Sprite(I).Old
Next I
For I = 0 To 5 'Piirretään kuvat
PiirräSprite Sprite(I), Sprite(I).Value, Sprite(I).Mask
Next I
zz = BitBlt(PL!pKuva.hDC, 0, 0, PL!pKuva.ScaleWidth, PL!pKuva.ScaleHeight, PL!pBuffer1.hDC, 0, 0, vbSrcCopy)
PL!pKuva.Refresh
'PL!pBuffer1.Refresh 'Ota kommentti merkki pois, niin näet Bufferin
Timer1.Enabled = True
End SubHyvin toimii :)
Ja asiahan on näin että näitä bitblt virityksiä ei ole koskaan liikaa.
Ei mutta tämähän on aivan mahtava :o
Pitää ottaa osote ylös, että voi ohjata tänne kaikki "mITEN SAA NIIN ETTÄ UKKO EI MEE SEINÄSTÄ LÄPI NIINQ TGFLLÄ!11111" -kysyjät.
tuomas kirjoitti:
Ja asiahan on näin että näitä bitblt virityksiä ei ole koskaan liikaa.
Just niin. Mahtava.
Oikein hyvältä vaikuttaa. (noita [koodivb]-tageja tosin ei tarvita koodivinkeissä, joten ne voit ottaa pois)
Blaze: Tässä on tosiaan loistavia funktioita tuon sortin kyselijöille. Toivotaan vain, että ymmärtäisivät koodistakin jotain.
bitblt toimii kyllä munkäsittääkseni niinkin, että sitä kutsuu tavallisena subina... mutta loistava esimerkki spriteistä!
lainaus:
bitblt toimii kyllä munkäsittääkseni niinkin, että sitä kutsuu tavallisena subina... mutta loistava esimerkki spriteistä!
Todellakin.
Alustus on silloin:
Public Declare Sub BitBlt Lib "gdi32" (ByVal hDestDC As Long, ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long)
Ja kutsuminen (Esim.)
BitBlt PL!pVanha(X).hDC, 0, 0, I.ScaleX, I.ScaleY, PL!pBuffer2.hDC, I.X, I.Y, vbSrcCopy
Tässä uusi esimerkki. lisäys esimerkkiin.
Ohjelma käyttää kahta puskuria, muttei varastoi spriten vanhaa grafiikkaa.
Spritejä voi olla 1- 200 kpl.
Linkki muuttettu 5.1.2006 http://koti.mbnet.fi/joresoft/Download/Esim/
Ohjelman tekniikka:
PL!pKuva - pelikentän näkyvä kuva
F1!pBuffer1 ' Piirto puskuri
F2!pBuffer2 ' Taustakuvan alkuperäinen versio.
1) Asetetaan pBuffer2 kuva pBuffer1:een.
2) Liikutetaan kaikkia Spritejä.
3) Piirretään kaikki Spritet pBuffer1:een.
4) Kopioidaan pBuffer1, pKuva:aan.
Mielen-kiinyoinen.
Aihe on jo aika vanha, joten et voi enää vastata siihen.