Lightning and Fire Works (Explosions / Particle Trails)

Post your FreeBASIC source, examples, tips and tricks here. Please don’t post code without including an explanation.
Post Reply
KristopherWindsor
Posts: 2428
Joined: Jul 19, 2006 19:17
Location: Sunnyvale, CA
Contact:

Lightning and Fire Works (Explosions / Particle Trails)

Post by KristopherWindsor »

These are two seperate programs, but quite similar in coding style and size.
The lightning is drawn with lines, and the fire explosions are drawn with individual pixels.

Code: Select all


' Lightning! v1.0
' (C) 2007 i-TECH and Kristopher Windsor

Const screenx = 800, screeny = 600
Const midx = screenx / 2, midy = screeny / 2
Const ubolt = 3, ulightningbends = 10, shrinkspeed = .7

Type bolt
  As Integer lightningbends 'if one, then the lightning is a straight line from top to bottom
  As Integer midpointsx(0 To ulightningbends)
  As Integer midpointsy(0 To ulightningbends)
  As Integer thewidth
  As Integer timeleft 'frames until lightning turns off
End Type

Screenres screenx, screeny, 32

Dim As Integer fc, pmx, pmy, pmb, mx, my, mb, p
Dim As Integer st
Dim As Double d
Dim As String key
Dim As bolt bolts(1 To ubolt)

Setmouse midx, midy
Sleep 500
st = Timer

Do
  fc += 1
  pmx = mx: pmy = my: pmb = mb
  Getmouse mx, my,, mb

  'redo the first lightning if the mouse moves or a button if pressed / released
  If pmx <> mx Or pmy <> my Or pmb <> mb Then bolts(1).timeleft = 0

  For a As Integer = 1 To ubolt
    With bolts(a)
      If .timeleft Then
        .timeleft -= 1
      Else
        If Int(Rnd * 30) = 0 Then 'don't recreate lightning instantly
          .lightningbends = my * .01 + 1
          'top point
          .midpointsx(0) = mx + (200 * Rnd) * Sgn(Rnd - Rnd)
          .midpointsy(0) = 0 'top of the screen
          'final destination
          .midpointsx(.lightningbends) = mx
          .midpointsy(.lightningbends) = my
          .thewidth = (.midpointsy(.lightningbends) - .midpointsy(0)) * .2
          .timeleft = 30 'about one second
          'define the jagged midpoints
          For b As Integer = 1 To .lightningbends - 1
            .midpointsx(b) = (.midpointsx(.lightningbends) + .midpointsx(0)) * .5 + _
              (.midpointsx(.lightningbends) - .midpointsx(0)) * _
              ((.lightningbends - b) / (.lightningbends + 1#)) * (Rnd - Rnd)
            .midpointsy(b) = (b / (.lightningbends + 1#)) * _
              (.midpointsy(.lightningbends) - .midpointsy(0)) + _
              .midpointsy(0) + (Rnd - Rnd) * 10
          Next b
        End If
      End If
    End With
  Next a

  Screenlock
  Cls
  Print "FPS: " & Int(fc / (Timer - st)) & " "
  'Circle (mx, my), 4, &HFFFFFFFF
  For a As Integer = 1 To ubolt
    With bolts(a)
      If .timeleft Then
        p = .thewidth / shrinkspeed 'undoes the first shrink
        For b As Integer = 0 To .lightningbends - 1
          p *= shrinkspeed
          For c As Integer = 0 To p
            d = Iif(c > p * .5, 1 - c / p, 1 + (c - p) / p) * 3 '*3 gives more white
            'Iif handles colors with too much blue
            Line (.midpointsx(b) + c, .midpointsy(b)) - _
              (.midpointsx(b + 1) + c * shrinkspeed, .midpointsy(b + 1)), _
              Rgb(255, 255, Int(255 * Iif(d > 1, 1#, d)))
          Next c
        Next b
      End If
    End With
  Next a
  Screenunlock

  Sleep 20
  key = Inkey
Loop Until key = Chr(27)
System

Code: Select all


' Fire Works! v1.0
' (C) 2007 i-TECH and Kristopher Windsor

Const screenx = 800, screeny = 600
Const midx = screenx / 2, midy = screeny / 2
Const twopi = 6.283185307179586, upix = 5000, true = -1
Const mode_cancel = 1, mode_bounce = 2, mode_spin = 3, mode_rain = 4

Type dot
  As Double d, o
  'these can be replaced with constants if the fire is not moving
  As Integer x, y
End Type

Screenres screenx, screeny, 32

Dim Shared As Integer fc, mx, my, ms, mb, explosionsize
Dim Shared As Integer mode, xv, yv
Dim Shared As Double st
Dim Shared As String key
Dim Shared As dot pix(1 To upix)

For a As Integer = 1 To upix
  With pix(a)
    .d = 0
    .o = Rnd * twopi
    'center of explosion; only used because the explosion can move piece by piece this way
    .x = midx
    .y = midy
  End With
Next a
Setmouse midx, midy
Locate 2, 1
Print "Press keys [1], [2], [3], and [4] for effects,"
Print "the scroll wheel to change the explosion size,"
Print "or the mouse buttons to clear the screen."
Sleep 500
st = Timer

Do
  fc += 1

  'automatically move the mouse for effect
  Select Case mode
  Case mode_bounce
    'mouse moves and bounces from screen
    mx += xv
    my += yv
    If mx < 0 Then mx = 0: xv =- xv
    If mx >= screenx Then mx = screenx: xv =- xv
    If my < 0 Then my = 0: yv =- yv
    If my >= screeny Then my = screeny: yv =- yv
    Setmouse mx, my
  Case mode_spin
    'mouse spins in circles around the screen (not in an oval shape)
    mx = midx + Cos(fc * .1) * midy '+ Cos(fc * .19) * 250 'additional spinning
    my = midy + Sin(fc * .1) * midy '+ Sin(fc * .19) * 250
    Setmouse mx, my
  Case mode_rain
    'all pix() rain down the screen
    For a As Integer = 1 To upix
      With pix(a)
        .y += 2
      End With
    Next a
  End Select

  'get the mouse after moving it (still gets mb when in bounce mode)
  Getmouse mx, my, ms, mb
  'find explosion size based on the scroll wheel
  explosionsize = Abs(50 + ms * 10)

  Select Case Val(key)
  Case mode_cancel
    mode = mode_cancel 'turn mode off
    Setmouse midx, midy
  Case mode_bounce
    mode = mode_bounce
    xv = (Int(Rnd * 12) + 1) * Sgn(Rnd - Rnd)
    yv = (Int(Rnd * 12) + 1) * Sgn(Rnd - Rnd)
  Case mode_spin
    mode = mode_spin
  Case mode_rain
    mode = mode_rain
  End Select

  For a As Integer = 1 To upix
    With pix(a)
      If Int(Rnd * 5) Then
        .d += Rnd * 3
      Else
        If .d > explosionsize Then
          .d = 0
          .o = Rnd * twopi
          .x = mx
          .y = my
        End If
        .d += Rnd * 3
      End If
    End With
  Next a

  Screenlock
  If mb Then Cls Else Locate 1, 1
  Print "FPS: " & Int(fc / (Timer - st)) & " Explosion size: " & explosionsize & " "
  For b As Integer = 1 To upix
    With pix(b)
      Pset (Cos(.o) * .d + .x, Sin(.o) * .d + .y), Rgb(255, .d + .d, 0)
    End With
  Next b
  Screenunlock

  Sleep 20
  key = Inkey
Loop Until key = Chr(27)
System

Clyde_Radcliffe
Posts: 22
Joined: Aug 29, 2006 11:59
Contact:

Post by Clyde_Radcliffe »

Very impressive dude, nice effects :)

Cheers and all the best,
Clyde.
Skyler
Posts: 242
Joined: Sep 26, 2006 16:30

Post by Skyler »

Cool! It's better than my particle effect I made a while ago.
Mindless
Posts: 110
Joined: Jun 25, 2005 14:50
Location: USA

Post by Mindless »

explosion effect 4 with an explosion size of 0 makes nice blood spots <_<
Zamaster
Posts: 1025
Joined: Jun 20, 2005 21:40
Contact:

Post by Zamaster »

Not bad. There is a much better way to do lightning however. You can produce more organic looking bolts and have a ton of ways to modify it that makes a big difference, very easily. Its also much faster and allows per pixel based effects. The bolt can be slowly morphed and so on. On the downside, it requires alot more memory. The concept is riddiculously
simple:

Get the deltas from point A to point B. Choose a value of chaos (c). Make an Ordered Pair array filled with delta x + delta y elements that define a direction made up of -1, 1 or 0s. Add c/2 x's and c/2 -x's to the end of it for y as well. Shuffle the array, a good shuffle is the amount of elements x2 random swaps. Now, read each array element adding the deltas to an x and y value till you hit the end. You now have a jagged, winding bolt of electricity from point A to B. This can be moded to have only so many points between x and y by changing the 1's and amount of deltas in the list. Very easy, and impressive too! Give it a spin.
counting_pine
Site Admin
Posts: 6323
Joined: Jul 05, 2005 17:32
Location: Manchester, Lancs

Post by counting_pine »

Zamaster wrote:a good shuffle is the amount of elements x2 random swaps.
It's arguable the most intuitive way to randomize an array.
But a more effective way, which ensures all the elements get swapped, is to go through each element of the array in order, and swap it with a (probably different) random element.

Code: Select all

const n as integer = 10
dim as integer i, i2
dim as integer array(0 to n - 1): for i = 0 to n - 1: array(i) = i: next i

print "ordered:",
for i = 0 to n - 1
    print array(i);
next i: print

randomize
for i = 0 to n - 2
    i2 = i + int(rnd * (n - i))
    swap array(i), array(i2)
next i


print "shuffled:",
for i = 0 to n - 1
    print array(i);
next i: print
Zamaster
Posts: 1025
Joined: Jun 20, 2005 21:40
Contact:

Post by Zamaster »

Yeah, I figured Id be corrected on that : )
MythGuyDK
Posts: 22
Joined: Sep 21, 2006 20:01

Post by MythGuyDK »

It doesn't work for me... >_>
KristopherWindsor
Posts: 2428
Joined: Jul 19, 2006 19:17
Location: Sunnyvale, CA
Contact:

Post by KristopherWindsor »

MythGuyDK wrote:It doesn't work for me... >_>
If your computer is running in 800x600 mode, then you need to tell the program to start in full-screen mode. (Windows cannot be the full height of the screen- at least for FB.) Replace the Screenres line with this (add ,, 1):

Screenres screenx, screeny, 32,, 1
anonymous1337
Posts: 5494
Joined: Sep 12, 2005 20:06
Location: California

Post by anonymous1337 »

(Windows cannot be the full height of the screen- at least for FB.)
Since when?! I do this all the time. It is indeed correct to say that it generally causes slowdowns when this is done, however. That should be expected, afaik.
KristopherWindsor
Posts: 2428
Joined: Jul 19, 2006 19:17
Location: Sunnyvale, CA
Contact:

Post by KristopherWindsor »

anonymous1337 wrote:
(Windows cannot be the full height of the screen- at least for FB.)
Since when?! I do this all the time. It is indeed correct to say that it generally causes slowdowns when this is done, however. That should be expected, afaik.
For FB graphic programs on my computer, the display doesn't look right, you can see each new frame being drawn from the top to the bottom of the window, and each frame takes about 2-5 seconds to redraw. I have to minimize the graphic window (which slows the whole computer and makes the mouse invisible), then close the console window behind it. But windows the full width of the screen are fine. :-)
cha0s
Site Admin
Posts: 5319
Joined: May 27, 2005 6:42
Location: USA
Contact:

Post by cha0s »

KristopherWindsor wrote:
anonymous1337 wrote:
(Windows cannot be the full height of the screen- at least for FB.)
Since when?! I do this all the time. It is indeed correct to say that it generally causes slowdowns when this is done, however. That should be expected, afaik.
For FB graphic programs on my computer, the display doesn't look right, you can see each new frame being drawn from the top to the bottom of the window, and each frame takes about 2-5 seconds to redraw. I have to minimize the graphic window (which slows the whole computer and makes the mouse invisible), then close the console window behind it. But windows the full width of the screen are fine. :-)
Sorry, but you're a total lamer. :P You even posted in anonymous1337's other post something inane like "Uh.. I don't see how this is different from my codez :-)"

If you'd run anonymous1337's, you'd see that GDI fixes the "2-5 seconds to redraw". Hello!
KristopherWindsor
Posts: 2428
Joined: Jul 19, 2006 19:17
Location: Sunnyvale, CA
Contact:

Post by KristopherWindsor »

cha0s wrote:
KristopherWindsor wrote:
anonymous1337 wrote:Since when?! I do this all the time. It is indeed correct to say that it generally causes slowdowns when this is done, however. That should be expected, afaik.
For FB graphic programs on my computer, the display doesn't look right, you can see each new frame being drawn from the top to the bottom of the window, and each frame takes about 2-5 seconds to redraw. I have to minimize the graphic window (which slows the whole computer and makes the mouse invisible), then close the console window behind it. But windows the full width of the screen are fine. :-)
Sorry, but you're a total lamer. :P You even posted in anonymous1337's other post something inane like "Uh.. I don't see how this is different from my codez :-)"

If you'd run anonymous1337's, you'd see that GDI fixes the "2-5 seconds to redraw". Hello!
Okay, but it is still easy to start the program in full-screen than to call functions to set the environment. I figured he might be having the same trouble I would if I set my monitor to 800x600. :-)
(But FYI, learning about SetEnviron has not solved my laptop problem, and I cannot get it to run FB programs full-screen. :-|)
DrV
Site Admin
Posts: 2116
Joined: May 27, 2005 18:39
Location: Midwestern USA
Contact:

Post by DrV »

If you are still using the 01 May release, there is a bug with fullscreen in the ddraw driver that is fixed in CVS since 07 May - please try a CVS build and see if this fixes your problem.
MystikShadows
Posts: 612
Joined: Jun 15, 2005 13:22
Location: Upstate NY
Contact:

Post by MystikShadows »

Kristopher, not sure what laptop configuration you have, but here I have a P3 1.2 gHz, 16 Meg video accelerated card (not top notch but still surprisingly responsive :-).

And with that, the FB 0.17b that chaos announced on may 7th doesn't have a problem running full screen (in all supported SCREEN modes).


I have a Dell Latitude if that's any help. ;-)
Post Reply