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.