Koodia: Kokoelmien väliset törmäykset

Oletko tehnyt jotain, mistä muut voisivat hyötyä. Postita vinkit tänne.
Post Reply
JATothrim
Tech Developer
Tech Developer
Posts: 606
Joined: Tue Aug 28, 2007 6:46 pm
Location: Kuopio

Koodia: Kokoelmien väliset törmäykset

Post by JATothrim »

Tämä projekti valmistui nyt ennätysajassa. 8-)

Törmäykset tarkistetaan kokoelmien välillä yleensä kahden For-Each sisällä. Tämä esimerkkipeli heittää koko ajatuksen roskakoriin: kokoelmien instanssit linkitetään objekteihin, jolloin ObjectInteger() funktiolla saadaan instanssi suoraan objektista. Päätin siis tehdä esimerkkipelin, joka hyödyntää tätä tekniikkaa. Objektit lentävät räjähdyksen tai morapuukon voimasta ja hahmo-objektit voivat työntää muita hahmoja pois tieltään. Esimerkkipeli ei sisällä ainottakaan For-each looppia, joka olisi toisen For-each loopin sisällä! ;)
Toisena tavoitteena oli tuottaa aloittelijoille iso koodi möhkäle, josta voi ottaa oppia. Kyllästyin siihen, että F8 nappulan alta paljastuva oppitunti nro. 18 on niin suppea törmäystarkistusten osalta.

Joten saanen esitellä seuraavat 564 riviä koodia:

Code: Select all

// Esimerkki KokoelmaA<->KokoelmaA<->KokoelmaB törmäyksistä, joka on yleinen
// tapaus CB peleissä.
// Esimerkkipeli näyttää kuinka kokoelmien väliset
// törmäykset kannattaa toteuttaa CB:llä. Ohjelma on jaettu
// funktioihin paremman luettavuuden saavuttamiseksi.
// Koodi on kohtalaisen hyvin komentoitu, verratuna siihen miten iso
// tämä esimerkkiohjelma on.
// KOODIN JÄLJITTELY TAI KOPIONTI ON EHDOTTAMSTI KANATTAVAA JA SALLITTUA!
// Ohjelman tekijä [JATothrim] ei ole vastuussa, jos tekemäsi copypaste peliprojekti hajoaa käsiin, mavittaa tai koodi tuhoaa koneesi. Ohjelman kokeilu täysin omalla vastuulla.
// (C) JATothrim, 2011.

// PELI LATAA CB:n mukana tulevaa mediaa! Vaihda LoadGameContent() ChDir komennon polku oikeaksi! (rivi: 238)
// KONTROLLIT: WASD, P, P+RSHIFT, HIIRI, 1,2,3 vaihtaa asetta.

SCREEN 800,600

//================================================================================
//    Kokoelma lentäville ammuksille
//================================================================================
Type Bullet
    Field obj As integer        'objekti
    Field speed As Float        'ammuksen nopeus
    Field bDestroy As Byte      'jos instanssi halutaan poistaa, tämä flagi asetetaan päälle
EndType

//================================================================================
//    Kokoelma pelaajille
//================================================================================
Type Player
    Field obj As integer        'objekti
    Field bIsControlled As Byte 'ohjaako pelaaja tätä hahmoa?
    Field life As Float         'elämän määrä    [0.0, 1.0]
    Field damage As Float       'saatu vahinko
    Field wounded As integer    'haavoittumis ajastin
    Field weapon As integer     'ase jota pelaaja pitää kädessä
    // jos jokin osuu pelaajaan häntä liikutetaan tämän vektorin perusteella
    Field throwSpeedX As Float
    Field throwSpeedY As Float 
    Field bDestroy As Byte      'jos instanssi halutaan poistaa, tämä flagi asetetaan päälle
EndType

// Player\weapon:1 ==> Mora
// Player\weapon:2 ==> Itsari C4:llä (ei toteutettu, mutta oli suunniteltu)
// Player\weapon:3 ==> Rapid Gauss Bazooka (haha :DD)

//================================================================================
//    Muutujat ladattavalle/globaalille medialle.
//================================================================================
Global glb_objPlayer As integer
Global glb_objBullet As integer
Global glb_objMora As integer
Global glb_sfxExplosion As integer
Global glb_imgExplosion As integer
Global glb_imgTilemap As integer
Global glb_imgLifeBar As integer
Global glb_imgMouse As integer
Global glb_objMap As integer
Global glb_fntArial32 As integer
Global glb_fntArial48 As integer
Global glb_bMediaLoaded As Byte
glb_bMediaLoaded = 0    // ei olla ladattu vielä mitään.

//================================================================================
// Pelin globaalit muuttujat.
// Funktiot välittävät tapahtumia/dataa muille funktioille asettamlla näitä flageja päälle/pois.
//================================================================================
Global glb_iKillMultipler As integer
Global glb_bKill As Byte
Global glb_iKillScore As integer

// Pelin päälooppi, joka kutsuu muita funktioita.
MainGameLoop()
End        //lopetetaan ohjelma.



Function MainGameLoop()

    LoadGameContent() 'ladataan media.
    If glb_bMediaLoaded = 0 Then Return 0
    
    // Luodaan ohjattu pelaaja
    SpawnNewPlayer()
    cPlayer.Player = Last(Player)
    cPlayer\bIsControlled = 1
    
    // "Kill multipler":n muuttujat.
    bShowKills = 0
    iKill_timer = Timer()
    Kill_strobo = 0
    bSuicide = 0
    
    Repeat
        
        If KeyHit(cbkeyp) Or (KeyDown(cbkeyp) And KeyDown(cbkeyrshift))
            // spawnataan uusi pelaaja, mutta ei vaihdeta siihen.
            SpawnNewPlayer()
        EndIf
        
        //============================================================================
        // Aseiden käyttö
        //============================================================================
        If KeyHit(cbkey1) Then cPlayer\weapon = 1
        If KeyHit(cbkey2) Then cPlayer\weapon = 2
        If KeyHit(cbkey3) Then cPlayer\weapon = 3
        
        
        If cPlayer\bIsControlled = 1
            UseWeapon_Mora(ConvertToInteger(cPlayer))
            // TODO: UseWeapon_Suicide
            UseWeapon_Bazooka(ConvertToInteger(cPlayer))
        EndIf
        
        //================================================================================
        // Päivitä hahmot
        //================================================================================
        UpdatePlayers()
        
        //================================================================================
        // Päivitä ammukset
        //================================================================================
        UpdateBullets()
        
        //================================================================================
        // Tarkista kuoliko ohjattu hahmo ennen sen varsinaista tuhoamista.
        //================================================================================
        If cPlayer\bDestroy = 1
            // jokin nirhasi ohjaamamme hahmon, luodaan uusi:
            SpawnNewPlayer()
            newPlayer.Player = Last(Player)
            newPlayer\bIsControlled = 1
            cPlayer\bIsControlled = 0
            cPlayer = newPlayer
            bSuicide =  1
            glb_iKillScore = 0
        EndIf
        
        glb_bKill = 0 // nollataan osuma flagi
        
        //================================================================================
        // Tuhoa instansseja ja liipaise efektejä.
        //================================================================================
        UpdatePlayers_Destroy()
        UpdateBullets_Destroy()
        
        //================================================================================
        // Käsittele glb_iKillMultipler ja bSuicide muutujat. glb_iKillMultipler kasvaa
        // UpdateBullets_Destroy() funktiossa.
        //================================================================================
        If glb_iKillMultipler > 0 And iKill_timer > Timer()
            bShowKills = glb_iKillMultipler
        ElseIf glb_iKillMultipler > 0 And iKill_timer + 100 < Timer()
            iKill_timer = Timer() + 5000    // 5sek aikaa saada kerrointa ylös
            bShowKills = glb_iKillMultipler
        Else
            glb_iKillMultipler = 0
            bShowKills = 0
        EndIf
        
        If bSuicide = 1 And iKill_timer > Timer()
            bShowKills = -1
        ElseIf bSuicide = 1 And iKill_timer + 100 < Timer()
            iKill_timer = Timer() + 1000
            bShowKills = -1
        Else
            bSuicide = 0
        EndIf
        
        If glb_bKill = 1
            glb_iKillScore = glb_iKillScore + 13 * glb_iKillMultipler
        EndIf
        
        // Piirretään objektit!
        DrawGame
        
        
        //================================================================================
        // Piirretään muu grafiikka
        //================================================================================
        DrawToWorld ON
        // <Pelimaailmaan sijoittuva grafiikka.>
        For iPlayer.Player = Each Player
            Color 255-255*iPlayer\life, 255*iPlayer\life, 0
            Box ObjectX(iPlayer\obj)-30, ObjectY(iPlayer\obj)+50, 60 * iPlayer\life, 3
        Next iPlayer
        DrawToWorld OFF
        
        // Life-bar
        Color 255-255*cPlayer\life, 255*cPlayer\life, 0
        Box 20, 10, ImageWidth(glb_imgLifeBar)+4, ImageHeight(glb_imgLifeBar)+4, 0
        DrawImageBox glb_imgLifeBar, 22,12, 0,0, ImageWidth(glb_imgLifeBar)*cPlayer\life,ImageHeight(glb_imgLifeBar)
        // Masokisti kerroin. :D
        If cPlayer\wounded > 300
            SetFont glb_fntArial32
            Text 20, ImageHeight(glb_imgLifeBar)+20, "! MASOCHIST "+(cPlayer\wounded-300)/10+"% !"
        EndIf
        
        // Piirretään tappo kerroin
        If bShowKills <> 0
            Kill_strobo + 1
            If Kill_strobo Mod 2 = 0
                Color (Kill_strobo Mod 3 = 0)*255, (Kill_strobo Mod 3 = 1)*255, (Kill_strobo Mod 3 = 2)*255
                SetFont glb_fntArial48
                If bShowKills = -1
                    CenterText ScreenWidth()/2, 50, "!! SUICIDE !!"
                ElseIf bShowKills >= 4
                    CenterText ScreenWidth()/2, 50, "!! MULTI-KILL !!"
                ElseIf bShowKills >= 3
                    CenterText ScreenWidth()/2, 50, "!! TRIPLE-KILL !!"
                ElseIf bShowKills >= 2
                    CenterText ScreenWidth()/2, 50, "!! DOUBLE-KILL !!"
                ElseIf bShowKills = 1
                    CenterText ScreenWidth()/2, 50, "!! KILL !!"
                EndIf
            EndIf
        EndIf
        
        // FPS
        SetFont glb_fntArial32
        Text ScreenWidth()-160, 20,"FPS: "+FPS()
        
        Text 20, ScreenHeight()-60, "KILLSCORE:"+glb_iKillScore
        
        DrawScreen
        
        // piilotetaan mora
        ShowObject glb_objMora, 0
    Until KeyHit(cbkeyesc)
    
    // Tässä meidän pitäisi vapauttaa kaikki varatut resurssit, mm.  Bullet kokoelma
    // ja ladattu tilemap; ENNEN kuin poistumme funktiosta.
    // Tällöin mahdollisen päävalikon ei tarvitse siivota meidän sotkujamme jälkikäteen.
EndFunction


Function LoadGameContent()
    // Ladataan pelin media. ChDir lyhentää polkua kätevästi.
    'ChDir "C:\Program Files\CoolBasic\Media"
    DefaultVisible OFF
    glb_objPlayer = LoadObject("Media\soldier.bmp", 360)
    glb_objBullet = LoadObject("Media\bigbullet.bmp", 72)
    glb_objMora   = LoadObject("Media\cannon.bmp", 8)
    glb_sfxExplosion = LoadSound("Media\Cannon.wav")
    glb_imgExplosion = LoadAnimImage("Media\bang.bmp", 32,32, 0, 8)
    glb_imgTilemap = LoadImage("Media\tileset.bmp")
    glb_imgLifeBar = LoadImage("Media\life.jpg")
    glb_imgMouse = LoadImage("Media\crosshair.bmp")
    glb_fntArial32 = LoadFont("Arial",32)
    glb_fntArial48 = LoadFont("Arial",48)
    DefaultVisible ON
    // tilemap kannattaa ladata viimeisenä, sillä muuten joudumme järjestämään sen joka tapauksessa uudestaan.
    glb_objMap = LoadMap("Media\cdm2.til", glb_imgTilemap)
    ObjectString glb_objMap, "object_glb_objMap"
    
    ShowMouse glb_imgMouse
    glb_bMediaLoaded = 1
EndFunction

//================================================================================
//    Pelaaja kokoelman toiminnot ja sitä käsittelevät funktiot:
//================================================================================
Function SpawnNewPlayer()
    // Luodaan uusi instanssi kokoelmaan:
    newPlayer.Player = New(Player)
    // kloonataan sille objekti:
    newPlayer\obj = CloneObject(glb_objPlayer)
    // Linkitetään instanssi objektiin.
    ObjectInteger newPlayer\obj, ConvertToInteger(newPlayer)
    ObjectString newPlayer\obj, "type_Player"    // ObjectString keroo mitä tyyppiä objekti ON.
    newPlayer\life = 1.0
    newPlayer\wounded = 20            // saatamme spwanautua keskelle helvettiä, joten tämä päälle. :D
    newPlayer\weapon = Rand(1,3)    // sattuman varainen ase.
    
    // Spawnataan objekti kartalle.
    SpawnObject(newPlayer\obj)
    
    //Asetetaan törmäys objekteihin johon voimme törmätä.
    ObjectRange newPlayer\obj, 30,30
    For iplayer.Player = Each Player
        If iplayer <> newPlayer
            // Meidän täytyy asettaa törmäys kumpaankin suuntaan, että se toimisi oikein.
            SetupCollision newPlayer\obj, iplayer\obj, 2,2,2
            SetupCollision iplayer\obj, newPlayer\obj, 2,2,2
        EndIf
    Next iplayer
    
    // Lopuksi vielä karttaan ja mahd. muihin liikkumattomiin objektiehin.
    SetupCollision newPlayer\obj, glb_objMap, 2,4,2
    
EndFunction

//================================================================================
// Siirretään objekti satunnaiseen kohtaan kartalle
//================================================================================
Function SpawnObject(_obj)
    While True
        x = Rand(1, MapWidth())
        y = Rand(1, MapHeight())
        tBack = GetMap2(0, x, y)
        tHit = GetMap2(2, x, y)
        If tBack > 0 And tHit = 0 Then
            wx = (x * 32 - 16) - ((MapWidth() * 32) / 2)
            wy = ((y * 32 - 16) - ((MapHeight() * 32) / 2)) * -1
            PositionObject _obj, wx, wy
            RotateObject _obj, Rand(0, 360)
            Exit
         EndIf
    Wend
EndFunction

Const F_THROW_SLOWDOWN = 0.8756        'heiton nopeuden vähentyminen
Const F_THROW_SPEEDLIMIT = 20.0        'tätä kovempaa objekteja ei tulla heittämään.
Function UpdatePlayers()
    For iPlayer.Player = Each Player
        
        //============================================================================
        // Pelaajan liikkuminen
        //============================================================================
        If iPlayer\bIsControlled = 1 
            // näppäimistö:
            player_forward# = 0.0
            player_sideways# = 0.0
            If KeyDown(cbkeyw) Then player_forward = 4.0
            If KeyDown(cbkeys) Then player_forward = -3.0
            If KeyDown(cbkeyd) Then player_sideways = 2.0
            If KeyDown(cbkeya) Then player_sideways = -2.0
            
            // Jos meillä ON heittoa päällä, emme liikuta pelaajaa nopeasti.
            If Abs(iPlayer\throwSpeedX) > 0.05 Or Abs(iPlayer\throwSpeedY) > 0.05
                player_forward = player_forward * 0.1
                player_sideways = player_sideways * 0.1
            EndIf
            
            // hiiri + objektin liikutus.    
            RotateObject iPlayer\obj, GetAngle(ObjectX(iPlayer\obj), -ObjectY(iPlayer\obj), MouseWX(), -MouseWY())
            MoveObject iPlayer\obj, player_forward, player_sideways
            CloneCameraPosition iPlayer\obj        
        EndIf
        
        //============================================================================
        // Tarkistetaan pelaajan törmäykset
        //============================================================================
        collisions = CountCollisions(iPlayer\obj)
        For i = 1 To collisions
            target_obj = GetCollision(iPlayer\obj, i)
            If ObjectString(target_obj) = "object_glb_objMap"
                // <Osumme kartta objektiin.>
                // Koska CB:n liukuva törmäystunnistus päästää objektit menemään toisensa läpi varsin helposti,
                // joudumme avittamaan sitä hieman. Estä pelaajan heittäminen seinän läpi.
                angle = CollisionAngle(iPlayer\obj, i)
                If angle = 90 Or angle = 270 Then iPlayer\throwSpeedY = 0
                If angle = 0 Or angle = 180 Then iPlayer\throwSpeedX = 0
            ElseIf ObjectString(target_obj) = "type_Player"
                // <Osuimme toiseen pelaaja objektiin.>
                // Aiheuta ketjureaktio: lisä heittonopeutta muihin törmääviin objekteihin.
                // Nappaa instanssi objektista
                targetplayer.Player = ConvertToType(ObjectInteger(target_obj))
                // laske nopeudet
                targetplayer\throwSpeedX = Max( Min( (targetplayer\throwSpeedX + iPlayer\throwSpeedX) * F_THROW_SLOWDOWN, F_THROW_SPEEDLIMIT), -F_THROW_SPEEDLIMIT)
                targetplayer\throwSpeedY = Max( Min( (targetplayer\throwSpeedY + iPlayer\throwSpeedY) * F_THROW_SLOWDOWN, F_THROW_SPEEDLIMIT), -F_THROW_SPEEDLIMIT)
                iPlayer\throwSpeedX = Cos(CollisionAngle(iPlayer\obj, i) + 180) * (iPlayer\throwSpeedX / 2.0)
                iPlayer\throwSpeedY = Sin(CollisionAngle(iPlayer\obj, i) + 180) * (iPlayer\throwSpeedY / 2.0)
            End If
        Next i
        
        // Pelaajen heittely
        TranslateObject iPlayer\obj, iPlayer\throwSpeedX, iPlayer\throwSpeedY
        iPlayer\throwSpeedX = iPlayer\throwSpeedX * F_THROW_SLOWDOWN
        iPlayer\throwSpeedY = iPlayer\throwSpeedY * F_THROW_SLOWDOWN
        
        //============================================================================
        // Haavoittumis systeemi; ehkä vähän turhan monimutkainen? :-)
        //============================================================================
        If iPlayer\wounded >= 0
            //jos saatiin liikaa damagea kerralla, välkytetään pelaajaa
            If iPlayer\wounded Mod 10 = 5
                GhostObject iPlayer\obj, 100
            EndIf
            If iPlayer\wounded Mod 10 = 0
                GhostObject iPlayer\obj, 0.4
            EndIf
            
            If iPlayer\wounded = 0 Then GhostObject iPlayer\obj, 100
            If iPlayer\wounded > 300 Then iPlayer\damage = iPlayer\damage * 0.3    // otamme vähemmän vahinkoa masokistina. :>
        EndIf
        iPlayer\wounded = iPlayer\wounded - 1
        // vähennetään damage elämästä. :(
        iPlayer\life = iPlayer\life - iPlayer\damage
        // jos saatiin liikaa damagea kerralla, liipaistaan välkkymis efekti. (~sekunti @60fps)
        If iPlayer\damage >= 0.1 Then iPlayer\wounded = iPlayer\wounded + 60
        iPlayer\damage = 0
        
        // Tarkistetaan onko pelaaja hengissä
        If iPlayer\life < 0
            iPlayer\bDestroy = 1
        EndIf                
    Next iPlayer
EndFunction
        
Function UpdatePlayers_Destroy()
    For iPlayer.Player = Each Player
        If iPlayer\bDestroy
            // <todo: luo veripläntti>
            // Lasketaan tapot
            glb_iKillMultipler = glb_iKillMultipler + 1
            glb_bKill = 1
            
            // Soitetaan ääniefekti.
            sfx_vol# = Max(20, 100 / Distance(ObjectX(iPlayer\obj), ObjectY(iPlayer\obj), CameraX(), CameraY()) )
            sfx_pan# = Cos( GetAngle(CameraX(), -CameraY(), ObjectX(iPlayer\obj), -ObjectY(iPlayer\obj)) ) * 90
            PlaySound glb_sfxExplosion, sfx_vol, sfx_pan

            
            DeleteObject iPlayer\obj
            Delete iPlayer
        EndIf
    Next iPlayer
EndFunction        
    

//============================================================================
// ASE: MORA-PUUKKO (ei kokoelmaa)
//============================================================================
Function UseWeapon_Mora(type_player As integer)

    iPlayer.Player = ConvertToType(type_player)
    
    If iPlayer\weapon = 1 And MouseHit(1)
        collisions = CountCollisions(iPlayer\obj)
        ang# = 0
        // Selataan törmäykset läpi
        For i = 1 To collisions
            target_obj = GetCollision(iPlayer\obj, i)
            // Tarkistetaan mitä tyyppiä objekti oli
            If ObjectString(target_obj) = "type_Player"
                // Napataan instanssi objektista:
                target.Player = ConvertToType(ObjectInteger(target_obj))
                If target <> NULL
                    // lisätään damagea. Mitä lähempänä selkää puukotettiin sitä enemmän damagea!
                    target\damage = target\damage + Abs(1.0 - Abs(Sin(ObjectAngle(target_obj)) - Sin(ObjectAngle(iPlayer\obj)) ) / 2.0 ) + 0.1
                    // heitetään uhria satunnaisesti pois päin puukottajasta.
                    dist# = Rnd(5,10)
                    ang# = WrapAngle(ObjectAngle(iPlayer\obj) + Rnd(-60.0,60.0))
                    target\throwSpeedX = Cos(ang) * dist
                    target\throwSpeedY = Sin(ang) * dist
                EndIf
                
            ElseIf ObjectString(target_obj) = "object_glb_objMap"
                // kartan hakkaaminen moralla ei ole terveellistä,
                // mutta tästä saa itselleen "masokistista kestävyttä".
                // Saattaa pelastaa pommitaajalta tai singon täysosumalta!
                iPlayer\wounded = iPlayer\wounded + 60
                iPlayer\damage = iPlayer\damage + 0.05
                dist# = Rnd(15)
                ang# = WrapAngle(CollisionAngle(target_obj, i) + Rnd(-30,30))
                iPlayer\throwSpeedX = iPlayer\throwSpeedX + Cos(ang) * dist
                iPlayer\throwSpeedY = iPlayer\throwSpeedY - Sin(ang) * dist
                
            EndIf
        Next i
        
        // näytetään mora
        ObjectOrder glb_objMora,  1
        ShowObject glb_objMora, 1
        CloneObjectPosition glb_objMora, iPlayer\obj
        CloneObjectOrientation glb_objMora, iPlayer\obj
        MoveObject glb_objMora, 20,5
        TurnObject glb_objMora, ang+Rnd(-5,5)
        
    EndIf
EndFunction

//============================================================================
//    Bullet kokoelman toiminnot ja sitä käsittelevät funktiot.
//    ASE: RAPID GAUSS BAZOOKA.
//============================================================================
Function UseWeapon_Bazooka(type_player As integer)
    iPlayer.Player = ConvertToType(type_player)
    
    // Tässä esimerkissä emme käytä mitään 'reload':ia, koska tarkoituksemme ON lähinnä testata miten
    // nopeasti voimme tarkistaa törmäyksiä. :P
    If iPlayer\weapon = 3 And MouseDown(1)
        // luodaan uusi instanssi
        newbullet.Bullet = New(Bullet)
        // klonaataan objekti
        newbullet\obj = CloneObject(glb_objBullet)
        // linkitetään instanssi ja objekti keskenään.
        ObjectInteger newbullet\obj, ConvertToInteger(newbullet)
        ObjectString newbullet\obj, "type_Bullet"
        
        // asetetaan objekti sopivaan paikkaan
        CloneObjectPosition newbullet\obj, iPlayer\obj
        CloneObjectOrientation newbullet\obj, iPlayer\obj
        MoveObject newbullet\obj, 30,0
        TurnObject newbullet\obj, Rnd(-10,10)
        
        newbullet\speed = Rnd(7,10)
        
        // Asetetaan törmäykset 
        For iplayer.Player = Each Player
            SetupCollision newbullet\obj, iplayer\obj, 2,2,1
        Next iplayer
    
        // Lopuksi vielä karttaan ja mahd. muihin liikkumattomiin objektiehin.
        SetupCollision newbullet\obj, glb_objMap, 2,4,1
        ResetObjectCollision  newbullet\obj
    EndIf
EndFunction

Function UpdateBullets()
    For ibullet.Bullet = Each Bullet
        
        // Tarkistetaan törmäykset
        collisions = CountCollisions(ibullet\obj)
        For i = 1 To collisions
            target_obj = GetCollision(ibullet\obj, i)
            If ObjectString(target_obj) = "type_Player"
                // napataan instanssi objektista:
                target.Player = ConvertToType(ObjectInteger(target_obj))
                If target <> NULL
                    target\damage = target\damage + 0.15
                    
                    cAngle# = WrapAngle(CollisionAngle(ibullet\obj, i)+180)
                    x# = Cos(cAngle) * ibullet\speed
                    y# = Sin(cAngle) * ibullet\speed
                    target\throwSpeedX = Max( Min( (target\throwSpeedX + x) * F_THROW_SLOWDOWN, F_THROW_SPEEDLIMIT), -F_THROW_SPEEDLIMIT)
                    target\throwSpeedY = Max( Min( (target\throwSpeedY + y) * F_THROW_SLOWDOWN, F_THROW_SPEEDLIMIT), -F_THROW_SPEEDLIMIT)
                EndIf
            EndIf
        Next i
        
        // Tuhotaan ammus heti kun se osuu johonkin.
        If collisions > 0 Then ibullet\bDestroy = 1
        
        MoveObject ibullet\obj, ibullet\speed
    Next ibullet
EndFunction

Function UpdateBullets_Destroy()
    For ibullet.Bullet = Each Bullet
        // CB:n törmäysjärjestelmä pettää, jos objekti liikkuu liian paljon per frame.
        // Tällöin objektit pääsevät toistensa läpi.
        // GetMap() tarkistus estää objekteja karkaamasta kartalta, koska se tarkistaa onko objekti seinätilen sisällä.
        // (kokeile ottaa se pois niin huomaat eron!)
        If GetMap(2, ObjectX(ibullet\obj), ObjectY(ibullet\obj)) = 1 Then ibullet\bDestroy = 1
        
        // ammuksen tuhoaminen
        If ibullet\bDestroy = 1
            // luodaan partikkelilähde ammuksen kohdalle
            neweffect = MakeEmitter(glb_imgExplosion,10)
            CloneObjectPosition neweffect, ibullet\obj   
            ParticleMovement neweffect,0,0
            ParticleEmission neweffect,2,1,1       
            ParticleAnimation neweffect,7
            // CB poistaa objektin puolestamme. Jos ObjectLife komentoa käytetään, niin
            // objektiin pitä suhtautua samalla tavalla kuin olisi kutsuttu DeleteObjektia.
            // ObjectLife(objekti) näet aiheuttaa MAV:in, jos objekti ON ehditty jo poistaa.
            ObjectLife neweffect,11
            
            DeleteObject ibullet\obj    'tuhotaan objekti
            Delete ibullet    'tuhotaan instanssi
        EndIf
    Next ibullet
EndFunction
Ja koska koko koodi on nopeasti tehty + minun kirjoittamaa, varautukaa silmiä verestävään typo-laakiin ja muihin kummallisuuksiin. :roll:
EDIT: ChDir kommentoitu pois, pitäisi toimia nyt copy-pastella editoriin.
Last edited by JATothrim on Sat Sep 17, 2011 12:18 pm, edited 1 time in total.
-On selkeästi impulsiivinen koodaaja joka...
ohjelmoi C++:lla rekursiivisesti instantioidun templaten, jonka jokainen instantiaatio instantioi sekundäärisen singleton-template-luokan, jonka jokainen instanssi käynistää säikeen tulostakseen 'jea'.
Latexi95
Guru
Posts: 1166
Joined: Sat Sep 20, 2008 5:10 pm
Location: Lempäälä

Re: Koodia: Kokoelmien väliset törmäykset

Post by Latexi95 »

Oho... Aina vaan joku keksii tavan optimoida koodia. Tämähän vaikutti paljon nopeammalta, kun mitä for-each tyylillä toteutettu räiskintä. Asiasta voisi kyllä tehdä jonkun testinkin.
Awaclus
Forum Veteran
Posts: 2939
Joined: Tue Aug 28, 2007 2:50 pm

Re: Koodia: Kokoelmien väliset törmäykset

Post by Awaclus »

Varsin pätevä koodi, tulee varmasti käytettyä. Huonoimmalla tietokoneellani nimittäin ei ole paljon muuta käyttöä kuin CB-koodaus, ja jos on paljon ammuksia ja vihollisia yhtäaikaa kentällä, alkaa pätkimään ja testaaminen on hidasta.

That's 100% C++/IDE -konkari for you.
User avatar
Misthema
Advanced Member
Posts: 312
Joined: Mon Aug 27, 2007 8:32 pm
Location: Turku, Finland
Contact:

Re: Koodia: Kokoelmien väliset törmäykset

Post by Misthema »

Hyvin tuntui pyörivän. Ainoa vaan, että kun vihollisia alkaa olemaan tarpeeksi monta ja FPS tippuu paljon, saattaa käydä näin:
Attachments
Vihu meni seinän läpi kun ammuin...
Vihu meni seinän läpi kun ammuin...
funneh.PNG (103.17 KiB) Viewed 5385 times
Post Reply