
-----------------------------------
zero-impact
Sun Jan 18, 2009 10:14 pm

Particle Engine
-----------------------------------
This is a revamped version of a particle engine I made last year.
It now runs much much faster.

The controls are as follows:

Hold space bar to attract the particles to the mouse.

Hold Control to repulse the particles away from the mouse.

Click and hold the mouse to spawn particles.


Any tips, comments or criticism are greatly appreciated http://compsci.ca/v3/images/smiles/icon_smile.gif


Note: Try playing around with some of the constants for different effects. Also if it is running too slowly for you just change the MAXPART constant. As well as in the graphics procedure you can uncomment the drawfillbox for a neat effect :)


%%particlesim%%
setscreen ("graphics:max;max;nobuttonbar;offscreenonly")

type particle :
    record
        x : int
        y : int
        xvel : real
        yvel : real
        col : int
    end record

const GRAV : real := 0.9
const AIR : real := 0.99
const TRANSFER : real := 0.5
const FRIC := 0.8
const NULL := 9876543
const BACKCOL : int := black

var mousex, mousey, mouseClick : int
var spawnRate := 10
const MAXPART := 2000
var part : array 1 .. MAXPART of particle
var mouseAngle : real
var chars : array char of boolean

for i : 1 .. MAXPART
    part (i).x := NULL
    part (i).y := NULL
    part (i).xvel := 0
    part (i).yvel := 0
    part (i).col := 0
end for

var currentPart : int := 0

proc spawnParticle (particlex : int, particley : int)
    for k : 1 .. spawnRate
        if currentPart = MAXPART then
            currentPart := 0
        end if
        currentPart += 1
        part (currentPart).x := particlex + k
        part (currentPart).y := particley

        %part (currentPart).xvel := Rand.Int (-10, 10)
        %part (currentPart).yvel := Rand.Int (1, 4)
        part (currentPart).xvel := cosd (Rand.Int (0,360)) * 10 %Help from http://compsci.ca/v3/viewtopic.php?t=17607
        part (currentPart).yvel := sind (Rand.Int (0,360)) * 10 % help from http://compsci.ca/v3/viewtopic.php?t=17607
        
        part (currentPart).col := Rand.Int (0, 15)

        if part (currentPart).col = black then
            part (currentPart).col += 1
        end if
    end for
end spawnParticle

function getMouseAngle (x, y : real) : real %Help from compsci.ca    http://compsci.ca/v3/viewtopic.php?t=17607
    if x = 0 and y = 0 then
        result 0
    elsif x = 0 and y > 0 then
        result 90
    elsif x = 0 and y < 0 then
        result 270
    elsif y = 0 and x > 0 then
        result 0
    elsif y = 0 and x < 0 then
        result 180
    elsif x > 0 and y > 0 then
        result arctand (y / x)
    elsif x < 0 and y > 0 then
        result 180 + arctand (y / x)
    elsif x > 0 and y < 0 then
        result 360 + arctand (y / x)
    elsif x < 0 and y < 0 then
        result 180 + arctand (y / x)
    else
        result 0
    end if
end getMouseAngle


proc getInput
        Mouse.Where (mousex, mousey, mouseClick)
        if mouseClick = 1 then
            spawnParticle (mousex, mousey)
        end if
end getInput

proc physics
    for i : 1 .. upper (part)

        Input.KeyDown (chars)
        if chars (' ') then
            mouseAngle := getMouseAngle (mousex - part (i).x, mousey - part (i).y)  %%Help from compsci.ca
            part (i).xvel += cosd (mouseAngle) * 2 %Help from http://compsci.ca/v3/viewtopic.php?t=17607
            part (i).yvel += sind (mouseAngle) * 2 % help from http://compsci.ca/v3/viewtopic.php?t=17607
        elsif chars (KEY_CTRL) then
            mouseAngle := getMouseAngle (mousex - part (i).x, mousey - part (i).y)          %%Help from compsci.ca
            part (i).xvel += -round (cosd (mouseAngle) * 2) %Help from http://compsci.ca/v3/viewtopic.php?t=17607
            part (i).yvel += -round (sind (mouseAngle) * 2) % help from http://compsci.ca/v3/viewtopic.php?t=17607
        end if



        if part (i).x = NULL & part (i).y = NULL then
            %do nothing
        else
            if part (i).y > 0 then
                part (i).yvel -= GRAV   %gravity
            end if
            if part (i).y < 0 then
                part (i).y := 0
                part (i).yvel := -part (i).yvel * TRANSFER
            end if
            if part (i).x >= maxx then
                part (i).x := 1
                %part (i).xvel := -part (i).xvel * TRANSFER  %bounce off right wall
                %part (i).on := false
            end if
            if part (i).x  0 then
        result 90
    elsif x = 0 and y < 0 then
        result 270
    elsif y = 0 and x > 0 then
        result 0
    elsif y = 0 and x < 0 then
        result 180
    elsif x > 0 and y > 0 then
        result arctand (y / x)
    elsif x < 0 and y > 0 then
        result 180 + arctand (y / x)
    elsif x > 0 and y < 0 then
        result 360 + arctand (y / x)
    elsif x < 0 and y < 0 then
        result 180 + arctand (y / x)
    else
        result 0
    end if
end getMouseAngle


proc getInput
    Mouse.Where (mousex, mousey, mouseClick)
    if mouseClick = 1 then
        spawnParticle (mousex, mousey)
    end if
end getInput

proc physics
    for i : 1 .. upper (part)

        Input.KeyDown (chars)
        if chars (' ') then
            mouseAngle := getMouseAngle (mousex - part (i).x, mousey - part (i).y)  %%Help from compsci.ca
            part (i).xvel += cosd (mouseAngle) * 2 %Help from http://compsci.ca/v3/viewtopic.php?t=17607
            part (i).yvel += sind (mouseAngle) * 2 % help from http://compsci.ca/v3/viewtopic.php?t=17607
        elsif chars (KEY_CTRL) then
            mouseAngle := getMouseAngle (mousex - part (i).x, mousey - part (i).y)          %%Help from compsci.ca
            part (i).xvel += -cosd (mouseAngle) * 2 %Help from http://compsci.ca/v3/viewtopic.php?t=17607
            part (i).yvel += -sind (mouseAngle) * 2 % help from http://compsci.ca/v3/viewtopic.php?t=17607
        end if

        part (i).prevSize := part (i).size

        if part (i).gettingSmaller then
            part (i).size -= 1
        elsif ~part (i).gettingSmaller then
            part (i).size += 1
        end if

        if part (i).size >= MAXSIZE or part (i).size  0 then
                part (i).yvel -= GRAV   %gravity
            end if
           /* if part (i).y < 0 then
             part (i).y := 0
             part (i).yvel := -part (i).yvel * TRANSFER
             end if
             if part (i).x >= maxx then
             part (i).x := 1 %infinite walls
             %part (i).xvel := -part (i).xvel * TRANSFER  %bounce off right wall
             %part (i).on := false
             end if
             if part (i).x  0 then
        result 90
    elsif x = 0 and y < 0 then
        result 270
    elsif y = 0 and x > 0 then
        result 0
    elsif y = 0 and x < 0 then
        result 180
    elsif x > 0 and y > 0 then
        result arctand (y / x)
    elsif x < 0 and y > 0 then
        result 180 + arctand (y / x)
    elsif x > 0 and y < 0 then
        result 360 + arctand (y / x)
    elsif x < 0 and y < 0 then
        result 180 + arctand (y / x)
    else
        result 0
    end if
end getMouseAngle


proc getInput
    Mouse.Where (mousex, mousey, mouseClick)
    if mouseClick = 1 then
        spawnParticle (mousex, mousey)
    end if
end getInput

proc physics
    for i : 1 .. upper (part)

        Input.KeyDown (chars)
        if chars (' ') then
            mouseAngle := getMouseAngle (mousex - part (i).x, mousey - part (i).y)  %%Help from compsci.ca
            part (i).xvel += cosd (mouseAngle) * 2 %Help from http://compsci.ca/v3/viewtopic.php?t=17607
            part (i).yvel += sind (mouseAngle) * 2 % help from http://compsci.ca/v3/viewtopic.php?t=17607
        elsif chars (KEY_CTRL) then
            mouseAngle := getMouseAngle (mousex - part (i).x, mousey - part (i).y)          %%Help from compsci.ca
            part (i).xvel += -cosd (mouseAngle) * 2 %Help from http://compsci.ca/v3/viewtopic.php?t=17607
            part (i).yvel += -sind (mouseAngle) * 2 % help from http://compsci.ca/v3/viewtopic.php?t=17607
        end if



        if part (i).x = NULL & part (i).y = NULL then
            %do nothing
        else
            if part (i).y > 0 then
                part (i).yvel -= GRAV   %gravity
            end if
             if part (i).y < 0 then
             part (i).y := 0
             part (i).yvel := -part (i).yvel * TRANSFER
             end if
             if part (i).y > maxy then
             part (i).y := maxy
             part (i).yvel := -part (i).yvel * TRANSFER
             end if
             if part (i).x >= maxx then
             part (i).x := maxx - 1 %infinite walls
             part (i).xvel := -part (i).xvel * TRANSFER  %bounce off right wall
             %part (i).on := false
             end if
             if part (i).x 