
-----------------------------------
Catalyst
Sun Apr 27, 2003 2:12 pm

[source] 2D Particle Engine
-----------------------------------
Here is a standard 2D particle system
If you have any questions on how to use it look at the demo or post the questions here

note: if the particle count goes too high it become very unsuable (i recommend  resetX
        resetY := s -> resetX
        forceX := s -> forceX
        forceY := s -> forceY
    end LoadSystemVars
    proc Init (X, Y, XV, YV, RAD, MASS, LIFE, MLIFE, INT : real, C : int, PIC : boolean)
        x := X
        y := Y
        xv := XV
        yv := YV
        radius := RAD
        mass := MASS
        life := LIFE
        maxLife := MLIFE
        c := C
        inter := INT
        picFlag := PIC
        if picFlag then
            pWidth := Pic.Width (c) div 2
            pHeight := Pic.Height (c) div 2
        end if
    end Init
    proc ReInit (X, Y, XV, YV, LIFE, MLIFE : real)
        x := X
        y := Y
        xv := XV
        yv := YV
        maxLife := MLIFE
        life := LIFE
    end ReInit
    proc DrawParticle
        if picFlag then
            Pic.Draw (c, round (x - pWidth), round (y - pHeight), picMerge)
        else
            if radius < 1 then
                drawdot (round (x), round (y), round (((life / maxLife) * 255) + 255))
            else
                drawfilloval (round (x), round (y), round (radius), round (radius), round (((life / maxLife) * 255) + 255))
            end if
        end if
    end DrawParticle
    proc Run
        xv += forceX
        yv += forceY
        x += xv
        y += yv
        life -= inter
    end Run
end Particle
class ParticleSystem
    import Particle, ParticleSysRec
    export Default, InitSystem, InitVectRand, InitBaseVect, InitPosRand, Update, DrawSystem,
        SetReset
    var Default : ^ParticleSysRec
    new Default
    var maxParticles, LifeC : int := 2
    var sourceX, sourceY, forceX, forceY, maxLife, baseXv, baseYv : real
    var rpRealModX, rpRealModY, rvMinX, rvMinY, rvMaxX, rvMaxY, rvRealModX, rvRealModY, rpMinX, rpMinY, rpMaxX, rpMaxY : real
    var ParticleSys : flexible array 1 .. 1 of ^Particle
    proc InitVectRand (rrmx, rrmy, rminx, rmaxx, rminy, rmaxy : real)
        rvRealModX := rrmx
        rvRealModY := rrmy
        rvMinX := rminx
        rvMaxX := rmaxx
        rvMinY := rminy
        rvMaxY := rmaxy
    end InitVectRand
    proc InitPosRand (rrmx, rrmy, rminx, rmaxx, rminy, rmaxy : real)
        rpRealModX := rrmx
        rpRealModY := rrmy
        rpMinX := rminx
        rpMaxX := rmaxx
        rpMinY := rminy
        rpMaxY := rmaxy
    end InitPosRand
    proc InitBaseVect (X, Y : real)
        baseXv := X
        baseYv := Y
    end InitBaseVect
      proc InitSystem (maxP : int, sx, sy, fx, fy, mas, rad, mLife, Int : real,c:int, pf : boolean)
        Default -> Init (sx, sy, fx, fy)
        sourceX := sx
        sourceY := sy
        forceX := fx
        forceY := fy
        maxLife := mLife
        maxParticles := maxP
        new ParticleSys, maxParticles
        for i : 1 .. maxParticles
            new ParticleSys (i)
            ParticleSys (i) -> LoadSystemVars (Default)
            ParticleSys (i) -> Init (
                ((sourceX + ((Rand.Real * rpRealModX)) * Rand.Int (round (rpMinX), round (rpMaxX)))),
                ((sourceY + ((Rand.Real * rpRealModY)) * Rand.Int (round (rpMinY), round (rpMaxY)))),
                ((baseXv + ((Rand.Real * rvRealModX)) * Rand.Int (round (rvMinX), round (rvMaxX)))),
                ((baseYv + ((Rand.Real * rvRealModY)) * Rand.Int (round (rvMinY), round (rvMaxY)))),
                rad, mas, maxLife - Rand.Int (0, maxLife div LifeC), mLife, Int, c, pf)
        end for
    end InitSystem
    proc Update
        for i : 1 .. maxParticles
            ParticleSys (i) -> Run
            if ParticleSys (i) -> GetLife  ReInit (
                    ((sourceX + ((Rand.Real * rpRealModX)) * Rand.Int (round (rpMinX), round (rpMaxX)))),
                    ((sourceY + ((Rand.Real * rpRealModY)) * Rand.Int (round (rpMinY), round (rpMaxY)))),
                    ((baseXv + ((Rand.Real * rvRealModX)) * Rand.Int (round (rvMinX), round (rvMaxX)))),
                    ((baseYv + ((Rand.Real * rvRealModY)) * Rand.Int (round (rvMinY), round (rvMaxY)))),
                    maxLife - Rand.Int (0, maxLife div LifeC), maxLife)
            end if
        end for
    end Update
    proc DrawSystem
        for i : 1 .. maxParticles
            ParticleSys (i) -> DrawParticle
        end for
    end DrawSystem
    proc SetReset (X, Y : real)
        sourceX := X
        sourceY := Y
    end SetReset
end ParticleSystem
 
 


Now heres a demo using it:


proc AddGradient (c1, c2, n : int)
    var clr : int
    var r1, g1, b1, r2, g2, b2, p, p0 : real
    RGB.GetColor (c1, r1, g1, b1)
    RGB.GetColor (c2, r2, g2, b2)
    const a := 50
    for i : 1 .. n
        p := (i / n) * 100
        p0 := 100 - p
        clr := RGB.AddColor ((((r1 * p) + (r2 * p0)) / 2) / a, (((g1 * p) + (g2 * p0)) / 2) / a, (((b1 * p) + (b2 * p0)) / 2) / a)
    end for
end AddGradient
View.Set ("graphics:640;640,position:300;300,offscreenonly,nobuttonbar")
AddGradient (9, 7, 28)
AddGradient (12, 9, 100)
AddGradient (14, 12, 118)
AddGradient (0, 14, 10)
var Spray : ^ParticleSystem
new Spray
var Spray2 : ^ParticleSystem
new Spray2
var x, y, z, x0, y0 : int := maxx div 2
var angle, angle2, sinC : real := 0
sinC := 0
angle2 := 0
Spray -> InitVectRand (1, 1, -1, 1, 1, 1)
Spray -> InitPosRand (1, 1, -1, 1, -1, 1)
Spray -> InitBaseVect (5, 5)
Spray -> InitSystem (1000, maxx div 2, maxy div 2, -0.15, -0.1, 1, 0, 80, 1.5,1,false)
Spray2 -> InitVectRand (1, 1, -1, 1, 1, 1)
Spray2 -> InitPosRand (1, 1, -1, 1, -1, 1)
Spray2 -> InitBaseVect (-5, -5)
Spray2 -> InitSystem (1000, maxx div 2, maxy div 2, 0.15, 0.1, 1, 0, 80, 1.5,1, false)
loop
    sinC += 0.5
    mousewhere (x, y, z)
    Spray2 -> InitBaseVect (-cosd (angle) * 5, -sind (angle) * 5)
    Spray -> InitBaseVect (cosd (angle) * 5, sind (angle) * 5)
    Spray -> SetReset (x0 + cosd (angle2) * 50, y0 + sind (angle2) * 50)
    Spray2 -> SetReset (x0 - cosd (angle2) * 50, y0 - sind (angle2) * 50)
    if sind (sinC) * 10 < 0 then
        angle -= sind (sinC) * 10
    else
        angle += sind (sinC) * 10
    end if
    if cosd (sinC) * 10 < 0 then
        angle2 -= cosd (sinC) * 10
    else
        angle2 += cosd (sinC) * 10
    end if
    if z = 1 then
        Spray -> SetReset (x + cosd (angle2) * 50, y + sind (angle2) * 50)
        Spray2 -> SetReset (x - cosd (angle2) * 50, y - sind (angle2) * 50)
        x0 := x
        y0 := y
    end if
    Spray -> Update
    Spray -> DrawSystem
    Spray2 -> Update
    Spray2 -> DrawSystem
    View.Update
    drawfillbox (0, 0, maxx, maxy, 7)
end loop

-----------------------------------
Asok
Sun Apr 27, 2003 2:23 pm


-----------------------------------
Ass kickingly cool Catalyst! Commenting would help but still thanks for sharing!

+30 Bits!

-----------------------------------
Catalyst
Sun Apr 27, 2003 2:25 pm


-----------------------------------
sry, not the commenting type....
if u got ne questions about the engine feel free to ask

-----------------------------------
Tony
Sun Apr 27, 2003 2:28 pm


-----------------------------------
that is truly amazing...

If anyone will be using this code, make sure to credit Catalyst

such as with Particle Engine programmed by Catalyst, posted on www.compsci.ca or something similar at the end of your program in credits. Or in About window...

+20Bits on top of that too - Tony

-----------------------------------
Catalyst
Sun Apr 27, 2003 2:30 pm


-----------------------------------
oh this might be apparent but u can use pictures as particles...


drawfillstar (0,0,10,10,14)
var pic:int:=Pic.New (0,0,10,10)
View.Set ("graphics:640;640,position:300;300,offscreenonly,nobuttonbar")
AddGradient (9, 7, 28)
AddGradient (12, 9, 100)
AddGradient (14, 12, 118)
AddGradient (0, 14, 10)
var Spray : ^ParticleSystem
new Spray
var Spray2 : ^ParticleSystem
new Spray2
var x, y, z, x0, y0 : int := maxx div 2
var angle, angle2, sinC : real := 0
sinC := 0
angle2 := 0
Spray -> InitVectRand (1, 1, -1, 1, 1, 1)
Spray -> InitPosRand (1, 1, -1, 1, -1, 1)
Spray -> InitBaseVect (5, 5)
Spray -> InitSystem (200, maxx div 2, maxy div 2, -0.15, -0.1, 1, 0, 80, 1.5,pic,true)
Spray2 -> InitVectRand (1, 1, -1, 1, 1, 1)
Spray2 -> InitPosRand (1, 1, -1, 1, -1, 1)
Spray2 -> InitBaseVect (-5, -5)
Spray2 -> InitSystem (200, maxx div 2, maxy div 2, 0.15, 0.1, 1, 0, 80, 1.5,pic, true)
var t, t0 : int
loop
%clock (t)
    sinC += 0.5
    mousewhere (x, y, z)
    Spray2 -> InitBaseVect (-cosd (angle) * 5, -sind (angle) * 5)
    Spray -> InitBaseVect (cosd (angle) * 5, sind (angle) * 5)
    Spray -> SetReset (x0 + cosd (angle2) * 50, y0 + sind (angle2) * 50)
    Spray2 -> SetReset (x0 - cosd (angle2) * 50, y0 - sind (angle2) * 50)
    if sind (sinC) * 10 < 0 then
        angle -= sind (sinC) * 10
    else
        angle += sind (sinC) * 10
    end if
    if cosd (sinC) * 10 < 0 then
        angle2 -= cosd (sinC) * 10
    else
        angle2 += cosd (sinC) * 10
    end if
    if z = 1 then
        Spray -> SetReset (x + cosd (angle2) * 50, y + sind (angle2) * 50)
        Spray2 -> SetReset (x - cosd (angle2) * 50, y - sind (angle2) * 50)
        x0 := x
        y0 := y
    end if
    Spray -> Update
    Spray -> DrawSystem
    Spray2 -> Update
    Spray2 -> DrawSystem
        % clock(t0)
        % locate (1,1)
        % put 1000/(t0-t)
    View.Update
    drawfillbox (0, 0, maxx, maxy, 7)
end loop


-----------------------------------
JSBN
Sun Apr 27, 2003 3:11 pm


-----------------------------------
Yaowza!...
 +50 bits
-note the 50 bits also includes those for your other AWSOMe programs!

-----------------------------------
jamez
Thu May 01, 2003 9:22 am


-----------------------------------
lol tony...trying to plug your website :P
