Posted: Sun Jan 18, 2009 10:14 pm Post subject: 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
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
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
part (i).x := maxx - 1
%part (i).xvel := -part (i).xvel * TRANSFER %bounce off left wall
%part (i).x := 0
end if
end if
part (i).xvel *= AIR
part (i).x += round (part (i).xvel) %adding the x and y vel to the a and y position
part (i).y += round (part (i).yvel)
end for
end physics
proc gfx
drawfillbox (0, 0, maxx, maxy, BACKCOL) %background
for i : 1 .. upper (part)
%drawfillbox (part (i).x, part (i).y, part (i).x + 5, part (i).y + 5, part (i).col) %particle
drawdot (part (i).x, part (i).y, part (i).col) %particle
end for
View.Update
end gfx
loop
getInput
physics
gfx
Time.DelaySinceLast (30)
end loop
[/code][/syntax]
Sponsor Sponsor
saltpro15
Posted: Sun Jan 18, 2009 10:15 pm Post subject: RE:Particle Engine
cool, great job lawson
Amit
Posted: Sun Jan 18, 2009 10:29 pm Post subject: Re: Particle Engine
Very impressive, this is one of the better particle engines I've seen. Just one thing I saw, you wrote
Turing:
if part (i).x = NULL & part (i).y = NULL then %do nothing else
*physics code*
It does that same thing, but it gets rid of the unnecessary else statement.
zero-impact
Posted: Sun Jan 18, 2009 10:29 pm Post subject: Re: Particle Engine
Hey uhm saltpro I dont believe I know who you are?
and thanks Amit, I'm glad you caught that
Amit
Posted: Sun Jan 18, 2009 10:34 pm Post subject: Re: Particle Engine
No problem, glad to help. One other thing, there is a constant FRIC that never seems to get used. Something you were going to include?
zero-impact
Posted: Mon Jan 19, 2009 7:34 am Post subject: RE:Particle Engine
Oh yea it was just to stop the particles from sliding along the floor but the air friction works fine.
saltpro15
Posted: Mon Jan 19, 2009 1:15 pm Post subject: RE:Particle Engine
drew
zero-impact
Posted: Mon Jan 19, 2009 3:06 pm Post subject: Re: Particle Engine
oooh hey
Sponsor Sponsor
SNIPERDUDE
Posted: Thu Jan 22, 2009 10:18 am Post subject: RE:Particle Engine
This is a great improvement from last years, I remember it quite well. I'm very surprised at the speed it's running, much faster than mine or any other I've seen, kudos. One thing that should be done I think is make the particles go invisible when the particles stop moving or have a constant altitude (stop moving vertically).
Awesome job 8)
zero-impact
Posted: Thu Jan 22, 2009 6:42 pm Post subject: Re: Particle Engine
Thanks a lot SNIPERDUDE. I'm very surprised that you actually remembered that from the first version I posted.
This is just a small modification I did to show my teacher some things you could do with it.
type particle :
record
x : int
y : int
xvel : real
yvel : real
col : int
prevSize : int
size : int
gettingSmaller : boolean
shape : int %1 box 2 oval
end record
const MAXPART := 2000
const SPAWNRATE := 10
const GRAV : real := 0
const AIR : real := 0.99
const TRANSFER : real := 0.5
const FRIC := 0.8
const NULL := 9876543
const BACKCOL : int := black
const MAXSIZE := 20
var mousex, mousey, mouseClick : int
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
part (i).prevSize := -1
part (i).size := 0
part (i).gettingSmaller := true
part (i).shape := 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)
part (currentPart).size := Rand.Int (1, MAXSIZE - 1)
part (currentPart).shape := Rand.Int (1, 6)
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 += -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
if part (i).prevSize < part (i).size then
part (i).gettingSmaller := true
else
part (i).gettingSmaller := false
end if
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 %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
part (i).x := maxx - 1 %infinite walls
%part (i).xvel := -part (i).xvel * TRANSFER %bounce off left wall
%part (i).x := 0
end if*/
end if
part (i).xvel *= AIR
part (i).yvel *= AIR
part (i).x += round (part (i).xvel) %adding the x and y vel to the a and y position
part (i).y += round (part (i).yvel)
end for
end physics
proc gfx
drawfillbox (0, 0, maxx, maxy, BACKCOL) %background
for i : 1 .. upper (part)
%drawoval (part (i).x, part (i).y, part (i).size, part (i).size, part (i).col) %particle
if part (i).shape = 1 then
drawfillbox (part (i).x, part (i).y, part (i).x + part (i).size, part (i).y + part (i).size, part (i).col)
elsif part (i).shape = 2 then
drawfilloval (part (i).x, part (i).y, part (i).size, part (i).size, part (i).col)
elsif part (i).shape = 3 then
drawbox (part (i).x, part (i).y, part (i).x + part (i).size, part (i).y + part (i).size, part (i).col)
elsif part (i).shape = 4 then
drawoval (part (i).x, part (i).y, part (i).size, part (i).size, part (i).col)
elsif part (i).shape = 5 then
drawstar (part (i).x, part (i).y, part (i).x + part (i).size, part (i).y + part (i).size, part (i).col)
elsif part (i).shape = 6 then
drawfillstar (part (i).x, part (i).y, part (i).x + part (i).size, part (i).y + part (i).size, part (i).col)
end if
%drawdot (part (i).x, part (i).y, part (i).col) %particle
end for
View.Update
end gfx
loop
getInput
physics
gfx
Time.DelaySinceLast (30)
end loop
saltpro15
Posted: Thu Jan 22, 2009 6:51 pm Post subject: RE:Particle Engine
oh lawson, just had to one-up paul's particle engine eh? xD
A.J
Posted: Thu Jan 22, 2009 9:01 pm Post subject: Re: Particle Engine
congrats
you really outdone yourslef (200 lines....wow)
instead of the stars and the constantly shrinking/growing ovals, why not actually have particles instead ? (like dots, for instance)
but u did a really good job
well done!
zero-impact
Posted: Fri Jan 23, 2009 12:31 pm Post subject: Re: Particle Engine
Drew- lol not really. Just seeing his inspired me to improve mine a bit.
A.J. - You can very easily change it back to particles if you look at the gfx procedure. You just have to take out the if statements and replace it with drawdot (part (i).x, part (i).y, part (i).col) The stars and such were just to spruce it up a little :p
This is a miniputt game a friend of mine did for his final assignment. It uses the particle engine for the stars.