: AyaanScript+ — GEOMETRY DASH+ (full game with multiple modes)
:
: Auto-runner with cube/ship/ball/UFO modes, level select, noclip cheat,
: real emoji icons downloaded via curl, parallax background.
:
: TITLE SCREEN
:   1 / 2 / 3 / 4  - pick level
:   N              - toggle noclip
:   ESC            - quit
:
: GAMEPLAY
:   SPACE      - cube: jump | ship: thrust | ball: flip gravity | UFO: flap
:   N          - toggle noclip
:   M          - cycle game mode (cube -> ship -> ball -> UFO)
:   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 — real emoji icons via emojicdn.elk.sh CDN
:  Uses tempfile to resolve a cross-platform path (works on Linux + Windows)
: ====================================================================
psyska -/ "Downloading real icons from emojicdn..."

tempfile "gd_cube.png"  -> p_cube
tempfile "gd_ship.png"  -> p_ship
tempfile "gd_ball.png"  -> p_ball
tempfile "gd_ufo.png"   -> p_ufo
tempfile "gd_cloud.png" -> p_cloud
tempfile "gd_spike.png" -> p_spike

: cube (yellow square emoji)
curl "https://emojicdn.elk.sh/%F0%9F%9F%A8" p_cube
gui_2d_load_image "cube_icon" p_cube

: ship (rocket emoji)
curl "https://emojicdn.elk.sh/%F0%9F%9A%80" p_ship
gui_2d_load_image "ship_icon" p_ship

: ball (black circle emoji)
curl "https://emojicdn.elk.sh/%E2%9A%AB" p_ball
gui_2d_load_image "ball_icon" p_ball

: UFO (flying saucer emoji)
curl "https://emojicdn.elk.sh/%F0%9F%9B%B8" p_ufo
gui_2d_load_image "ufo_icon" p_ufo

: cloud (white cloud emoji)
curl "https://emojicdn.elk.sh/%E2%98%81%EF%B8%8F" p_cloud
gui_2d_load_image "cloud" p_cloud

: spike (red triangle emoji) — for HUD only
curl "https://emojicdn.elk.sh/%F0%9F%94%BA" p_spike
gui_2d_load_image "spike_icon" p_spike

gui_2d_color_key "#ff00ff"
psyska -/ "Icons loaded."

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

: ====================================================================
:  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 ball_grav_dir = 1
set ball_flip_cd = 0
set last_n = 0
set last_m = 0
set last_r = 0
set last_space = 0
set last_esc = 0
set running = 1
set frame = 0
set ship_angle = 0
set goal_x = 5200
set mode_switch = 99999
set start_mode = 0

list obs_x = []
list obs_t = []
list obs_h = []

func load_level
    lclear obs_x
    lclear obs_t
    lclear obs_h
    set start_mode = 0
    set mode_switch = 99999
    if level == 1
        : Stereo Madness — cube
        list obs_x = [550, 720, 880, 1050, 1280, 1450, 1700, 1900, 2150, 2350, 2550, 2800, 3050, 3280, 3500, 3700, 3950, 4250, 4550, 4900]
        list obs_t = [0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0]
        list obs_h = [0, 0, 0, 80, 0, 60, 0, 0, 80, 0, 100, 60, 0, 0, 80, 0, 0, 0, 80, 0]
        set goal_x = 5200
        set start_mode = 0
    endif
    if level == 2
        : Polargeist — denser
        list obs_x = [500, 650, 800, 950, 1100, 1300, 1500, 1700, 1900, 2100, 2300, 2500, 2700, 2900, 3100, 3300, 3500, 3700, 3900, 4100]
        list obs_t = [0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0]
        list obs_h = [0, 60, 0, 100, 0, 0, 80, 0, 60, 100, 0, 0, 80, 0, 60, 0, 0, 100, 0, 0]
        set goal_x = 4400
        set start_mode = 0
    endif
    if level == 3
        : Ship Trial — switches to ship at 1200
        list obs_x = [550, 800, 1500, 1700, 1900, 2100, 2300, 2500, 2700, 2900, 3100, 3300, 3500, 3700, 3900, 4100, 4300, 4500, 4700, 4900]
        list obs_t = [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
        list obs_h = [0, 0, 120, 80, 140, 100, 60, 120, 80, 140, 100, 60, 120, 80, 140, 100, 60, 120, 80, 140]
        set goal_x = 5200
        set mode_switch = 1200
        set start_mode = 0
    endif
    if level == 4
        : Ball + UFO mix
        list obs_x = [550, 750, 950, 1150, 1400, 1600, 1800, 2000, 2200, 2400, 2700, 2900, 3100, 3300, 3500, 3700, 3900, 4100, 4300, 4500]
        list obs_t = [0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1]
        list obs_h = [0, 0, 100, 60, 120, 0, 0, 80, 140, 60, 0, 0, 100, 80, 140, 0, 0, 120, 60, 100]
        set goal_x = 4800
        set mode_switch = 800
        set start_mode = 2
    endif
endfunc

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 = start_mode
    set ball_grav_dir = 1
    set ball_flip_cd = 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"
        gui_gradient_rect 0 0 W H "#1a1428" "#3a2848"

        gui_text_big 180 60 "GEOMETRY DASH+" "white" 4
        gui_text 280 140 "Built on AyaanScript+" "lightgray"

        : level buttons
        gui_fill_rect 200 180 400 50 "#3a4060"
        gui_rect 200 180 400 50 "white"
        gui_text 220 195 "1.  Stereo Madness (Cube)" "yellow"
        gui_text 220 213 "    20 obstacles, classic cube mode" "lightgray"

        gui_fill_rect 200 240 400 50 "#3a4060"
        gui_rect 200 240 400 50 "white"
        gui_text 220 255 "2.  Polargeist (Cube, harder)" "yellow"
        gui_text 220 273 "    Denser obstacle pattern" "lightgray"

        gui_fill_rect 200 300 400 50 "#3a4060"
        gui_rect 200 300 400 50 "white"
        gui_text 220 315 "3.  Ship Trial (Cube + Ship)" "yellow"
        gui_text 220 333 "    Switches to ship at distance 1200" "lightgray"

        gui_fill_rect 200 360 400 50 "#3a4060"
        gui_rect 200 360 400 50 "white"
        gui_text 220 375 "4.  Ball Madness (Ball + UFO)" "yellow"
        gui_text 220 393 "    Flip-gravity ball, then UFO" "lightgray"

        gui_text 200 440 "Press 1-4 to play.  N = noclip cheat.  ESC = quit." "white"
        gui_text 200 460 "In game: SPACE acts based on mode.  M cycles modes." "lightgray"
        if noclip == 1
            gui_text 200 480 "[NOCLIP ENABLED]" "magenta"
        endif

        : draw the 4 icons preview
        gui_2d_draw_image_scaled 660 180 50 50 "cube_icon"
        gui_2d_draw_image_scaled 660 240 50 50 "ship_icon"
        gui_2d_draw_image_scaled 660 300 50 50 "ball_icon"
        gui_2d_draw_image_scaled 660 360 50 50 "ufo_icon"

        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 "4" -> k4
        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
        if k4 == 1
            set level = 4
            call load_level
            call reset_player
            set state = "playing"
        endif
    endif

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

        : parallax clouds (real emoji PNG)
        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 80 50 "cloud"
        endrepeat

        : parallax mountains (shapes)
        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
            gui_fill_rect 0 0 W CEILING_Y "#1a1a25"
            gui_fill_rect 0 {CEILING_Y - 4} W 4 "white"
        endif
        if mode == 3
            : UFO mode has ceiling too
            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 = {mode + 1}
                if mode > 3
                    set mode = 0
                endif
                set vy = 0
                set ball_grav_dir = 1
            endif
            set last_m = 1
        else
            set last_m = 0
        endif
        if kr2 == 1
            if last_r == 0
                call reset_player
            endif
            set last_r = 1
        else
            set last_r = 0
        endif

        : auto-switch at preset distance
        if world_offset > mode_switch
            if mode == start_mode
                set mode = {start_mode + 1}
                if mode > 3
                    set mode = 1
                endif
                set vy = 0
            endif
        endif

        : ===== PHYSICS BY MODE =====
        if mode == 0
            : === CUBE: gravity + jump ===
            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: thrust on hold ===
            if ks == 1
                set vy = {vy + SHIP_THRUST}
            else
                set vy = {vy + SHIP_GRAVITY}
            endif
            if vy > 10
                set vy = 10
            endif
            if vy < -10
                set vy = -10
            endif
            set py = {py + vy}
            if py < CEILING_Y
                set py = CEILING_Y
                set vy = 0
            endif
            if py >= PLAYER_REST_Y
                set py = PLAYER_REST_Y
                set vy = 0
            endif
            set ship_angle = {vy * 0.08}
        endif
        if mode == 2
            : === BALL: gravity in current direction, SPACE flips it ===
            set ball_flip_cd = {ball_flip_cd - 1}
            if ks == 1
                if ball_flip_cd <= 0
                    set ball_grav_dir = {0 - ball_grav_dir}
                    set ball_flip_cd = BALL_FLIP_COOLDOWN
                endif
            endif
            set vy = {vy + GRAVITY * ball_grav_dir}
            if vy > 12
                set vy = 12
            endif
            if vy < -12
                set vy = -12
            endif
            set py = {py + vy}
            if py >= PLAYER_REST_Y
                set py = PLAYER_REST_Y
                set vy = 0
            endif
            if py < CEILING_Y
                set py = CEILING_Y
                set vy = 0
            endif
            set rotation = {rotation + 0.12}
        endif
        if mode == 3
            : === UFO: tap to flap (instant velocity) ===
            if ks == 1
                if last_space == 0
                    set vy = UFO_FLAP_VEL
                endif
                set last_space = 1
            else
                set last_space = 0
            endif
            set vy = {vy + SHIP_GRAVITY}
            if vy > 12
                set vy = 12
            endif
            set py = {py + vy}
            if py < CEILING_Y
                set py = CEILING_Y
                set vy = 0
            endif
            if py >= PLAYER_REST_Y
                set py = PLAYER_REST_Y
                set vy = 0
            endif
            set ship_angle = {vy * 0.05}
        endif
        if mode != 3
            set last_space = 0
        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 20 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 == 2
                                    if py + PLAYER_SIZE > block_top + 20
                                        set state = "game_over"
                                    endif
                                    if vy >= 0
                                        if p_bottom > block_top
                                            if p_bottom < {block_top + 18}
                                                set py = {block_top - PLAYER_SIZE}
                                                set vy = 0
                                            endif
                                        endif
                                    endif
                                endif
                                if mode == 1
                                    set state = "game_over"
                                endif
                                if mode == 3
                                    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 20 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
                        : red spike triangle
                        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"
                        gui_line {sx + 40} GROUND_Y {sx + 20} {GROUND_Y - 40} "#aa2222"
                    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 (real emoji icon!) =====
        set icon_name = "cube_icon"
        if mode == 1
            set icon_name = "ship_icon"
        endif
        if mode == 2
            set icon_name = "ball_icon"
        endif
        if mode == 3
            set icon_name = "ufo_icon"
        endif
        : noclip tint via outlined box
        if noclip == 1
            gui_fill_rect {PLAYER_X - 4} {py - 4} {PLAYER_SIZE + 8} {PLAYER_SIZE + 8} "#aa44ff"
        endif
        gui_2d_draw_image_scaled PLAYER_X py PLAYER_SIZE PLAYER_SIZE icon_name
        : ship 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
        : UFO flap visual
        if mode == 3
            if ks == 1
                gui_fill_circle {PLAYER_X + 20} {py + 45} 6 "#aaffff"
            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
        if mode == 2
            set mode_label = "BALL"
        endif
        if mode == 3
            set mode_label = "UFO"
        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  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
                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
                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!"
