: AyaanScript+ — Fireworks display
: Click anywhere with the mouse to launch a firework!
: Rockets fly up, explode into particles, particles fall with gravity.

const W = 800
const H = 600
gui_native "AyaanScript+ — Fireworks" W H
gui_fps 60

: rockets (active flying-up firework cores)
list rxs = []
list rys = []
list rvxs = []
list rvys = []
list rcols = []

: explosion particles
list pxs = []
list pys = []
list pvxs = []
list pvys = []
list plife = []
list pcols = []

set gravity = 0.18
set running = 1
set last_mouse = 0
set frame = 0
set PI = 3.14159265

set autolaunch_timer = 0

while running == 1
    gui_open running
    if running == 0
        break
    endif

    : night sky gradient
    gui_gradient_rect 0 0 W H "#000010" "#1a0040"
    gui_text_big 20 20 "FIREWORKS" "white" 2
    gui_text 20 60 "CLICK to launch  |  ESC quits" "lightgray"

    : auto-launch every ~60 frames if nothing on screen
    set autolaunch_timer = {autolaunch_timer + 1}
    if autolaunch_timer > 50
        rand sx 100 700
        rand cidx 0 4
        rand jitter -3 3
        set jx = {jitter / 5}
        push rxs sx
        push rys 580
        push rvxs jx
        push rvys -11
        if cidx == 0
            push rcols "#ff5555"
        endif
        if cidx == 1
            push rcols "#55ff55"
        endif
        if cidx == 2
            push rcols "#5599ff"
        endif
        if cidx == 3
            push rcols "#ffff55"
        endif
        if cidx == 4
            push rcols "#ff55ff"
        endif
        set autolaunch_timer = 0
    endif

    : mouse launch
    gui_mouse_down lmb
    if lmb == 1
        if last_mouse == 0
            gui_mouse_x mx
            gui_mouse_y my
            rand cidx 0 4
            push rxs mx
            push rys 580
            push rvxs 0
            set rvy = {0 - sqrt(2 * gravity * (580 - my))}
            push rvys rvy
            if cidx == 0
                push rcols "#ff5555"
            endif
            if cidx == 1
                push rcols "#55ff55"
            endif
            if cidx == 2
                push rcols "#5599ff"
            endif
            if cidx == 3
                push rcols "#ffff55"
            endif
            if cidx == 4
                push rcols "#ff55ff"
            endif
        endif
        set last_mouse = 1
    else
        set last_mouse = 0
    endif

    : update + draw rockets
    lsize rxs -> nr
    set ri = 0
    list new_rxs = []
    list new_rys = []
    list new_rvxs = []
    list new_rvys = []
    list new_rcols = []
    repeat nr ri
        set ridx = {ri - 1}
        list_at rxs ridx -> rx
        list_at rys ridx -> ry
        list_at rvxs ridx -> rvx
        list_at rvys ridx -> rvy
        list_at rcols ridx -> rcol
        set rvy = {rvy + gravity}
        set rx = {rx + rvx}
        set ry = {ry + rvy}

        : draw the rocket as glowing dot + trail
        gui_fill_circle rx ry 3 rcol
        gui_fill_circle rx {ry + 4} 2 rcol
        gui_pixel rx {ry + 8} rcol

        if rvy >= 0
            : peak reached - explode!
            set pcount = 0
            repeat 32 pcount
                set ang = {pcount * 2 * PI / 32}
                rand sp 3 7
                set pvx = {cos(ang) * sp}
                set pvy = {sin(ang) * sp}
                push pxs rx
                push pys ry
                push pvxs pvx
                push pvys pvy
                push plife 60
                push pcols rcol
            endrepeat
        else
            push new_rxs rx
            push new_rys ry
            push new_rvxs rvx
            push new_rvys rvy
            push new_rcols rcol
        endif
    endrepeat
    list rxs = []
    list rys = []
    list rvxs = []
    list rvys = []
    list rcols = []
    foreach v in new_rxs
        push rxs v
    endforeach
    foreach v in new_rys
        push rys v
    endforeach
    foreach v in new_rvxs
        push rvxs v
    endforeach
    foreach v in new_rvys
        push rvys v
    endforeach
    foreach v in new_rcols
        push rcols v
    endforeach

    : update + draw explosion particles
    lsize pxs -> np
    set pi = 0
    list new_pxs = []
    list new_pys = []
    list new_pvxs = []
    list new_pvys = []
    list new_plife = []
    list new_pcols = []
    repeat np pi
        set pidx = {pi - 1}
        list_at pxs pidx -> px
        list_at pys pidx -> py
        list_at pvxs pidx -> pvx
        list_at pvys pidx -> pvy
        list_at plife pidx -> life
        list_at pcols pidx -> pcol

        set pvy = {pvy + gravity / 2}
        set pvx = {pvx * 0.98}
        set px = {px + pvx}
        set py = {py + pvy}
        set life = {life - 1}

        : alpha fade
        set a = {life * 4}
        if a > 255
            set a = 255
        endif
        if a < 0
            set a = 0
        endif
        gui_alpha_pixel px py pcol a
        set px2 = {px + 1}
        gui_alpha_pixel px2 py pcol a
        set py2 = {py + 1}
        gui_alpha_pixel px py2 pcol a

        if life > 0
            push new_pxs px
            push new_pys py
            push new_pvxs pvx
            push new_pvys pvy
            push new_plife life
            push new_pcols pcol
        endif
    endrepeat
    list pxs = []
    list pys = []
    list pvxs = []
    list pvys = []
    list plife = []
    list pcols = []
    foreach v in new_pxs
        push pxs v
    endforeach
    foreach v in new_pys
        push pys v
    endforeach
    foreach v in new_pvxs
        push pvxs v
    endforeach
    foreach v in new_pvys
        push pvys v
    endforeach
    foreach v in new_plife
        push plife v
    endforeach
    foreach v in new_pcols
        push pcols v
    endforeach

    gui_key_down "esc" -> esc
    if esc == 1
        set running = 0
    endif

    set frame = {frame + 1}
    gui_update
endwhile

gui_close
