Kirjautuminen

Haku

Tehtävät

Keskustelu: Koodit: VB6: Lentävät Neliöt

Oltzi [09.09.2005 00:06:42]

#

Lähes valmis näytönsäästäjä, piirtää kaikessa yksinkertaisuudessaan Windowsin GDI-funktioita käyttäen erilaisia neliöitä ruudulle. Neliöiden määrän ja koon saa muutettua koodista. Piirtää Athlon 1800+:lla sujuvasti noin 2000 neliötä.
Lähdekoodi zipissä: http://koti.mbnet.fi/oltzi/neliot/neliot.zip
Suora .exe: http://koti.mbnet.fi/oltzi/neliot/neliot.exe

Form1.frm

' LENTÄVÄT NELIÖT
' Author: Olli Moisio (oltzi@mbnet.fi)

Option Explicit

Private Declare Function GetTickCount Lib "kernel32" () As Long
Private Declare Function SetCursorPos Lib "user32" (ByVal x As Long, ByVal y As Long) As Long

' *********** KONFFAUS ***********
Private Const NELIOMAARA As Integer = 20
'Kuinka monta neliötä piirretään. Pyörii AMD Athlon XP 1800+:llä sujuvasti noin 2000 neliöön asti,
'kun MINIMISIVUKOKO=0.05 ja MAKSIMISIVUKOKO=0.1
Private Const MINIMISIVUKOKO As Double = 0.1 'Minimikoko neliön sivulle, 0.1 = 10% ruudusta
Private Const MAKSIMISIVUKOKO As Double = 0.3 'Maksimikoko neliön sivulle, 0.3 = 10% ruudusta
Private Const MAKSIMIVAUHTI As Integer = 10 'Maksiminopeus pikseleinä yhden loopin aikana
Private Const PAIVITYSVALI As Integer = 20 'ms: 1000/20 = 50 fps
' ********** /KONFFAUS ***********

Private MAKSIMIXKOKO As Integer
Private MINIMIXKOKO As Integer
Private MAKSIMIYKOKO As Integer
Private MINIMIYKOKO As Integer

'Neliötyyppi
Private Type Nelio
    X1 As Integer 'Neliön vasemman yläkulman x-koordinaatti
    Y1 As Integer 'Neliön vasemman yläkulman y-koordinaatti
    leveys As Integer
    korkeus As Integer
    vari As Long
    xsuunta As Integer 'X-tason suunta: -1 = vasemmalle, 1 = oikealle
    ysuunta As Integer 'Y-tason suunta: -1 = ylöspäin, 1 = alaspäin
End Type

Private Neliot(NELIOMAARA - 1) As Nelio
Private Lopeta As Boolean 'Kun Lopeta = true, ohjelma päättyy

Private HIIRIX As Integer 'hiiren x-koordinaatti
Private HIIRIY As Integer 'hiiren y-koordinaatti

Private Sub Form_Click()
    Lopeta = True 'Klikkaus lopettaa ohjelman
End Sub

Private Sub Form_KeyPress(KeyAscii As Integer)
    Lopeta = True 'Mikä tahansa näppäin lopettaa ohjelman
End Sub

Private Sub Form_Load()
    Form1.BackColor = vbBlack
    Form1.AutoRedraw = True
    Form1.WindowState = 2
    Form1.ScaleMode = 3 'pikseleinä

    Form1.Show
    HIIRIX = 0
    HIIRIY = 0
    Lopeta = False

    Call SetCursorPos(Form1.ScaleWidth, Form1.ScaleHeight)
    ' Siirretään hiiri oikeaan alanurkkaan pois tieltä
    Alustus
    PaaLooppi
End Sub

Private Sub Form_MouseMove(Button As Integer, Shift As Integer, x As Single, y As Single)
'Asettaa Lopeta-muuttujan arvoksi tosi, mikäli hiirtä liikutetaan
    If ((HIIRIX = 0) And (HIIRIY = 0)) Then
        HIIRIX = x
        HIIRIY = y
    Else
        If ((Abs(HIIRIX - x) > 20) Or (Abs(HIIRIY - y) > 20)) Then Lopeta = True
        'Jos hiiri liikkuu yli 20 pikseliä, lopetetaan
    End If
End Sub

Private Sub Form_Resize()
'Päivitetään muuttujat kun ikkunan kokoa muutetaan

    MAKSIMIXKOKO = Form1.ScaleWidth * MAKSIMISIVUKOKO
    MINIMIXKOKO = Form1.ScaleWidth * MINIMISIVUKOKO

    MAKSIMIYKOKO = Form1.ScaleHeight * MAKSIMISIVUKOKO
    MINIMIYKOKO = Form1.ScaleHeight * MINIMISIVUKOKO
    Alustus (True) 'Päivitetään neliöille uudet mitat, ei kosketa muihin arvoihin
End Sub

Private Sub Alustus(Optional OnlyResize As Boolean = False)
'Alustaa Neliöiden arvot, mikäli OnlyResize=true, muutetaan vain mitat
'Neliön nopeus on suoraan verrannollinen sen kokoon. Mitä isompi neliö,
'sitä hitaampi ja toisinpäin.

    Dim i As Integer
    Randomize
    For i = 0 To NELIOMAARA - 1
        Neliot(i).leveys = (Rnd * (MAKSIMIXKOKO - MINIMIXKOKO)) + MINIMIXKOKO
        Neliot(i).korkeus = (Rnd * (MAKSIMIYKOKO - MINIMIYKOKO)) + MINIMIYKOKO
        'Annetaan neliöille satunnaiset mitat MAKSIMIXKOKO ja MAKSIMIYKOKO muuttujien mukaan
        Neliot(i).X1 = (Rnd * (Form1.ScaleWidth - Neliot(i).leveys - 10))
        Neliot(i).Y1 = (Rnd * (Form1.ScaleHeight - Neliot(i).korkeus - 10))
        'Arvotaan Neliölle sattumanvaraiset paikat, vähintään 10 pikselin päähän reunasta
        If (OnlyResize = False) Then
            'Arvotaan myös väri ja neliön suunta
            Neliot(i).vari = RGB(Int(Rnd * 255), Int(Rnd * 255), Int(Rnd * 255))
            Neliot(i).xsuunta = YksiTaiMiinusYksi
            Neliot(i).ysuunta = YksiTaiMiinusYksi
        End If
    Next i
End Sub

Private Sub Piirra()
'Piirrä-aliohjelma, kutsutaan PiirraNelio-aliohjelmaa jokaisen neliön kohdalla
    Dim i As Integer
    Me.Cls 'putsataan ruutu
    For i = 0 To NELIOMAARA - 1
        Call PiirraNelio(Neliot(i).X1, Neliot(i).Y1, _
            Neliot(i).X1 + Neliot(i).leveys, Neliot(i).Y1 + Neliot(i).korkeus, Neliot(i).vari)
    Next i
    Me.Refresh 'kaikki piirretty, päivitetään ruutu
End Sub

Private Sub Liikuta()
'Liikuta-aliohjelma, tarkistetaan osuuko neliö seinään, jos osuu vaihdetaan suuntaa.
'Varmasti löytyy helpompikin tapa toteuttaa. :)

    Dim i As Integer, suhde As Double
    For i = 0 To NELIOMAARA - 1
        suhde = 1 - (Neliot(i).leveys / MAKSIMIXKOKO) * (Neliot(i).korkeus / MAKSIMIYKOKO)
        If (Neliot(i).xsuunta = 1) Then 'Ollaanko menossa oikealle
            If ((Neliot(i).X1 + Neliot(i).leveys) >= Form1.ScaleWidth) Then
            'Onko neliön oikeanpuoleinen sivu kiinni ruudun oikeassa reunassa, tai sen yli
                Neliot(i).xsuunta = -1 'Vaihdetaan x-suunta
                Neliot(i).X1 = Form1.ScaleWidth - Neliot(i).leveys - 1
                'Siirretään neliö kiinni ruudun oikeaan laitaan
            End If
        Else 'Ollaan menossa vasemmalle
            If ((Neliot(i).X1 <= 0)) Then 'Ollaanko vasemmassa laidassa, tai sen yli
                Neliot(i).xsuunta = 1 'Vaihdetaan x-suunta
                Neliot(i).X1 = 1 'Laitetaan neliö kiinni ruudun vasempaan laitaan
            End If
        End If

        If (Neliot(i).ysuunta = 1) Then 'Mennäänkö alaspäin
            If ((Neliot(i).Y1 + Neliot(i).korkeus) >= Form1.ScaleHeight) Then
            'Ollaanko alalaidassa kiinni, tai sen yli
                Neliot(i).ysuunta = -1 'Käännetään y-suunta
                Neliot(i).Y1 = Form1.ScaleHeight - Neliot(i).korkeus - 1
                'Laitetaan kiinni alalaitaan
            End If
        Else 'Ollaan menossa ylöspäin
            If ((Neliot(i).Y1 <= 0)) Then 'Ollaanko ylälaidassa, tai sen yli
                Neliot(i).ysuunta = 1 'Suunnaksi alaspäin
                Neliot(i).Y1 = 1 'Siirretään ruudun ylälaitaan
            End If
        End If

        Neliot(i).X1 = Neliot(i).X1 + (Neliot(i).xsuunta * suhde * MAKSIMIVAUHTI)
        Neliot(i).Y1 = Neliot(i).Y1 + (Neliot(i).ysuunta * suhde * MAKSIMIVAUHTI)
        'Ja lopuksi siirretään neliöitä eteenpäin:
        '   X-suunnan ja Y-Suunnan etumerkeistä on kiinni tuleeko muutoksesta miinus- vai pluspuolinen
        'Suhde-muuttuja kertoo kuinka iso neliö on verrattuna maksimikokoon:
        '   1.0 = Koko pienin mahdollinen, siis suurin mahdollinen vauhti
        '   0.0 = Koko suurin mahdollinen, täysin pysähtynyt
        '   jne..
    Next i
End Sub

Private Sub PaaLooppi()
'Päälooppi, pyöritetään Do While -looppia PAIVITYSVALI-muuttujan mukaisessa tahdissa,
'niin kauan kun Lopeta = false
    Dim timer As Long

    timer = GetTickCount()
    Do While (Lopeta = False)
        If PAIVITYSVALI < (GetTickCount() - timer) Then
        'Onko PAIVITYSVALI:n mukainen aika mennyt
            timer = GetTickCount() 'päivitetään timer
            Liikuta
            Piirra
        End If
        DoEvents
    Loop
End
End Sub

Module1.bas

Private Declare Function FillRect Lib "user32" (ByVal hdc As Long, lpRect As RECT, ByVal hBrush As Long) As Long
Private Declare Function SetRect Lib "user32" (lpRect As RECT, ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long) As Long
Private Declare Function CreatePen Lib "gdi32" (ByVal nPenStyle As Long, ByVal nWidth As Long, ByVal crColor As Long) As Long
Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
Private Declare Function Rectangle Lib "gdi32" (ByVal hdc As Long, ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long) As Long

'Fillrectin vaatima formaatti, sisältää neliön koordinaatit
Private Type RECT
    Left As Long
    Top As Long
    Right As Long
    Bottom As Long
End Type

Public Sub PiirraNelio(X1 As Integer, Y1 As Integer, X2 As Integer, Y2 As Integer, color As Long)
'Piirtää neliön formiin

    Dim R As RECT, brush As Long
    brush = CreatePen(0, 5, color)
    'Luodaan pensseli: 0 = kiinteä pensseli, 5 = pensselin leveys
    SetRect R, X1, Y1, X2, Y2
    'Laitetaan piirrettävän neliön koordinaatit R-muuttujaan
    FillRect Form1.hdc, R, brush
    'Piirretään R:n määrittelemä neliö Form1:lle käyttäen aiemmin määriteltyä pensseliä
    Rectangle Form1.hdc, X1, Y1, X2, Y2
    'Piirretään neliölle reunat
    DeleteObject brush
    'Vapautetaan muistia poistamalla pensseli käytöstä
End Sub

Public Function YksiTaiMiinusYksi() As Integer
'Palauttaa sattumanvaraisesti joko 1 tai -1. Ei mikään elegantein toteutus :D
'Käytetään antamaan neliöille satunnaiset suunnat: 1 = mennään oikealle, -1 = vasemmalle
'Vastaavasti: 1 = mennään alaspäin, -1 = mennään ylöspäin

    Dim i As Integer
    Randomize
        i = (Rnd * 9) + 1
    If (i <= 5) Then
        YksiTaiMiinusYksi = -1
    Else
        YksiTaiMiinusYksi = 1
    End If
End Function

T.M. [26.09.2005 20:19:58]

#

Mustia neliöitä mustalla pohjalla... tai sitten tuo exe ei toimi koneellani oikein :P

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta