Kirjautuminen

Haku

Tehtävät

Oppaat: Grafiikka: Metapallot

Kirjoittaja: peki. Vuosi: 2004.

Metapallot on eräs demoefekti. Se oli hyvin yleinen ja suosittu muutama vuosi takaperin. Nyttemmin se on mennyt pois muodista. Mielestäni se on yksi parhaimmista ja kauneimmista efekteistä, joka on koodattu. Tässä oppaassa käsittelen metapallojen tekoa pseudokielellä. Lopussa on myös linkki julkaisemaani VB.NET-koodivinkkiin.

Tämän yritämme saada aikaan (näyttää toiminnassa paljon paremmalta kuin kuvassa).

Matematiikka

Matemaattisesti metapallot on aika simppeli efekti. Temppu on siinä, että saa reaaliajassa näkyviin monta metapalloa ilman ruudunpäivityksen takkuilua.

Metapallot perustuvat fysiikasta tuttuun sähkökentän voimakkuusfunktioon Y = 1 / X2. Kuvitellaanpa tämä funktio piirrettynä koordinaatistoon:

Käyrä siis alkaa y = 1 / 0 -pisteestä (eli sähkökentän voimakkuus on ääretön), josta se laskee nopeasti lähelle nollaa. Tämän jälkeen käyrä lähenee hitaasti x-akselia kuitenkaan sitä koskaan koskettamatta. Juuri tällaista väriliukuahan me haemme!

Toteutus

Nyt, kun meillä on sopiva käyrä, voimme alkaa miettiä, kuinka metapallot toteuttaisimme.

Ajatellaanpa, että meillä on kaksiulotteinen taulukko. Se sisältää liukulukuarvoja yhtä monelle pikselille, kuin ruudulla niitä on. Käykäämme läpi kaikki pallot silmukassa. Silmukan sisälle tehdään kaksi lisäsilmukkaa, jotta voitaisiin kelata läpi kaikki pikselit.

Pseudokoodina näin:

for i = 0; i < palloja; i++;
  for x = 0; x < naytonleveys; x++;
    for y = 0; y < naytonkorkeus; y++;

Lisäämme aina taulukkoon arvon, joka lasketaan kaavasta Y = 1 / X2. Kaava on kuitenkin ennen tätä muutettava toiseen muotoon, koska tämä kaava laskee liukuvärin käyrälle koko näytön leveydeltä. Eli se siis vain visualisoi käyrän annettuun piirtopintaan, vaikka haluamme piirtää rajallisen kokoisen pallon. Meidän on siis muutettava käyrää siten, että kaavasta saatu luku on valmiiksi transformoitu maailmakoordinaatistoon.

Kaava muuntuu tähän muotoon: Rpallo / [(Xpallo - Xpikseli)2 + (Ypallo - Ypikseli)2]

Pseudokoodina:

for i = 0; i < palloja; i++;
  for x = 0; x < naytonleveys; x++;
    for y = 0; y < naytonkorkeus; y++;
      p[x,y] += pallot[i].R / ((pallot[i].X - x) ^ 2 + (pallot[i].Y - y) ^ 2)

Nyt meillä on taulukko, joka sisältää "raakalasketun" kirkkauden jokaiselle pikselille.

Piirtäminen

Koska taulukkomme sisältää myös äärettömän suuria arvoja, täytyy meidän rajoittaa niitä. Esimerkiksi jos arvo on suurempi, kuin 1, arvo on 1. Jotta efekti saataisiin kauniiksi, on myös alinta mahdollista kirkkautta syytä rajoittaa. Tämä on tietenkin oman maun mukaista, mutta itse käytän arvoa 0.1 ja 0.2 väliltä. Eli jos arvo on vaikkapa pienempi kuin 0.15, arvo on 0.

Itse piirtäminen sujuu niin, että näytön jokaisen pikselin väri asetetaan vastaamaan taulukon nykyistä kirkkautta. Pseudokoodina:

for i = 0; i < palloja; i++;
  for x = 0; x < naytonleveys; x++;
    for y = 0; y < naytonkorkeus; y++;
      p[x,y] += pallot[i].R / ((pallot[i].X - x) ^2 + (pallot[i].Y - y) ^2)

      if i = palloja - 1 then
        if p[x,y] > 1 then p[x,y] = 1
        if p[x,y] < 0.15 then p[x,y] = 0

        naytto[x, y] = RGB(0, 0, p[x,y] * 255)
      end if
    next
  next
next

Kuva tietenkin voidaan piirtää vasta, kun taulukkoon on viimeisenkin pallon arvot lisätty. Pallojen liikuttaminen täytyy hoitaa erillisessä silmukassa tai viimeisen siirrettävää palloa koskevan pikselin taulukkoon tallentamisen jälkeen.

Toinen mahdollinen piirtotapa on koostaa viiva, joka kiertää metapallon, ja täyttää tämä alue jollain värillä. Itse pidän kuitenkin tätä osoittamaani tapaa hienompana.

Valmiin VB.NET-version löytää Putkasta täältä. Siitä voi myös katsoa optimointivinkkejä.

Loppusanat

Tällä samalla tekniikalla voi visualisoida minkä tahansa kaavan, joten käykääpä kokeilemaan. Google kyllä auttaa.

-- Google will be with you. Always. --

Pekka Järvinen, 15.4.2004

Kommentit

peki [27.04.2004 20:17:08]

Lainaa #

Soodan tekemä käännös VB6:een löytyy nyt täältä:
http://www.ohjelmointiputka.net/koodivinkit/24317-vb6-net-metapallot-vb6-lle

hunajavohveli [21.05.2004 15:10:49]

Lainaa #

Hieno opas. Minäkin tajusin, ja ohjelmoin QB:lle metapallot, vaikka en lukenut kuin vähän oppaan alkua.

Tumpi [13.12.2004 23:41:37]

Lainaa #

Kiva, tein PHP:lle.

moptim [27.08.2006 07:44:28]

Lainaa #

peki kirjoitti:

Soodan tekemä käännös VB6:een löytyy nyt täältä:

Se käyttäjänimi ei ole "Sooda" vaan "sooda".

BlueByte [22.10.2006 07:37:46]

Lainaa #

Tämän oppaan nimi pitäisi olla metaympyrät, koska nuo eivät ole palloja vaan ympyröitä.

moptim [08.12.2006 21:04:46]

Lainaa #

Tuo on muuten aivan totta :P

miiro [06.08.2007 19:13:48]

Lainaa #

moptim kirjoitti:

peki kirjoitti:

Soodan tekemä käännös VB6:een löytyy nyt täältä:

Se käyttäjänimi ei ole "Sooda" vaan "sooda".

Lauseen ensimmäinen sana kirjoitetaan isolla alkukirjaimella.
[/offtopic "toivon että kummatkin kommentit poistetaan, kiitos"]

Kirjoita kommentti

Huomio! Kommentoi tässä ainoastaan tämän oppaan hyviä ja huonoja puolia. Älä kirjoita muita kysymyksiä tähän. Jos koodisi ei toimi tai tarvitset muuten vain apua ohjelmoinnissa, lähetä viesti keskusteluun.

Muista lukea keskustelun ohjeet.
Tietoa sivustosta