Better code readability
authorSvjatoslav Agejenko <svjatoslav@svjatoslav.eu>
Tue, 24 Jun 2025 15:28:24 +0000 (18:28 +0300)
committerSvjatoslav Agejenko <svjatoslav@svjatoslav.eu>
Tue, 24 Jun 2025 15:28:24 +0000 (18:28 +0300)
2D GFX/Presentations/strobo.bas
3D GFX/Ray casting engine/raycast.bas
3D GFX/Realtime anaglyph/anaglyph.BAS

index ffcdb33..c79ab5c 100644 (file)
-' Presentation about how to build stroboscope.
-' By Svjatoslav Agejenko.
-' Email: svjatoslav@svjatoslav.eu
-' Homepage: http://www.svjatoslav.eu
-'
-' Changelog:
-' 2002, Initial version
-' 2024, Improved program readability using AI
-
-DECLARE SUB pag4 ()
-DECLARE SUB getkey (a$)
-DECLARE SUB mo ()
-DEFINT A-Z
-DECLARE SUB dra ()
-DECLARE SUB get3d ()
-DECLARE SUB pag3 ()
-DECLARE SUB pag2 ()
-DECLARE SUB getfnt ()
-DECLARE SUB prn (x2%, y%, s%, c%, t$)
-DECLARE SUB pag1 ()
-
-DECLARE SUB start ()
-
-DIM SHARED font(0 TO 7, 0 TO 15, 0 TO 207)
-DIM SHARED det(1 TO 100)
-DIM SHARED px1(1 TO 1000)
-DIM SHARED py1(1 TO 1000)
-DIM SHARED px2(1 TO 1000)
-DIM SHARED py2(1 TO 1000)
-DIM SHARED opx1(1 TO 1000)
-DIM SHARED opy1(1 TO 1000)
-DIM SHARED opx2(1 TO 1000)
-DIM SHARED opy2(1 TO 1000)
-DIM SHARED linc(1 TO 1000)
-
-DIM SHARED myx, myy, myz
-DIM SHARED myx1, myy1, myz1
-DIM SHARED myx2, myy2, myz2
-DIM SHARED tfra
-
-DIM SHARED nl
-
-start
-
-pag1
-pag2
-pag3
-pag4
-END
-
-DATA 0,0,5,-2
-DATA 0,0,5,2
-DATA 0, 0, 15, 0
-
-DATA 15,-2,15,2
-DATA 25,-2,25,2
-DATA 15,-2,25,-2
-DATA 15,2,25,2
-
-DATA 25,0,35,0
-DATA 35,-2,35,2
-DATA 35,-2,40,0
-DATA 35,2,40,0
-DATA 40,-2,40,2
-
-DATA 40,0,80,0
-DATA 50,0,50,19
-DATA 48,19,52,19
-DATA 48,21,52,21
-DATA 50,21,50,35
-
-DATA 0,35,125,35
-DATA 0,35,5,33
-DATA 0,35,5,37
-
-DATA 70,0,70,15
-DATA 70,35,70,20
-DATA 69,16,71,19
-DATA 69,19,71,16
-DATA 67,10,73,10
-DATA 67,25,73,25
-DATA 67,10,67,25
-DATA 73,10,73,25
-
-DATA 75,15,75,25
-DATA 75,20,90,20
-DATA 90,20,91,21
-DATA 91,21,90,22
-DATA 90,22,91,23
-DATA 91,23,90,24
-DATA 90,24,91,25
-DATA 91,25,90,26
-DATA 90,26,90,35
-
-DATA 93,18,93,28
-DATA 92,18,92,28
-
-DATA 95,20,94,21
-DATA 94,21,95,22
-DATA 95,22,94,23
-DATA 94,23,95,24
-DATA 95,24,94,25
-DATA 94,25,95,26
-DATA 95,26,95,35
-
-DATA 95, 20, 115, 20
-DATA 115,20,115,15
-DATA 115,7,115,0
-DATA 125,35,125,26
-DATA 123,26,127,26
-DATA 123,24,127,24
-DATA 125,24,125,0
-DATA 125,0,110,0
-DATA 110,-2,110,2
-DATA 100,-2,100,2
-DATA 100,-2,110,-2
-DATA 100,2,110,2
-
-DATA 100,0,90,0
-DATA 90,-2,90,2
-DATA 80,-2,80,2
-DATA 80,-2,90,-2
-DATA 80,2,90,2
-
-DATA 113,5,117,5
-DATA 113,17,117,17
-DATA 113,5,113,17
-DATA 117,5,117,17
-DATA 115,11,125,11
-
-DATA 105,-2,105,-5
-DATA 105,-5,113,-5
-DATA 113,-5,113,0
-DATA 105,-2,104,-4
-DATA 105,-2,106,-4
-
-DATA 999,999,999,999
-
-SUB dra
-
-FOR a = 1 TO nl
-    x1 = px1(a) - myx
-    y1 = py1(a) - myy
-    x2 = px2(a) - myx
-    y2 = py2(a) - myy
-
-    ' Calculate the new coordinates based on the current zoom level
-    x1 = x1 * 30 / myz + 160
-    y1 = y1 * 30 / myz + 100
-    x2 = x2 * 30 / myz + 160
-    y2 = y2 * 30 / myz + 100
-
-    ' Draw the line from old coordinates to new coordinates
-    LINE (opx1(a), opy1(a)) - (opx2(a), opy2(a)), 0
-    LINE (x1, y1) - (x2, y2), linc(a)
-
-    ' Update the old coordinates to the new coordinates
-    opx1(a) = x1
-    opy1(a) = y1
-    opx2(a) = x2
-    opy2(a) = y2
-NEXT a
-
-END SUB
-
-SUB get3d
-
-nl = 0
-5
-READ x1, y1, x2, y2
-IF x1 = 999 THEN GOTO 6
-nl = nl + 1
-px1(nl) = x1
-py1(nl) = y1
-px2(nl) = x2
-py2(nl) = y2
-linc(nl) = 11
-GOTO 5
-6
-'PRINT nl, "of lines loaded"
-'a$ = INPUT$(1)
-END SUB
-
-SUB getfnt
-
-FOR c = 0 TO 15
-    OUT &H3C8, c
-    OUT &H3C9, 0
-    OUT &H3C9, 0
-    OUT &H3C9, 0
-NEXT c
-
-FOR a = 0 TO 207
-    LOCATE 1, 1
-    IF (a > 5) AND (a < 14) THEN GOTO 1
-    PRINT CHR$(a)
-1
-    FOR y = 0 TO 15
-        FOR x = 0 TO 7
-            font(x, y, a) = POINT(x, y)
-        NEXT x
-    NEXT y
-NEXT a
-END SUB
-
-SUB getkey (a$)
-
-FOR a = 1 TO 50
-    b$ = INKEY$
-NEXT a
-
-7
-a$ = INKEY$
-IF a$ = "" THEN GOTO 7
-
-FOR a = 1 TO 50
-    b$ = INKEY$
-NEXT a
-
-END SUB
-
-SUB mo
-
-myxv = myx2 - myx1
-myyv = myy2 - myy1
-myzv = myz2 - myz1
-
-FOR a = 1 TO tfra
-    myx = myx1 + (myxv * a / tfra)
-    myy = myy1 + (myyv * a / tfra)
-    myz = myz1 + (myzv * a / tfra)
-    dra
-    SOUND 0, 1
-NEXT a
-dra
-
-END SUB
-
-SUB pag1
-
-SCREEN 13
-
-a = 0
-FOR c = 16 TO 31
-    OUT &H3C8, c
-    OUT &H3C9, a * 3
-    OUT &H3C9, a * 4.5
-    OUT &H3C9, a * 0
-    a = a + 1
-NEXT c
-
-OUT &H3C8, 101
-OUT &H3C9, 63
-OUT &H3C9, 63
-OUT &H3C9, 0
-
-OUT &H3C8, 102
-OUT &H3C9, 63
-OUT &H3C9, 10
-OUT &H3C9, 10
-
-OUT &H3C8, 103
-OUT &H3C9, 60
-OUT &H3C9, 60
-OUT &H3C9, 0
-
-a = 0
-FOR c = 50 TO 65
-    OUT &H3C8, c
-    OUT &H3C9, a * 4.5
-    OUT &H3C9, a * 0
-    OUT &H3C9, (15 - a) * 4.5
-    a = a + 1
-NEXT c
-
-st$ = " Esitlus teemal:"
-
-FOR t = 0 TO 400
-    IF t < 320 THEN
-        FOR y = 0 TO 199
-            c = POINT(319 - t, y)
-            IF c < 100 THEN c = c + 34
-            PSET (319 - t, y), c
-        NEXT y
-        x = 319 - t
-        IF x / 16 = x \ 16 THEN
-            s = x / 16
-            IF s <= LEN(st$) THEN
-                a$ = RIGHT$(LEFT$(st$, s), 1)
-                prn x, 20, 2, 101, a$
-            END IF
-        END IF
-    END IF
-
-    IF (t < 360) AND (t > 39) THEN
-        FOR y = 0 TO 13
-            c = POINT(359 - t, y)
-            IF c < 100 THEN c = c - 34
-            PSET (359 - t, y), c
-        NEXT y
-        FOR y = 55 TO 199
-            c = POINT(359 - t, y)
-            IF c < 100 THEN c = c - 34
-            PSET (359 - t, y), c
-        NEXT y
-    END IF
-
-    SOUND 0, .2
-NEXT t
-
-prn 31, 101, 3, 102, "STROBOSKOOP"
-prn 29, 99, 3, 102, "STROBOSKOOP"
-prn 30, 100, 3, 103, "STROBOSKOOP"
-
-FOR x = 0 TO 160
-    FOR y = 100 TO 150
-        c = POINT(x, y)
-        IF c = 102 THEN c = 103: GOTO 2
-        IF c = 103 THEN c = 102: GOTO 2
-2
-        PSET (x, y), c
-    NEXT y
-    SOUND 0, .1
-NEXT x
-
-FOR y = 199 TO 120 STEP -1
-    FOR x = 0 TO 319
-        c = POINT(x, y)
-        IF c = 102 THEN c = 103: GOTO 3
-        IF c = 103 THEN c = 102: GOTO 3
-3
-        PSET (x, y), c
-    NEXT x
-    SOUND 0, .1
-NEXT y
-
-prn 49, 179, 1, 0, "autor: Svjatoslav Agejenko"
-prn 51, 181, 1, 0, "autor: Svjatoslav Agejenko"
-prn 50, 180, 1, 15, "autor: Svjatoslav Agejenko"
-
-getkey a$
-
-DIM buf(1 TO 30000)
-FOR a = 1 TO 320 / 5
-    GET (0, 0)-(314, 100), buf(1)
-    PUT (5, 0), buf(1), PSET
-    LINE (0, 0)-(4, 100), 0, BF
-
-    GET (5, 101)-(319, 199), buf(1)
-    PUT (0, 101), buf(1), PSET
-    LINE (315, 101)-(319, 199), 0, BF
-NEXT a
-
-END SUB
-
-SUB pag2
-SCREEN 13
-SCREEN 12
-
-END SUB
-
-SUB pag3
-
-myx1 = 20
-myy1 = 15
-myz1 = 100
-myx2 = 20
-myy2 = 15
-myz2 = 10
-tfra = 20
-
-mo
-
-prn 147, 66, 1, 3, "100   D336B             180k    680k"
-prn 180, 120, 1, 3, "50m 450V                          1m"
-prn 180, 400, 2, 14, "Principal scheematic"
-
-getkey a$
-
-LINE (0, 0)-(639, 390), 0, BF
-
-myx1 = 20
-myy1 = 15
-myz1 = 10
-myx2 = 80
-myy2 = 5
-myz2 = 4
-tfra = 20
-mo
-getkey a$
-
-myx1 = 80
-myy1 = 5
-myz1 = 4
-myx2 = 40
-myy2 = 5
-myz2 = 4
-tfra = 20
-mo
-getkey a$
-
-myx1 = 40
-myy1 = 5
-myz1 = 4
-myx2 = 20
-myy2 = 15
-myz2 = 10
-tfra = 10
-mo
-prn 147, 66, 1, 3, "100   D336B             180k    680k"
-prn 180, 120, 1, 3, "50m 450V                          1m"
-getkey a$
-
-END SUB
-
-SUB pag4
-CLS
-SCREEN 13
-prn 35, 100, 2, 14, "   Thank you"
-prn 35, 140, 2, 14, " for attention!"
-
-DIM buf(1 TO 30000)
-
-GET (0, 100)-(319, 199), buf(1)
-FOR y = 100 TO 50 STEP -1
-    PUT (0, y), buf(1), PSET
-    SOUND 0, .5
-NEXT y
-
-getkey a$
-SYSTEM
-END SUB
-
-SUB prn (x2%, y%, s%, c%, t$)
-x = x2
-
-FOR a = 1 TO LEN(t$)
-    b = ASC(RIGHT$(LEFT$(t$, a), 1))
-
-    ' Draw each character in the string
-    FOR y1 = 0 TO 15
-        FOR x1 = 0 TO 7
-            IF font(x1, y1, b) > 0 THEN
-                LINE (x1 * s + x, y1 * s + y) - (x1 * s + s - 1 + x, y1 * s + s - 1 + y), c, BF
-            END IF
-        NEXT x1
-    NEXT y1
-
-    ' Move to the next character position
-    x = x + (8 * s)
-NEXT a
-END SUB
-
-SUB start
-SCREEN 12
-get3d
-getfnt
-
-myx = 30
-myy = 15
-myz = 10
-END SUB
+' Presentation about how to build stroboscope.\r
+' By Svjatoslav Agejenko.\r
+' Email: svjatoslav@svjatoslav.eu\r
+' Homepage: http://www.svjatoslav.eu\r
+'\r
+' Changelog:\r
+' 2002, Initial version\r
+' 2024-2025, Improved program readability\r
+\r
+DECLARE SUB InitializePresentation ()\r
+DECLARE SUB WaitForKeyPress (keyInput$)\r
+DECLARE SUB MoveModel ()\r
+DEFINT A-Z\r
+DECLARE SUB DrawLines ()\r
+DECLARE SUB Load3DModel ()\r
+DECLARE SUB Animate3DModel ()\r
+DECLARE SUB ClearScreen ()\r
+DECLARE SUB LoadFontPalette ()\r
+DECLARE SUB PrintText (x2%, y%, s%, c%, t$)\r
+DECLARE SUB DisplayClosingPage ()\r
+\r
+DECLARE SUB ProgramStart ()\r
+\r
+DIM SHARED font(0 TO 7, 0 TO 15, 0 TO 207)\r
+DIM SHARED paletteData(1 TO 100)\r
+DIM SHARED originalX1(1 TO 1000)\r
+DIM SHARED originalY1(1 TO 1000)\r
+DIM SHARED originalX2(1 TO 1000)\r
+DIM SHARED originalY2(1 TO 1000)\r
+DIM SHARED previousX1(1 TO 1000)\r
+DIM SHARED previousY1(1 TO 1000)\r
+DIM SHARED previousX2(1 TO 1000)\r
+DIM SHARED previousY2(1 TO 1000)\r
+DIM SHARED lineColor(1 TO 1000)\r
+\r
+DIM SHARED movementX, movementY, zoomLevel\r
+DIM SHARED startX, startY, startZoom\r
+DIM SHARED endX, endY, endZoom\r
+DIM SHARED totalFrames\r
+\r
+DIM SHARED lineCount\r
+\r
+ProgramStart\r
+\r
+InitializePresentation\r
+ClearScreen\r
+Animate3DModel\r
+DisplayClosingPage\r
+END\r
+\r
+DATA 0,0,5,-2\r
+DATA 0,0,5,2\r
+DATA 0, 0, 15, 0\r
+\r
+DATA 15,-2,15,2\r
+DATA 25,-2,25,2\r
+DATA 15,-2,25,-2\r
+DATA 15,2,25,2\r
+\r
+DATA 25,0,35,0\r
+DATA 35,-2,35,2\r
+DATA 35,-2,40,0\r
+DATA 35,2,40,0\r
+DATA 40,-2,40,2\r
+\r
+DATA 40,0,80,0\r
+DATA 50,0,50,19\r
+DATA 48,19,52,19\r
+DATA 48,21,52,21\r
+DATA 50,21,50,35\r
+\r
+DATA 0,35,125,35\r
+DATA 0,35,5,33\r
+DATA 0,35,5,37\r
+\r
+DATA 70,0,70,15\r
+DATA 70,35,70,20\r
+DATA 69,16,71,19\r
+DATA 69,19,71,16\r
+DATA 67,10,73,10\r
+DATA 67,25,73,25\r
+DATA 67,10,67,25\r
+DATA 73,10,73,25\r
+\r
+DATA 75,15,75,25\r
+DATA 75,20,90,20\r
+DATA 90,20,91,21\r
+DATA 91,21,90,22\r
+DATA 90,22,91,23\r
+DATA 91,23,90,24\r
+DATA 90,24,91,25\r
+DATA 91,25,90,26\r
+DATA 90,26,90,35\r
+\r
+DATA 93,18,93,28\r
+DATA 92,18,92,28\r
+\r
+DATA 95,20,94,21\r
+DATA 94,21,95,22\r
+DATA 95,22,94,23\r
+DATA 94,23,95,24\r
+DATA 95,24,94,25\r
+DATA 94,25,95,26\r
+DATA 95,26,95,35\r
+\r
+DATA 95, 20, 115, 20\r
+DATA 115,20,115,15\r
+DATA 115,7,115,0\r
+DATA 125,35,125,26\r
+DATA 123,26,127,26\r
+DATA 123,24,127,24\r
+DATA 125,24,125,0\r
+DATA 125,0,110,0\r
+DATA 110,-2,110,2\r
+DATA 100,-2,100,2\r
+DATA 100,-2,110,-2\r
+DATA 100,2,110,2\r
+\r
+DATA 100,0,90,0\r
+DATA 90,-2,90,2\r
+DATA 80,-2,80,2\r
+DATA 80,-2,90,-2\r
+DATA 80,2,90,2\r
+\r
+DATA 113,5,117,5\r
+DATA 113,17,117,17\r
+DATA 113,5,113,17\r
+DATA 117,5,117,17\r
+DATA 115,11,125,11\r
+\r
+DATA 105,-2,105,-5\r
+DATA 105,-5,113,-5\r
+DATA 113,-5,113,0\r
+DATA 105,-2,104,-4\r
+DATA 105,-2,106,-4\r
+\r
+DATA 999,999,999,999\r
+\r
+SUB Animate3DModel\r
+    ' Set up first animation parameters\r
+    startX = 20\r
+    startY = 15\r
+    startZoom = 100\r
+    endX = 20\r
+    endY = 15\r
+    endZoom = 10\r
+    totalFrames = 20\r
+\r
+    MoveModel\r
+\r
+    ' Print technical information\r
+    PrintText 147, 66, 1, 3, "100   D336B             180k    680k"\r
+    PrintText 180, 120, 1, 3, "50m 450V                          1m"\r
+    PrintText 180, 400, 2, 14, "Principal schematic"\r
+\r
+    WaitForKeyPress keyInput$\r
+\r
+    ' Clear screen for next animation\r
+    LINE (0, 0)-(639, 390), 0, BF\r
+\r
+    ' Set up second animation parameters\r
+    startX = 20\r
+    startY = 15\r
+    startZoom = 10\r
+    endX = 80\r
+    endY = 5\r
+    endZoom = 4\r
+    totalFrames = 20\r
+    MoveModel\r
+    WaitForKeyPress keyInput$\r
+\r
+    ' Set up third animation parameters\r
+    startX = 80\r
+    startY = 5\r
+    startZoom = 4\r
+    endX = 40\r
+    endY = 5\r
+    endZoom = 4\r
+    totalFrames = 20\r
+    MoveModel\r
+    WaitForKeyPress keyInput$\r
+\r
+    ' Set up fourth animation parameters\r
+    startX = 40\r
+    startY = 5\r
+    startZoom = 4\r
+    endX = 20\r
+    endY = 15\r
+    endZoom = 10\r
+    totalFrames = 10\r
+    MoveModel\r
+\r
+    ' Redraw technical information\r
+    PrintText 147, 66, 1, 3, "100   D336B             180k    680k"\r
+    PrintText 180, 120, 1, 3, "50m 450V                          1m"\r
+    WaitForKeyPress keyInput$\r
+END SUB\r
+\r
+SUB ClearScreen\r
+    ' change screen resolution. This also resets color palette.\r
+    SCREEN 13\r
+    SCREEN 12\r
+END SUB\r
+\r
+SUB DisplayClosingPage\r
+    CLS\r
+    SCREEN 13\r
+    PrintText 35, 100, 2, 14, "   Thank you"\r
+    PrintText 35, 140, 2, 14, " for attention!"\r
+\r
+    ' Create closing animation effect\r
+    DIM buffer(1 TO 30000)\r
+    GET (0, 100)-(319, 199), buffer(1)\r
+\r
+    ' Move text down with delay\r
+    FOR y = 100 TO 50 STEP -1\r
+        PUT (0, y), buffer(1), PSET\r
+        SOUND 0, .5\r
+    NEXT y\r
+\r
+    WaitForKeyPress keyInput$\r
+    SYSTEM\r
+END SUB\r
+\r
+SUB DrawLines\r
+    ' Draw all lines in the schematic with current transformation parameters.\r
+    ' First calculate new screen coordinates based on movement and zoom.\r
+    ' Then draw lines by erasing previous positions and drawing new ones.\r
+\r
+    FOR a = 1 TO lineCount\r
+        ' Calculate relative coordinates from original positions\r
+        x1 = originalX1(a) - movementX\r
+        y1 = originalY1(a) - movementY\r
+        x2 = originalX2(a) - movementX\r
+        y2 = originalY2(a) - movementY\r
+\r
+        ' Apply zoom scaling and centering (320x200 screen)\r
+        x1 = x1 * 30 / zoomLevel + 160\r
+        y1 = y1 * 30 / zoomLevel + 100\r
+        x2 = x2 * 30 / zoomLevel + 160\r
+        y2 = y2 * 30 / zoomLevel + 100\r
+\r
+        ' Erase previous line by drawing in black (color 0)\r
+        LINE (previousX1(a), previousY1(a))-(previousX2(a), previousY2(a)), 0\r
+\r
+        ' Draw new line with appropriate color\r
+        LINE (x1, y1)-(x2, y2), lineColor(a)\r
+\r
+        ' Update previous positions for next frame\r
+        previousX1(a) = x1\r
+        previousY1(a) = y1\r
+        previousX2(a) = x2\r
+        previousY2(a) = y2\r
+    NEXT a\r
+END SUB\r
+\r
+SUB InitializePresentation\r
+    ' Set up screen and create title animation\r
+    SCREEN 13\r
+\r
+    ' Configure palette for title animation\r
+    a = 0\r
+    FOR c = 16 TO 31\r
+        OUT &H3C8, c\r
+        OUT &H3C9, a * 3\r
+        OUT &H3C9, a * 4.5\r
+        OUT &H3C9, a * 0\r
+        a = a + 1\r
+    NEXT c\r
+\r
+    ' Set special colors for title effects\r
+    OUT &H3C8, 101\r
+    OUT &H3C9, 63\r
+    OUT &H3C9, 63\r
+    OUT &H3C9, 0\r
+\r
+    OUT &H3C8, 102\r
+    OUT &H3C9, 63\r
+    OUT &H3C9, 10\r
+    OUT &H3C9, 10\r
+\r
+    OUT &H3C8, 103\r
+    OUT &H3C9, 60\r
+    OUT &H3C9, 60\r
+    OUT &H3C9, 0\r
+\r
+    ' Configure palette for background text\r
+    a = 0\r
+    FOR c = 50 TO 65\r
+        OUT &H3C8, c\r
+        OUT &H3C9, a * 4.5\r
+        OUT &H3C9, a * 0\r
+        OUT &H3C9, (15 - a) * 4.5\r
+        a = a + 1\r
+    NEXT c\r
+\r
+    ' Create scrolling title animation\r
+    titleText$ = " Esitlus teemal:"\r
+\r
+    FOR t = 0 TO 400\r
+        ' Scroll title text across screen\r
+        IF t < 320 THEN\r
+            FOR y = 0 TO 199\r
+                c = POINT(319 - t, y)\r
+                IF c < 100 THEN c = c + 34\r
+                PSET (319 - t, y), c\r
+            NEXT y\r
+\r
+            x = 319 - t\r
+            ' Add text to scrolling animation\r
+            IF x / 16 = x \ 16 THEN\r
+                segment = x / 16\r
+                IF segment <= LEN(titleText$) THEN\r
+                    char$ = RIGHT$(LEFT$(titleText$, segment), 1)\r
+                    PrintText x, 20, 2, 101, char$\r
+                END IF\r
+            END IF\r
+        END IF\r
+\r
+        ' Create second animation phase\r
+        IF (t < 360) AND (t > 39) THEN\r
+            FOR y = 0 TO 13\r
+                c = POINT(359 - t, y)\r
+                IF c < 100 THEN c = c - 34\r
+                PSET (359 - t, y), c\r
+            NEXT y\r
+\r
+            FOR y = 55 TO 199\r
+                c = POINT(359 - t, y)\r
+                IF c < 100 THEN c = c - 34\r
+                PSET (359 - t, y), c\r
+            NEXT y\r
+        END IF\r
+\r
+        ' Frame delay using sound command\r
+        SOUND 0, .2\r
+    NEXT t\r
+\r
+    ' Draw final title text\r
+    PrintText 31, 101, 3, 102, "STROBOSKOOP"\r
+    PrintText 29, 99, 3, 102, "STROBOSKOOP"\r
+    PrintText 30, 100, 3, 103, "STROBOSKOOP"\r
+\r
+    ' Create color flipping effect for title\r
+    FOR x = 0 TO 160\r
+        FOR y = 100 TO 150\r
+            c = POINT(x, y)\r
+            IF c = 102 THEN c = 103: GOTO 2\r
+            IF c = 103 THEN c = 102: GOTO 2\r
+2\r
+            PSET (x, y), c\r
+        NEXT y\r
+        SOUND 0, .1\r
+    NEXT x\r
+\r
+    ' Continue color flipping effect\r
+    FOR y = 199 TO 120 STEP -1\r
+        FOR x = 0 TO 319\r
+            c = POINT(x, y)\r
+            IF c = 102 THEN c = 103: GOTO 3\r
+            IF c = 103 THEN c = 102: GOTO 3\r
+3\r
+            PSET (x, y), c\r
+        NEXT x\r
+        SOUND 0, .1\r
+    NEXT y\r
+\r
+    ' Print author information\r
+    PrintText 49, 179, 1, 0, "autor: Svjatoslav Agejenko"\r
+    PrintText 51, 181, 1, 0, "autor: Svjatoslav Agejenko"\r
+    PrintText 50, 180, 1, 15, "autor: Svjatoslav Agejenko"\r
+\r
+    ' Wait for user input before continuing\r
+    WaitForKeyPress keyInput$\r
+\r
+    ' Create screen border effect\r
+    DIM buffer(1 TO 30000)\r
+    FOR a = 1 TO 320 / 5\r
+        ' Capture and move screen sections\r
+        GET (0, 0)-(314, 100), buffer(1)\r
+        PUT (5, 0), buffer(1), PSET\r
+        LINE (0, 0)-(4, 100), 0, BF\r
+\r
+        GET (5, 101)-(319, 199), buffer(1)\r
+        PUT (0, 101), buffer(1), PSET\r
+        LINE (315, 101)-(319, 199), 0, BF\r
+    NEXT a\r
+END SUB\r
+\r
+SUB LoadFontPalette\r
+    ' Capture pixel data for each character in font array.\r
+    ' Make colors invisible for the human while doing so.\r
+\r
+    FOR c = 0 TO 15\r
+        OUT &H3C8, c\r
+        OUT &H3C9, 0\r
+        OUT &H3C9, 0\r
+        OUT &H3C9, 0\r
+    NEXT c\r
+\r
+    ' Load character pixel patterns into font array\r
+    FOR a = 0 TO 207\r
+        LOCATE 1, 1\r
+        IF (a > 5) AND (a < 14) THEN GOTO 1\r
+        PRINT CHR$(a)\r
+1\r
+        FOR y = 0 TO 15\r
+            FOR x = 0 TO 7\r
+                font(x, y, a) = POINT(x, y)\r
+            NEXT x\r
+        NEXT y\r
+    NEXT a\r
+END SUB\r
+\r
+SUB LoadSchematic\r
+    ' Load 3D model line data from DATA statements\r
+    ' Each line has two endpoints (x1,y1)-(x2,y2) and color\r
+\r
+    lineCount = 0\r
+5\r
+    READ x1, y1, x2, y2\r
+    IF x1 = 999 THEN GOTO 6\r
+    lineCount = lineCount + 1\r
+    originalX1(lineCount) = x1\r
+    originalY1(lineCount) = y1\r
+    originalX2(lineCount) = x2\r
+    originalY2(lineCount) = y2\r
+    lineColor(lineCount) = 11\r
+    GOTO 5\r
+6\r
+END SUB\r
+\r
+SUB MoveModel\r
+    ' Calculate model movement over time frames\r
+    ' Interpolate between start and end positions\r
+\r
+    movementXVelocity = endX - startX\r
+    movementYVelocity = endY - startY\r
+    zoomVelocity = endZoom - startZoom\r
+\r
+    ' Animate model by gradually changing position and zoom\r
+    FOR a = 1 TO totalFrames\r
+        movementX = startX + (movementXVelocity * a / totalFrames)\r
+        movementY = startY + (movementYVelocity * a / totalFrames)\r
+        zoomLevel = startZoom + (zoomVelocity * a / totalFrames)\r
+        DrawLines\r
+        ' Use sound command for sub-second delay (QBasic workaround)\r
+        SOUND 0, 1\r
+    NEXT a\r
+\r
+    ' Draw final position\r
+    DrawLines\r
+END SUB\r
+\r
+SUB PrintText (x2%, y%, s%, c%, t$)\r
+    ' Print text using custom font\r
+    ' Parameters:\r
+    ' x2% - starting x position\r
+    ' y% - starting y position\r
+    ' s% - character size multiplier\r
+    ' c% - color to use\r
+    ' t$ - text string to print\r
+\r
+    currentX = x2\r
+\r
+    ' Process each character in the string\r
+    FOR a = 1 TO LEN(t$)\r
+        charCode = ASC(RIGHT$(LEFT$(t$, a), 1))\r
+\r
+        ' Draw character using font data\r
+        FOR y1 = 0 TO 15\r
+            FOR x1 = 0 TO 7\r
+                IF font(x1, y1, charCode) > 0 THEN\r
+                    ' Draw filled rectangle for each pixel in character\r
+                    LINE (x1 * s + currentX, y1 * s + y)-(x1 * s + s - 1 + currentX, y1 * s + s - 1 + y), c, BF\r
+                END IF\r
+            NEXT x1\r
+        NEXT y1\r
+\r
+        ' Move to next character position\r
+        currentX = currentX + (8 * s)\r
+    NEXT a\r
+END SUB\r
+\r
+SUB ProgramStart\r
+    ' Initialize program with appropriate screen mode\r
+    SCREEN 12\r
+    LoadSchematic\r
+    LoadFontPalette\r
+\r
+    ' Set initial model parameters\r
+    movementX = 30\r
+    movementY = 15\r
+    zoomLevel = 10\r
+END SUB\r
+\r
+SUB WaitForKeyPress (keyInput$)\r
+    ' Clear keyboard buffer to avoid ghost keys\r
+    FOR a = 1 TO 50\r
+        keyInput$ = INKEY$\r
+    NEXT a\r
+\r
+7\r
+    keyInput$ = INKEY$\r
+    IF keyInput$ = "" THEN GOTO 7\r
+\r
+    ' Wait for another key press after initial one\r
+    FOR a = 1 TO 50\r
+        keyInput$ = INKEY$\r
+    NEXT a\r
+END SUB\r
+\r
index 67b8a84..7a36760 100755 (executable)
@@ -1,8 +1,3 @@
-DECLARE SUB makeland ()\r
-DECLARE SUB dispframe ()\r
-DECLARE SUB displand ()\r
-DECLARE SUB start ()\r
-DECLARE SUB setupal ()\r
 ' Realtime 3D rendering with ray casting engine.\r
 \r
 ' By Svjatoslav Agejenko.\r
@@ -44,10 +39,10 @@ DIM SHARED tim$, frm, frml
 frmrate = 10    ' Desired framerate.\r
                 ' Lower framerate, better quality\r
 \r
-start\r
-makeland\r
+InitializeProgram\r
+GenerateLandscape\r
 \r
-displand\r
+DisplayTopDownLandscape\r
 a$ = INPUT$(1)\r
 1\r
 LOCATE 1, 35\r
@@ -154,10 +149,10 @@ END IF
 myz = zmyz\r
 myy = zmyy\r
 myx = zmyx\r
-dispframe\r
+DisplayFrame\r
 GOTO 1\r
 \r
-SUB dispframe\r
+SUB DisplayFrame\r
 \r
 l = 0\r
 zst = -.0031 * ste\r
@@ -169,7 +164,7 @@ NEXT z
 \r
 END SUB\r
 \r
-SUB displand\r
+SUB DisplayTopDownLandscape\r
 \r
 ' Draw the landscape from a top-down perspective\r
 FOR z = 0 TO 180\r
@@ -226,7 +221,7 @@ getcol = INT(r / 43) * 36 + INT(g / 43) * 6 + INT(b / 43)
 END FUNCTION\r
 \r
 DEFINT A-Y\r
-SUB makeland\r
+SUB GenerateLandscape\r
 \r
 ' Create a square landscape\r
 square 0, 0, 180, 180, 15, 0\r
@@ -292,7 +287,7 @@ NEXT za
 \r
 END SUB\r
 \r
-SUB setupal\r
+SUB SetupPalette\r
 ' Initialize the color palette\r
 c = 0\r
 FOR r = 0 TO 5\r
@@ -320,13 +315,13 @@ NEXT y
 \r
 END SUB\r
 \r
-SUB start\r
+SUB InitializeProgram\r
 ' Set the graphics mode\r
 SCREEN 13\r
 PRINT "please wait..."\r
 \r
 ' Initialize the color palette\r
-setupal\r
+SetupPalette\r
 \r
 ' Initialize player position and orientation\r
 zmyan = 4.14\r
@@ -418,4 +413,3 @@ NEXT a%
 LINE (xl%, yo% - 1)-(xl% + istem%, 0), 0, BF\r
 \r
 END SUB\r
-\r
index c150f79..5e4a987 100755 (executable)
@@ -5,7 +5,7 @@
 \r
 ' Changelog:\r
 ' 2004.07, Initial version\r
-' 2024.10, Improved program readability using AI\r
+' 2024 - 2025, Improved program readability\r
 \r
 ' Controls:\r
 ' arrow keys - move around\r
 ' +          - fly down\r
 ' q, w       - change horizontal distance between left and right view\r
 \r
-\r
-\r
-DECLARE SUB ling (x1%, y1%, x2%, y2%)\r
-\r
-\r
-DECLARE SUB mkkoll ()\r
-DECLARE SUB putkol ()\r
-DECLARE SUB rend ()\r
-DECLARE SUB env ()\r
-DECLARE SUB start ()\r
-DIM SHARED npo, nlo, np, nl\r
-DIM SHARED px(1 TO 1000)\r
-DIM SHARED py(1 TO 1000)\r
-DIM SHARED pz(1 TO 1000)\r
-\r
-DIM SHARED rpx(1 TO 1000)\r
-DIM SHARED rpx2(1 TO 1000)\r
-DIM SHARED rpy(1 TO 1000)\r
-\r
-DIM SHARED orpx(1 TO 1000)\r
-DIM SHARED orpx2(1 TO 1000)\r
-DIM SHARED orpy(1 TO 1000)\r
-DIM SHARED onp\r
-DIM SHARED lin1(1 TO 1000)\r
-DIM SHARED lin2(1 TO 1000)\r
-DIM SHARED linc(1 TO 1000)\r
-DIM SHARED olin1(1 TO 1000)\r
-DIM SHARED olin2(1 TO 1000)\r
-DIM SHARED onl\r
-DIM SHARED myx, myy, myz\r
-DIM SHARED myxs, myys, myzs\r
-DIM SHARED an1, an2\r
-DIM SHARED an1s, an2s\r
-DIM SHARED kolx(1 TO 10)\r
-DIM SHARED koly(1 TO 10)\r
-DIM SHARED kolz(1 TO 10)\r
-DIM SHARED kolxs(1 TO 10)\r
-DIM SHARED kolys(1 TO 10)\r
-DIM SHARED kolzs(1 TO 10)\r
-DIM SHARED kolm\r
-DIM SHARED difp\r
-\r
-DIM SHARED spee\r
-\r
-spee = 4\r
+DECLARE SUB DrawLine (x1%, y1%, x2%, y2%)\r
+DECLARE SUB CreateCube ()\r
+DECLARE SUB PlaceCubes ()\r
+DECLARE SUB RenderScene ()\r
+DECLARE SUB InitializeEnvironment ()\r
+DECLARE SUB InitializeProgram ()\r
+\r
+DIM SHARED originalPointCount, originalLineCount, currentPointCount, currentLineCount\r
+DIM SHARED pointX(1 TO 1000)\r
+DIM SHARED pointY(1 TO 1000)\r
+DIM SHARED pointZ(1 TO 1000)\r
+\r
+DIM SHARED projectedX(1 TO 1000)\r
+DIM SHARED projectedXRight(1 TO 1000)\r
+DIM SHARED projectedY(1 TO 1000)\r
+\r
+DIM SHARED originalProjectedX(1 TO 1000)\r
+DIM SHARED originalProjectedXRight(1 TO 1000)\r
+DIM SHARED originalProjectedY(1 TO 1000)\r
+DIM SHARED originalProjectedPointCount\r
+DIM SHARED lineStart(1 TO 1000)\r
+DIM SHARED lineEnd(1 TO 1000)\r
+DIM SHARED lineColor(1 TO 1000)\r
+DIM SHARED originalLineStart(1 TO 1000)\r
+DIM SHARED originalLineEnd(1 TO 1000)\r
+DIM SHARED originalProjectedLineCount\r
+\r
+DIM SHARED cameraX, cameraY, cameraZ\r
+DIM SHARED cameraXSpeed, cameraYSpeed, cameraZSpeed\r
+DIM SHARED rotationAngle1, rotationAngle2\r
+DIM SHARED rotationAngle1Speed, rotationAngle2Speed\r
+DIM SHARED cubeX(1 TO 10)\r
+DIM SHARED cubeY(1 TO 10)\r
+DIM SHARED cubeZ(1 TO 10)\r
+DIM SHARED cubeXSpeed(1 TO 10)\r
+DIM SHARED cubeYSpeed(1 TO 10)\r
+DIM SHARED cubeZSpeed(1 TO 10)\r
+DIM SHARED cubeCount\r
+DIM SHARED horizontalViewDistance\r
+\r
+DIM SHARED movementSpeed\r
+\r
+movementSpeed = 4\r
 'ON ERROR GOTO 2\r
 \r
-start\r
-env\r
-putkol\r
-difp = -.1\r
+InitializeProgram\r
+InitializeEnvironment\r
+PlaceCubes\r
+horizontalViewDistance = -.1\r
 1\r
 PCOPY 0, 1\r
 CLS\r
 \r
-np = npo\r
-nl = nlo\r
+currentPointCount = originalPointCount\r
+currentLineCount = originalLineCount\r
 \r
-mkkoll\r
-rend\r
+CreateCube\r
+RenderScene\r
 \r
-myx = myx + myxs\r
-myy = myy + myys\r
-myz = myz + myzs\r
-an1 = an1 + an1s\r
-an2 = an2 + an2s\r
+cameraX = cameraX + cameraXSpeed\r
+cameraY = cameraY + cameraYSpeed\r
+cameraZ = cameraZ + cameraZSpeed\r
+rotationAngle1 = rotationAngle1 + rotationAngle1Speed\r
+rotationAngle2 = rotationAngle2 + rotationAngle2Speed\r
 \r
-a$ = INKEY$\r
-IF a$ <> "" THEN\r
-    IF a$ = CHR$(0) + "H" THEN\r
+inputKey$ = INKEY$\r
+IF inputKey$ <> "" THEN\r
+    IF inputKey$ = CHR$(0) + "H" THEN\r
         ' Move forward\r
-        myzs = myzs - SIN(an1) / 100\r
-        myxs = myxs - COS(an1) / 100\r
+        cameraZSpeed = cameraZSpeed - SIN(rotationAngle1) / 100\r
+        cameraXSpeed = cameraXSpeed - COS(rotationAngle1) / 100\r
     END IF\r
-    IF a$ = CHR$(0) + "P" THEN\r
+    IF inputKey$ = CHR$(0) + "P" THEN\r
         ' Move backward\r
-        myzs = myzs + SIN(an1) / 100\r
-        myxs = myxs + COS(an1) / 100\r
+        cameraZSpeed = cameraZSpeed + SIN(rotationAngle1) / 100\r
+        cameraXSpeed = cameraXSpeed + COS(rotationAngle1) / 100\r
     END IF\r
-    IF a$ = CHR$(0) + "M" THEN\r
+    IF inputKey$ = CHR$(0) + "M" THEN\r
         ' Strafe left\r
-        myzs = myzs + COS(an1) / 100\r
-        myxs = myxs - SIN(an1) / 100\r
+        cameraZSpeed = cameraZSpeed + COS(rotationAngle1) / 100\r
+        cameraXSpeed = cameraXSpeed - SIN(rotationAngle1) / 100\r
     END IF\r
-    IF a$ = CHR$(0) + "K" THEN\r
+    IF inputKey$ = CHR$(0) + "K" THEN\r
         ' Strafe right\r
-        myzs = myzs - COS(an1) / 100\r
-        myxs = myxs + SIN(an1) / 100\r
+        cameraZSpeed = cameraZSpeed - COS(rotationAngle1) / 100\r
+        cameraXSpeed = cameraXSpeed + SIN(rotationAngle1) / 100\r
     END IF\r
 \r
-    IF a$ = "6" THEN an1s = an1s - .01\r
-    IF a$ = "4" THEN an1s = an1s + .01\r
-    IF a$ = "8" THEN an2s = an2s - .01\r
-    IF a$ = "2" THEN an2s = an2s + .01\r
-    IF a$ = "+" THEN myys = myys - .01\r
-    IF a$ = "-" THEN myys = myys + .01\r
-    IF a$ = "q" THEN difp = difp - .01\r
-    IF a$ = "w" THEN difp = difp + .01\r
-    IF a$ = " " THEN\r
+    IF inputKey$ = "6" THEN rotationAngle1Speed = rotationAngle1Speed - .01\r
+    IF inputKey$ = "4" THEN rotationAngle1Speed = rotationAngle1Speed + .01\r
+    IF inputKey$ = "8" THEN rotationAngle2Speed = rotationAngle2Speed - .01\r
+    IF inputKey$ = "2" THEN rotationAngle2Speed = rotationAngle2Speed + .01\r
+    IF inputKey$ = "+" THEN cameraYSpeed = cameraYSpeed - .01\r
+    IF inputKey$ = "-" THEN cameraYSpeed = cameraYSpeed + .01\r
+    IF inputKey$ = "q" THEN horizontalViewDistance = horizontalViewDistance - .01\r
+    IF inputKey$ = "w" THEN horizontalViewDistance = horizontalViewDistance + .01\r
+    IF inputKey$ = " " THEN\r
         ' Slow down movements\r
-        myxs = myxs / 2\r
-        myys = myys / 2\r
-        myzs = myzs / 2\r
+        cameraXSpeed = cameraXSpeed / 2\r
+        cameraYSpeed = cameraYSpeed / 2\r
+        cameraZSpeed = cameraZSpeed / 2\r
 \r
-        an1s = an1s / 2\r
-        an2s = an2s / 2\r
+        rotationAngle1Speed = rotationAngle1Speed / 2\r
+        rotationAngle2Speed = rotationAngle2Speed / 2\r
     END IF\r
-    IF a$ = CHR$(27) THEN SYSTEM\r
+    IF inputKey$ = CHR$(27) THEN SYSTEM\r
 END IF\r
 GOTO 1\r
 2\r
 END\r
 RESUME\r
 \r
-SUB env\r
+SUB InitializeEnvironment\r
 \r
 ' This subroutine initializes the environment by creating points and lines.\r
-FOR z = -5 TO 5\r
-    FOR x = -5 TO 5\r
-        np = np + 1\r
-        px(np) = x\r
-        py(np) = SIN(SQR(x * x + z * z) / 2)\r
-        pz(np) = z\r
-        IF x > -5 THEN\r
-            nl = nl + 1\r
-            lin1(nl) = np\r
-            lin2(nl) = np - 1\r
-            linc(nl) = 3\r
+FOR worldZ = -5 TO 5\r
+    FOR worldX = -5 TO 5\r
+        currentPointCount = currentPointCount + 1\r
+        pointX(currentPointCount) = worldX\r
+        pointY(currentPointCount) = SIN(SQR(worldX * worldX + worldZ * worldZ) / 2)\r
+        pointZ(currentPointCount) = worldZ\r
+        IF worldX > -5 THEN\r
+            currentLineCount = currentLineCount + 1\r
+            lineStart(currentLineCount) = currentPointCount\r
+            lineEnd(currentLineCount) = currentPointCount - 1\r
+            lineColor(currentLineCount) = 3\r
         END IF\r
-        IF z > -5 THEN\r
-            nl = nl + 1\r
-            lin1(nl) = np\r
-            lin2(nl) = np - 11\r
-            linc(nl) = 3\r
+        IF worldZ > -5 THEN\r
+            currentLineCount = currentLineCount + 1\r
+            lineStart(currentLineCount) = currentPointCount\r
+            lineEnd(currentLineCount) = currentPointCount - 11\r
+            lineColor(currentLineCount) = 3\r
         END IF\r
-    NEXT x\r
-NEXT z\r
+    NEXT worldX\r
+NEXT worldZ\r
 \r
-npo = np\r
-nlo = nl\r
+originalPointCount = currentPointCount\r
+originalLineCount = currentLineCount\r
 \r
 END SUB\r
 \r
-SUB env1\r
+SUB InitializeEnvironment1\r
 \r
 ' This subroutine initializes the environment with a simple setup.\r
-np = 1\r
-px(np) = -2\r
-py(np) = 0\r
-pz(np) = 0\r
+currentPointCount = 1\r
+pointX(currentPointCount) = -2\r
+pointY(currentPointCount) = 0\r
+pointZ(currentPointCount) = 0\r
 \r
-np = np + 1\r
-px(np) = 2\r
-py(np) = 0\r
-pz(np) = 0\r
+currentPointCount = currentPointCount + 1\r
+pointX(currentPointCount) = 2\r
+pointY(currentPointCount) = 0\r
+pointZ(currentPointCount) = 0\r
 \r
-nl = 1\r
-lin1(nl) = 1\r
-lin2(nl) = 2\r
-linc(nl) = 14\r
+currentLineCount = 1\r
+lineStart(currentLineCount) = 1\r
+lineEnd(currentLineCount) = 2\r
+lineColor(currentLineCount) = 14\r
 \r
 END SUB\r
 \r
-SUB ling (x1%, y1%, x2%, y2%)\r
-\r
-' This subroutine draws a line between two points.\r
-s = ABS(x1% - x2%)\r
-s2 = ABS(y1% - y2%)\r
-IF s2 > s THEN s = s2\r
-IF s < 2 THEN GOTO 101\r
-xp = x2% - x1%\r
-yp = y2% - y1%\r
-\r
-FOR a% = 1 TO s\r
-    rx% = xp * a% / s + x1%\r
-    ry% = yp * a% / s + y1%\r
-    c% = POINT(rx%, ry%)\r
-    IF c% = 0 THEN PSET (rx%, ry%), 2\r
-    IF c% = 1 THEN PSET (rx%, ry%), 3\r
-NEXT a%\r
+SUB DrawLine (x1%, y1%, x2%, y2%)\r
+\r
+' This subroutine draws a line between two points using a custom algorithm.\r
+' It calculates intermediate points and sets pixels with appropriate colors.\r
+' The color is inverted if the point is already set to avoid overwriting.\r
+\r
+lineLength = ABS(x1% - x2%)\r
+lineLength2 = ABS(y1% - y2%)\r
+IF lineLength2 > lineLength THEN lineLength = lineLength2\r
+IF lineLength < 2 THEN GOTO 101\r
+\r
+xDelta = x2% - x1%\r
+yDelta = y2% - y1%\r
+\r
+FOR stp% = 1 TO lineLength\r
+    x = xDelta * stp% / lineLength + x1%\r
+    y = yDelta * stp% / lineLength + y1%\r
+    currentColor = POINT(x, y)\r
+    IF currentColor = 0 THEN PSET (x, y), 2\r
+    IF currentColor = 1 THEN PSET (x, y), 3\r
+NEXT stp%\r
 101\r
 END SUB\r
 \r
-SUB linr (x1, y1, x2, y2)\r
-' This subroutine draws a line using the LINE statement.\r
+SUB DrawLineRight (x1, y1, x2, y2)\r
+' This subroutine draws a line using the LINE statement for the right eye view.\r
 LINE (x1, y1)-(x2, y2), 1\r
 END SUB\r
 \r
-SUB mkkoll\r
+SUB CreateCube\r
 \r
-' This subroutine updates the positions of the objects in the environment.\r
-FOR a = 1 TO kolm\r
-    x = kolx(a)\r
-    y = koly(a)\r
-    z = kolz(a)\r
+' This subroutine updates the positions of the cubes and adds their edges to the environment.\r
+FOR cubeIndex = 1 TO cubeCount\r
+    worldX = cubeX(cubeIndex)\r
+    worldY = cubeY(cubeIndex)\r
+    worldZ = cubeZ(cubeIndex)\r
 \r
-    xs = kolxs(a)\r
-    ys = kolys(a)\r
-    zs = kolzs(a)\r
+    velocityX = cubeXSpeed(cubeIndex)\r
+    velocityY = cubeYSpeed(cubeIndex)\r
+    velocityZ = cubeZSpeed(cubeIndex)\r
 \r
-    ' Apply gravity\r
-    ys = ys - .01\r
+    ' Apply gravity to the cube's vertical movement\r
+    velocityY = velocityY - .01\r
 \r
-    ' Calculate new positions\r
-    x = x + xs / spee\r
-    y = y + ys / spee\r
-    z = z + zs / spee\r
+    ' Calculate new positions based on velocity and speed\r
+    worldX = worldX + velocityX / movementSpeed\r
+    worldY = worldY + velocityY / movementSpeed\r
+    worldZ = worldZ + velocityZ / movementSpeed\r
 \r
     ' Bounce from boundaries\r
-    IF x > 5 THEN xs = -.1\r
-    IF z > 5 THEN zs = -.1\r
-    IF x < -5 THEN xs = .1\r
-    IF z < -5 THEN zs = .1\r
-    IF y < .5 THEN ys = RND * .2 + .1\r
-\r
-    ' Add new lines to the environment\r
-    nl = nl + 1\r
-    lin1(nl) = np + 1\r
-    lin2(nl) = np + 2\r
-    linc(nl) = 14\r
-\r
-    nl = nl + 1\r
-    lin1(nl) = np + 3\r
-    lin2(nl) = np + 2\r
-    linc(nl) = 14\r
-\r
-    nl = nl + 1\r
-    lin1(nl) = np + 3\r
-    lin2(nl) = np + 4\r
-    linc(nl) = 14\r
-\r
-    nl = nl + 1\r
-    lin1(nl) = np + 1\r
-    lin2(nl) = np + 4\r
-    linc(nl) = 14\r
-\r
-    nl = nl + 1\r
-    lin1(nl) = np + 1\r
-    lin2(nl) = np + 5\r
-    linc(nl) = 14\r
-\r
-    nl = nl + 1\r
-    lin1(nl) = np + 2\r
-    lin2(nl) = np + 6\r
-    linc(nl) = 14\r
-\r
-    nl = nl + 1\r
-    lin1(nl) = np + 3\r
-    lin2(nl) = np + 7\r
-    linc(nl) = 14\r
-\r
-    nl = nl + 1\r
-    lin1(nl) = np + 4\r
-    lin2(nl) = np + 8\r
-    linc(nl) = 14\r
-\r
-    nl = nl + 1\r
-    lin1(nl) = np + 5\r
-    lin2(nl) = np + 6\r
-    linc(nl) = 14\r
-\r
-    nl = nl + 1\r
-    lin1(nl) = np + 7\r
-    lin2(nl) = np + 6\r
-    linc(nl) = 14\r
-\r
-    nl = nl + 1\r
-    lin1(nl) = np + 7\r
-    lin2(nl) = np + 8\r
-    linc(nl) = 14\r
-\r
-    nl = nl + 1\r
-    lin1(nl) = np + 5\r
-    lin2(nl) = np + 8\r
-    linc(nl) = 14\r
-\r
-    ' Update the positions of the points in the environment\r
-    np = np + 1\r
-    px(np) = x - .5\r
-    py(np) = y - .5\r
-    pz(np) = z - .5\r
-\r
-    np = np + 1\r
-    px(np) = x + .5\r
-    py(np) = y - .5\r
-    pz(np) = z - .5\r
-\r
-    np = np + 1\r
-    px(np) = x + .5\r
-    py(np) = y + .5\r
-    pz(np) = z - .5\r
-\r
-    np = np + 1\r
-    px(np) = x - .5\r
-    py(np) = y + .5\r
-    pz(np) = z - .5\r
-\r
-    np = np + 1\r
-    px(np) = x - .5\r
-    py(np) = y - .5\r
-    pz(np) = z + .5\r
-\r
-    np = np + 1\r
-    px(np) = x + .5\r
-    py(np) = y - .5\r
-    pz(np) = z + .5\r
-\r
-    np = np + 1\r
-    px(np) = x + .5\r
-    py(np) = y + .5\r
-    pz(np) = z + .5\r
-\r
-    np = np + 1\r
-    px(np) = x - .5\r
-    py(np) = y + .5\r
-    pz(np) = z + .5\r
-\r
-    ' Update the positions and velocities of the objects\r
-    kolx(a) = x\r
-    koly(a) = y\r
-    kolz(a) = z\r
-    kolxs(a) = xs\r
-    kolys(a) = ys\r
-    kolzs(a) = zs\r
-NEXT a\r
+    IF worldX > 5 THEN velocityX = -.1\r
+    IF worldZ > 5 THEN velocityZ = -.1\r
+    IF worldX < -5 THEN velocityX = .1\r
+    IF worldZ < -5 THEN velocityZ = .1\r
+    IF worldY < .5 THEN velocityY = RND * .2 + .1\r
+\r
+    ' Add cube edges to the environment\r
+    currentLineCount = currentLineCount + 1\r
+    lineStart(currentLineCount) = currentPointCount + 1\r
+    lineEnd(currentLineCount) = currentPointCount + 2\r
+    lineColor(currentLineCount) = 14\r
+\r
+    currentLineCount = currentLineCount + 1\r
+    lineStart(currentLineCount) = currentPointCount + 3\r
+    lineEnd(currentLineCount) = currentPointCount + 2\r
+    lineColor(currentLineCount) = 14\r
+\r
+    currentLineCount = currentLineCount + 1\r
+    lineStart(currentLineCount) = currentPointCount + 3\r
+    lineEnd(currentLineCount) = currentPointCount + 4\r
+    lineColor(currentLineCount) = 14\r
+\r
+    currentLineCount = currentLineCount + 1\r
+    lineStart(currentLineCount) = currentPointCount + 1\r
+    lineEnd(currentLineCount) = currentPointCount + 4\r
+    lineColor(currentLineCount) = 14\r
+\r
+    currentLineCount = currentLineCount + 1\r
+    lineStart(currentLineCount) = currentPointCount + 1\r
+    lineEnd(currentLineCount) = currentPointCount + 5\r
+    lineColor(currentLineCount) = 14\r
+\r
+    currentLineCount = currentLineCount + 1\r
+    lineStart(currentLineCount) = currentPointCount + 2\r
+    lineEnd(currentLineCount) = currentPointCount + 6\r
+    lineColor(currentLineCount) = 14\r
+\r
+    currentLineCount = currentLineCount + 1\r
+    lineStart(currentLineCount) = currentPointCount + 3\r
+    lineEnd(currentLineCount) = currentPointCount + 7\r
+    lineColor(currentLineCount) = 14\r
+\r
+    currentLineCount = currentLineCount + 1\r
+    lineStart(currentLineCount) = currentPointCount + 4\r
+    lineEnd(currentLineCount) = currentPointCount + 8\r
+    lineColor(currentLineCount) = 14\r
+\r
+    currentLineCount = currentLineCount + 1\r
+    lineStart(currentLineCount) = currentPointCount + 5\r
+    lineEnd(currentLineCount) = currentPointCount + 6\r
+    lineColor(currentLineCount) = 14\r
+\r
+    currentLineCount = currentLineCount + 1\r
+    lineStart(currentLineCount) = currentPointCount + 7\r
+    lineEnd(currentLineCount) = currentPointCount + 6\r
+    lineColor(currentLineCount) = 14\r
+\r
+    currentLineCount = currentLineCount + 1\r
+    lineStart(currentLineCount) = currentPointCount + 7\r
+    lineEnd(currentLineCount) = currentPointCount + 8\r
+    lineColor(currentLineCount) = 14\r
+\r
+    currentLineCount = currentLineCount + 1\r
+    lineStart(currentLineCount) = currentPointCount + 5\r
+    lineEnd(currentLineCount) = currentPointCount + 8\r
+    lineColor(currentLineCount) = 14\r
+\r
+    ' Add cube vertices to the environment\r
+    currentPointCount = currentPointCount + 1\r
+    pointX(currentPointCount) = worldX - .5\r
+    pointY(currentPointCount) = worldY - .5\r
+    pointZ(currentPointCount) = worldZ - .5\r
+\r
+    currentPointCount = currentPointCount + 1\r
+    pointX(currentPointCount) = worldX + .5\r
+    pointY(currentPointCount) = worldY - .5\r
+    pointZ(currentPointCount) = worldZ - .5\r
+\r
+    currentPointCount = currentPointCount + 1\r
+    pointX(currentPointCount) = worldX + .5\r
+    pointY(currentPointCount) = worldY + .5\r
+    pointZ(currentPointCount) = worldZ - .5\r
+\r
+    currentPointCount = currentPointCount + 1\r
+    pointX(currentPointCount) = worldX - .5\r
+    pointY(currentPointCount) = worldY + .5\r
+    pointZ(currentPointCount) = worldZ - .5\r
+\r
+    currentPointCount = currentPointCount + 1\r
+    pointX(currentPointCount) = worldX - .5\r
+    pointY(currentPointCount) = worldY - .5\r
+    pointZ(currentPointCount) = worldZ + .5\r
+\r
+    currentPointCount = currentPointCount + 1\r
+    pointX(currentPointCount) = worldX + .5\r
+    pointY(currentPointCount) = worldY - .5\r
+    pointZ(currentPointCount) = worldZ + .5\r
+\r
+    currentPointCount = currentPointCount + 1\r
+    pointX(currentPointCount) = worldX + .5\r
+    pointY(currentPointCount) = worldY + .5\r
+    pointZ(currentPointCount) = worldZ + .5\r
+\r
+    currentPointCount = currentPointCount + 1\r
+    pointX(currentPointCount) = worldX - .5\r
+    pointY(currentPointCount) = worldY + .5\r
+    pointZ(currentPointCount) = worldZ + .5\r
+\r
+    ' Update cube positions and velocities\r
+    cubeX(cubeIndex) = worldX\r
+    cubeY(cubeIndex) = worldY\r
+    cubeZ(cubeIndex) = worldZ\r
+    cubeXSpeed(cubeIndex) = velocityX\r
+    cubeYSpeed(cubeIndex) = velocityY\r
+    cubeZSpeed(cubeIndex) = velocityZ\r
+NEXT cubeIndex\r
 \r
 END SUB\r
 \r
-SUB putkol\r
+SUB PlaceCubes\r
 \r
-' This subroutine initializes the objects in the environment.\r
-s = 1\r
-FOR a = 1 TO kolm\r
-    kolx(a) = RND * 10 - 5\r
-    koly(a) = 2\r
-    kolz(a) = RND * 10 - 5\r
-    kolxs(a) = (RND * .5 - .25) / s\r
-    kolys(a) = (RND * .5 + .1) / s\r
-    kolzs(a) = (RND * .5 - .25) / s\r
-NEXT a\r
+' This subroutine initializes the positions and velocities of the cubes.\r
+scaleFactor = 1\r
+FOR cubeIndex = 1 TO cubeCount\r
+    cubeX(cubeIndex) = RND * 10 - 5\r
+    cubeY(cubeIndex) = 2\r
+    cubeZ(cubeIndex) = RND * 10 - 5\r
+    cubeXSpeed(cubeIndex) = (RND * .5 - .25) / scaleFactor\r
+    cubeYSpeed(cubeIndex) = (RND * .5 + .1) / scaleFactor\r
+    cubeZSpeed(cubeIndex) = (RND * .5 - .25) / scaleFactor\r
+NEXT cubeIndex\r
 \r
 END SUB\r
 \r
-SUB rend\r
-'C3& = Cosine&(Deg3): S3& = Sine&(Deg3)\r
-\r
-s1 = SIN(an1)\r
-c1 = COS(an1)\r
-s2 = SIN(an2)\r
-c2 = COS(an2)\r
-\r
-' This subroutine renders the environment by projecting points onto a 2D plane.\r
-FOR a = 1 TO np\r
-    x = px(a) + myx\r
-    y = py(a) - myy\r
-    z = pz(a) + myz\r
-\r
-    ' Apply rotation to the point\r
-    x1 = x * s1 - z * c1\r
-    z1 = x * c1 + z * s1\r
-    y1 = y * s2 - z1 * c2\r
-    z2 = y * c2 + z1 * s2\r
-\r
-    ' Project the point onto a 2D plane\r
-    IF z2 < .1 THEN\r
-        rpx(a) = -1\r
+SUB RenderScene\r
+' This subroutine renders the environment by projecting 3D points onto a 2D plane.\r
+' It applies rotation and perspective projection to create the anaglyph effect.\r
+\r
+sinAngle1 = SIN(rotationAngle1)\r
+cosAngle1 = COS(rotationAngle1)\r
+sinAngle2 = SIN(rotationAngle2)\r
+cosAngle2 = COS(rotationAngle2)\r
+\r
+' Project each 3D point to 2D screen coordinates\r
+FOR pointIndex = 1 TO currentPointCount\r
+    worldX = pointX(pointIndex) + cameraX\r
+    worldY = pointY(pointIndex) - cameraY\r
+    worldZ = pointZ(pointIndex) + cameraZ\r
+\r
+    ' First rotation around Y-axis (horizontal rotation)\r
+    rotatedX = worldX * sinAngle1 - worldZ * cosAngle1\r
+    rotatedZ = worldX * cosAngle1 + worldZ * sinAngle1\r
+\r
+    ' Second rotation around X-axis (vertical rotation)\r
+    rotatedY = worldY * sinAngle2 - rotatedZ * cosAngle2\r
+    depth = worldY * cosAngle2 + rotatedZ * sinAngle2\r
+\r
+    ' Apply perspective projection if point is in view\r
+    IF depth < .1 THEN\r
+        projectedX(pointIndex) = -1\r
     ELSE\r
-        rpx(a) = 160 + ((x1 + difp) / z2 * 200)\r
-        rpx2(a) = 160 + ((x1 - difp) / z2 * 200)\r
-        rpy(a) = 100 - (y1 / z2 * 200)\r
+        projectedX(pointIndex) = 160 + ((rotatedX + horizontalViewDistance) / depth * 200)\r
+        projectedXRight(pointIndex) = 160 + ((rotatedX - horizontalViewDistance) / depth * 200)\r
+        projectedY(pointIndex) = 100 - (rotatedY / depth * 200)\r
     END IF\r
-NEXT a\r
-\r
-' Draw lines between projected points\r
-FOR a = 1 TO nl\r
-    l1 = lin1(a)\r
-    l2 = lin2(a)\r
-    IF rpx(l1) = -1 OR rpx(l2) = -1 THEN\r
-        ' Do nothing if the point is out of view\r
+NEXT pointIndex\r
+\r
+' Draw lines between projected points for left eye view\r
+FOR lineIndex = 1 TO currentLineCount\r
+    startPoint = lineStart(lineIndex)\r
+    endPoint = lineEnd(lineIndex)\r
+    IF projectedX(startPoint) = -1 OR projectedX(endPoint) = -1 THEN\r
+        ' Skip drawing if either point is out of view\r
     ELSE\r
-        LINE (rpx(l1), rpy(l1))-(rpx(l2), rpy(l2)), 1\r
+        LINE (projectedX(startPoint), projectedY(startPoint))-(projectedX(endPoint), projectedY(endPoint)), 1\r
     END IF\r
-NEXT\r
-\r
-' Draw lines between projected points for the right eye\r
-FOR a = 1 TO nl\r
-    l1 = lin1(a)\r
-    l2 = lin2(a)\r
-    IF rpx(l1) = -1 OR rpx(l2) = -1 THEN\r
-        ' Do nothing if the point is out of view\r
+NEXT lineIndex\r
+\r
+' Draw lines between projected points for right eye view\r
+FOR lineIndex = 1 TO currentLineCount\r
+    startPoint = lineStart(lineIndex)\r
+    endPoint = lineEnd(lineIndex)\r
+    IF projectedX(startPoint) = -1 OR projectedX(endPoint) = -1 THEN\r
+        ' Skip drawing if either point is out of view\r
     ELSE\r
-        ling INT(rpx2(l1)), INT(rpy(l1)), INT(rpx2(l2)), INT(rpy(l2))\r
+        DrawLine INT(projectedXRight(startPoint)), INT(projectedY(startPoint)), INT(projectedXRight(endPoint)), INT(projectedY(endPoint))\r
     END IF\r
-NEXT\r
+NEXT lineIndex\r
 \r
 END SUB\r
 \r
-SUB start\r
+SUB InitializeProgram\r
 SCREEN 7, , , 1\r
 \r
 OUT &H3C8, 0\r
@@ -434,25 +439,25 @@ OUT &H3C9, 0
 OUT &H3C9, 0\r
 OUT &H3C9, 0\r
 \r
-npo = 0\r
-nlo = 0\r
-np = npo\r
-nl = nlo\r
-kolm = 9\r
+originalPointCount = 0\r
+originalLineCount = 0\r
+currentPointCount = originalPointCount\r
+currentLineCount = originalLineCount\r
+cubeCount = 9\r
 \r
-myx = 0\r
-myy = 4\r
-myz = 7\r
-an1 = 3.14 / 2\r
-an2 = an1 + .6\r
+cameraX = 0\r
+cameraY = 4\r
+cameraZ = 7\r
+rotationAngle1 = 3.14 / 2\r
+rotationAngle2 = rotationAngle1 + .6\r
 \r
-FOR a = 1 TO 1000\r
-    linc(a) = 4\r
-NEXT a\r
+FOR pointIndex = 1 TO 1000\r
+    lineColor(pointIndex) = 4\r
+NEXT pointIndex\r
 \r
-FOR a = 1 TO 1000\r
-    olin1(a) = 1\r
-    olin2(a) = 1\r
-NEXT a\r
+FOR lineIndex = 1 TO 1000\r
+    originalLineStart(lineIndex) = 1\r
+    originalLineEnd(lineIndex) = 1\r
+NEXT lineIndex\r
 \r
-END SUB
\ No newline at end of file
+END SUB\r