: AyaanScript+ — GEOMETRY DASH+ (full game)
:
: Auto-runner with multiple game modes, level select, noclip cheat,
: downloaded online icon sprite, parallax background.
:
: TITLE SCREEN
:   1 / 2 / 3  - pick level
:   ESC        - quit
:
: GAMEPLAY
:   SPACE      - cube: jump   |   ship: thrust upward (hold)
:   N          - toggle noclip
:   M          - cycle game mode (cube / ship)
:   R          - restart level
:   ESC        - back to menu

const W = 800
const H = 600
gui_native "AyaanScript+ - Geometry Dash+" W H
gui_fps 60

: ====================================================================
:  ASSET BOOTSTRAP — try to download an icon sprite; fall back to shape
: ====================================================================
: A small yellow GD-style cube sprite via placehold.co (stable URL).
psyska -/ "Downloading player icon..."
curl "https://placehold.co/40x40/FFDD44/000000.png?text=GD" "/tmp/gd_icon.png"
gui_2d_load_image "icon" "/tmp/gd_icon.png"
gui_2d_image_size "icon" icon_w icon_h
set has_icon = 0
if icon_w > 0
    set has_icon = 1
    psyska -/ "Icon loaded ({icon_w}x{icon_h})"
endif

: parallax cloud sprite (also from web)
curl "https://placehold.co/100x60/FFFFFF/E0E8FF.png" "/tmp/gd_cloud.png"
gui_2d_load_image "cloud" "/tmp/gd_cloud.png"
gui_2d_color_key "#ff00ff"

: ====================================================================
:  GAME CONSTANTS
: ====================================================================
const PLAYER_X = 150
const PLAYER_SIZE = 40
const GROUND_Y = 480
const PLAYER_REST_Y = 440
const GRAVITY = 0.9
const JUMP_VEL = -16
const SHIP_THRUST = -0.85
const SHIP_GRAVITY = 0.55
const SCROLL_SPEED = 6
const CEILING_Y = 80

: ====================================================================
:  LEVEL DATA (3 levels — parallel arrays for selected level)
: ====================================================================
: Level 1 — "Stereo Madness" — basic cube level
list L1_x = [550, 720, 880, 1050, 1280, 1450, 1700, 1900, 2150, 2350, 2550, 2800, 3050, 3280, 3500, 3700, 3950, 4250, 4550, 4900]
list L1_t = [0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0]
list L1_h = [0, 0, 0, 80, 0, 60, 0, 0, 80, 0, 100, 60, 0, 0, 80, 0, 0, 0, 80, 0]
const L1_GOAL = 5200
const L1_MODE_SWITCH = 99999

: Level 2 — "Polargeist" — denser, mixed
list L2_x = [500, 650, 800, 950, 1100, 1300, 1500, 1700, 1900, 2100, 2300, 2500, 2700, 2900, 3100, 3300, 3500, 3700, 3900, 4100]
list L2_t = [0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0]
list L2_h = [0, 60, 0, 100, 0, 0, 80, 0, 60, 100, 0, 0, 80, 0, 60, 0, 0, 100, 0, 0]
const L2_GOAL = 4400
const L2_MODE_SWITCH = 99999

: Level 3 — "Ship Trial" — ship mode after 1200 units
list L3_x = [550, 800, 1500, 1700, 1900, 2100, 2300, 2500, 2700, 2900, 3100, 3300, 3500, 3700, 3900, 4100, 4300, 4500, 4700, 4900]
list L3_t = [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
list L3_h = [0, 0, 120, 80, 140, 100, 60, 120, 80, 140, 100, 60, 120, 80, 140, 100, 60, 120, 80, 140]
const L3_GOAL = 5200
const L3_MODE_SWITCH = 1200

const N_OBS = 20

: ====================================================================
:  GAME STATE
: ====================================================================
set state = "menu"
set level = 1
set py = PLAYER_REST_Y
set vy = 0
set on_ground = 1
set world_offset = 0
set rotation = 0
set score = 0
set noclip = 0
set mode = 0
set last_n = 0
set last_m = 0
set last_r = 0
set last_space = 0
set last_1 = 0
set last_2 = 0
set last_3 = 0
set last_esc = 0
set running = 1
set frame = 0
set ship_angle = 0

func load_level
    if level == 1
        lclear obs_x
        lclear obs_t
        lclear obs_h
        foreach v in L1_x
            push obs_x v
        endforeach
        foreach v in L1_t
            push obs_t v
        endforeach
        foreach v in L1_h
            push obs_h v
        endforeach
        set goal_x = L1_GOAL
        set mode_switch = L1_MODE_SWITCH
    endif
    if level == 2
        lclear obs_x
        lclear obs_t
        lclear obs_h
        foreach v in L2_x
            push obs_x v
        endforeach
        foreach v in L2_t
            push obs_t v
        endforeach
        foreach v in L2_h
            push obs_h v
        endforeach
        set goal_x = L2_GOAL
        set mode_switch = L2_MODE_SWITCH
    endif
    if level == 3
        lclear obs_x
        lclear obs_t
        lclear obs_h
        foreach v in L3_x
            push obs_x v
        endforeach
        foreach v in L3_t
            push obs_t v
        endforeach
        foreach v in L3_h
            push obs_h v
        endforeach
        set goal_x = L3_GOAL
        set mode_switch = L3_MODE_SWITCH
    endif
endfunc

list obs_x = []
list obs_t = []
list obs_h = []
set goal_x = 5200
set mode_switch = 99999

func reset_player
    set py = PLAYER_REST_Y
    set vy = 0
    set on_ground = 1
    set world_offset = 0
    set rotation = 0
    set score = 0
    set mode = 0
    set ship_angle = 0
endfunc

: ====================================================================
:  MAIN LOOP
: ====================================================================
while running == 1
    gui_open running
    if running == 0
        break
    endif

    gui_key_down "esc" -> esc

    if state == "menu"
        : background
        gui_gradient_rect 0 0 W H "#1a1428" "#3a2848"

        : title
        gui_text_big 180 80 "GEOMETRY DASH+" "white" 4
        gui_text 280 160 "Built on AyaanScript+" "lightgray"

        : levels
        gui_fill_rect 200 220 400 60 "#3a4060"
        gui_rect 200 220 400 60 "white"
        gui_text 220 240 "1.  Stereo Madness (Cube)" "yellow"
        gui_text 220 258 "    20 obstacles, classic cube" "lightgray"

        gui_fill_rect 200 300 400 60 "#3a4060"
        gui_rect 200 300 400 60 "white"
        gui_text 220 320 "2.  Polargeist (Cube, harder)" "yellow"
        gui_text 220 338 "    Denser obstacle pattern" "lightgray"

        gui_fill_rect 200 380 400 60 "#3a4060"
        gui_rect 200 380 400 60 "white"
        gui_text 220 400 "3.  Ship Trial (Cube + Ship)" "yellow"
        gui_text 220 418 "    Auto-switches to ship at 1200" "lightgray"

        gui_text 200 480 "Press 1, 2, or 3 to play.  N=noclip  ESC=quit" "white"
        gui_text 200 500 "In game: SPACE jump/thrust  M=cycle mode  R=restart" "lightgray"

        : draw icon preview if loaded
        if has_icon == 1
            gui_2d_draw_image 700 250 "icon"
        else
            gui_fill_rect 700 250 40 40 "#ffdd44"
            gui_rect 700 250 40 40 "black"
        endif

        if esc == 1
            set running = 0
        endif

        gui_key_down "1" -> k1
        gui_key_down "2" -> k2
        gui_key_down "3" -> k3
        gui_key_down "n" -> kn
        if kn == 1
            if last_n == 0
                set noclip = {1 - noclip}
            endif
            set last_n = 1
        else
            set last_n = 0
        endif
        if k1 == 1
            set level = 1
            call load_level
            call reset_player
            set state = "playing"
        endif
        if k2 == 1
            set level = 2
            call load_level
            call reset_player
            set state = "playing"
        endif
        if k3 == 1
            set level = 3
            call load_level
            call reset_player
            set state = "playing"
        endif
    endif

    if state == "playing"
        : background — parallax sky
        gui_gradient_rect 0 0 W H "#3a5078" "#789ac8"

        : parallax clouds
        set cloud_off = {int(world_offset / 4) - int(world_offset / 4 / 250) * 250}
        set ci = 0
        repeat 4 ci
            set cx = {(ci - 1) * 250 - cloud_off}
            set cy = {80 + (ci - 1) * 30}
            gui_2d_draw_image_scaled cx cy 100 60 "cloud"
        endrepeat

        : parallax mountains
        set mtn_off = {int(world_offset / 2) - int(world_offset / 2 / 400) * 400}
        set mi = 0
        repeat 4 mi
            set mx = {(mi - 1) * 400 - mtn_off}
            gui_fill_triangle mx 480 {mx + 200} 280 {mx + 400} 480 "#4a6090"
            gui_fill_triangle {mx + 100} 480 {mx + 300} 320 {mx + 500} 480 "#5a70a0"
        endrepeat

        : ground
        gui_fill_rect 0 GROUND_Y W {H - GROUND_Y} "#1a1a25"
        gui_fill_rect 0 GROUND_Y W 4 "white"
        if mode == 1
            : ship-mode ceiling
            gui_fill_rect 0 0 W CEILING_Y "#1a1a25"
            gui_fill_rect 0 {CEILING_Y - 4} W 4 "white"
        endif

        : ===== INPUT =====
        if esc == 1
            if last_esc == 0
                set state = "menu"
            endif
            set last_esc = 1
        else
            set last_esc = 0
        endif

        gui_key_down "space" -> ks
        gui_key_down "n" -> kn
        gui_key_down "m" -> km
        gui_key_down "r" -> kr2

        if kn == 1
            if last_n == 0
                set noclip = {1 - noclip}
            endif
            set last_n = 1
        else
            set last_n = 0
        endif
        if km == 1
            if last_m == 0
                set mode = {1 - mode}
            endif
            set last_m = 1
        else
            set last_m = 0
        endif
        if kr2 == 1
            if last_r == 0
                call reset_player
                call load_level
            endif
            set last_r = 1
        else
            set last_r = 0
        endif

        : auto-switch to ship at preset distance
        if world_offset > mode_switch
            if mode == 0
                set mode = 1
                set vy = 0
            endif
        endif

        : ===== PHYSICS BY MODE =====
        if mode == 0
            : cube mode
            if ks == 1
                if on_ground == 1
                    set vy = JUMP_VEL
                    set on_ground = 0
                endif
            endif
            set vy = {vy + GRAVITY}
            set py = {py + vy}
            if py >= PLAYER_REST_Y
                set py = PLAYER_REST_Y
                set vy = 0
                set on_ground = 1
            endif
            if on_ground == 0
                set rotation = {rotation + 0.16}
            endif
        endif
        if mode == 1
            : ship mode
            if ks == 1
                set vy = {vy + SHIP_THRUST}
            else
                set vy = {vy + SHIP_GRAVITY}
            endif
            : clamp velocity
            if vy > 10
                set vy = 10
            endif
            if vy < -10
                set vy = -10
            endif
            set py = {py + vy}
            : ceiling
            if py < CEILING_Y
                set py = CEILING_Y
                set vy = 0
            endif
            : floor
            if py >= PLAYER_REST_Y
                set py = PLAYER_REST_Y
                set vy = 0
            endif
            : visual angle based on velocity
            set ship_angle = {vy * 0.08}
        endif

        : advance world
        set world_offset = {world_offset + SCROLL_SPEED}
        set score = {int(world_offset / 10)}

        : ===== COLLISIONS (skip if noclip) =====
        if noclip == 0
            set i = 0
            repeat N_OBS i
                set k = {i - 1}
                list_at obs_x k -> ox
                list_at obs_t k -> ot
                list_at obs_h k -> oh
                set sx = {ox - world_offset}
                if sx > 100
                    if sx < 220
                        if ot == 0
                            set dx_to_spike = {sx + 20 - PLAYER_X - 20}
                            if dx_to_spike > -38
                                if dx_to_spike < 35
                                    if py > 410
                                        set state = "game_over"
                                    endif
                                endif
                            endif
                        endif
                        if ot == 1
                            set block_top = {GROUND_Y - oh}
                            set bx_left = sx
                            set bx_right = {sx + 60}
                            set px_right = {PLAYER_X + PLAYER_SIZE}
                            set overlap_x = 0
                            if px_right > bx_left
                                if PLAYER_X < bx_right
                                    set overlap_x = 1
                                endif
                            endif
                            if overlap_x == 1
                                set p_bottom = {py + PLAYER_SIZE}
                                if mode == 0
                                    if vy >= 0
                                        if p_bottom > block_top
                                            if p_bottom < {block_top + 18}
                                                set py = {block_top - PLAYER_SIZE}
                                                set vy = 0
                                                set on_ground = 1
                                            endif
                                        endif
                                    endif
                                    if py + PLAYER_SIZE > block_top + 20
                                        set state = "game_over"
                                    endif
                                endif
                                if mode == 1
                                    set state = "game_over"
                                endif
                            endif
                        endif
                    endif
                endif
            endrepeat
        endif

        : ===== WIN CHECK =====
        if world_offset > goal_x
            set state = "won"
        endif

        : ===== DRAW OBSTACLES =====
        set ri = 0
        repeat N_OBS ri
            set rk = {ri - 1}
            list_at obs_x rk -> ox
            list_at obs_t rk -> ot
            list_at obs_h rk -> oh
            set sx = {ox - world_offset}
            if sx > -100
                if sx < W
                    if ot == 0
                        gui_fill_triangle sx GROUND_Y {sx + 40} GROUND_Y {sx + 20} {GROUND_Y - 40} "#ff4444"
                        gui_line sx GROUND_Y {sx + 20} {GROUND_Y - 40} "#ffaaaa"
                    endif
                    if ot == 1
                        set by = {GROUND_Y - oh}
                        gui_fill_rect sx by 60 oh "#44aaff"
                        gui_rect sx by 60 oh "white"
                        gui_fill_rect sx by 60 4 "#aaddff"
                    endif
                endif
            endif
        endrepeat

        : goal flag
        set gsx = {goal_x - world_offset}
        if gsx > -50
            if gsx < {W + 50}
                gui_fill_rect gsx {GROUND_Y - 120} 4 120 "white"
                gui_fill_triangle {gsx + 4} {GROUND_Y - 120} {gsx + 64} {GROUND_Y - 100} {gsx + 4} {GROUND_Y - 80} "#ffdd33"
                gui_text gsx {GROUND_Y - 130} "GOAL" "yellow"
            endif
        endif

        : ===== DRAW PLAYER =====
        set cx = {PLAYER_X + 20}
        set cy = {py + 20}
        set use_rot = rotation
        if mode == 1
            set use_rot = ship_angle
        endif
        set cr = {cos(use_rot)}
        set sr = {sin(use_rot)}
        set s = 20
        set c1x = {cx + (0 - s) * cr - (0 - s) * sr}
        set c1y = {cy + (0 - s) * sr + (0 - s) * cr}
        set c2x = {cx + s * cr - (0 - s) * sr}
        set c2y = {cy + s * sr + (0 - s) * cr}
        set c3x = {cx + s * cr - s * sr}
        set c3y = {cy + s * sr + s * cr}
        set c4x = {cx + (0 - s) * cr - s * sr}
        set c4y = {cy + (0 - s) * sr + s * cr}
        set color_p = "#ffdd44"
        if mode == 1
            set color_p = "#44ffdd"
        endif
        if noclip == 1
            set color_p = "#aa44ff"
        endif
        gui_fill_triangle c1x c1y c2x c2y c3x c3y color_p
        gui_fill_triangle c1x c1y c3x c3y c4x c4y color_p
        gui_line c1x c1y c2x c2y "black"
        gui_line c2x c2y c3x c3y "black"
        gui_line c3x c3y c4x c4y "black"
        gui_line c4x c4y c1x c1y "black"
        : in ship mode, add a small thrust trail
        if mode == 1
            if ks == 1
                gui_fill_circle {PLAYER_X - 5} {py + 30} 5 "#ff8844"
                gui_fill_circle {PLAYER_X - 12} {py + 35} 3 "#ffaa44"
            endif
        endif

        : ===== HUD =====
        gui_text_big 20 20 "DASH+" "white" 2
        gui_text 100 20 "score:" "white"
        gui_text 160 20 score "yellow"
        set mode_label = "CUBE"
        if mode == 1
            set mode_label = "SHIP"
        endif
        gui_text 20 60 "mode:" "white"
        gui_text 70 60 mode_label "cyan"
        if noclip == 1
            gui_text 130 60 "[NOCLIP]" "magenta"
        endif

        : progress bar
        set bar_x = 250
        set bar_y = 25
        set bar_w = 400
        set bar_h = 20
        gui_rect bar_x bar_y bar_w bar_h "white"
        set prog = {int(world_offset * bar_w / goal_x)}
        if prog > bar_w
            set prog = bar_w
        endif
        gui_fill_rect {bar_x + 2} {bar_y + 2} prog {bar_h - 4} "#44ff66"

        gui_text 20 H - 30 "SPACE jump/thrust  N noclip  M mode  R restart  ESC menu" "lightgray"

        set frame = {frame + 1}
    endif

    if state == "game_over"
        gui_clear "#0a0a14"
        gui_fill_rect 180 200 440 220 "#000000"
        gui_rect 180 200 440 220 "red"
        gui_text_big 270 230 "GAME OVER" "red" 3
        gui_text 290 300 "Score:" "white"
        gui_text 360 300 score "yellow"
        gui_text 250 340 "R to retry  |  ESC to menu" "lightgray"
        gui_key_down "r" -> krg
        if krg == 1
            if last_r == 0
                call reset_player
                call load_level
                set state = "playing"
            endif
            set last_r = 1
        else
            set last_r = 0
        endif
        if esc == 1
            if last_esc == 0
                set state = "menu"
            endif
            set last_esc = 1
        else
            set last_esc = 0
        endif
    endif

    if state == "won"
        gui_clear "#001020"
        gui_fill_rect 180 200 440 220 "#000000"
        gui_rect 180 200 440 220 "yellow"
        gui_text_big 290 230 "YOU WIN!" "yellow" 3
        gui_text 290 300 "Final score:" "white"
        gui_text 430 300 score "yellow"
        gui_text 250 340 "R to retry  |  ESC to menu" "lightgray"
        gui_key_down "r" -> krw
        if krw == 1
            if last_r == 0
                call reset_player
                call load_level
                set state = "playing"
            endif
            set last_r = 1
        else
            set last_r = 0
        endif
        if esc == 1
            if last_esc == 0
                set state = "menu"
            endif
            set last_esc = 1
        else
            set last_esc = 0
        endif
    endif

    gui_update
endwhile

gui_close
psyska -/ "Goodbye!"
