• Welcome to Dark Bit Factory & Gravity.
 

Some particle FX[BB2D]

Started by mike_g, December 30, 2006

Previous topic - Next topic

0 Members and 0 Guests are viewing this topic.

mike_g

Ive been coding in Blitz for about a year now, but only just got round to having a go at doing particle effects. Theres some pretty amazing stuff on this site. Makes me feel kinda dumb. Anyway heres my attempt. Its kinda like a slinky thing that follows the mouse around.

Graphics 1024, 768
Global particles = CreateImage(GraphicsWidth(), GraphicsHeight())
Global count, oldtime, fps ;for fps
Global mode
Global col_timer, col_change
SeedRnd MilliSecs()

Type particle
Field x#, y#, id, ang#, spd
;For colour effects
Field r, g, b; rf, gf, bf
;for circle particles. start size and expand rate
Field rad#, expand#, expand_max
End Type

Global rf =5
Global gf =5
Global bf =5

SetBuffer BackBuffer()
While Not KeyHit(1)
Cls
If mode = 0
NEW_BURST(MouseX(), MouseY(),10)
CIRCLE_PARTICLES(0)
Text 460, 0, "MOVE THE MOUSE"
If mousehit(1) Then mode = 1
COL_CHANGE()
Else
If Rand(0, 2) = 0 Then NEW_BURST(Rand(0, 1023), Rand(0, 768),Rand(10, 30))
CIRCLE_PARTICLES(1)
t=t+ 1
If t > 100
mode = 0
t=0
EndIf
EndIf

DrawImage particles, 0, 0
FPS()
Flip
Wend

;---------------------------;
Function NEW_BURST(x_pos, y_pos, parts)
a_step# = Float(360)/parts
test = a_step#
For i = 1 To parts
p.particle = New particle
p\x = x_pos
p\y = y_pos
p\ang# = angle#
angle# = angle# + a_step#


p\expand = 0.1
p\rad = 0.1
p\expand_max = 10
p\spd = 1
p\rad = 0.1
p\expand_max = 30
p\spd = 1
If mode = 1 Then p\expand = Float(Rand(1, 5))/10

p\r = 255
p\g = 255
p\b = 255
Next
End Function
;---------------------------;
Function CIRCLE_PARTICLES(fill)
SetBuffer ImageBuffer(particles)
Cls
LockBuffer
For p.particle = Each particle
If p\x < -rad Or p\x >= GraphicsWidth()+rad Or p\y < -rad Or p\y >= GraphicsWidth()+rad
Delete p.particle
Else
If p\rad# < p\expand_max Then p\rad# = p\rad# + p\expand#


If p\r >= rf Then p\r = p\r - rf
If p\g >= gf Then p\g = p\g - gf
If p\b >= bf Then p\b = p\b - bf
col = (p\r Shl 16) + (p\g Shl 8) + p\b

p\x = p\x +Cos(p\ang)*p\spd
p\y = p\y +Sin(p\ang)*p\spd
If fill = 0
CIRCLE(p\x, p\y, p\rad, col)
Else
F_CIRCLE(p\x, p\y, p\rad, col)
EndIf
If col <= (rf Shl 16)+(gf Shl 8)+bf Then Delete p.particle
EndIf
Next


UnlockBuffer
SetBuffer BackBuffer()
End Function
;---------------------------;
Function CIRCLE(cx, cy, rad, col)
inc# = Float(360/(rad*Pi*2))
steps = 360/inc#
For i = 0 To steps
x = (cx - rad * Cos(deg#))
y = (cy - rad * Sin(deg#))
If x >= 0 And x < GraphicsWidth() And y >= 0 And y < GraphicsHeight()
WritePixelFast x, y, col
EndIf
deg# = deg# + inc#
Next
End Function
;---------------------------;
Function F_CIRCLE(cx, cy, rad, col)
inc# = Float(360/(rad*Pi*2))
steps = 90/inc#
For i = 0 To steps
x1 = (cx - rad * Cos(deg#))
y1 = (cy - rad * Sin(deg#))

x2 = cx+cx-x1
y2 = cy+cy-y1

If x1 < 0 Then x1 = 0
If x2 > 1023 Then x2 = 1023
If y1 < 0 Then y1 = 0
If y1 > 767 Then y1 = 767
If y2 < 0 Then y2 = 0
If y2 > 767 Then y2 = 767

For x = x1 To x2
WritePixelFast x, y1, col
Next
For x = x1 To x2
WritePixelFast x, y2, col
Next
deg# = deg# + inc#
Next
End Function
;---------------------------;
Function FPS()
Text 0, 0, "FPS: "+fps
time = MilliSecs() - oldtime
count = count + 1
If time >= 1000
fps = count
count = 0
oldtime=MilliSecs()
EndIf
End Function
;---------------------------;
Function COL_CHANGE()
col_timer = col_timer + 1
If col_timer = 10
col_timer = 0
If col_change = 0
rf = rf - 1
If rf = 0
col_change = col_change + 1
EndIf
Else If col_change = 1
rf = rf + 1
gf = gf - 1
If gf = 0
col_change = col_change + 1
EndIf
Else If col_change = 2
bf = bf - 1
gf = gf + 1
If bf = 0
col_change = col_change + 1
EndIf
Else If col_change = 3
rf = rf - 1
gf = gf - 1
bf = bf + 1
If rf = 0
col_change = col_change + 1
EndIf
Else If col_change = 4
rf = rf + 1
bf = bf - 1
If bf = 0
col_change = col_change + 1
EndIf
Else If col_change = 5
bf = bf + 1
gf = gf + 1
If bf = 5
col_change =  0
EndIf
EndIf
EndIf
End Function

Shockwave

Cheers for the source :) I can't run it on this comp as I don't have blitz installed but have some karma. Someone else will be able to run it.  O0
Shockwave ^ Codigos
Challenge Trophies Won:

mike_g

#2
What no BB? Oh well. I uploaded an exe to my site for anyone that aint got it here
Stupid brinkster dosent let me do remote linking. So you will have to click on the "Particle Thing" link there.



Shockwave

Thanks for the exe :) And that is bloody good. I like the explosions :)
Shockwave ^ Codigos
Challenge Trophies Won:

mike_g

Thanx. Yeah the explosions arent too bad. My FPS goes down to about 30 though when they go off. (My laptops got a 1.46ghz Athlon + 16MB mobility U1 graphics card). Anyway I plan on working on the speed a bit and adding more different kinds of effects. Hopefully I'll be able to use some of this stuff in a game someday.

Stonemonkey

Nice stuff but i get a MAV a few moments after clicking the mouse :( possibly something being drawn offscreen?

Jim

#6
Me too, it crashes with the explosions.  Nice fx though!

edit: I think you need to check y1 and y2 more carefully in the 2nd loop.

Jim
Challenge Trophies Won:

mike_g

#7
Thats really strange. Doesent crash for me. I dont think that the problem would be that its drawing off screen.

This is the code that constarains the empty circle to the screen:
If x >= 0 And x < GraphicsWidth() And y >= 0 And y < GraphicsHeight()
And this constarins the filled circles (x1 = x start pos; x2 = x end pos, etc):
If x1 < 0 Then x1 = 0
If x2 >= GraphicsWidth() Then x2 =GraphicsWidth()-1
If y1 < 0 Then y1 = 0
If y2 >= GraphicsHeight() Then y2 = GraphicsHeight()-1


If either of you guys have Blitz Basic. You could try run the prog with the debug on. That might help me to find out what going wrong. Cheers.

EDIT:
Quote from: Jimedit: I think you need to check y1 and y2 more carefully in the 2nd loop.
Will do. /EDIT

Ghost^BHT

Nice effect :)
change your bounds checking to this:
        If x1 < 0 Then x1 = 0
   If x2 > 767 Then x2 =767
   If y1 < 0 Then y1 = 0
   If y1 > 767 y1 = 767
   If y2 < 0 Then y2 = 0
   If y2 > 767 Then y2 =  767
should work

mike_g

Okay cool. I modified the code and uploaded the new exe.

Only thing I did different was do this:  If x2 > 1023 Then x2 = 1023
Instead of this: If x2 > 767 Then x2 =767

As I figured it may have been a typo. Then again maybe it wasent but hopefully it should fix things.

Jim

Yeah, that looks like a typo.  You've fixed it though and it works like a charm now.

It would make a really cool demo if you added some automatic mouse movements (sine waves, etc) and even timed it in with some music.

It's a really nice effect.

Jim
Challenge Trophies Won:

mike_g

Quote from: JimIt would make a really cool demo if you added some automatic mouse movements (sine waves, etc) and even timed it in with some music.

Yeah mabe next year :P In the mean time have fun peeps  :D

Jim

It's next year now.  Where is it!? :p :D :D

Jim
Challenge Trophies Won:

mike_g

Okay. Heres something for the new year :D The movements automatic now, no sound yet though.

I also replaced my empty circle function with a Bresenham version wrote by Gosse as its over twice as fast.

I uploaded an exe here. Its the fizzy vortex link.

And heres the code:

Graphics 1024, 768
Global particles = CreateImage(GraphicsWidth(), GraphicsHeight())
Global count, oldtime, fps ;for fps
Global mode
Global col_timer, col_change
SeedRnd MilliSecs()

Type particle
Field x#, y#, id, ang#, spd
;For colour effects
Field r, g, b; rf, gf, bf
;for circle particles. start size and expand rate
Field rad#, expand#, expand_max
End Type

Global rf =10
Global gf =10
Global bf =10

cx = 512: cy = 360: radius = 100
radmod = 1: degmod = 5

SetBuffer BackBuffer()
While Not KeyHit(1)
Cls
If mode = 0
degree = degree + degmod
If degree = 360 Then degree = 0

radius = radius + radmod
If radius > 300 Then radmod = -1
If radius < 50 Then radmod = 1

x_pos = (cx - radius * Cos(degree))
y_pos = (cy - radius * Sin(degree))
x_pos2 = (cx + radius * Cos(degree))
y_pos2 = (cy + radius * Sin(degree))

NEW_BURST(x_pos, y_pos, 8)
NEW_BURST(x_pos2, y_pos2, 8)

CIRCLE_PARTICLES(0)
Text 460, 0, "MOVE THE MOUSE"
If MouseHit(1)  Then mode = 1
If MouseHit(2) degmod = - degmod
COL_CHANGE()
Else
If Rand(0, 2) = 0 Then NEW_BURST(Rand(0, 1023), Rand(0, 768),Rand(10, 30))
CIRCLE_PARTICLES(1)
t=t+ 1
If t > 100
mode = 0
t=0
EndIf
EndIf

DrawImage particles, 0, 0
FPS()
Flip
Wend
;---------------------------;
Function NEW_BURST(x_pos, y_pos, parts)
a_step# = Float(360)/parts
test = a_step#
For i = 1 To parts
p.particle = New particle
p\x = x_pos
p\y = y_pos
p\ang# = Rand(0, 356)
p\expand = 0.1
p\rad = 0.1
p\expand_max = 10
p\spd = 1
p\rad = 0.1
p\expand_max = 30
p\spd = 1
If mode = 1 Then p\expand = Float(Rand(1, 5))/10

p\r = 255
p\g = 255
p\b = 255
Next
End Function
;---------------------------;
Function CIRCLE_PARTICLES(fill)
SetBuffer ImageBuffer(particles)
Cls
LockBuffer
For p.particle = Each particle
If p\x < -rad Or p\x >= GraphicsWidth()+rad Or p\y < -rad Or p\y >= GraphicsWidth()+rad
Delete p.particle
Else
If p\rad# < p\expand_max Then p\rad# = p\rad# + p\expand#


If p\r >= rf Then p\r = p\r - rf
If p\g >= gf Then p\g = p\g - gf
If p\b >= bf Then p\b = p\b - bf
col = (p\r Shl 16) + (p\g Shl 8) + p\b

p\x = p\x +Cos(p\ang)*p\spd
p\y = p\y +Sin(p\ang)*p\spd
If fill = 0
CIRCLE(p\x, p\y, p\rad, col)
Else
F_CIRCLE(p\x, p\y, p\rad, col)
EndIf
If col <= (rf Shl 16)+(gf Shl 8)+bf Then Delete p.particle
EndIf
Next


UnlockBuffer
SetBuffer BackBuffer()
End Function
;---------------------------;
Function CIRCLE(cx, cy, radius, col)
   d = 3 - (radius Shl 1)
   x = 0
   y = radius
   LockBuffer
   Repeat
      WritePixel cx + x, cy + y, col
      WritePixel cx + x, cy - y, col
      WritePixel cx - x, cy + y, col
      WritePixel cx - x, cy - y, col
      WritePixel cx + y, cy + x, col
      WritePixel cx + y, cy - x, col
      WritePixel cx - y, cy + x, col
      WritePixel cx - y, cy - x, col
      If d < 0 Then
         d = d + (x Shl 2) + 6
      Else
         d = d + ((x-y) Shl 2) + 10
         y = y - 1
      End If
      x = x + 1
   Until x > y
   UnlockBuffer
End Function
;---------------------------;
Function F_CIRCLE(cx, cy, rad, col)
inc# = Float(360/(rad*Pi*2))
steps = 90/inc#
For i = 0 To steps
x1 = (cx - rad * Cos(deg#))
y1 = (cy - rad * Sin(deg#))

x2 = cx+cx-x1
y2 = cy+cy-y1

If x1 < 0 Then x1 = 0
If x2 > 1023 Then x2 = 1023
If y1 < 0 Then y1 = 0
If y1 > 767 Then y1 = 767
If y2 < 0 Then y2 = 0
If y2 > 767 Then y2 = 767

For x = x1 To x2
WritePixelFast x, y1, col
Next
For x = x1 To x2
WritePixelFast x, y2, col
Next
deg# = deg# + inc#
Next
End Function
;---------------------------;
Function FPS()
Text 0, 0, "FPS: "+fps
time = MilliSecs() - oldtime
count = count + 1
If time >= 1000
fps = count
count = 0
oldtime=MilliSecs()
EndIf
End Function
;---------------------------;
Function COL_CHANGE()
col_timer = col_timer + 1
If col_timer = 10
col_timer = 0
If col_change = 0
rf = rf - 1
If rf = 0
col_change = col_change + 1
EndIf
Else If col_change = 1
rf = rf + 1
gf = gf - 1
If gf = 0
col_change = col_change + 1
EndIf
Else If col_change = 2
bf = bf - 1
gf = gf + 1
If bf = 0
col_change = col_change + 1
EndIf
Else If col_change = 3
rf = rf - 1
gf = gf - 1
bf = bf + 1
If rf = 0
col_change = col_change + 1
EndIf
Else If col_change = 4
rf = rf + 1
bf = bf - 1
If bf = 0
col_change = col_change + 1
EndIf
Else If col_change = 5
bf = bf + 1
gf = gf + 1
If bf = 5
col_change =  0
EndIf
EndIf
EndIf
End Function

Ghost^BHT

Nice.  :clap: But to be honest I liked the the other effect better. It looked like tentacles

Paul

I really like the second one better  :)
I will bite you - http://s5.bitefight.se/c.php?uid=31059
Challenge Trophies Won:

taj

Thanks for posting an exe mike_g ... it helps lamers like me who dont have basic set up.
I felt like I was falling into an endless glass of champagne watching that. Too much New Year.
It'll make a really good addition to an underwater scene.

Nicely optimised now too.

Challenge Trophies Won:

mike_g

To be honest I'm not sure which I like best. I might one longer demo that does both. At the moment I am thinking about writing a function to draw empty squares with rounded corners. If I can get that done I could then put a couple of extra parameters in it and have the circles morph into squares and back. Anyway thanks for the feedback guys.