From 30f623a8d9327b92f244ca4612f2a7ce11dff7b5 Mon Sep 17 00:00:00 2001 From: Svjatoslav Agejenko Date: Sat, 16 Aug 2025 14:45:19 +0300 Subject: [PATCH] Better code readability --- Games/Pomppu Paavo/Pomppu Paavo.bas | 889 ++++++++++++++++++---------- 1 file changed, 577 insertions(+), 312 deletions(-) diff --git a/Games/Pomppu Paavo/Pomppu Paavo.bas b/Games/Pomppu Paavo/Pomppu Paavo.bas index 7d86bf4..91a1657 100755 --- a/Games/Pomppu Paavo/Pomppu Paavo.bas +++ b/Games/Pomppu Paavo/Pomppu Paavo.bas @@ -1,3 +1,5 @@ +DECLARE SUB RenderSpriteFromFile (x%, y%, widthMultiplier%, heightMultiplier%, SpriteName$) +DECLARE SUB RenderFlippedSpriteFromFile (x%, y%, widthMultiplier%, heightMultiplier%, Filename$) ' Pomppu Paavo 2 ' ' This program is free software: released under Creative Commons Zero (CC0) license @@ -7,73 +9,141 @@ ' ' Changelog: ' 1999, Initial version +' 2025, Improved program readability DECLARE SUB UpdateLoadingScreen () DECLARE SUB HandleEscapeKey () DECLARE SUB PlayHurtSound () DECLARE SUB GameOverSequence () - DECLARE SUB HandlePlayerDeath () DEFINT A-Z DECLARE SUB InitializeAllLevelData () -DECLARE SUB UpdateHUD (zaz%) -DECLARE SUB RenderImageFromTextFile (a1%, b1%, c1%, d1%, a$) +DECLARE SUB UpdateHUD (coinIncrementAmount%) DECLARE SUB LoadCurrentLevel () -DECLARE SUB wiew (a1%, b1%, c1%, d1%, a$) -DECLARE SUB intro () -DECLARE SUB inpur () +DECLARE SUB ShowIntroScreen () +DECLARE SUB WaitForUserInput () DIM SHARED userInput$ +' Grid representing solid level elements (m = block, o = breakable, etc.) DIM SHARED levelGrid(-5 TO 20, -5 TO 20) AS STRING -DIM SHARED ruum1(-5 TO 20, -5 TO 20) AS STRING + +' Tracks interactive objects like breakable blocks separately from main grid +DIM SHARED interactiveObjectsGrid(-5 TO 20, -5 TO 20) AS STRING + +' Stores raw text-based level layouts for all worlds DIM SHARED levelData(1 TO 11, 1 TO 10) AS STRING * 15 + +' Background color index for each world's sky DIM SHARED levelSkyColor(1 TO 10) AS INTEGER -DIM SHARED currentWorld AS INTEGER -DIM SHARED previousWorld AS INTEGER + +' Current active level number (1-10) +DIM SHARED currentLevelNumber AS INTEGER + +' Previously played level number (for backtracking after death) +DIM SHARED previousLevelNumber AS INTEGER + +' Temporary storage for current level's row data during loading DIM SHARED levelRowData(1 TO 15) AS STRING * 15 -DIM SHARED pilv(2100) -DIM SHARED kast(202) -DIM SHARED tellis(202) -DIM SHARED poosas(1000) -DIM SHARED puu(2000) -DIM SHARED tuhi(202) -DIM SHARED munt(202) -DIM SHARED munt1(400) -DIM SHARED munt2(200) -DIM SHARED mari0(402) -DIM SHARED mari(202, 1 TO 5) -DIM SHARED koll(1 TO 230, 1 TO 10) -DIM SHARED koll1(1 TO 202, 1 TO 5) -DIM SHARED mobX(1 TO 10) -DIM SHARED mobY(1 TO 10) -DIM SHARED kollal(1 TO 10) -DIM SHARED kolled(1 TO 10) - -DIM SHARED hudCoinDigits(1 TO 5) + +' Buffer to store cloud sprite image data +DIM SHARED cloudSpriteBuffer(2100) + +' Buffer for solid block sprite images +DIM SHARED solidBlockSpriteBuffer(202) + +' Buffer for brick/block sprite images +DIM SHARED brickSpriteBuffer(202) + +' Buffer for power-up item sprites (like mushrooms) +DIM SHARED powerUpSpriteBuffer(1000) + +' Buffer for tree sprite images +DIM SHARED treeSpriteBuffer(2000) + +' Buffer for empty space sprite (used when clearing coins/breakables) +DIM SHARED emptySpaceSpriteBuffer(202) + +' Main coin sprite buffer +DIM SHARED coinSpriteBuffer(202) + +' Larger coin variant sprite buffer +DIM SHARED largeCoinSpriteBuffer(400) + +' Smaller coin variant sprite buffer +DIM SHARED smallCoinSpriteBuffer(200) + +' Player character animation frames (base + walking variants) +DIM SHARED playerAnimationFrames(402) + +' Primary player sprite animation frames array +DIM SHARED playerWalkingFrames(202, 1 TO 5) + +' Enemy base sprite buffers (stores background under enemies for erasing) +DIM SHARED enemyBackgroundBuffers(1 TO 230, 1 TO 10) + +' Enemy walking animation frames +DIM SHARED enemyWalkingFrames(1 TO 202, 1 TO 5) + +' X positions of all enemies (max 10 per level) +DIM SHARED enemyXPositions(1 TO 10) + +' Y positions of all enemies +DIM SHARED enemyYPositions(1 TO 10) + +' Vertical movement speeds for enemies (positive = down) +DIM SHARED enemyVerticalSpeeds(1 TO 10) + +' Horizontal movement speeds for enemies (positive = right) +DIM SHARED enemyHorizontalSpeeds(1 TO 10) + +' Array storing individual digits of coin counter (index 1=ones, 2=tens) +DIM SHARED CoinDigits(1 TO 5) + +' Pre-loaded digit images for HUD display (0-9) DIM SHARED digitImages(100, 0 TO 11) + +' Number of remaining player lives DIM SHARED lives -DIM SHARED raha -DIM SHARED clra, clrb -DIM SHARED a1, b1 +' Total coins collected by player +DIM SHARED coinsCollected + +' Flag: set when a coin needs to be cleared from grid +DIM SHARED shouldClearCoinFlag + +' Grid X position where coin needs clearing +DIM SHARED clearCoinGridX -DIM SHARED prog -prog = 1 +' Grid Y position where coin needs clearing +DIM SHARED clearCoinGridY + +' Player's current X coordinate on screen +DIM SHARED playerX + +' Player's current Y coordinate on screen +DIM SHARED playerY + +' Counter tracking loading progress dots +DIM SHARED loadingProgressDotCount + +loadingProgressDotCount = 1 SCREEN 13 -currentWorld = 1 -previousWorld = 1 +currentLevelNumber = 1 +previousLevelNumber = 1 InitializeAllLevelData 1 -zpqf = 4 -FOR a = 0 TO 254 -OUT &H3C8, a +' Reset entire VGA palette to black (0-254) +FOR colorIndex = 0 TO 254 +OUT &H3C8, colorIndex OUT &H3C9, 0 OUT &H3C9, 0 OUT &H3C9, 0 -NEXT a +NEXT colorIndex + +' Set color 255 to bright white (60/63 intensity) OUT &H3C8, 255 OUT &H3C9, 60 OUT &H3C9, 60 @@ -82,244 +152,366 @@ LOCATE 20, 3 COLOR 255 PRINT "LOADING " - +' Load all game assets sequentially with visual feedback UpdateLoadingScreen -wiew 0, 0, 1, 1, "pilv" -GET (1, 1)-(109, 35), pilv +RenderSpriteFromFile 0, 0, 1, 1, "pilv" +GET (1, 1)-(109, 35), cloudSpriteBuffer + UpdateLoadingScreen -wiew 0, 0, 1, 1, "kast" -GET (1, 2)-(20, 21), kast +RenderSpriteFromFile 0, 0, 1, 1, "kast" +GET (1, 2)-(20, 21), solidBlockSpriteBuffer + UpdateLoadingScreen -wiew 0, 0, 1, 1, "tellis" -GET (1, 2)-(20, 21), tellis +RenderSpriteFromFile 0, 0, 1, 1, "tellis" +GET (1, 2)-(20, 21), brickSpriteBuffer + UpdateLoadingScreen -GET (1, 2)-(20, 21), tuhi -wiew 0, 0, 1, 1, "paavo1" -GET (1, 2)-(20, 21), mari(202, 1) +GET (1, 2)-(20, 21), emptySpaceSpriteBuffer + +RenderSpriteFromFile 0, 0, 1, 1, "paavo1" +GET (1, 2)-(20, 21), playerWalkingFrames(202, 1) + UpdateLoadingScreen -RenderImageFromTextFile 0, 0, 1, 1, "paavo1" -GET (3, 2)-(22, 21), mari(202, 2) +RenderFlippedSpriteFromFile 0, 0, 1, 1, "paavo1" +GET (3, 2)-(22, 21), playerWalkingFrames(202, 2) + UpdateLoadingScreen -wiew 0, 0, 1, 1, "paavo2" -GET (1, 2)-(20, 21), mari(202, 3) +RenderSpriteFromFile 0, 0, 1, 1, "paavo2" +GET (1, 2)-(20, 21), playerWalkingFrames(202, 3) + UpdateLoadingScreen -RenderImageFromTextFile 0, 0, 1, 1, "paavo2" -GET (3, 2)-(22, 21), mari(202, 4) +RenderFlippedSpriteFromFile 0, 0, 1, 1, "paavo2" +GET (3, 2)-(22, 21), playerWalkingFrames(202, 4) + UpdateLoadingScreen -wiew 0, 0, 1, 1, "poosas" -GET (1, 1)-(60, 21), poosas +RenderSpriteFromFile 0, 0, 1, 1, "poosas" +GET (1, 1)-(60, 21), powerUpSpriteBuffer + UpdateLoadingScreen -wiew 0, 0, 1, 1, "puu" -GET (1, 1)-(40, 60), puu +RenderSpriteFromFile 0, 0, 1, 1, "puu" +GET (1, 1)-(40, 60), treeSpriteBuffer + UpdateLoadingScreen -wiew 0, 0, 1, 1, "munt" -GET (1, 1)-(10, 11), munt +RenderSpriteFromFile 0, 0, 1, 1, "munt" +GET (1, 1)-(10, 11), coinSpriteBuffer + UpdateLoadingScreen -wiew 0, 0, 1, 1, "munt1" -GET (0, 2)-(20, 11), munt1 +RenderSpriteFromFile 0, 0, 1, 1, "munt1" +GET (0, 2)-(20, 11), largeCoinSpriteBuffer + UpdateLoadingScreen -wiew 0, 0, 1, 1, "munt2" -GET (0, 2)-(20, 11), munt2 +RenderSpriteFromFile 0, 0, 1, 1, "munt2" +GET (0, 2)-(20, 11), smallCoinSpriteBuffer +' Load all numeric digit sprites for HUD display UpdateLoadingScreen -wiew 0, 0, 1, 1, "0" +RenderSpriteFromFile 0, 0, 1, 1, "0" GET (0, 2)-(10, 11), digitImages(100, 0) + UpdateLoadingScreen -wiew 0, 0, 1, 1, "1" +RenderSpriteFromFile 0, 0, 1, 1, "1" GET (0, 2)-(10, 11), digitImages(100, 1) + UpdateLoadingScreen -wiew 0, 0, 1, 1, "2" +RenderSpriteFromFile 0, 0, 1, 1, "2" GET (0, 2)-(10, 11), digitImages(100, 2) + UpdateLoadingScreen -wiew 0, 0, 1, 1, "3" +RenderSpriteFromFile 0, 0, 1, 1, "3" GET (0, 2)-(10, 11), digitImages(100, 3) + UpdateLoadingScreen -wiew 0, 0, 1, 1, "4" +RenderSpriteFromFile 0, 0, 1, 1, "4" GET (0, 2)-(10, 11), digitImages(100, 4) + UpdateLoadingScreen -wiew 0, 0, 1, 1, "5" +RenderSpriteFromFile 0, 0, 1, 1, "5" GET (0, 2)-(10, 11), digitImages(100, 5) + UpdateLoadingScreen -wiew 0, 0, 1, 1, "6" +RenderSpriteFromFile 0, 0, 1, 1, "6" GET (0, 2)-(10, 11), digitImages(100, 6) + UpdateLoadingScreen -wiew 0, 0, 1, 1, "7" +RenderSpriteFromFile 0, 0, 1, 1, "7" GET (0, 2)-(10, 11), digitImages(100, 7) + UpdateLoadingScreen -wiew 0, 0, 1, 1, "8" +RenderSpriteFromFile 0, 0, 1, 1, "8" GET (0, 2)-(10, 11), digitImages(100, 8) + UpdateLoadingScreen GET (0, 2)-(10, 11), digitImages(100, 10) -wiew 0, 0, 1, 1, "9" +RenderSpriteFromFile 0, 0, 1, 1, "9" GET (0, 2)-(10, 11), digitImages(100, 9) +' Load enemy sprite frames UpdateLoadingScreen -wiew 0, 0, 1, 1, "tigu" -GET (1, 2)-(20, 21), koll1(202, 1) +RenderSpriteFromFile 0, 0, 1, 1, "tigu" +GET (1, 2)-(20, 21), enemyWalkingFrames(202, 1) + UpdateLoadingScreen -wiew 0, 0, 1, 1, "tigu1" -GET (3, 2)-(22, 21), koll1(202, 2) +RenderSpriteFromFile 0, 0, 1, 1, "tigu1" +GET (3, 2)-(22, 21), enemyWalkingFrames(202, 2) + UpdateLoadingScreen -RenderImageFromTextFile 0, 0, 1, 1, "tigu" -GET (1, 2)-(20, 21), koll1(202, 3) +RenderFlippedSpriteFromFile 0, 0, 1, 1, "tigu" +GET (1, 2)-(20, 21), enemyWalkingFrames(202, 3) + UpdateLoadingScreen -RenderImageFromTextFile 0, 0, 1, 1, "tigu1" -GET (3, 2)-(22, 21), koll1(202, 4) +RenderFlippedSpriteFromFile 0, 0, 1, 1, "tigu1" +GET (3, 2)-(22, 21), enemyWalkingFrames(202, 4) SCREEN 0 SCREEN 13 LoadCurrentLevel -a1 = 50 -b1 = 50 -edasi = 0 -liig = 1 -ov1 = 1 -ov2 = 2 -raha = 0 +playerX = 50 +playerY = 50 +horizontalMovementSpeed = 0 +currentWalkFrameIndex = 1 +leftWalkFrameIndex = 1 +rightWalkFrameIndex = 2 +coinsCollected = 0 lives = 3 -z = 1 +animationFrameCounter = 1 UpdateHUD 0 12 -IF b1 > 0 THEN GET (a1, b1)-(a1 + 20, b1 + 20), mari0: PUT (a1, b1), mari(202, liig), OR - -FOR ox = 1 TO 10 -IF mobY(ox) < 170 AND z = 1 THEN - mobY(ox) = mobY(ox) + kollal(ox) - mobX(ox) = mobX(ox) + kolled(ox) - GET (mobX(ox), mobY(ox))-(mobX(ox) + 20, mobY(ox) + 20), koll(202, ox) - IF kolled(ox) <= 0 THEN kolll = 1 ELSE kolll = 3 - IF zz > 2 THEN kolll = kolll + 1: IF zz = 3 THEN kollal(ox) = kollal(ox) + 1 - PUT (mobX(ox), mobY(ox)), koll1(202, kolll) -END IF -NEXT ox +' Save current player position background before drawing character +IF playerY > 0 THEN GET (playerX, playerY)-(playerX + 20, playerY + 20), playerAnimationFrames: PUT (playerX, playerY), playerWalkingFrames(202, currentWalkFrameIndex), OR + +' Process all enemies (max 10) +FOR enemyIndex = 1 TO 10 + ' Only update visible enemies above bottom of screen + IF enemyYPositions(enemyIndex) < 170 AND animationFrameCounter = 1 THEN + ' Apply vertical and horizontal movement + enemyYPositions(enemyIndex) = enemyYPositions(enemyIndex) + enemyVerticalSpeeds(enemyIndex) + enemyXPositions(enemyIndex) = enemyXPositions(enemyIndex) + enemyHorizontalSpeeds(enemyIndex) + ' Save background under enemy for later erasing + GET (enemyXPositions(enemyIndex), enemyYPositions(enemyIndex))-(enemyXPositions(enemyIndex) + 20, enemyYPositions(enemyIndex) + 20), enemyBackgroundBuffers(202, enemyIndex) + + ' Determine which walking animation frame to show + IF enemyHorizontalSpeeds(enemyIndex) <= 0 THEN walkAnimationPhase = 1 ELSE walkAnimationPhase = 3 + IF enemyAnimationFrameCounter > 2 THEN walkAnimationPhase = walkAnimationPhase + 1: IF enemyAnimationFrameCounter = 3 THEN enemyVerticalSpeeds(enemyIndex) = enemyVerticalSpeeds(enemyIndex) + 1 + + ' Draw enemy with correct animation frame + PUT (enemyXPositions(enemyIndex), enemyYPositions(enemyIndex)), enemyWalkingFrames(202, walkAnimationPhase) + END IF +NEXT enemyIndex + +' Create short delay using silent sound (QBasic lacks proper delay function) SOUND 0, .5 -z = z + 1 -IF z > 3 THEN z = 1 -IF z = 1 THEN -zz = zz + 1 -IF zz > 5 THEN zz = 0 -alla = alla + 1 -IF edasi > 0 THEN edasi = edasi - 1: zy = zy + 1 -IF edasi < 0 THEN edasi = edasi + 1: zy = zy + 1 -IF zy > 2 THEN zy = 1 -IF zy = 2 THEN ov1 = 1: ov2 = 2 -IF zy = 1 THEN ov1 = 3: ov2 = 4 - -FOR ox = 1 TO 10 -IF mobY(ox) < 170 THEN -IF levelGrid((mobX(ox) + 20) / 20, (mobY(ox) + 9) / 20) = "m" THEN kollal(ox) = -1 -IF mobX(ox) > 270 THEN kolled(ox) = -1 -IF mobX(ox) < 2 THEN kolled(ox) = 1 -IF levelGrid((mobX(ox) + 28) / 20, mobY(ox) / 20) = "m" THEN kolled(ox) = -1 -IF levelGrid((mobX(ox) + 10) / 20, mobY(ox) / 20) = "m" THEN kolled(ox) = 1 -IF mobX(ox) - 20 < a1 AND mobX(ox) + 20 > a1 AND mobY(ox) - 5 < b1 AND mobY(ox) + 20 > b1 THEN PlayHurtSound: HandlePlayerDeath: GOTO 12 -END IF -NEXT ox + +' Cycle through animation frames +animationFrameCounter = animationFrameCounter + 1 +IF animationFrameCounter > 3 THEN animationFrameCounter = 1 + +' Every third frame, process physics and input +IF animationFrameCounter = 1 THEN + enemyAnimationFrameCounter = enemyAnimationFrameCounter + 1 + IF enemyAnimationFrameCounter > 5 THEN enemyAnimationFrameCounter = 0 + + ' Apply gravity to player (increases downward speed each frame) + verticalMovementSpeed = verticalMovementSpeed + 1 + + ' Gradually reduce horizontal movement (friction effect) + IF horizontalMovementSpeed > 0 THEN horizontalMovementSpeed = horizontalMovementSpeed - 1: walkAnimationPhaseCounter = walkAnimationPhaseCounter + 1 + IF horizontalMovementSpeed < 0 THEN horizontalMovementSpeed = horizontalMovementSpeed + 1: walkAnimationPhaseCounter = walkAnimationPhaseCounter + 1 + + ' Alternate between walk animation phases every 2 frames + IF walkAnimationPhaseCounter > 2 THEN walkAnimationPhaseCounter = 1 + IF walkAnimationPhaseCounter = 2 THEN leftWalkFrameIndex = 1: rightWalkFrameIndex = 2 + IF walkAnimationPhaseCounter = 1 THEN leftWalkFrameIndex = 3: rightWalkFrameIndex = 4 + + ' Process enemy collisions and movements + FOR enemyIndex = 1 TO 10 + IF enemyYPositions(enemyIndex) < 170 THEN + ' Reverse vertical direction when hitting ceiling block + IF levelGrid((enemyXPositions(enemyIndex) + 20) / 20, (enemyYPositions(enemyIndex) + 9) / 20) = "m" THEN enemyVerticalSpeeds(enemyIndex) = -1 + + ' Reverse horizontal direction at screen edges + IF enemyXPositions(enemyIndex) > 270 THEN enemyHorizontalSpeeds(enemyIndex) = -1 + IF enemyXPositions(enemyIndex) < 2 THEN enemyHorizontalSpeeds(enemyIndex) = 1 + + ' Reverse horizontal direction when hitting wall blocks + IF levelGrid((enemyXPositions(enemyIndex) + 28) / 20, enemyYPositions(enemyIndex) / 20) = "m" THEN enemyHorizontalSpeeds(enemyIndex) = -1 + IF levelGrid((enemyXPositions(enemyIndex) + 10) / 20, enemyYPositions(enemyIndex) / 20) = "m" THEN enemyHorizontalSpeeds(enemyIndex) = 1 + + ' Check for collision with player (trigger death) + IF enemyXPositions(enemyIndex) - 20 < playerX AND enemyXPositions(enemyIndex) + 20 > playerX AND enemyYPositions(enemyIndex) - 5 < playerY AND enemyYPositions(enemyIndex) + 20 > playerY THEN PlayHurtSound: HandlePlayerDeath: GOTO 12 + END IF + NEXT enemyIndex END IF -IF levelGrid((a1 + 15) / 20, (b1 + 9) / 20) = "m" THEN alla = -1: ao = 0 -IF levelGrid((a1 + 25) / 20, (b1 + 9) / 20) = "m" THEN alla = -1: ao = 0 -IF levelGrid((a1 + 20) / 20, (b1 - 8) / 20) = "m" THEN alla = 1: ao = 20 -IF levelGrid((a1 + 28) / 20, (b1) / 20) = "m" THEN edasi = -1: qa = 1 -IF levelGrid((a1 + 10) / 20, (b1) / 20) = "m" THEN edasi = 1: qa = 1 - -IF ruum1((a1 + 20) / 20, (b1 - 8) / 20) = "o" THEN alla = 1: ruum1((a1 + 20) / 20, (b1 - 8) / 20) = "": levelGrid((a1 + 20) / 20, (b1 - 8) / 20) = "2": clra = ((a1 + 20) / 20) - 1: clrb = (b1 - 8) / 20: clr = 1: SOUND 50, .5 -IF levelGrid((a1 + 20) / 20, (b1) / 20) = "1" THEN levelGrid((a1 + 20) / 20, (b1) / 20) = "2": clra = ((a1 + 21) / 20) - 1: clrb = (b1) / 20: clr = 1: raha = raha + 1: UpdateHUD 1: SOUND 1000, 1: SOUND 2000, 1 -ao = ao + 1 -a$ = INKEY$ -IF a$ = CHR$(0) + "H" AND ao < 10 THEN alla = -6 -IF a$ = CHR$(0) + "M" AND qa = 0 THEN edasi = edasi + 3: liig = ov1 -IF a$ = CHR$(0) + "K" AND qa = 0 THEN edasi = edasi - 3: liig = ov2 -IF a$ = CHR$(27) THEN HandleEscapeKey -IF a$ = "+" AND qa = 0 THEN currentWorld = currentWorld + 1: LoadCurrentLevel: GOTO 12 -IF qa <> 0 THEN qa = 0 -IF edasi > 5 THEN edasi = 3 -IF edasi < -5 THEN edasi = -3 -IF alla > 3 THEN alla = 3 - -IF b1 > 0 THEN PUT (a1, b1), mari0, PSET - -IF z = 1 THEN -FOR ox = 10 TO 1 STEP -1 -IF mobY(ox) < 170 THEN PUT (mobX(ox), mobY(ox)), koll(202, ox), PSET -NEXT ox +' Check for player collisions with level geometry: + +' Ceiling collision (reverse gravity) +IF levelGrid((playerX + 15) / 20, (playerY + 9) / 20) = "m" THEN verticalMovementSpeed = -1: airTimeCounter = 0 + +' Right wall collision +IF levelGrid((playerX + 25) / 20, (playerY + 9) / 20) = "m" THEN verticalMovementSpeed = -1: airTimeCounter = 0 + +' Floor collision (stop falling) +IF levelGrid((playerX + 20) / 20, (playerY - 8) / 20) = "m" THEN verticalMovementSpeed = 1: airTimeCounter = 20 + +' Right wall collision +IF levelGrid((playerX + 28) / 20, (playerY) / 20) = "m" THEN horizontalMovementSpeed = -1: wallCollisionLock = 1 + +' Left wall collision +IF levelGrid((playerX + 10) / 20, (playerY) / 20) = "m" THEN horizontalMovementSpeed = 1: wallCollisionLock = 1 + +' Breakable block collision (turn into empty space) +IF interactiveObjectsGrid((playerX + 20) / 20, (playerY - 8) / 20) = "o" THEN verticalMovementSpeed = 1: interactiveObjectsGrid((playerX + 20) / 20, (playerY - 8) / 20) = "": levelGrid((playerX + 20) / 20, (playerY - 8) / 20) = "2": clearCoinGridX _ += ((playerX + 20) / 20) - 1: clearCoinGridY = (playerY - 8) / 20: shouldClearCoinFlag = 1: SOUND 50, .5 + +' Coin collection +IF levelGrid((playerX + 20) / 20, (playerY) / 20) = "1" THEN levelGrid((playerX + 20) / 20, (playerY) / 20) = "2": clearCoinGridX = ((playerX + 21) / 20) - 1: clearCoinGridY = (playerY) / 20: shouldClearCoinFlag = 1: coinsCollected = coinsCollected _ ++ 1: UpdateHUD 1: SOUND 1000, 1: SOUND 2000, 1 + +' Track time in air for jump control +airTimeCounter = airTimeCounter + 1 + +' Process keyboard input: +userInput$ = INKEY$ +' Jump when up arrow pressed (only if not already high in air) +IF userInput$ = CHR$(0) + "H" AND airTimeCounter < 10 THEN verticalMovementSpeed = -6 +' Move right with right arrow +IF userInput$ = CHR$(0) + "M" AND wallCollisionLock = 0 THEN horizontalMovementSpeed = horizontalMovementSpeed + 3: currentWalkFrameIndex = leftWalkFrameIndex +' Move left with left arrow +IF userInput$ = CHR$(0) + "K" AND wallCollisionLock = 0 THEN horizontalMovementSpeed = horizontalMovementSpeed - 3: currentWalkFrameIndex = rightWalkFrameIndex +' Escape key handler +IF userInput$ = CHR$(27) THEN HandleEscapeKey +' Level skip (debug only - plus key) +IF userInput$ = "+" AND wallCollisionLock = 0 THEN currentLevelNumber = currentLevelNumber + 1: LoadCurrentLevel: GOTO 12 +' Reset wall collision lock each frame +IF wallCollisionLock <> 0 THEN wallCollisionLock = 0 + +' Cap movement speeds to prevent excessive speed +IF horizontalMovementSpeed > 5 THEN horizontalMovementSpeed = 3 +IF horizontalMovementSpeed < -5 THEN horizontalMovementSpeed = -3 +IF verticalMovementSpeed > 3 THEN verticalMovementSpeed = 3 + +' Restore background where player was previously drawn +IF playerY > 0 THEN PUT (playerX, playerY), playerAnimationFrames, PSET + +' Redraw enemies on this animation frame +IF animationFrameCounter = 1 THEN + FOR enemyIndex = 10 TO 1 STEP -1 + IF enemyYPositions(enemyIndex) < 170 THEN PUT (enemyXPositions(enemyIndex), enemyYPositions(enemyIndex)), enemyBackgroundBuffers(202, enemyIndex), PSET + NEXT enemyIndex END IF +' Apply physics to player position +playerY = playerY + verticalMovementSpeed +playerX = playerX + horizontalMovementSpeed + +' Clear collected coin/block from screen +IF shouldClearCoinFlag > 0 THEN shouldClearCoinFlag = 0: PUT (clearCoinGridX * 20, clearCoinGridY * 20), emptySpaceSpriteBuffer, PSET -b1 = b1 + alla -a1 = a1 + edasi -IF clr > 0 THEN clr = 0: PUT (clra * 20, clrb * 20), tuhi, PSET -IF a1 > 280 THEN currentWorld = currentWorld + 1: LoadCurrentLevel: a1 = 3 -IF a1 < 2 THEN currentWorld = currentWorld - 1: LoadCurrentLevel: a1 = 279 -IF b1 > 170 THEN FOR a = 3000 TO 500 STEP -100: SOUND a, .3: NEXT a: HandlePlayerDeath +' Level transition when reaching screen edges +IF playerX > 280 THEN currentLevelNumber = currentLevelNumber + 1: LoadCurrentLevel: playerX = 3 +IF playerX < 2 THEN currentLevelNumber = currentLevelNumber - 1: LoadCurrentLevel: playerX = 279 + +' Player death when falling off bottom of screen +IF playerY > 170 THEN FOR tone = 3000 TO 500 STEP -100: SOUND tone, .3: NEXT tone: HandlePlayerDeath GOTO 12 SUB GameOverSequence -DIM diep(1 TO 2000) -GET (0, 0)-(150, 20), diep +' Shows game over screen with animated death effect. +' First displays "You are killed!" text, then pixelates the screen, +' adds flying debris animation, waits for keypress, then fades to black. + +DIM deathScreenBuffer(1 TO 2000) +GET (0, 0)-(150, 20), deathScreenBuffer LOCATE 1, 1 PRINT "You are " LOCATE 2, 1 PRINT " killed! " +' Create pixelated death effect by scaling up screen area FOR x = 0 TO 80 -FOR y = 0 TO 16 -IF POINT(x, y) > 0 THEN LINE (x * 5, y * 5 + 50)-(x * 5 + 4, y * 5 + 54), 4, BF -NEXT y + FOR y = 0 TO 16 + ' Only process non-background pixels + IF POINT(x, y) > 0 THEN + ' Draw 5x5 block for each original pixel (magnification effect) + LINE (x * 5, y * 5 + 50)-(x * 5 + 4, y * 5 + 54), 4, BF + END IF + NEXT y NEXT x -PUT (0, 0), diep, PSET - -FOR a = 1 TO 100 -x = RND * 290 + 4 -y = RND * 170 + 4 -GET (x, y)-(x + 20, y + 20), diep -x = x + RND * 4 - 2 -y = y + RND * 4 - 1 -PUT (x, y), diep, PSET -NEXT a -FOR a = 1 TO 50 -a$ = INKEY$ -NEXT a -a$ = INPUT$(1) - -FOR a = 0 TO 100 -SOUND 0, .05 -LINE (0, a)-(320, a), 4 -LINE (0, 200 - a)-(320, 200 - a), 4 -NEXT a -FOR a = 32 TO 0 STEP -1 -SOUND 0, .5 -OUT &H3C8, 4 -OUT &H3C9, a -OUT &H3C9, 0 -OUT &H3C9, 0 -NEXT a +PUT (0, 0), deathScreenBuffer, PSET + +' Add random flying debris particles +FOR particle = 1 TO 100 + x = RND * 290 + 4 + y = RND * 170 + 4 + GET (x, y)-(x + 20, y + 20), deathScreenBuffer + x = x + RND * 4 - 2 + y = y + RND * 4 - 1 + PUT (x, y), deathScreenBuffer, PSET +NEXT particle + +' Wait briefly before requiring keypress +FOR waitCount = 1 TO 50 + userInput$ = INKEY$ +NEXT waitCount +userInput$ = INPUT$(1) + +' Draw closing red lines from top and bottom +FOR lineIndex = 0 TO 10 + SOUND 0, .05 + LINE (0, lineIndex)-(320, lineIndex), 4 + LINE (0, 200 - lineIndex)-(320, 200 - lineIndex), 4 +NEXT lineIndex + +' Fade out red color channel to black +FOR fadeStep = 32 TO 0 STEP -1 + SOUND 0, .5 + OUT &H3C8, 4 + OUT &H3C9, fadeStep + OUT &H3C9, 0 + OUT &H3C9, 0 +NEXT fadeStep END END SUB SUB HandleEscapeKey -FOR b = 0 TO 20 -FOR a = b TO 200 STEP 20 -LINE (0, a)-(320, a), 0 -NEXT a -SOUND 0, .5 -NEXT b +' Handles ESC key press: performs smooth screen fadeout then exits to DOS. + +' Fade screen to black in vertical bands +FOR band = 0 TO 20 + FOR lineIndex = band TO 200 STEP 20 + LINE (0, lineIndex)-(320, lineIndex), 0 + NEXT lineIndex + SOUND 0, .5 +NEXT band SYSTEM END SUB SUB HandlePlayerDeath -IF currentWorld > 1 THEN currentWorld = currentWorld - 1 +' Processes player death: moves back one level, resets player position, +' decreases remaining lives, and updates HUD display. +' Does not end game - continues playing from previous level. + +IF currentLevelNumber > 1 THEN currentLevelNumber = currentLevelNumber - 1 LoadCurrentLevel -a1 = 20 -b1 = 100 +playerX = 20 +playerY = 100 lives = lives - 1 UpdateHUD 0 END SUB SUB InitializeAllLevelData +' Sets up all level layouts as text-based grids. +' Each character represents a game element: +' m = solid block +' o = breakable block +' $ = coin +' . = power-up item +' + = tree/decoration +' numbers 1-9 = enemy spawn points + levelSkyColor(1) = 1 levelData(1, 1) = "m " levelData(2, 1) = "m - - " @@ -431,145 +623,218 @@ levelData(8, 10) = "m . 1 " levelData(9, 10) = "mmmmmmmmmmm mm" END SUB -SUB inpur -userInput$ = "" -WHILE userInput$ = "" -userInput$ = INKEY$ -WEND -END SUB - -SUB intro -CLS -wiew 2, 2, 10, 1, "win.i01" -END SUB - SUB LoadCurrentLevel -IF currentWorld > 10 THEN -CLS -PRINT "Mission complete!" -PRINT "Game over" -END +' Loads and renders the currently selected level: +' 1. Validates level number (ends game at level 11) +' 2. Copies level data into working arrays +' 3. Resets interactive object grid +' 4. Clears enemy positions +' 5. Renders all level elements based on character codes + +IF currentLevelNumber > 10 THEN + CLS + PRINT "Mission complete!" + PRINT "Game over" + END END IF -FOR a = 1 TO 10 -levelRowData(a + 1) = levelData(a, currentWorld) -NEXT a - -FOR a = 1 TO 10 -FOR b = 1 TO 15 -IF levelGrid(b, a - 2) = "2" THEN MID$(levelData(a, previousWorld), b) = " " -NEXT b -NEXT a -previousWorld = currentWorld - -FOR a = -3 TO 20 -FOR b = -3 TO 20 -levelGrid(a, b) = "" -ruum1(a, b) = "" -NEXT b -NEXT a - -FOR a = 1 TO 10 -mobY(a) = 1000 -kolled(a) = 1 -kollal(a) = 0 -NEXT a +' Copy level rows into temporary storage +FOR rowIndex = 1 TO 10 + levelRowData(rowIndex + 1) = levelData(rowIndex, currentLevelNumber) +NEXT rowIndex + +' Clear breakable blocks from previous level +FOR rowIndex = 1 TO 10 + FOR columnIndex = 1 TO 15 + IF levelGrid(columnIndex, rowIndex - 2) = "2" THEN MID$(levelData(rowIndex, previousLevelNumber), columnIndex) = " " + NEXT columnIndex +NEXT rowIndex +previousLevelNumber = currentLevelNumber + +' Reset entire level grids to empty +FOR x = -3 TO 20 + FOR y = -3 TO 20 + levelGrid(x, y) = "" + interactiveObjectsGrid(x, y) = "" + NEXT y +NEXT x + +' Reset all enemies to off-screen positions +FOR enemyIndex = 1 TO 10 + enemyYPositions(enemyIndex) = 1000 + enemyHorizontalSpeeds(enemyIndex) = 1 + enemyVerticalSpeeds(enemyIndex) = 0 +NEXT enemyIndex +' Set background color and clear screen CLS -PAINT (1, 1), levelSkyColor(currentWorld) -GET (1, 2)-(20, 21), tuhi -FOR a = 2 TO 10 -FOR b = 1 TO 15 -c$ = RIGHT$(LEFT$(levelRowData(a), b), 1) -IF c$ = "-" THEN PUT ((b - 1) * 20, (a - 2) * 20), pilv, OR -IF c$ = "." THEN PUT ((b - 1) * 20, (a - 2) * 20), poosas, OR -IF c$ = "+" THEN PUT ((b - 1) * 20, (a - 2) * 20), puu, OR -IF c$ = "$" THEN PUT ((b - 1) * 20, (a - 2) * 20), munt, OR: levelGrid(b, a - 2) = "1" -IF c$ = "m" THEN PUT ((b - 1) * 20, (a - 2) * 20), kast, PSET: levelGrid(b, a - 2) = "m" -IF c$ = "o" THEN PUT ((b - 1) * 20, (a - 2) * 20), tellis, PSET: levelGrid(b, a - 2) = "m": ruum1(b, a - 2) = "o" -IF c$ = " " THEN levelGrid(b, a) = " " - -IF c$ = "1" THEN mobX(1) = (b - 1) * 20: mobY(1) = (a - 2) * 20: GET (mobX(1), mobY(1))-(mobX(1) + 20, mobY(1) + 20), koll(202, 1) -IF c$ = "2" THEN mobX(2) = (b - 1) * 20: mobY(2) = (a - 2) * 20: GET (mobX(2), mobY(2))-(mobX(2) + 20, mobY(2) + 20), koll(202, 2) -IF c$ = "3" THEN mobX(3) = (b - 1) * 20: mobY(3) = (a - 2) * 20: GET (mobX(3), mobY(3))-(mobX(3) + 20, mobY(3) + 20), koll(202, 3) -IF c$ = "4" THEN mobX(4) = (b - 1) * 20: mobY(4) = (a - 2) * 20: GET (mobX(4), mobY(4))-(mobX(4) + 20, mobY(4) + 20), koll(202, 4) -IF c$ = "5" THEN mobX(5) = (b - 1) * 20: mobY(5) = (a - 2) * 20: GET (mobX(5), mobY(5))-(mobX(5) + 20, mobY(5) + 20), koll(202, 5) -IF c$ = "6" THEN mobX(6) = (b - 1) * 20: mobY(6) = (a - 2) * 20: GET (mobX(6), mobY(6))-(mobX(6) + 20, mobY(6) + 20), koll(202, 6) -IF c$ = "7" THEN mobX(7) = (b - 1) * 20: mobY(7) = (a - 2) * 20: GET (mobX(7), mobY(7))-(mobX(7) + 20, mobY(7) + 20), koll(202, 7) -IF c$ = "8" THEN mobX(8) = (b - 1) * 20: mobY(8) = (a - 2) * 20: GET (mobX(8), mobY(8))-(mobX(8) + 20, mobY(8) + 20), koll(202, 8) -IF c$ = "9" THEN mobX(9) = (b - 1) * 20: mobY(9) = (a - 2) * 20: GET (mobX(9), mobY(9))-(mobX(9) + 20, mobY(9) + 20), koll(202, 9) -IF c$ = "0" THEN mobX(10) = (b - 1) * 20: mobY(10) = (a - 2) * 20: GET (mobX(10), mobY(10))-(mobX(10) + 20, mobY(10) + 20), koll(202, 10) -NEXT b -NEXT a +PAINT (1, 1), levelSkyColor(currentLevelNumber) +GET (1, 2)-(20, 21), emptySpaceSpriteBuffer + +' Process each character in level data to render elements +FOR rowIndex = 2 TO 10 + FOR columnIndex = 1 TO 15 + ' Extract single character from level data row + character$ = RIGHT$(LEFT$(levelRowData(rowIndex), columnIndex), 1) + + ' Render different elements based on character code + IF character$ = "-" THEN PUT ((columnIndex - 1) * 20, (rowIndex - 2) * 20), cloudSpriteBuffer, OR + IF character$ = "." THEN PUT ((columnIndex - 1) * 20, (rowIndex - 2) * 20), powerUpSpriteBuffer, OR + IF character$ = "+" THEN PUT ((columnIndex - 1) * 20, (rowIndex - 2) * 20), treeSpriteBuffer, OR + IF character$ = "$" THEN PUT ((columnIndex - 1) * 20, (rowIndex - 2) * 20), coinSpriteBuffer, OR: levelGrid(columnIndex, rowIndex - 2) = "1" + IF character$ = "m" THEN PUT ((columnIndex - 1) * 20, (rowIndex - 2) * 20), solidBlockSpriteBuffer, PSET: levelGrid(columnIndex, rowIndex - 2) = "m" + IF character$ = "o" THEN PUT ((columnIndex - 1) * 20, (rowIndex - 2) * 20), brickSpriteBuffer, PSET: levelGrid(columnIndex, rowIndex - 2) = "m": interactiveObjectsGrid(columnIndex, rowIndex - 2) = "o" + IF character$ = " " THEN levelGrid(columnIndex, rowIndex) = " " + + ' Place enemies based on numeric character codes (1-9,0) + IF character$ = "1" THEN enemyXPositions(1) = (columnIndex - 1) * 20: enemyYPositions(1) = (rowIndex - 2) * 20: GET (enemyXPositions(1), enemyYPositions(1))-(enemyXPositions(1) + 20, enemyYPositions(1) + 20), enemyBackgroundBuffers(202, 1) + IF character$ = "2" THEN enemyXPositions(2) = (columnIndex - 1) * 20: enemyYPositions(2) = (rowIndex - 2) * 20: GET (enemyXPositions(2), enemyYPositions(2))-(enemyXPositions(2) + 20, enemyYPositions(2) + 20), enemyBackgroundBuffers(202, 2) + IF character$ = "3" THEN enemyXPositions(3) = (columnIndex - 1) * 20: enemyYPositions(3) = (rowIndex - 2) * 20: GET (enemyXPositions(3), enemyYPositions(3))-(enemyXPositions(3) + 20, enemyYPositions(3) + 20), enemyBackgroundBuffers(202, 3) + IF character$ = "4" THEN enemyXPositions(4) = (columnIndex - 1) * 20: enemyYPositions(4) = (rowIndex - 2) * 20: GET (enemyXPositions(4), enemyYPositions(4))-(enemyXPositions(4) + 20, enemyYPositions(4) + 20), enemyBackgroundBuffers(202, 4) + IF character$ = "5" THEN enemyXPositions(5) = (columnIndex - 1) * 20: enemyYPositions(5) = (rowIndex - 2) * 20: GET (enemyXPositions(5), enemyYPositions(5))-(enemyXPositions(5) + 20, enemyYPositions(5) + 20), enemyBackgroundBuffers(202, 5) + IF character$ = "6" THEN enemyXPositions(6) = (columnIndex - 1) * 20: enemyYPositions(6) = (rowIndex - 2) * 20: GET (enemyXPositions(6), enemyYPositions(6))-(enemyXPositions(6) + 20, enemyYPositions(6) + 20), enemyBackgroundBuffers(202, 6) + IF character$ = "7" THEN enemyXPositions(7) = (columnIndex - 1) * 20: enemyYPositions(7) = (rowIndex - 2) * 20: GET (enemyXPositions(7), enemyYPositions(7))-(enemyXPositions(7) + 20, enemyYPositions(7) + 20), enemyBackgroundBuffers(202, 7) + IF character$ = "8" THEN enemyXPositions(8) = (columnIndex - 1) * 20: enemyYPositions(8) = (rowIndex - 2) * 20: GET (enemyXPositions(8), enemyYPositions(8))-(enemyXPositions(8) + 20, enemyYPositions(8) + 20), enemyBackgroundBuffers(202, 8) + IF character$ = "9" THEN enemyXPositions(9) = (columnIndex - 1) * 20: enemyYPositions(9) = (rowIndex - 2) * 20: GET (enemyXPositions(9), enemyYPositions(9))-(enemyXPositions(9) + 20, enemyYPositions(9) + 20), enemyBackgroundBuffers(202, 9) + IF character$ = "0" THEN enemyXPositions(10) = (columnIndex - 1) * 20: enemyYPositions(10) = (rowIndex - 2) * 20: GET (enemyXPositions(10), enemyYPositions(10))-(enemyXPositions(10) + 20, enemyYPositions(10) + 20), enemyBackgroundBuffers(202 _ +, 10) + NEXT columnIndex +NEXT rowIndex UpdateHUD 0 END SUB SUB PlayHurtSound -a = 1700 -b = 1900 -FOR c = 1 TO 50 -a = a + 3 -b = b - 5 -SOUND a, .2 -SOUND b, .2 -NEXT c +' Plays distinctive "hurt" sound effect with descending pitch. +' Creates two converging tones that slide downward in frequency. + +startFrequency = 1700 +endFrequency = 1900 +FOR toneStep = 1 TO 50 + startFrequency = startFrequency + 3 + endFrequency = endFrequency - 5 + SOUND startFrequency, .2 + SOUND endFrequency, .2 +NEXT toneStep END SUB -SUB RenderImageFromTextFile (a1, b1, c1, d1, a$) -a1 = a1 * 8 -b1 = b1 * 8 -laius1 = c1 - a1 -pikkus1 = d1 - b1 -OPEN a$ + ".i01" FOR INPUT AS #1 -INPUT #1, pikkus -FOR a = 1 TO pikkus -LINE INPUT #1, z$ -FOR b = LEN(z$) TO 1 STEP -1 -LINE (a1 + (b * c1), (b1 + (a * d1)) + 1)-(a1 + ((b + 1) * c1), b1 + ((a + 1) * d1)), ASC(LEFT$(RIGHT$(z$, b), 1)) - 40, BF -NEXT b -NEXT a +SUB RenderFlippedSpriteFromFile (x%, y%, widthMultiplier%, heightMultiplier%, Filename$) +' Renders sprite from text file but flips horizontally during rendering. +' File format: first line = height, subsequent lines contain ASCII art +' where each character's ASCII value determines color (offset by 40). + +x = x * 8 +y = y * 8 +spriteWidth = widthMultiplier - x +spriteHeight = heightMultiplier - y +OPEN Filename$ + ".i01" FOR INPUT AS #1 +INPUT #1, spriteHeight +FOR row = 1 TO spriteHeight + LINE INPUT #1, rowText$ + FOR column = LEN(rowText$) TO 1 STEP -1 + ' Calculate screen coordinates and color from ASCII value + currentColor = ASC(LEFT$(RIGHT$(rowText$, column), 1)) - 40 + ' Draw filled rectangle for each pixel (scaled by multipliers) + LINE (x + (column * widthMultiplier), (y + (row * heightMultiplier)) + 1)-(x + ((column + 1) * widthMultiplier), y + ((row + 1) * heightMultiplier)), currentColor, BF + NEXT column +NEXT row CLOSE END SUB -DEFINT A-Z -SUB UpdateHUD (zaz) +SUB RenderSpriteFromFile (x%, y%, widthMultiplier%, heightMultiplier%, SpriteName$) +' Renders sprite from text file in normal orientation. +' File format and rendering identical to RenderFlippedSpriteFromFile +' but processes characters left-to-right instead of right-to-left. + +spriteWidth = widthMultiplier - x +spriteHeight = heightMultiplier - y +OPEN SpriteName$ + ".i01" FOR INPUT AS #1 +INPUT #1, spriteHeight +FOR row = 1 TO spriteHeight + LINE INPUT #1, rowText$ + FOR column = 1 TO LEN(rowText$) + ' Calculate color from ASCII value (offset by 40) + currentColor = ASC(RIGHT$(LEFT$(rowText$, column), 1)) - 40 + ' Draw scaled pixel block + LINE (x + (column * widthMultiplier), (y + (row * heightMultiplier)) + 1)-(x + ((column + 1) * widthMultiplier) - 1, y + ((row + 1) * heightMultiplier)), currentColor, BF + NEXT column +NEXT row +CLOSE +END SUB + +SUB ShowIntroScreen +' Displays introductory splash screen using sprite rendering. + +CLS +RenderSpriteFromFile 2, 2, 10, 1, "win.i01" +END SUB + +SUB UpdateHUD (coinIncrementAmount%) +' Updates Heads-Up Display showing coins and lives: +' - Processes coin counter (with 100-coin bonus life) +' - Draws coin counter digits +' - Shows remaining lives + +' End game if no lives remain IF lives < 0 THEN GameOverSequence -PUT (0, 180), munt1, PSET -hudCoinDigits(1) = hudCoinDigits(1) + zaz -FOR b = 1 TO 3 -IF hudCoinDigits(1) > 9 THEN hudCoinDigits(1) = hudCoinDigits(1) - 10: hudCoinDigits(2) = hudCoinDigits(2) + 1 -IF hudCoinDigits(2) > 9 THEN hudCoinDigits(1) = 0: hudCoinDigits(2) = 0: lives = lives + 1 -NEXT b + +' Draw coin icon at left of HUD +PUT (0, 180), largeCoinSpriteBuffer, PSET + +' Add new coins to counter +CoinDigits(1) = CoinDigits(1) + coinIncrementAmount% + +' Handle decimal carry-over for coin counter +FOR digitPosition = 1 TO 3 + ' Carry from ones place to tens place + IF CoinDigits(1) > 9 THEN + CoinDigits(1) = CoinDigits(1) - 10 + CoinDigits(2) = CoinDigits(2) + 1 + END IF + + ' Convert 100 coins to extra life + IF CoinDigits(2) > 9 THEN + CoinDigits(1) = 0 + CoinDigits(2) = 0 + lives = lives + 1 + END IF +NEXT digitPosition + LOCATE 1, 1 -r = 3 -FOR a = 1 TO 2 -r = r - 1 -PUT ((a * 11) + 10, 180), digitImages(100, hudCoinDigits(r)), PSET -NEXT a +digitPosition = 3 +' Draw both digits of coin counter +FOR hudElement = 1 TO 2 + digitPosition = digitPosition - 1 + PUT ((hudElement * 11) + 10, 180), digitImages(100, CoinDigits(digitPosition)), PSET +NEXT hudElement + +' Cap maximum lives at 10 IF lives > 10 THEN lives = 10 + +' Draw "X" before lives counter PUT (43, 180), digitImages(100, 10), PSET -PUT (53, 180), munt2, PSET +' Draw small coin icon next to lives counter +PUT (53, 180), smallCoinSpriteBuffer, PSET +' Draw current lives count PUT (73, 180), digitImages(100, lives), PSET END SUB SUB UpdateLoadingScreen +' Visual progress indicator during asset loading. +' Draws black screen with incremental dots on bottom row. + LINE (0, 0)-(319, 150), 0, BF -LOCATE 20, 10 + prog -prog = prog + 1 +LOCATE 20, 10 + loadingProgressDotCount +loadingProgressDotCount = loadingProgressDotCount + 1 PRINT "." END SUB -SUB wiew (a1, b1, c1, d1, a$) -laius1 = c1 - a1 -pikkus1 = d1 - b1 -OPEN a$ + ".i01" FOR INPUT AS #1 -INPUT #1, pikkus -FOR a = 1 TO pikkus -LINE INPUT #1, z$ -FOR b = 1 TO LEN(z$) -LINE (a1 + (b * c1), (b1 + (a * d1)) + 1)-(a1 + ((b + 1) * c1) - 1, b1 + ((a + 1) * d1)), ASC(RIGHT$(LEFT$(z$, b), 1)) - 40, BF -NEXT b -NEXT a -CLOSE +SUB WaitForUserInput +' Waits for any keyboard input before continuing. +' Clears userInput$ variable first, then polls INKEY$ until non-empty. + +userInput$ = "" +WHILE userInput$ = "" + userInput$ = INKEY$ +WEND END SUB -- 2.20.1