From 403109d4994bf604ffe489048fde0f1e325a3643 Mon Sep 17 00:00:00 2001 From: Svjatoslav Agejenko Date: Wed, 25 Jun 2025 17:46:27 +0300 Subject: [PATCH] Better code readability --- 3D GFX/Maze explorer/mazeexplorer.bas | 306 ++++++++++++-------------- 3D GFX/Ray casting engine/raycast.bas | 272 ++++++++++++----------- 2 files changed, 278 insertions(+), 300 deletions(-) diff --git a/3D GFX/Maze explorer/mazeexplorer.bas b/3D GFX/Maze explorer/mazeexplorer.bas index 3b7353d..2810ade 100755 --- a/3D GFX/Maze explorer/mazeexplorer.bas +++ b/3D GFX/Maze explorer/mazeexplorer.bas @@ -1,4 +1,3 @@ -DECLARE SUB verifyTsrIsLoaded () ' Evolving 3D Maze explorer. ' ' By Svjatoslav Agejenko. @@ -7,7 +6,7 @@ DECLARE SUB verifyTsrIsLoaded () ' Changelog: ' 2003.12, Initial version -' 2024, Improved program readability using AI +' 2024 - 2025, Improved program readability ' ' Navigation: ' WASD - move around @@ -17,210 +16,216 @@ DECLARE SUB verifyTsrIsLoaded () ' ' Press 'q' to quit the program +DECLARE SUB verifyTsrIsLoaded () DECLARE SUB startText () -DECLARE SUB control () +DECLARE SUB handleInput () DECLARE SUB putByte (addr!, dat!) DECLARE SUB putWord (addr!, dat!) DECLARE FUNCTION getWord! (addr!) DECLARE FUNCTION getByte! (addr!) -DECLARE SUB start () -DECLARE SUB animate () +DECLARE SUB initializeProgram () +DECLARE SUB render3DScene () -DIM SHARED px(1 TO 500) -DIM SHARED py(1 TO 500) -DIM SHARED pz(1 TO 500) -DIM SHARED rpx(1 TO 500) -DIM SHARED rpy(1 TO 500) -DIM SHARED rpe(1 TO 500) +DIM SHARED pointX(1 TO 500) +DIM SHARED pointY(1 TO 500) +DIM SHARED pointZ(1 TO 500) +DIM SHARED renderedPointX(1 TO 500) +DIM SHARED renderedPointY(1 TO 500) +DIM SHARED renderedPointEnabled(1 TO 500) -DIM SHARED l1(1 TO 500) -DIM SHARED l2(1 TO 500) -DIM SHARED lc(1 TO 500) +DIM SHARED lineStart(1 TO 500) +DIM SHARED lineEnd(1 TO 500) +DIM SHARED lineColor(1 TO 500) -DIM SHARED nl, np +DIM SHARED lineCount, pointCount -DIM SHARED an1, an2, an3 +DIM SHARED angleY, angleX, angleZ -DIM SHARED tim +DIM SHARED frameTime -DIM SHARED extSEG, extADDR +DIM SHARED extensionSegment, extensionAddress -DIM SHARED myx, myy, myz -DIM SHARED myxs, myys, myzs -DIM SHARED buttonL, buttonR -DIM SHARED maxmove +DIM SHARED cameraX, cameraY, cameraZ +DIM SHARED cameraXSpeed, cameraYSpeed, cameraZSpeed +DIM SHARED leftMouseButton, rightMouseButton +DIM SHARED maxMove -nl = 0 -np = 0 +lineCount = 0 +pointCount = 0 -start +initializeProgram ' Initialize position variables -cx = 0 -cy = 0 -cz = 0 +currentX = 0 +currentY = 0 +currentZ = 0 -np = 1 -px(1) = 0 -py(1) = 0 -pz(1) = 0 +pointCount = 1 +pointX(pointCount) = currentX +pointY(pointCount) = currentY +pointZ(pointCount) = currentZ 1 -IF np < 500 THEN +IF pointCount < 500 THEN ' Increase the number of points and add a new point at the current position - np = np + 1 - px(np) = cx - py(np) = cy - pz(np) = cz + pointCount = pointCount + 1 + pointX(pointCount) = currentX + pointY(pointCount) = currentY + pointZ(pointCount) = currentZ ' Increase the number of lines and define a line between the new point and the previous one - nl = nl + 1 - l1(nl) = np - l2(nl) = np - 1 - lc(nl) = INT(RND * 15) + 1 + lineCount = lineCount + 1 + lineStart(lineCount) = pointCount + lineEnd(lineCount) = pointCount - 1 + lineColor(lineCount) = INT(RND * 15) + 1 - - SELECT CASE INT(RND * 3) ' Randomly choose orientation for the next move + ' Randomly choose orientation for the next move + SELECT CASE INT(RND * 3) CASE 0 - cx = RND * 500 - 250 + currentX = RND * 500 - 250 CASE 1 - cy = RND * 100 - 50 + currentY = RND * 100 - 50 CASE 2 - cz = RND * 500 - 250 + currentZ = RND * 500 - 250 END SELECT END IF - -control -animate +handleInput +render3DScene ' Copy the current screen to page 1 and clear the screen PCOPY 0, 1 CLS GOTO 1 -SUB animate +SUB render3DScene -s1 = SIN(an1) -s2 = SIN(an2) -s3 = SIN(an3) +' Calculate sine and cosine for Y-axis rotation +sinY = SIN(angleY) +cosY = COS(angleY) -c1 = COS(an1) -c2 = COS(an2) -c3 = COS(an3) +' Calculate sine and cosine for X-axis rotation +sinX = SIN(angleX) +cosX = COS(angleX) + +' Calculate sine and cosine for Z-axis rotation (not used in current code) +sinZ = SIN(angleZ) +cosZ = COS(angleZ) ' Project 3D points to 2D screen coordinates -FOR a = 1 TO np - x = px(a) - myx - y = py(a) - myy - z = pz(a) - myz - - ' Rotate around the Y axis - x1 = x * c1 + z * s1 - z1 = z * c1 - x * s1 - - ' Rotate around the X axis - y1 = y * c2 + z1 * s2 - z2 = z1 * c2 - y * s2 - - ' Check if the point is in front of the camera - IF z2 > 3 THEN - rpe(a) = 1 - rpx(a) = x1 / z2 * 130 + 160 - rpy(a) = y1 / z2 * 130 + 100 +FOR a = 1 TO pointCount + deltaX = pointX(a) - cameraX + deltaY = pointY(a) - cameraY + deltaZ = pointZ(a) - cameraZ + + ' Rotate around Y axis + rotatedX = deltaX * cosY + deltaZ * sinY + rotatedZ = deltaZ * cosY - deltaX * sinY + + ' Rotate around X axis + rotatedY = deltaY * cosX + rotatedZ * sinX + finalZ = rotatedZ * cosX - deltaY * sinX + + ' Check if the point is in front of the camera (finalZ > 3) + IF finalZ > 3 THEN + renderedPointEnabled(a) = 1 + renderedPointX(a) = rotatedX / finalZ * 130 + 160 + renderedPointY(a) = rotatedY / finalZ * 130 + 100 ELSE - rpe(a) = 0 + renderedPointEnabled(a) = 0 END IF NEXT a ' Draw lines between visible points -FOR a = 1 TO nl +FOR a = 1 TO lineCount - p1 = l1(a) - p2 = l2(a) - IF (rpe(p1) = 1) AND (rpe(p2) = 1) THEN LINE (rpx(p1), rpy(p1))-(rpx(p2), rpy(p2)), lc(a) + p1 = lineStart(a) + p2 = lineEnd(a) + IF (renderedPointEnabled(p1) = 1) AND (renderedPointEnabled(p2) = 1) THEN + LINE (renderedPointX(p1), renderedPointY(p1))-(renderedPointX(p2), renderedPointY(p2)), lineColor(a) + END IF NEXT a END SUB -SUB control +SUB handleInput ' Read mouse data IF getByte(8) <> 0 THEN putByte 8, 0 - ' read mouse translation along x axis - xp = getWord(2) + ' Read mouse translation along x axis + mouseXDelta = getWord(2) putWord 2, 0 - ' read mouse translation along y axis - yp = getWord(4) + ' Read mouse translation along y axis + mouseYDelta = getWord(4) putWord 4, 0 - ' read pressed mouse buttons + ' Read pressed mouse buttons button = getWord(6) putWord 6, 0 - ' detect if left, right or both mouse buttons were pressed - buttonL = 0 - buttonR = 0 - IF button = 1 THEN buttonL = 1 - IF button = 2 THEN buttonR = 1 - IF button = 3 THEN buttonL = 1: buttonR = 1 + ' Detect if left, right or both mouse buttons were pressed + leftMouseButton = 0 + rightMouseButton = 0 + IF button = 1 THEN leftMouseButton = 1 + IF button = 2 THEN rightMouseButton = 1 + IF button = 3 THEN leftMouseButton = 1: rightMouseButton = 1 - IF buttonR = 1 THEN - IF buttonL = 1 THEN + IF rightMouseButton = 1 THEN + IF leftMouseButton = 1 THEN ' If mouse left and right buttons are pressed at the same time, ' use mouse translation to move avatar around X and Z axis. - myxs = myxs + SIN(an1) * yp / 4 - myzs = myzs - COS(an1) * yp / 4 + cameraXSpeed = cameraXSpeed + SIN(angleY) * mouseYDelta / 4 + cameraZSpeed = cameraZSpeed - COS(angleY) * mouseYDelta / 4 GOTO 3 END IF ' If only right button is pressed, move around Y axis - myys = myys + yp / 4 + cameraYSpeed = cameraYSpeed + mouseYDelta / 4 3 - yp = 0 + mouseYDelta = 0 END IF END IF -' Limit mouse movement to maxmove -IF xp < -maxmove THEN xp = -maxmove -IF xp > maxmove THEN xp = maxmove -an1 = an1 - xp / 150 +' Limit mouse movement to maxMove +IF mouseXDelta < -maxMove THEN mouseXDelta = -maxMove +IF mouseXDelta > maxMove THEN mouseXDelta = maxMove +angleY = angleY - mouseXDelta / 150 -IF yp < -maxmove THEN yp = -maxmove -IF yp > maxmove THEN yp = maxmove -an2 = an2 - yp / 150 +IF mouseYDelta < -maxMove THEN mouseYDelta = -maxMove +IF mouseYDelta > maxMove THEN mouseYDelta = maxMove +angleX = angleX - mouseYDelta / 150 ' Read keyboard input and update player position -a$ = INKEY$ +keyInput$ = INKEY$ -IF a$ = "a" THEN myxs = myxs - COS(an1): myzs = myzs - SIN(an1) -IF a$ = "d" THEN myxs = myxs + COS(an1): myzs = myzs + SIN(an1) -IF a$ = "w" THEN myxs = myxs - SIN(an1): myzs = myzs + COS(an1) -IF a$ = "s" THEN myxs = myxs + SIN(an1): myzs = myzs - COS(an1) -IF a$ = "q" THEN SYSTEM +IF keyInput$ = "a" THEN cameraXSpeed = cameraXSpeed - COS(angleY): cameraZSpeed = cameraZSpeed - SIN(angleY) +IF keyInput$ = "d" THEN cameraXSpeed = cameraXSpeed + COS(angleY): cameraZSpeed = cameraZSpeed + SIN(angleY) +IF keyInput$ = "w" THEN cameraXSpeed = cameraXSpeed - SIN(angleY): cameraZSpeed = cameraZSpeed + COS(angleY) +IF keyInput$ = "s" THEN cameraXSpeed = cameraXSpeed + SIN(angleY): cameraZSpeed = cameraZSpeed - COS(angleY) +IF keyInput$ = "q" THEN SYSTEM ' Apply friction to player movement -myxs = myxs / 1.1 -myys = myys / 1.1 -myzs = myzs / 1.1 +cameraXSpeed = cameraXSpeed / 1.1 +cameraYSpeed = cameraYSpeed / 1.1 +cameraZSpeed = cameraZSpeed / 1.1 ' Update player position -myx = myx + myxs -myz = myz + myzs -myy = myy + myys +cameraX = cameraX + cameraXSpeed +cameraZ = cameraZ + cameraZSpeed +cameraY = cameraY + cameraYSpeed END SUB FUNCTION getByte (addr) -getByte = PEEK(extADDR + addr) +getByte = PEEK(extensionAddress + addr) END FUNCTION FUNCTION getWord (addr) -a = PEEK(extADDR + addr) -b = PEEK(extADDR + addr + 1) +a = PEEK(extensionAddress + addr) +b = PEEK(extensionAddress + addr + 1) ' Convert bytes to a hex string and then to an integer c$ = HEX$(a) @@ -232,42 +237,8 @@ c = VAL("&H" + HEX$(b) + c$) getWord = c END FUNCTION -SUB mousedemo - -cx = 150 -cy = 100 -maxmove = 50 -100 -frm = frm + 1 - -LOCATE 1, 1 -PRINT cx, cy -PRINT frm - -CIRCLE (cx, cy), 10, 0 -xp = getWord(2) -putWord 2, 0 -yp = getWord(4) -putWord 4, 0 - -IF xp < -maxmove THEN xp = -maxmove -IF xp > maxmove THEN xp = maxmove -cx = cx + xp - -IF yp < -maxmove THEN yp = -maxmove -IF yp > maxmove THEN yp = maxmove -cy = cy + yp - -CIRCLE (cx, cy), 10, 10 - -SOUND 0, .05 -GOTO 100 - -END SUB - SUB putByte (addr, dat) - -POKE (extADDR + addr), dat +POKE (extensionAddress + addr), dat END SUB SUB putWord (addr, dat) @@ -280,36 +251,38 @@ IF LEN(b$) < 4 THEN b$ = "0" + b$: GOTO 2 n1 = VAL("&H" + LEFT$(b$, 2)) n2 = VAL("&H" + RIGHT$(b$, 2)) -POKE (extADDR + addr), n2 -POKE (extADDR + addr + 1), n1 +POKE (extensionAddress + addr), n2 +POKE (extensionAddress + addr + 1), n1 END SUB -SUB start +SUB initializeProgram verifyTsrIsLoaded SCREEN 7, , , 1 -maxmove = 50 +' Set camera speed limit +maxMove = 50 END SUB SUB verifyTsrIsLoaded -DEF SEG = 0 ' read first from interrupt table +DEF SEG = 0 ' Read first from interrupt table -extSEG = PEEK(&H79 * 4 + 3) * 256 -extSEG = extSEG + PEEK(&H79 * 4 + 2) +extensionSegment = PEEK(&H79 * 4 + 3) * 256 +extensionSegment = extensionSegment + PEEK(&H79 * 4 + 2) -PRINT "Segment is: " + HEX$(extSEG) +PRINT "Segment is: " + HEX$(extensionSegment) -extADDR = PEEK(&H79 * 4 + 1) * 256 -extADDR = extADDR + PEEK(&H79 * 4 + 0) +extensionAddress = PEEK(&H79 * 4 + 1) * 256 +extensionAddress = extensionAddress + PEEK(&H79 * 4 + 0) -PRINT "relative address is:"; extADDR +PRINT "relative address is:"; extensionAddress -DEF SEG = extSEG +DEF SEG = extensionSegment +' Verify TSR signature IF getWord(0) <> 1983 THEN PRINT "FATAL ERROR: you must load" PRINT "QBasic extension TSR first!" @@ -317,4 +290,3 @@ IF getWord(0) <> 1983 THEN END IF END SUB - diff --git a/3D GFX/Ray casting engine/raycast.bas b/3D GFX/Ray casting engine/raycast.bas index 7a36760..46be305 100755 --- a/3D GFX/Ray casting engine/raycast.bas +++ b/3D GFX/Ray casting engine/raycast.bas @@ -1,3 +1,12 @@ +DECLARE SUB InitializeProgram () +DECLARE SUB GenerateLandscape () +DECLARE SUB DisplayTopDownLandscape () +DECLARE SUB DisplayFrame () +DECLARE FUNCTION getcol! (r!, g!, b!) +DECLARE SUB FillSquareArea (x1%, y1%, x2%, y2%, c%, h%) +DECLARE SUB CreateTower (towerX%, towerY%) +DECLARE SUB SetupPalette () +DECLARE SUB DrawLineFromPlayer (x%, y%, xl%) ' Realtime 3D rendering with ray casting engine. ' By Svjatoslav Agejenko. @@ -6,7 +15,7 @@ ' Changelog: ' 2003.03, Initial version -' 2024.10, Improved program readability using AI +' 2024 - 2025, Improved program readability ' 3D engine automatically adjusts quality to keep constant framerate at 10 fps. ' When framerate is lower than 10 fps, quality will be decreased to speed up rendering. @@ -21,11 +30,7 @@ ' Space - jump up (fly) ' ESC - exit program -DECLARE FUNCTION getcol! (r!, g!, b!) DEFINT A-Y -DECLARE SUB traceline (x%, y%, xl%) -DECLARE SUB tower (x%, y%) -DECLARE SUB square (x1%, y1%, x2%, y2%, c%, h%) DIM SHARED landh(0 TO 180, 0 TO 180) DIM SHARED landc(0 TO 180, 0 TO 180) @@ -152,13 +157,29 @@ myx = zmyx DisplayFrame GOTO 1 +SUB CreateTower (towerX%, towerY%) + +' Draw a tower at the specified position +FOR a = 10 TO 0 STEP -1 + ' Fill each level of the tower with color + FillSquareArea towerX% - a, towerY% - a, towerX% + a, towerY% + a, getcol(100, 0, a * 20), 20 - a +NEXT a + +' Draw the top of the tower +FillSquareArea towerX% - 11, towerY% - 11, towerX% - 9, towerY% - 9, getcol(255, 0, 0), 20 +FillSquareArea towerX% + 9, towerY% - 11, towerX% + 11, towerY% - 9, getcol(0, 255, 0), 20 +FillSquareArea towerX% - 11, towerY% + 9, towerX% - 9, towerY% + 11, getcol(0, 0, 255), 20 +FillSquareArea towerX% + 9, towerY% + 9, towerX% + 11, towerY% + 11, getcol(255, 255, 0), 20 + +END SUB + SUB DisplayFrame l = 0 zst = -.0031 * ste FOR z = .5 TO -.5 STEP zst ' Trace a line from the player's perspective - traceline SIN(zmyan + z) * dist + myx, COS(zmyan + z) * dist + myy, l + DrawLineFromPlayer SIN(zmyan + z) * dist + myx, COS(zmyan + z) * dist + myy, l l = l + ste NEXT z @@ -195,36 +216,84 @@ PRINT "Press any key to continue..." END SUB -DEFSNG A-Y -FUNCTION getcol (r, g, b) -IF r < 0 THEN - ' Ensure the color value is within bounds - r = 0 -END IF -IF g < 0 THEN - g = 0 -END IF -IF b < 0 THEN - b = 0 +SUB DrawLineFromPlayer (x%, y%, xl%) + +' Trace a line from the player's perspective +IF x < 0 THEN + ' Calculate the distance to the next point + zpr = myx / (myx - x) + x = 0 + y = myy - ((myy - y) * zpr) END IF -IF r > 255 THEN - r = 255 + +IF y < 0 THEN + ' Calculate the distance to the next point + zpr = myy / (myy - y) + y = 0 + x = myx - ((myx - x) * zpr) END IF -IF g > 255 THEN - g = 255 + +IF x > 180 THEN + ' Calculate the distance to the next point + zpr = (180 - myx) / (x - myx) + x = 180 + y = myy - ((myy - y) * zpr) END IF -IF b > 255 THEN - b = 255 + +IF y > 180 THEN + ' Calculate the distance to the next point + zpr = (180 - myy) / (y - myy) + y = 180 + x = myx - ((myx - x) * zpr) END IF -' Calculate the color index -getcol = INT(r / 43) * 36 + INT(g / 43) * 6 + INT(b / 43) -END FUNCTION -DEFINT A-Y +' Calculate the distance to the next point +lp% = SQR(ABS(myx - x) ^ 2 + ABS(myy - y) ^ 2) + +' Save the current player position and orientation +imyx% = myx +imyy% = myy +imyz% = myz +xp% = x - imyx% +yp% = y - imyy% +istem% = stem +imyan2% = myan2 + +' Draw the line +yo% = 200 +FOR a% = 1 TO lp% + cx% = xp% * a% / lp% + imyx% + cy% = yp% * a% / lp% + imyy% + yn% = imyan2% - ((landh(cx%, cy%) - imyz%) / a%) * 300 + + ' Draw the line segment + IF yn% < yo% THEN + LINE (xl%, yn%)-(xl% + istem%, yo% - 1), landc(cx%, cy%), BF + yo% = yn% + END IF +NEXT a% + +' Draw the final line segment +LINE (xl%, yo% - 1)-(xl% + istem%, 0), 0, BF + +END SUB + +SUB FillSquareArea (x1%, y1%, x2%, y2%, c%, h%) + +' Fill a square area with the specified color and height +FOR y = y1 TO y2 + FOR x = x1 TO x2 + landh(x, y) = h + landc(x, y) = c + NEXT x +NEXT y + +END SUB + SUB GenerateLandscape ' Create a square landscape -square 0, 0, 180, 180, 15, 0 +FillSquareArea 0, 0, 180, 180, 15, 0 ' Generate the landscape height and color FOR y = 0 TO 180 @@ -259,9 +328,9 @@ FOR y = 10 TO 90 NEXT y ' Add towers to the landscape -tower 20, 20 -tower 60, 20 -tower 40, 60 +CreateTower 20, 20 +CreateTower 60, 20 +CreateTower 40, 60 ' Generate a path FOR y = 100 TO 150 @@ -287,34 +356,32 @@ NEXT za END SUB -SUB SetupPalette -' Initialize the color palette -c = 0 -FOR r = 0 TO 5 - FOR g = 0 TO 5 - FOR b = 0 TO 5 - OUT &H3C8, c - c = c + 1 - OUT &H3C9, r * 12 - OUT &H3C9, g * 12 - OUT &H3C9, b * 12 - NEXT b - NEXT g -NEXT r -END SUB - -SUB square (x1%, y1%, x2%, y2%, c%, h%) - -' Fill a square area with the specified color and height -FOR y = y1 TO y2 - FOR x = x1 TO x2 - landh(x, y) = h - landc(x, y) = c - NEXT x -NEXT y - -END SUB +DEFSNG A-Y +FUNCTION getcol (r, g, b) +IF r < 0 THEN + ' Ensure the color value is within bounds + r = 0 +END IF +IF g < 0 THEN + g = 0 +END IF +IF b < 0 THEN + b = 0 +END IF +IF r > 255 THEN + r = 255 +END IF +IF g > 255 THEN + g = 255 +END IF +IF b > 255 THEN + b = 255 +END IF +' Calculate the color index +getcol = INT(r / 43) * 36 + INT(g / 43) * 6 + INT(b / 43) +END FUNCTION +DEFINT A-Y SUB InitializeProgram ' Set the graphics mode SCREEN 13 @@ -336,80 +403,19 @@ zmyz = 20 END SUB -SUB tower (x%, y%) - -' Draw a tower at the specified position -FOR a = 10 TO 0 STEP -1 - ' Fill each level of the tower with color - square x% - a, y% - a, x% + a, y% + a, getcol(100, 0, a * 20), 20 - a -NEXT a - -' Draw the top of the tower -square x% - 11, y% - 11, x% - 9, y% - 9, getcol(255, 0, 0), 20 -square x% + 9, y% - 11, x% + 11, y% - 9, getcol(0, 255, 0), 20 -square x% - 11, y% + 9, x% - 9, y% + 11, getcol(0, 0, 255), 20 -square x% + 9, y% + 9, x% + 11, y% + 11, getcol(255, 255, 0), 20 - +SUB SetupPalette +' Initialize the color palette +c = 0 +FOR r = 0 TO 5 + FOR g = 0 TO 5 + FOR b = 0 TO 5 + OUT &H3C8, c + c = c + 1 + OUT &H3C9, r * 12 + OUT &H3C9, g * 12 + OUT &H3C9, b * 12 + NEXT b + NEXT g +NEXT r END SUB -SUB traceline (x%, y%, xl%) - -' Trace a line from the player's perspective -IF x < 0 THEN - ' Calculate the distance to the next point - zpr = myx / (myx - x) - x = 0 - y = myy - ((myy - y) * zpr) -END IF - -IF y < 0 THEN - ' Calculate the distance to the next point - zpr = myy / (myy - y) - y = 0 - x = myx - ((myx - x) * zpr) -END IF - -IF x > 180 THEN - ' Calculate the distance to the next point - zpr = (180 - myx) / (x - myx) - x = 180 - y = myy - ((myy - y) * zpr) -END IF - -IF y > 180 THEN - ' Calculate the distance to the next point - zpr = (180 - myy) / (y - myy) - y = 180 - x = myx - ((myx - x) * zpr) -END IF - -' Calculate the distance to the next point -lp% = SQR(ABS(myx - x) ^ 2 + ABS(myy - y) ^ 2) - -' Save the current player position and orientation -imyx% = myx -imyy% = myy -imyz% = myz -xp% = x - imyx% -yp% = y - imyy% -istem% = stem -imyan2% = myan2 - -' Draw the line -yo% = 200 -FOR a% = 1 TO lp% - cx% = xp% * a% / lp% + imyx% - cy% = yp% * a% / lp% + imyy% - yn% = imyan2% - ((landh(cx%, cy%) - imyz%) / a%) * 300 - - ' Draw the line segment - IF yn% < yo% THEN - LINE (xl%, yn%)-(xl% + istem%, yo% - 1), landc(cx%, cy%), BF - yo% = yn% - END IF -NEXT a% - -' Draw the final line segment -LINE (xl%, yo% - 1)-(xl% + istem%, 0), 0, BF - -END SUB -- 2.20.1