Sivulta kuvatun maaston generoija

Oletko tehnyt jotain, mistä muut voisivat hyötyä. Postita vinkit tänne.
Post Reply
User avatar
axu
Devoted Member
Posts: 854
Joined: Tue Sep 18, 2007 6:50 pm

Sivulta kuvatun maaston generoija

Post by axu »

Kyllähän näitä maastogeneraattoreita on ennenkin nähty, mutta mielestäni tämä on ihan julkaisemisen arvoinen suoritus jo kommentointinsa vuoksi + epätasasta mutta sulavaa maastoa. Käyttökohde on esim. sivulta kuvattu tykkipeli. Yllätys yllätys :lol:

Code: Select all

Const ScreenW = 800
Const ScreenH = 600
SCREEN ScreenW, ScreenH


Terrain = CreateTerrain(ScreenW, ScreenH)
Repeat
    Color 255, 255, 255
    If GetKey() Then DeleteImage Terrain : Terrain = CreateTerrain(ScreenW, ScreenH)
    DrawImage Terrain, 0, 0
    
    DrawScreen
Forever


    //Luo realistista 2D -maastoa. Palauttaa kuvan. Parametrit:
        //Width ja Height kertovat luotavan kuvan koon.
        //Smoothness on maaston pehmeys, ]0, 1].
        //MaxH kertoo, kuinka kaukana maa saa olla kuvan reunasta.
Function CreateTerrain(Width, Height, Smoothness# = 0.99, MaxH = 100)
    GenMem = MakeMEMBlock(Width * 4)    //Luodaan muistipala johon tallennetaan maaston korkeudet peräkkäisinä kokonaislukuina.
    
    MaxH = Height / 2 - MaxH            //Lasketaan max. Y:n vaihteluväli [-MaxH, MaxH].
    MaxV# = (MaxH / Smoothness) - MaxH  //Kun tiedetään max. vaihteluväli sekä pehmennyskerroin, lasketaan nopeuden max. vaihteluväli [-MaxV, MaxV].
    
    VelY# = Rnd(-MaxV, MaxV)            //Arvotaan lähtönopeus,
    YDisp# = Rand(-MaxH / 2, MaxH / 2)  //sekä todennäköinen lähtökorkeus (normaalijakauman mukaisesti huippujen puolivälistä).
    For i = 1 To 200                    //Lasketaan maastoa jo ennen kuvaa, jotta saataisiin mahdollisimman realistinen alku maastolle.
        VelY = Max(-MaxV, Min(MaxV, VelY + Rnd(-.1, .1)))
        YDisp = (YDisp + VelY - Average) * Smoothness + Average
        AvgSum = AvgSum + YDisp
        Count = Count + 1
    Next i
    
    For x = 1 To Width
        VelY = Max(-MaxV, Min(MaxV, VelY + Rnd(-.1, .1)))       //Muutetaan korkeuden muutosnopeutta satunnaisella kiihtyvyydellä.
        YDisp = (YDisp + VelY - Average) * Smoothness + Average //Nostetaan/lasketaan maastoa ja pakotetaan se pysymään rajoissa pehmeästi.
        
        PokeInt GenMem, (x - 1)*4, YDisp                        //Tallennetaan korkeus.
        
        AvgSum = AvgSum + YDisp                                 //Lasketaan korkeuden keskiarvo,
        Count = Count + 1                                       //jonka avulla estetään tasaista
        Average = Max(-MaxH, Min(MaxH, Float(AvgSum) / Count))  //maastoa.
    Next x
    
    GenImg = MakeImage(Width, Height)   //Luodaan kuva
    DrawToImage GenImg                  //Nyt maalataan :)
        For x = 1 To Width              //Haetaan korkeudet muistipalasta ja piirretään viiva kerrallaan.
            Line x, Height, x, Height / 2 + PeekInt(GenMem, (x - 1)*4) - Average
        Next x
        Text 1, 1, Average
    DrawToScreen
    
    DeleteMEMBlock GenMem
    Return GenImg
EndFunction
Alunperin käytin tässä viittä siniaaltoa, jotka summataan, ja jottei tulisi niin tasaista ja säännönmukaista jälkeä, tein tämän systeemin(perusperiaatteeltaan sama menetelmä) aiheuttamaan pinnan epätasaisuutta. Sitten huomasinkin, että jos tähän käyttää suurempia arvoja niin tämä riittää itsessään generoimaan oikein mallikasta maastoa. Lisää kumpuja ja vuoria kyllä kaipaisin, että tämä tykkipeliin kelpaisikin... HUOM tämä ei sitten mitenkään ole graafisesti uljas ilmestys(itse tykkipeliin, jota olen tekemässä ajattelin teksturoida tuon sitten kunnolla, mutta se jääköön esimerkistä pois)!
EDIT:

Päätin sittenkin laittaa ne sinit sinne takaisin :D
Maasto ei ehkä ole yhtä realistista, mutta tykkipeliin kuuluvat montut ovat paikallaan ;)

Code: Select all

Const ScreenW = 800
Const ScreenH = 600
SCREEN ScreenW, ScreenH

Const SineCount = 5
Dim Sine_Amp(SineCount), Sine_Disp(SineCount), Sine_Speed#(SineCount)

Terrain = CreateTerrain(ScreenW, ScreenH)
Repeat
    Color 255, 255, 255
    If GetKey() Then DeleteImage Terrain : Terrain = CreateTerrain(ScreenW, ScreenH)
    DrawImage Terrain, 0, 0
    
    DrawScreen
Forever


    //Luo kumpuilevan realistista 2D -maastoa. Palauttaa kuvan. Parametrit:
        //Width ja Height kertovat luotavan kuvan koon.
        //Smoothness on maaston pehmeys, ]0, 1].
        //MaxH kertoo, kuinka kaukana maa saa olla kuvan reunasta.
        //MaxSine määrää siniaaltojen maksimiosuuden maastosta - siniaaltojen maksimisumma.
Function CreateTerrain(Width, Height, Smoothness# = 0.98, MaxH = 70, MaxSine = 100)
    GenImg = MakeImage(Width, Height)   //Luodaan kuva
    
    MaxH = Height / 2 - (MaxH + MaxSine)//Lasketaan max. Y:n vaihteluväli [-MaxH, MaxH] ottaen myös huomioon siniaallot.
    MaxV# = (MaxH / Smoothness) - MaxH  //Kun tiedetään max. vaihteluväli sekä pehmennyskerroin, lasketaan nopeuden max. vaihteluväli [-MaxV, MaxV].
    
    If MaxSine Then
        For i = 0 To SineCount
            Sine_Amp(i) = Rand(MaxSine / 2)
            MaxSine = MaxSine - Sine_Amp(i)
            Sine_Disp(i) = Rand(360)
            Sine_Speed(i) = Rnd(.1, 1)
        Next i
    End If
    VelY# = Rnd(-MaxV, MaxV)            //Arvotaan lähtönopeus,
    YDisp# = Rand(-MaxH / 2, MaxH / 2)  //sekä todennäköinen lähtökorkeus (normaalijakauman mukaisesti huippujen puolivälistä).
    For i = 1 To 300                    //Lasketaan maastoa jo ennen kuvaa, jotta saataisiin mahdollisimman realistinen alku maastolle.
        VelY = Max(-MaxV, Min(MaxV, VelY + Rnd(-.1, .1)))
        YDisp = (YDisp + VelY) * Smoothness
    Next i
        
    DrawToImage GenImg                  //Nyt maalataan :)
        For x = 1 To Width
            VelY = Max(-MaxV, Min(MaxV, VelY + Rnd(-.1, .1)))   //Muutetaan korkeuden muutosnopeutta satunnaisella kiihtyvyydellä.
            YDisp = (YDisp + VelY) * Smoothness                 //Nostetaan/lasketaan maastoa ja pakotetaan se pysymään rajoissa pehmeästi.
            
            y# = Height / 2 + YDisp
            For i = 0 To SineCount
                y = y + Sin(x * Sine_Speed(i) + Sine_Disp(i)) * Sine_Amp(i)
            Next i
            
            Line x, Height, x, y        //Piirretään viiva tämänhetkisestä korkeudesta maahan.
        Next x
    DrawToScreen
    
    Return GenImg
EndFunction
[/edit]
Jos tämä viesti on kirjoitettu alle 5 min. sitten, päivitä sivu. Se on saattanut jo muuttua :roll:
Image
Sly_Jack0
Devoted Member
Posts: 612
Joined: Mon Dec 10, 2007 8:25 am

Re: Sivulta kuvatun maaston generoija

Post by Sly_Jack0 »

Ihan hyvännäköistä maastoahan nuo tekevät. =) Mainostampa tässä nyt samalla omaa versiotani (joka kyllä on suurimmaksi osaksi otettu jostain ihan muusta tutoriaalista). Kyseinen generaattori käyttää kolmea päällekäistä siniaaltoa ja löytyy täältä.
Post Reply