NaaLaa
Parallax - Printable Version

+- NaaLaa (https://www.naalaa.com/forum)
+-- Forum: NaaLaa (https://www.naalaa.com/forum/forum-1.html)
+--- Forum: AI "Slop" (https://www.naalaa.com/forum/forum-11.html)
+--- Thread: Parallax (/thread-413.html)



Parallax - 1micha.elok - 08-04-2026

Parallax in game dev is a visual trick where background layers move slower than the stuff up front to make a flat 2D game look deep....

Code:
'====================================================
' PARALLAX AUTO-SCROLL DEMO v2 - 3 minute cycle
' - blinking stars (sin-driven alpha twinkle)
' - moon drawn with draw ellipse + glow halo
' - mountain silhouettes from sin() contours
' - treeline & trees with varied heights
'====================================================

set window "Parallax Demo", 384, 224, false, 2
set redraw off

constant SCROLL_SPEED = 90.0    ' camera pixels per frame
constant WORLD_W = 1535.0       ' one-way travel distance
visible CYCLE = 4 * WORLD_W / SCROLL_SPEED  ' = 180 seconds
constant GROUND_Y = 180

visible cam = [] ; cam.x = 0

' --- Build foreground trees with VARIED sizes (once, at startup) ---
' Deterministic per run. Add "randomize time()" above for a new forest each run.
visible trees = [] ; trees.num = 0
for i = 0 to 9
    trees[i] = []
    trees[i].x = i * 100 + rnd(0, 60)   ' scattered across world 0..960
    trees[i].w = 14 + rnd(0, 16)        ' width  varies 14-30
    trees[i].h = 28 + rnd(0, 38)        ' height varies 28-66
next
trees.num = 10

' ================= MAIN LOOP =================
do

    ' --- AUTO-SCROLL CAMERA (triangle wave / ping-pong) ---
    ' phase 0..0.5 : camera moves RIGHT  (0 -> WORLD_W)
    ' phase 0.5..1 : camera moves LEFT   (WORLD_W -> 0)
    t = (clock() / 1000) % CYCLE
    phase = t / CYCLE
    if phase < 0.5 then
        cam.x = WORLD_W * (phase * 2)
    else
        cam.x = WORLD_W * (2 - phase * 2)
    endif

    ' ==================== DRAWING ====================

    ' LAYER 0: Night sky (fixed, depth 0 - never moves)
    set color 10, 10, 30; draw rect 0, 0, 384, 224, true

    ' LAYER 1: BLINKING STARS (depth 0.5, wrapped with %)
    ' Alpha oscillates via sin(); each star gets its own phase offset
    ' so they twinkle independently instead of pulsing in sync
    tw = clock() / 500
    for s = 0 to 5
        alpha = int(128 + 127 * sin(tw + s * 1.7))
        set color 255, 255, 255, alpha
        sx = int((150 + s * 73 - cam.x * 0.5) % 440)
        sy = 14 + (s * 29) % 70      ' deterministic y scatter
        sz = 2 + s % 2               ' sizes alternate 2px / 3px
        draw rect sx, sy, sz, sz, true
    next
    set color 255, 255, 255, 255     ' restore full opacity

    ' LAYER 2: MOON with soft glow (depth 0.1, now draw ellipse)
    moonX = int(300 - cam.x * 0.1)
    set color 200, 200, 255, 40
    draw ellipse moonX, 60, 26, 26, true    ' faint glow halo
    set color 200, 200, 255
    draw ellipse moonX, 60, 16, 16, true    ' moon body
    set color 170, 170, 225
    draw ellipse moonX - 5, 56, 4, 4, true  ' craters
    draw ellipse moonX + 6, 64, 3, 3, true

    ' LAYER 3: MOUNTAIN SILHOUETTES via sin() contours (depth 0.2)
    ' made of TWO blended sine frequencies = natural mountain outline
    set color 40, 40, 60
    for mx = 0 to 384
        wx = mx + cam.x * 0.2                ' world x under this column
        mh = 70 + 45 * sin(wx / 45) + 18 * sin(wx / 19)
        draw rect mx, int(GROUND_Y - mh), 7, int(mh), true
    next

    ' LAYER 4: TREELINE with varying canopy heights (depth 0.5)
    ' Same slicing trick, higher frequencies = bumpy treetops
    set color 30, 50, 30
    for tx = 0 to 384
        wx = tx + cam.x * 0.5
        th = 28 + 14 * sin(wx / 23) + 9 * sin(wx / 11 + 1)
        draw rect tx, int(GROUND_Y - th), 11, int(th), true
    next

    ' LAYER 5: FOREGROUND TREES, varied sizes (depth 0.8)
    ' Precomputed table + tiled copies every 1000px = infinite forest
    set color 20, 30, 20
    for j = -1 to 1
        for i = 0 to trees.num - 1
            fx = int(trees[i].x + j * 1000 - cam.x * 0.8)
            if fx > -80 and fx < 460 then
                draw rect fx, GROUND_Y - trees[i].h, trees[i].w, trees[i].h, true
            endif
        next
    next

    ' LAYER 6: Ground = player layer (depth 1.0 - "real" world)
    set color 60, 40, 20; draw rect int(-cam.x), GROUND_Y, 1500, 50, true

    ' cycle timer proof
    set color 255, 255, 255
    set caret 8, 8
    'wln "Cycle : " + str(int(t)) + " / " + str(int(CYCLE)) + " sec"
    wln "cam.x : " + str(int(cam.x))
    wln "ESC to quit"

    redraw
    fwait 60
until keydown(KEY_ESCAPE)

Edited to make the mountains smoother


RE: Parallax - johnno56 - 08-04-2026

Cool... Nicely done!


RE: Parallax - 1micha.elok - 08-06-2026

(08-04-2026, 12:36 PM)johnno56 Wrote: Cool... Nicely done!

Please retry the updated code. I made some tweaks to smooth out the mountains.


RE: Parallax - Marcus - 08-06-2026

Very nice Smile