` Fireworks
 
` Dave Mayes
 
` Setup max fireworks
NumFireworks = 719
` Set number of sparks per firework
NumSparks = 99
 
` Number of modes
Modes = 11
 
` set firework mode
FireMode = rnd(Modes)
 
` Set resolution
set display mode 640,480,32
hide mouse
 
` Set max frame rate
sync rate 0
sync on
 
` firework data type
type tfirework
    state as integer
    x as float
    y as float
    xspeed as float
    yspeed as float
    burst as dword
endtype
 
`spark data type
type tspark
    x as float
    y as float
    xspeed as float
    yspeed as float
    life as float
endtype
 
` firework array
dim firework(NumFireworks) as tfirework
` spark array
dim spark(NumSparks,NumFireworks) as tspark
 
` Gravity value (nss)
gravity = 1
` Launch counter
Launch = 500
` Setup Offset
Offset = 0
` Mouse Click Test
HitMouse = 0
 
` setup initial fitework state (Dead)
for f = 0 to NumFireworks
    firework(f).state = 2
next f
 
 
`Main Loop
repeat
 
`   Clear screen for every other mode
    if (FireMode and 1) = 0 then   cls
 
`   lock display memory for extra speed
    lock pixels
 
`   Loop through the lanched fireworks
    for f = 0 to int(Launch / 25)
 
`       read firework status
        fs = firework(f).state
 
`       decide what to do
        if fs = 0 then gosub shoot
        if fs = 1 then gosub shower
        if fs = 2 then gosub newfirework
 
`   Update Offset
    inc Offset
 
`   on to the next firework
    next f
 
`   get frame rate
    fr = screen fps()
 
`   increase launched counter to max if frame rate still high enough
    if fr > 30 and Launch < NumFireworks * 25 then inc Launch
 
`   release display memory
    unlock pixels
 
`   display stats
    nf$ = "Number of fireworks " + str$(1 + int(Launch / 25))
    ns$ = "Number of sparks " + str$((1 + int(Launch / 25)) * (1 + NumSparks))
    fp$ = "Frames Per Second " + str$(fr)
    text 0,0,nf$
    text 0,10,ns$
    text 0,20,fp$
 
`   show frame
    sync
 
`   Check for left mouse button
    if MouseClick() = 1 and HitMouse = 0 and FireMode >0
        dec FireMode
        HitMouse = 1
    endif
 
`   Check for right mouse button
    if MouseClick() = 2 and HitMouse = 0 and FireMode < Modes
        inc FireMode
        hitMouse = 1
    endif
 
`   Check for no mouse buttons
    if MouseClick() = 0 then HitMouse = 0
 
` end of main loop
until spacekey()
end
 
` shoot firework into air
shoot:
 
` adjust position and add gravity
firework(f).x = firework(f).x + firework(f).xspeed * 0.99
firework(f).y = firework(f).y + firework(f).yspeed
firework(f).yspeed = firework(f).yspeed + gravity
 
` change state if not moving up the screen
if firework(f).yspeed > 0
    firework(f).state = 1
endif
 
` get updates co-ordinates
x# = firework(f).x
y# = firework(f).y
 
` get firework colour
r = rgbr(firework(f).burst)
g = rgbg(firework(f).burst)
b = rgbb(firework(f).burst)
 
` loop through each spark
for s = 0 to NumSparks
 
`   scale spark colour down to a third of normal
    sl# = spark(s,f).life / 300.0
 
`   draw spark
    dot x# + spark(s,f).xspeed,y# + spark(s,f).yspeed,rgb(r * sl#, g * sl#, b * sl#)
next sl
 
return
 
` display shower
shower:
 
` get co-ordinates
x# = firework(f).x
y# = firework(f).y
 
` get firework colour
r = rgbr(firework(f).burst)
g = rgbg(firework(f).burst)
b = rgbb(firework(f).burst)
 
` reset life counter
life = 0
 
` loop through each spark
for s = 0 to NumSparks
 
`   decrease spark life counter if more than zero
    if spark(s,f).life > 0
        dec spark(s,f).life
    endif
 
`   get spark life as percentage
    sl# = spark(s,f).life / 100.0
 
`   work on aprks that are alive and in the air
    if sl# > 0 and spark(s,f).y < screen height()
 
`       Increase life counter
        inc life
 
`       update spark position
        spark(s,f).x = spark(s,f).x + spark(s,f).xspeed
        spark(s,f).y = spark(s,f).y + spark(s,f).yspeed
 
`       adjust spark speed
        spark(s,f).xspeed = spark(s,f).xspeed * 0.99
        spark(s,f).yspeed = spark(s,f).yspeed + (gravity / 20.0)
 
`       draw spark
        dot x# + spark(s,f).x,y# + spark(s,f).y,rgb(r * sl#, g * sl#, b * sl#)
    endif
 
next s
 
` change state for dead fireworks
if life = 0
    firework(f).state = 2
endif
 
return
 
` create / recycle a firework
newfirework:
 
CurrentMode = FireMode
if CurrentMode > Modes - 2 then CurrentMode = rnd(Modes - 1)
 
if CurrentMode < 2
`   Mouse controlled
    firework(f).state = 1
    firework(f).x = mousex()
    firework(f).y = mousey()
endif
 
if CurrentMode = 2 or CurrentMode = 3
`   Set position to bottom center of screen
    firework(f).state = 0
    firework(f).x = screen width() / 2: `rnd(screen width())
    firework(f).y = screen height() - 1
endif
 
if CurrentMode = 4 or CurrentMode = 5
`   Cirlce Mode
    firework(f).state = 1
    firework(f).x = (screen width() / 2) + cos(offset * 0.05) * (screen height() / 4)
    firework(f).y = (screen height() / 2) + sin(offset * 0.05) * (screen height() / 4)
endif
 
if CurrentMode = 6 or CurrentMode = 7
`   Cirlce Mode
    firework(f).state = 1
    firework(f).x = (screen width() / 2) + cos(offset * 0.09) * (screen height() / 4)
    firework(f).y = (screen height() / 2) + sin(offset * 0.05) * (screen height() / 4)
endif
 
if CurrentMode = 8 or CurrentMode = 9
`   Cirlce Mode
    firework(f).state = 1
    firework(f).x = (screen width() / 2) + cos(offset * 0.05) * (screen height() / 4)
    firework(f).y = (screen height() / 2) + sin(offset * 0.09) * (screen height() / 4)
endif
 
 
` choose randon speeds for direction variables
firework(f).xspeed = (rnd(101) - 50)/5.0
firework(f).yspeed = -23 + (rnd(101) - 50)/15.0
 
` pick a colour, any colour
firework(f).burst = rgb(rnd(255),rnd(255),rnd(255))
 
` loop through each spark
for s = 0 to NumSparks
 
`   reset spark offset
    spark(s,f).x = 0
    spark(s,f).y = 0
 
`   choose random speed for directions
    a = rnd(359)
    r# = rnd(200) / 100.0 + .02
    spark(s,f).xspeed = cos(a) * r#
    spark(s,f).yspeed = sin(a) * r# - 1
 
`   set life between 80 and 100 percent
    spark(s,f).life = 100 - rnd(20)
 
next s
return