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
EDIT: ChDir kommentoitu pois, pitäisi toimia nyt copy-pastella editoriin.