I'm using lists as well. 2 actually. One for the active particles and one for the pool which has a logic within to reduce the pool size over the time
Interesting idea, so this helps to remove the slow memory allocation for creating and destroying types over and over.
Interesting idea, so this helps to remove the slow memory allocation for creating and destroying types over and over.
hmmm, this is what the link I posted above does for you automatically. in your code, you just do
list.AddLast()
it takes it from the pool and does your own clean routine *or* if there are none in the pool, it will create a new instance.
(you have to create and init and create function in your type as per the example)
but if you want the fastest and easiest to use.... your BEST bet is to embed a simple single (or double)linked list in your particle type. it's not a TList, all you do is have a global which points to the first particle. each particle points to the next one. that's it. this will be as fast as arrays. add a pool pointer and you remove the memory allocation.
now if you implement a double linked list then you can remove any particle at any time. if you just do a single list then you can only remove when you are normally processing the list (since you need to know the previous particle )which is all you need for particles.
here's impixi's example modified
'Particle System Test 'Particle pool list and live particle list SuperStrict Framework BRL.GLMax2D 'Framework BRL.D3D7Max2D Import BRL.Random Import BRL.PNGLoader Global ScreenWidth:Int = 800 Global ScreenHeight:Int = 600 Graphics ScreenWidth, ScreenHeight TParticle.Init 2000, "c:\program files\blitzmax\samples\birdie\games\tiledrop\media\part.png" Local Renders:Int, FPS:Int Local CurrentMS:Int, OldMS:Int Local MemAlloced:Int = GCMemAlloced() SetBlend ALPHABLEND While Not KeyHit(KEY_ESCAPE) Cls TParticle.RenderLive If MouseDown(MOUSE_LEFT) Then For Local i:Int = 0 To 10; TParticle.Spawn MouseX(), MouseY();Next If KeyHit(KEY_M) Then MemAlloced = GCMemAlloced() SetColor 255, 255, 255 SetAlpha 1.0 SetScale 1.0, 1.0 Renders :+ 1 CurrentMS = MilliSecs() If (CurrentMS - OldMS) >= 1000 OldMS = CurrentMS FPS = Renders Renders = 0 EndIf DrawText FPS + " FPS", 10, 10 DrawText "Memory: " + MemAlloced + " bytes", 10, 30 DrawText "Live particles: " + TParticle.LiveCount, 10, 70 DrawText "M - Memory useage. LEFT CLICK - spawn new particle.", 10, GraphicsHeight() - 30 Flip 0 Wend End Type TParticle Const STATUS_DEAD:Int = 0 Const STATUS_LIVE:Int = 1 Global ParticlePool:TParticle Global LiveParticles:TParticle Global LiveCount:Int Global ParticleImage:TImage Function Init(qty:Int, img_url:String= "") Local pixmap:TPixmap = LoadPixmap(img_url) If pixmap Then Pixmap = ResizePixmap(pixmap, 64, 64) ParticleImage = LoadImage(pixmap) Else ParticleImage = createSprite() EndIf For Local n:Int = 1 To qty Local p:TParticle = New TParticle p.NextParticle = ParticlePool ParticlePool = p Next LiveCount = 0 pixmap = Null GCCollect EndFunction Function Spawn(x:Int, y:Int) Local p:TParticle = Null If ParticlePool <> Null p = ParticlePool ParticlePool = p.NextParticle p.X = x p.Y = y p.XDir = Rnd(-0.15, 0.15) p.YDir = Rnd(-0.15, 0.15) p.R = Rand(32, 255) p.G = Rand(32, 255) p.B = Rand(32, 255) p.Size = Rnd(0.1, 0.5) p.Alpha = 1.0 p.NextParticle = LiveParticles LiveParticles = p LiveCount :+ 1 EndIf EndFunction Function RenderLive() Local lp:TParticle Local np:TParticle Local p:TParticle = LiveParticles While p np = p.NextParticle If p.Render() = STATUS_DEAD If lp lp.NextParticle = p.NextParticle Else LiveParticles = p.NextParticle EndIf p.NextParticle = ParticlePool ParticlePool = p LiveCount :- 1 Else lp = p EndIf p = np Wend EndFunction '------------------------------------- Field X:Float, Y:Float Field XDir:Float, YDir:Float Field R:Byte, G:Byte, B:Byte Field Size:Float Field Alpha:Float Field NextParticle:TParticle Method Render:Int() SetColor R, G, B SetAlpha Alpha X :+ XDir Y :+ YDir SetScale Size, Size DrawImage ParticleImage, X, Y Alpha :- 0.0005 Local Dead:Int = False If Alpha <= 0.0 Then Dead = True If X < 0 Or X > ScreenWidth Then Dead = True If Y < 0 Or Y > ScreenHeight Then Dead = True If Dead Then Return STATUS_DEAD Else Return STATUS_LIVE EndMethod EndType Function CreateSprite:TImage() Local size:Int = 64 Local img:TImage = CreateImage(size, size, 1, DYNAMICIMAGE|MASKEDIMAGE) SetBlend SOLIDBLEND SetColor 255, 255, 255 DrawOval 0, 0, Size, Size GrabImage(img, 0, 0) Return img EndFunction