2D "Asteroidi" moottori, asteroideja primitiivi peleihin!

Oletko tehnyt jotain, mistä muut voisivat hyötyä. Postita vinkit tänne.
Post Reply
User avatar
MaGetzUb
Guru
Posts: 1715
Joined: Sun Sep 09, 2007 12:35 pm
Location: Alavus

2D "Asteroidi" moottori, asteroideja primitiivi peleihin!

Post by MaGetzUb » Tue Jun 07, 2011 3:21 am

Tjoo, taas pukkaa uutta koodia minulta. :) Tein tämmöisen moottorin, joka generoi asteroidin (joka sitten voidaan piirtää kahvansa avulla vain ääriviivoja myöden haluttuihin koordinaatteihin).. ;)

Asteroidin luonti funktio:
Asteroid(points, minrad, rad) ~ Ekalla parametrillä määritetään asteroidin ääriviivojen nivelten määrä, ja minrad sekä rad parametreillä määritetään asteroidin minimi sekä maksimi säde. =) Maksimi sädettä ei ole pakko laittaa.
AsteroidRad(handle) ~ Kun laitat haluamasi asteroidin kahvan funktioon, funktio palauttaa asteroidin säteen.

Asteroidin piirto:
DrawAsteroid(handle, dx, dy, ang, scale) ~ Ekalle parametrille annetaan piirrettävän asteroidin kahva, sitten kahdelle seuraavalle parametrille annetaan piirto koordinaatit, niitä seuraavalle arvolle annetaan piirtokulma (ei pakollinen, mutta jos haluat pyörittää asteroidia akselinsa ympräri eri kulmiin, niin sitten voit antaa sille arvon), kulma-arvon jälkeen voit antaa vielä suurennus kerroinluvun. =)

Huom. Jos et tiedä mitä primitiivit on niin selitetäänpä: primitiivit on "alkukantaista" grafiikkaa kuten: Line, Box, Circle, Ellipse, Dot

Funktiot olkaapa hyvä:

Code: Select all

Function Asteroid(points, minrad, rad = 0)

    //Jos ei ole rad arvolle annettu muuttujaa, minradille annettu arvo muutetaan rad arvoksi, jos vähääkään 
    //ymmärtää kooodiani sen tajuaa tuola alempana. :)
    
    If rad = 0 Then rad = minrad : minrad = 0
    
    //Luodaan muistipala
    astr = MakeMEMBlock((points+1)*8+4)
    PokeInt astr, (points+1)*8, rad
    
    //Luodaan annettujen pisteiden kohdille "nivelet"
    For i = 0 To points
    
        //Haetaan kulmat kaikille nivelille, ja vähän värisytetään niitä
        ang# = (360 / points) * i + Rnd((360/points)*0.1)
        
        //Satunnaistetaan nivelen etäisyys origosta
        drad = minrad + Rnd(0, 1) * (rad - minrad)
        
        //Lasketaan nivelen x, ja y koordinaatit ylhäällä luotujen muuttujen mukaan
        pointx# = Cos(ang#) * drad
        pointy# = Sin(ang#) * drad
        
        //Kirjoitetaan muistipalaan
        PokeFloat astr, i*8, pointx#
        PokeFloat astr, i*8+4, pointy#
        
    Next i
    
    //Ja palautetaan muistipalan kahva
    Return astr
    
End Function 

Function AsteroidRad(handle)
    Return PeekInt(handle, MEMBlockSize(handle)-4)
EndFunction 

Function DrawAsteroid(handle, dx, dy, angle# = 0, scale# = 1.0)

    size = (MEMBlockSize(handle)-4) / 8
    For i = 0 To size-1
        
        //Haetaan "nykyisen" nivelen koordinaatit.. *
        x# = PeekFloat(handle, i*8)
        y# = PeekFloat(handle, i*8+4)
        
        //Pyöritetään koordinaatit akselinsa ympäri *
        roX# = Cos(angle#) * x + Sin(angle#) * y
        roy# = Cos(angle#) * y - Sin(angle#) * x
        
        //Piirretään viivat ja haetaan aijemman pisteen koordinaatit
        If i > 0 Then 
            
            //Sama homma kuin tuola ylhäällä tähdellä (*) merkatut kohdat
            bx# = PeekFloat(handle, (i-1)*8)
            by# = PeekFloat(handle, (i-1)*8+4)
            
            broX# = Cos(angle#) * bx + Sin(angle#) * by
            broy# = Cos(angle#) * by - Sin(angle#) * bx  
            
            //Piirretään viiva aijemman ja nykyisen pisteen välille
            Line dx+broX*scale#, dy+broy*scale#, dx+rox*scale#, dy+roy*scale#
            
            If i = (size-1) Then //Tässä kohtaa silmukassa vedetään viimmeisestä pisteestä viiva ekaan pisteeseen :)
                
                //Ja taas sama homma kuin tuola ylhäällä tähdellä (*) merkatut kohdat
                fx# = PeekFloat(handle, 0)
                fy# = PeekFloat(handle, 4)
                
                froX# = Cos(angle#) * fx + Sin(angle#) * fy
                froy# = Cos(angle#) * fy - Sin(angle#) * fx    
                
                //Piirretään se vika viiva 
                Line dx+rox*scale#, dy+roy*scale#, dx + frox*scale#, dy + froy*scale#
            EndIf 
        EndIf 
        
    Next i

End Function

Esimerkki + Funktiot olkaapa hyvä:

Code: Select all

//Luodaan kaksi eri asteroidia...
asteroidi = Asteroid(12, 60)
asteroidi2 = Asteroid(18, 80, 140)

Repeat 
    
    //Uusitaan asteroidit
    If KeyHit(28) Then 
        //Tuhotaan muistipalat
        DeleteMEMBlock asteroidi
        DeleteMEMBlock asteroidi2
        //Luodaan uudet :)
        asteroidi = Asteroid(12, 60)
        asteroidi2 = Asteroid(18, 80, 140)
        //Uusimis arvo on nyt tosi
        astrd = True 
    Else 
        //Uusimisarvo on nyt epätosi
        astrd = False 
    EndIf 
    
    //Väännetään kulmaa
    ang = ang + 1
    
    //Venytetään asteroidia :)
    scale# = Sin(ang*2) * 0.5
    //Piirretään kaksi eri asteroidia vain jos niitä ei ole uusittu
    If Not astrd Then DrawAsteroid(asteroidi, 200, 150, ang)
    If Not astrd Then DrawAsteroid(asteroidi2, 200, 150, ang, 1+scale#) //Alempi skaalataan ;)
    
    DrawScreen
Forever 




Function Asteroid(points, minrad, rad = 0)

    //Jos ei ole rad arvolle annettu muuttujaa, minradille annettu arvo muutetaan rad arvoksi, jos vähääkään 
    //ymmärtää kooodiani sen tajuaa tuola alempana. :)
    
    If rad = 0 Then rad = minrad : minrad = 0
    
    //Luodaan muistipala
    astr = MakeMEMBlock((points+1)*8+4)
    PokeInt astr, (points+1)*8, rad
    
    //Luodaan annettujen pisteiden kohdille "nivelet"
    For i = 0 To points
    
        //Haetaan kulmat kaikille nivelille, ja vähän värisytetään niitä
        ang# = (360 / points) * i + Rnd((360/points)*0.1)
        
        //Satunnaistetaan nivelen etäisyys origosta
        drad = minrad + Rnd(0, 1) * (rad - minrad)
        
        //Lasketaan nivelen x, ja y koordinaatit ylhäällä luotujen muuttujen mukaan
        pointx# = Cos(ang#) * drad
        pointy# = Sin(ang#) * drad
        
        //Kirjoitetaan muistipalaan
        PokeFloat astr, i*8, pointx#
        PokeFloat astr, i*8+4, pointy#
        
    Next i
    
    //Ja palautetaan muistipalan kahva
    Return astr
    
End Function 

Function AsteroidRad(handle)
    Return PeekInt(handle, MEMBlockSize(handle)-4)
EndFunction 

Function DrawAsteroid(handle, dx, dy, angle# = 0, scale# = 1.0)

    size = (MEMBlockSize(handle)-4) / 8
    For i = 0 To size-1
        
        //Haetaan "nykyisen" nivelen koordinaatit.. *
        x# = PeekFloat(handle, i*8)
        y# = PeekFloat(handle, i*8+4)
        
        //Pyöritetään koordinaatit akselinsa ympäri *
        roX# = Cos(angle#) * x + Sin(angle#) * y
        roy# = Cos(angle#) * y - Sin(angle#) * x
        
        //Piirretään viivat ja haetaan aijemman pisteen koordinaatit
        If i > 0 Then 
            
            //Sama homma kuin tuola ylhäällä tähdellä (*) merkatut kohdat
            bx# = PeekFloat(handle, (i-1)*8)
            by# = PeekFloat(handle, (i-1)*8+4)
            
            broX# = Cos(angle#) * bx + Sin(angle#) * by
            broy# = Cos(angle#) * by - Sin(angle#) * bx  
            
            //Piirretään viiva aijemman ja nykyisen pisteen välille
            Line dx+broX*scale#, dy+broy*scale#, dx+rox*scale#, dy+roy*scale#
            
            If i = (size-1) Then //Tässä kohtaa silmukassa vedetään viimmeisestä pisteestä viiva ekaan pisteeseen :)
                
                //Ja taas sama homma kuin tuola ylhäällä tähdellä (*) merkatut kohdat
                fx# = PeekFloat(handle, 0)
                fy# = PeekFloat(handle, 4)
                
                froX# = Cos(angle#) * fx + Sin(angle#) * fy
                froy# = Cos(angle#) * fy - Sin(angle#) * fx    
                
                //Piirretään se vika viiva 
                Line dx+rox*scale#, dy+roy*scale#, dx + frox*scale#, dy + froy*scale#
            EndIf 
        EndIf 
        
    Next i

End Function
Offtopic: Huh onpas kellokin jo paljon (03:20am), kirjoitus virheitä voi olla mutta koodin toimivuus on taattu. :)
EDIT:

Esimerkki 2 (+Funktiot):

Code: Select all

Const SW = 800
Const SH = 600

Const PosX = 0
Const PosY = 1
Const Angle = 2
Const VelX = 3
Const VelY = 4
Const AnglePlus = 5
Const Aster = 6

SCREEN SW, SH 

Dim Asteroids(10, 6) As Float 

For i = 0 To 10
    Asteroids(i, PosX) = Rand(ScreenWidth())
    Asteroids(i, PosY) = Rand(ScreenHeight())
    Asteroids(i, Angle) = 0
    Asteroids(i, VelX) = Rnd(0.25, 1) * 4
    Asteroids(i, VelY) = Rnd(0.25, 1) * 4
    Asteroids(i, AnglePlus) = Rnd(0.25, 1) * 8
    Asteroids(i, Aster) = Asteroid(Rand(5, 30), 15, 40)
Next i



Repeat 

    For i = 0 To 10
    
        Asteroids(i, PosX) = Asteroids(i, PosX) + Asteroids(i, VelX)
        Asteroids(i, PosY) = Asteroids(i, PosY) + Asteroids(i, VelY)
        
        Asteroids(i, Angle) = Asteroids(i, Angle) + Asteroids(i, AnglePlus)
        

        DrawAsteroid(Asteroids(i, Aster), Asteroids(i, PosX), Asteroids(i, PosY), Asteroids(i, Angle))
        
        For b = 0 To 10
            If i <> b Then 
                If Distance(Asteroids(i, PosX), Asteroids(i, PosY), Asteroids(b, PosX), Asteroids(b, PosY)) < AsteroidRad(Asteroids(i, Aster)) + AsteroidRad(Asteroids(i, Aster)) Then 
                    ivx = Asteroids(i, VelX)
                    ivy = Asteroids(i, VelY)
                    Asteroids(i, VelX) = Asteroids(b, VelX)
                    Asteroids(i, VelY) = Asteroids(b, VelY)
                    Asteroids(b, VelX) = ivx
                    Asteroids(b, VelY) = ivy
                EndIf 
             EndIf 
        Next b
        
        If Asteroids(i, PosX) < 0 Or Asteroids(i, PosX) > SW Then Asteroids(i, VelX) = - Asteroids(i, VelX) : Asteroids(i, AnglePlus) = - Asteroids(i, AnglePlus)
        If Asteroids(i, PosY) < 0 Or Asteroids(i, PosY) > SH Then Asteroids(i, VelY) = - Asteroids(i, VelY) : Asteroids(i, AnglePlus) = - Asteroids(i, AnglePlus)

    Next i


    DrawScreen
Forever 




Function Asteroid(points, minrad, rad = 0)

    //Jos ei ole rad arvolle annettu muuttujaa, minradille annettu arvo muutetaan rad arvoksi, jos vähääkään 
    //ymmärtää kooodiani sen tajuaa tuola alempana. :)
    
    If rad = 0 Then rad = minrad : minrad = 0
    
    //Luodaan muistipala
    astr = MakeMEMBlock((points+1)*8+4)
    PokeInt astr, (points+1)*8, rad
    
    //Luodaan annettujen pisteiden kohdille "nivelet"
    For i = 0 To points
    
        //Haetaan kulmat kaikille nivelille, ja vähän värisytetään niitä
        ang# = (360 / points) * i + Rnd((360/points)*0.1)
        
        //Satunnaistetaan nivelen etäisyys origosta
        drad = minrad + Rnd(0, 1) * (rad - minrad)
        
        //Lasketaan nivelen x, ja y koordinaatit ylhäällä luotujen muuttujen mukaan
        pointx# = Cos(ang#) * drad
        pointy# = Sin(ang#) * drad
        
        //Kirjoitetaan muistipalaan
        PokeFloat astr, i*8, pointx#
        PokeFloat astr, i*8+4, pointy#
        
    Next i
    
    //Ja palautetaan muistipalan kahva
    Return astr
    
End Function 

Function AsteroidRad(handle)
    Return PeekInt(handle, MEMBlockSize(handle)-4)
EndFunction 

Function DrawAsteroid(handle, dx, dy, angle# = 0, scale# = 1.0)

    size = (MEMBlockSize(handle)-4) / 8
    For i = 0 To size-1
        
        //Haetaan "nykyisen" nivelen koordinaatit.. *
        x# = PeekFloat(handle, i*8)
        y# = PeekFloat(handle, i*8+4)
        
        //Pyöritetään koordinaatit akselinsa ympäri *
        roX# = Cos(angle#) * x + Sin(angle#) * y
        roy# = Cos(angle#) * y - Sin(angle#) * x
        
        //Piirretään viivat ja haetaan aijemman pisteen koordinaatit
        If i > 0 Then 
            
            //Sama homma kuin tuola ylhäällä tähdellä (*) merkatut kohdat
            bx# = PeekFloat(handle, (i-1)*8)
            by# = PeekFloat(handle, (i-1)*8+4)
            
            broX# = Cos(angle#) * bx + Sin(angle#) * by
            broy# = Cos(angle#) * by - Sin(angle#) * bx  
            
            //Piirretään viiva aijemman ja nykyisen pisteen välille
            Line dx+broX*scale#, dy+broy*scale#, dx+rox*scale#, dy+roy*scale#
            
            If i = (size-1) Then //Tässä kohtaa silmukassa vedetään viimmeisestä pisteestä viiva ekaan pisteeseen :)
                
                //Ja taas sama homma kuin tuola ylhäällä tähdellä (*) merkatut kohdat
                fx# = PeekFloat(handle, 0)
                fy# = PeekFloat(handle, 4)
                
                froX# = Cos(angle#) * fx + Sin(angle#) * fy
                froy# = Cos(angle#) * fy - Sin(angle#) * fx    
                
                //Piirretään se vika viiva 
                Line dx+rox*scale#, dy+roy*scale#, dx + frox*scale#, dy + froy*scale#
            EndIf 
        EndIf 
        
    Next i

End Function
[/edit]
Solar Eclipse
Meneillä olevat Projektit:
We're in a simulation, and God is trying to debug us.

User avatar
elmo123
Active Member
Posts: 153
Joined: Sun Sep 09, 2007 4:19 pm

Re: 2D "Asteroidi" moottori, asteroideja primitiivi peleihin

Post by elmo123 » Thu Jun 23, 2011 7:49 pm

'asteroid'.PNG
"Asteroidi"
'asteroid'.PNG (20.21 KiB) Viewed 3204 times
Onko sisemmänkin tarkoitus näyttää asteroidilta?
Kiinnostuin pelien tekemisestä ennen 1. luokkaa.
Sitten 3. luokalla tuli CB. Ja siitä se alkoi.

Blender! TF2! CB! Game Maker! Nokia-mollaus! Kitaransoitto! Breakdance! MadTracker! Minecraft!

User avatar
MaGetzUb
Guru
Posts: 1715
Joined: Sun Sep 09, 2007 12:35 pm
Location: Alavus

Re: 2D "Asteroidi" moottori, asteroideja primitiivi peleihin

Post by MaGetzUb » Fri Jun 24, 2011 1:07 am

elmo123 wrote:
'asteroid'.PNG
Onko sisemmänkin tarkoitus näyttää asteroidilta?
Jep, siinä on vain kaksi asteroidia päällekkäin. :)
Solar Eclipse
Meneillä olevat Projektit:
We're in a simulation, and God is trying to debug us.

User avatar
elmo123
Active Member
Posts: 153
Joined: Sun Sep 09, 2007 4:19 pm

Re: 2D "Asteroidi" moottori, asteroideja primitiivi peleihin

Post by elmo123 » Fri Jun 24, 2011 2:31 pm

MaGetzUb wrote:
elmo123 wrote:
'asteroid'.PNG
Onko sisemmänkin tarkoitus näyttää asteroidilta?
Jep, siinä on vain kaksi asteroidia päällekkäin. :)
Tarkoitin sen pienemmän asteroidin muotoa. Hienon pohjan olet kumminkin luonut vektorigrafiikalle, joskin itse olisin käyttänyt napakoordinaatteja, jotta muodon pyöritys sujuisi hieman kätevämmin kuin

Code: Select all

        //Pyöritetään koordinaatit akselinsa ympäri *
        roX# = Cos(angle#) * x + Sin(angle#) * y
        roy# = Cos(angle#) * y - Sin(angle#) * x
Kiinnostuin pelien tekemisestä ennen 1. luokkaa.
Sitten 3. luokalla tuli CB. Ja siitä se alkoi.

Blender! TF2! CB! Game Maker! Nokia-mollaus! Kitaransoitto! Breakdance! MadTracker! Minecraft!

User avatar
MaGetzUb
Guru
Posts: 1715
Joined: Sun Sep 09, 2007 12:35 pm
Location: Alavus

Re: 2D "Asteroidi" moottori, asteroideja primitiivi peleihin

Post by MaGetzUb » Fri Jun 24, 2011 6:03 pm

elmo123 wrote:
MaGetzUb wrote:
elmo123 wrote:
'asteroid'.PNG
Onko sisemmänkin tarkoitus näyttää asteroidilta?
Jep, siinä on vain kaksi asteroidia päällekkäin. :)
Tarkoitin sen pienemmän asteroidin muotoa. Hienon pohjan olet kumminkin luonut vektorigrafiikalle, joskin itse olisin käyttänyt napakoordinaatteja, jotta muodon pyöritys sujuisi hieman kätevämmin kuin

Code: Select all

        //Pyöritetään koordinaatit akselinsa ympäri *
..pyörittelykoodi..
Mitähän nyt ajat takaa? En oikein ymmärrä. Minusta paras tyyli on tuo:

Code: Select all

roX# = Cos(angle#) * x + Sin(angle#) * y
roy# = Cos(angle#) * y - Sin(angle#) * y
Sitäpaitsi Avaruudes pyörii kaikenmuotoisia ja näköisiä kiviä ettei teräväkulmaisuus ole edes mikään ihme. :D
EDIT:

Njoo, olishan kyllä pelkän kulman ja etäisyyden voinut tallentaa muistipalaan. Mutta ei se olisi ainakaan datamenekin kannalta ollut yhtää sen optimaalisempaa kun kulma oltaisiin tallennettu desimaaleina ja etäisyys myös. :)

Solar Eclipse
Meneillä olevat Projektit:
We're in a simulation, and God is trying to debug us.

Post Reply