Author Topic: Break Thru  (Read 306 times)

0 Members and 1 Guest are viewing this topic.

Offline Jaze

  • Newbie
  • Posts: 59
Break Thru
« on: July 19, 2021, 02:47:54 PM »
This game is a clone of Break Out on the Atari 2600 and Arkanoid for the 8-bit Nintendo. I gave up trying to make a bonus drop creating 2 balls. Anyway, it came out pretty good. I'm thinking of doing another clone with graphics instead of text like this one. It will be my first foray into graphics of any kind. The graphics would be filled rectangles and a circle so I think it would be a good starting point.

Code: QB64: [Select]
  1. ' Creator: Jaze McAskill -- mcaskilljaze@gmail.com
  2.  
  3. WIDTH 80, 50
  4. TYPE coordinate
  5.     x AS INTEGER
  6.     y AS INTEGER
  7.  
  8. TYPE droppingLetter
  9.     x AS INTEGER
  10.     y AS SINGLE
  11.     letter AS INTEGER
  12.  
  13.  
  14. GOTO beginning
  15. crap:
  16. PRINT "Error, error line"
  17.  
  18. beginning:
  19. CONST TRUE = 1
  20. CONST FALSE = 0
  21. CONST leftDirection = 19200 '   to make the code more readable with the left and right arrowkeys
  22. CONST rightDirection = 19712 '
  23. CONST upAndLeft = 1 'the ball always moves in one diagonal direction
  24. CONST upAndRight = 2
  25. CONST downAndLeft = 3
  26. CONST downAndRight = 4
  27. CONST theBackground = 0 '           to determine what the ball hit
  28. CONST theBrick = 1
  29. CONST theWall = 2
  30. CONST thePaddle = 3
  31. CONST theBall = 4
  32. CONST theBonus = 5
  33. CONST hitWallSound$ = "O2L30G"
  34. CONST hitPaddleSound$ = "O3L30C"
  35. CONST hitBrickSound$ = "O3L30G"
  36. CONST deathSound$ = "O4L15CO3CO2CO1L10C"
  37. CONST successBeep = "L9O2DL15DL9DL4F"
  38. CONST letterE = 69 'to lengthen / expand the paddle
  39. CONST letterS = 83 'to shrink the paddle
  40. CONST letterPlus = 43 ' score increase
  41. CONST letterMinus = 45 ' score decrease
  42. CONST letterStar = 42 'score multiplier
  43.  
  44. 'I share everything so I don't have to worry whether or not I was supposed to pass something. Plus it removes the need to pass the same variable multiple times
  45. DIM SHARED creationBoard(2 TO 79, 2 TO 46) AS INTEGER 'the colors on the board when creating a level
  46. FOR initializeArrayX = 2 TO 79
  47.     FOR initializeArrayY = 2 TO 46
  48.         creationBoard(initializeArrayX, initializeArrayY) = 1 'set the board to the background color
  49. DIM SHARED brick AS coordinate: brick.x = 2: brick.y = 2 'start the creation board at 2, 2
  50. DIM SHARED ball(1 TO 2) AS coordinate 'to track where the ball is on the board
  51. DIM SHARED ballDirection(1 TO 2) AS INTEGER 'track the ball's direction using the directional constants above
  52. DIM SHARED paddleLeft AS SINGLE ' the leftmost character of the paddle
  53. DIM SHARED board(1 TO 80, 1 TO 48, 1 TO 2) AS INTEGER 'the board for the game
  54. DIM SHARED numberOfBricks AS INTEGER 'the number of bricks currently on the board
  55. DIM SHARED currentLevel AS INTEGER: currentLevel = 1 'start at level 1
  56. DIM SHARED numberOfGuys AS INTEGER: numberOfGuys = 5
  57. DIM SHARED score AS INTEGER: scorte = 0
  58. DIM SHARED spaceToStart: spaceToStart = FALSE 'whether or not the spacebar was pushed to begin the level
  59. DIM SHARED debugMode AS INTEGER: debugMode = FALSE 'to bounce the ball off the bottom or to decrement numberOfGuys
  60. DIM SHARED penUp, currentColor, eraserOn AS INTEGER: penUp = TRUE: currentColor = 0: eraserOn = FALSE
  61. DIM SHARED mute AS INTEGER: mute = -1 ' -1 mute is off (sound on)
  62. DIM SHARED lastLevelCreated AS INTEGER: lastLevelCreated = 0
  63. DIM SHARED changeBallSomewhat AS INTEGER: changeBallSomewhat = 0 'used to move the ball a little bit to avoid never hitting all of the bricks
  64. DIM levelChecking AS INTEGER: levelChecking = 0 'used in the following loop to check what is the highest level
  65. DIM SHARED activeLetter AS droppingLetter: activeLetter.x = 0: activeLetter.y = 0: activeLetter.letter = 0
  66. DIM SHARED paddleLength AS INTEGER: paddleLength = 8
  67. DIM SHARED activeBall AS INTEGER 'as is or both if 3
  68.  
  69. CALL Menu
  70.  
  71. SUB Menu
  72.     printTheMenu = TRUE 'used to stop the menu from flickering
  73.     DO
  74.         IF printTheMenu = TRUE THEN
  75.             COLOR 14, 1
  76.             CLS
  77.             LOCATE 20, 1
  78.             PRINT CenterText$("Menu")
  79.             PRINT CenterText$("------")
  80.             PRINT
  81.             PRINT CenterText$("1.) Instructions")
  82.             PRINT
  83.             PRINT CenterText$("2.) Create A Level")
  84.             PRINT
  85.             PRINT CenterText$("3.) Play The Game")
  86.             PRINT
  87.             PRINT CenterText$("4.) Exit")
  88.             printTheMenu = FALSE
  89.         END IF
  90.         menuCommand$ = INKEY$
  91.         SELECT CASE menuCommand$
  92.             CASE "1"
  93.                 CALL Instructions
  94.                 printTheMenu = TRUE
  95.             CASE "2"
  96.                 CALL CreationMain
  97.                 printTheMenu = TRUE
  98.             CASE "3"
  99.                 CALL Main
  100.                 printTheMenu = TRUE
  101.         END SELECT
  102.     LOOP UNTIL menuCommand$ = "4"
  103.     END
  104.  
  105. SUB Instructions
  106.     COLOR 10, 1
  107.     CLS
  108.     LOCATE 2
  109.     PRINT CenterText$("Level Creator")
  110.     PRINT CenterText$("---------------")
  111.  
  112.     PRINT CenterText$("The available commands are listed at the bottom of the screen.")
  113.     PRINT CenterText$("When the pen is up, the cursor moves without adding to the level")
  114.     PRINT CenterText$("being created. When the pen is down the current brick is added")
  115.     PRINT CenterText$("to the level being created. The other commands are self explanatory.")
  116.     COLOR 12, 1
  117.     PRINT CenterText$("If no levels have been created, the default level is used.")
  118.     PRINT CenterText$("If you progress beyond all levels created, the last level created repeats.")
  119.     PRINT
  120.     PRINT
  121.     COLOR 14, 1
  122.     PRINT CenterText$("Game")
  123.     PRINT CenterText$("------")
  124.  
  125.     PRINT CenterText$("The object of the game is to progress to the next level by")
  126.     PRINT CenterText$("destroying all of the bricks. To do this you must position the")
  127.     PRINT
  128.     COLOR 15, 1
  129.     PRINT CenterText$(CHR$(219) + CHR$(219) + CHR$(219) + CHR$(219) + CHR$(219) + CHR$(219) + CHR$(219) + CHR$(219))
  130.     PRINT
  131.     COLOR 14, 1
  132.     PRINT CenterText$("under the ball so that it is reflected toward the bricks using")
  133.     PRINT CenterText$("the left and right arrow keys.")
  134.     LOCATE 24, 21
  135.     PRINT "Push ";: COLOR 13, 1: PRINT "[SPACEBAR]";: COLOR 14, 1: PRINT " to set the ball in motion."
  136.     PRINT: PRINT
  137.     COLOR 13, 1:
  138.     LOCATE , 5: PRINT "     Available Commands                         Bonus Drops": COLOR 14, 1: PRINT
  139.     LOCATE , 5: PRINT "+ to increase the game speed               E = Expand paddle": PRINT
  140.     LOCATE , 5: PRINT "- to decrease the game speed               S = Shrink paddle": PRINT
  141.     LOCATE , 5: PRINT "P to pause the game                        + = Plus 15 points": PRINT
  142.     LOCATE , 5: PRINT "M to toggle mute on and off                - = Minus 15 points": PRINT
  143.     LOCATE , 2: PRINT "[ESC] to return to the main menu           * = Score multiplier (-1, 1.5 or 2)": PRINT
  144.     PRINT: PRINT
  145.     PRINT CenterText$("Push C to turn on debug mode and O to turn it off.")
  146.     LOCATE 48
  147.     COLOR 15, 1
  148.     PRINT CenterText$("Push any key to continue.")
  149.     CALL P(FALSE)
  150.  
  151. FUNCTION CenterText$ (thisString$)
  152.     returnString$ = SPACE$(INT((80 - LEN(thisString$)) / 2)) + thisString$
  153.     CenterText$ = returnString$
  154.  
  155. SUB PrintBrick (x, y, onOrOff)
  156.     IF onOrOff = TRUE THEN
  157.         useColor = board(x, y, 2) 'print the brick instead of erasing it, pick up the color there
  158.     ELSEIF onOrOff = FALSE THEN
  159.         useColor = 1
  160.     END IF
  161.     FOR across = 0 TO 5
  162.         LOCATE y, x + across
  163.         COLOR useColor
  164.         PRINT CHR$(219)
  165.         board(x + across, y, 1) = 219
  166.         board(x + across, y, 2) = useColor
  167.     NEXT across
  168.     IF onOrOff = FALSE THEN 'brick is destroyed
  169.         numberOfBricks = numberOfBricks - 1
  170.         score = score + 5
  171.         chanceOfLetter = INT(RND * 100) + 1
  172.         IF chanceOfLetter <= 25 AND activeLetter.letter = 0 THEN ' 25% chance of bonus
  173.             pickingLetter = INT(RND * 5) + 1 'choose which bonus to activate
  174.             SELECT CASE pickingLetter
  175.                 CASE 1
  176.                     activeLetter.letter = letterE
  177.                 CASE 2
  178.                     activeLetter.letter = letterS
  179.                 CASE 3
  180.                     activeLetter.letter = letterPlus
  181.                 CASE 4
  182.                     activeLetter.letter = letterMinus
  183.                 CASE 5
  184.                     activeLetter.letter = letterStar
  185.             END SELECT
  186.             activeLetter.x = x + 3 'place the falling letter near the center of destroyed brick
  187.             activeLetter.y = y + 1
  188.             CALL PrintLetter(TRUE)
  189.         END IF
  190.         CALL PrintBoard
  191.     END IF
  192.  
  193. SUB PrintLetter (onOrOff)
  194.     IF INT(activeLetter.y) < 47 THEN 'whether the bonus letter is done falling
  195.         IF onOrOff = TRUE THEN 'display the bonus letter
  196.             clr = 9
  197.         ELSE
  198.             clr = 1 'remove bonus letter from display
  199.         END IF
  200.         CALL PlaceChar(activeLetter.x, activeLetter.y, activeLetter.letter, clr) 'put the letter on the board
  201.     ELSEIF activeLetter.y >= 47 THEN 'activate the letter or ignore it
  202.         IF paddleLeft <= activeLetter.x AND activeLetter.x <= paddleLeft + paddleLength - 1 THEN 'letter was caught
  203.             SELECT CASE activeLetter.letter 'which letter to activate
  204.                 CASE letterE 'lengthen the paddle
  205.                     IF paddleLength <= 10 THEN paddleLength = paddleLength + 2
  206.                     CALL PrintPaddle(TRUE)
  207.                 CASE letterS 'shrink the paddle
  208.                     IF paddleLength >= 8 THEN
  209.                         CALL PrintPaddle(FALSE)
  210.                         paddleLength = paddleLength - 2
  211.                         CALL PrintPaddle(TRUE)
  212.                     ELSEIF paddleLength > 5 AND paddleLength <= 7 THEN
  213.                         CALL PrintPaddle(FALSE)
  214.                         paddleLength = paddleLength - 1
  215.                         CALL PrintPaddle(TRUE)
  216.                     END IF
  217.                 CASE letterPlus 'increase score
  218.                     score = score + 15
  219.                 CASE letterMinus ' decrease score
  220.                     score = score - 15
  221.                 CASE letterStar 'multiply the score
  222.                     DIM multiplier AS SINGLE
  223.                     multiplier = INT(RND * 3) + 1
  224.                     IF multiplier = 1 THEN
  225.                         multiplier = -1
  226.                     ELSEIF multiplier = 3 THEN
  227.                         multiplier = 1.5
  228.                     END IF
  229.                     score = INT(score * multiplier)
  230.             END SELECT 'action has been done with selected bonus letter
  231.         END IF ' the letter has finished being caught
  232.         activeLetter.x = 0: activeLetter.y = 0: activeLetter.letter = 0 'the letter is no longer active
  233.     END IF
  234.  
  235. SUB PrintLevel (cl)
  236.     'clear the playing field
  237.     FOR x = 1 TO 80: FOR y = 1 TO 48 'make the board blue
  238.             board(x, y, 1) = 219 '    ASCII code of board space
  239.             board(x, y, 2) = 1 '      color of board space
  240.     NEXT y: NEXT x
  241.     COLOR 1, 1: CLS
  242.     'print left, right and top borders and put them on the board
  243.     FOR y = 1 TO 48
  244.         LOCATE y, 1: COLOR 12, 1: PRINT CHR$(219) 'print the left border to the screen
  245.         LOCATE y, 80: COLOR 12, 1: PRINT CHR$(219) 'print the right border to the screen
  246.         CALL PlaceChar(1, y, 219, 12) ' put the position, ASCII code and color on the board to make the left border
  247.         CALL PlaceChar(80, y, 219, 12) ' same to make the left border on the board
  248.     NEXT y
  249.     FOR x = 1 TO 80
  250.         LOCATE 1, x: COLOR 12, 1: PRINT CHR$(219) 'print the top border to the screen
  251.         CALL PlaceChar(x, 1, 219, 12) ' put the top border on the board
  252.     NEXT x
  253.     paddleLeft = INT(RND * (72 - 2 + 1)) + 2 'position the paddle to start
  254.     paddleLength = 8
  255.     CALL PrintPaddle(TRUE) ' put the paddle on the board with the left at x coordinate 36
  256.     activeBall = 1
  257.     ball(activeBall).x = paddleLeft + 4: ball(activeBall).y = 47 ' position the ball/moving ball
  258.     CALL PrintBall(activeBall, TRUE) ' put the ball on the board
  259.     ballDirection(activeBall) = INT(RND * 2) + 1 'randomize the starting direction of the ball as up and left or up and right
  260.     IF _FILEEXISTS("Highest Level") THEN
  261.         OPEN "Highest Level" FOR INPUT AS #1
  262.         INPUT #1, highLev$
  263.         highestLevel = VAL(highLev$)
  264.         CLOSE #1
  265.     ELSE
  266.         highestLevel = 0
  267.     END IF
  268.     filename$ = ""
  269.     IF currentLevel < highestLevel THEN
  270.         filename$ = "Level " + S$(currentLevel)
  271.     ELSEIF highestLevel <> 0 THEN
  272.         filename$ = "Level " + S$(highestLevel)
  273.     END IF
  274.     IF filename$ <> "" THEN
  275.         OPEN filename$ FOR INPUT AS #1 'open the file with the level information
  276.         FOR xCounting = 2 TO 79 ' x coordinate of the board
  277.             FOR yCounting = 2 TO 46 ' y coordinate of the board
  278.                 INPUT #1, boardColor$ ' get the color of the board at xCounting, yCounting
  279.                 board(xCounting, yCounting, 2) = VAL(boardColor$) 'color the board at xCounting, yCounting
  280.         NEXT: NEXT
  281.         CLOSE #1
  282.     ELSE
  283.         FOR x = 2 TO 79
  284.             CALL PlaceChar(x, 2, 219, 14) 'put a yellow (14) block (219) at x, y on the board
  285.             CALL PlaceChar(x, 4, 219, 14)
  286.             CALL PlaceChar(x, 6, 219, 14)
  287.         NEXT x
  288.         lastLevelCreated = 1
  289.     END IF
  290.     numberOfBricks = 0 ' after a level has been put on the board, count the number of bricks on it
  291.     FOR brickCountingY = 2 TO 46 'with this set to 47 the ball was being counted as a brick sometimes
  292.         FOR brickCountingX = 2 TO 79 STEP 6 'each brick is 6 blocks long
  293.             IF board(brickCountingX, brickCountingY, 2) <> 1 THEN
  294.                 numberOfBricks = numberOfBricks + 1
  295.             END IF
  296.     NEXT: NEXT
  297.     CALL PrintBoard 'print the board to the screen
  298.     spaceToStart = FALSE 'spacebar has yet to be puched to start the current level
  299.  
  300. SUB Main
  301.     CALL PrintLevel(currentLevel) 'put the current level on the board and print it out
  302.     printOutBoard = FALSE ' to avoid flicker of the board being constantly printed, the need to print it is false
  303.     delaySpeed = 0.029 'delay to use inside the main DO-LOOP
  304.     activeBall = 1
  305.     DO
  306.         debugging$ = INKEY$ 'using strings instead of _KEYDOWN(code) is easier. i initially added INKEY$ for debugging
  307.         IF spaceToStart = TRUE THEN ' the spacebar has been hit to start the game
  308.             IF activeBall <> 3 THEN
  309.                 CALL PrintBall(activeBall, FALSE)
  310.                 CALL MoveBall(activeBall)
  311.                 CALL PrintBall(activeBall, TRUE)
  312.             ELSE
  313.                 CALL PrintBall(1, FALSE)
  314.                 CALL PrintBall(2, FALSE)
  315.                 CALL MoveBall(1)
  316.                 CALL MoveBall(2)
  317.                 CALL PrintBall(1, TRUE)
  318.                 CALL PrintBall(2, TRUE)
  319.             END IF
  320.             IF _KEYDOWN(leftDirection) = -1 THEN 'the left arrow key had been pushed
  321.                 CALL PrintPaddle(FALSE) ' remove the paddle from the board
  322.                 paddleLeft = paddleLeft - 1.5 ' move the paddle leftward
  323.                 CALL PrintPaddle(TRUE) ' put the paddle on the board at the new position
  324.                 printOutBoard = TRUE 'it is now needed to print the board to the screen
  325.             ELSEIF _KEYDOWN(rightDirection) = -1 THEN
  326.                 CALL PrintPaddle(FALSE)
  327.                 paddleLeft = paddleLeft + 1.5
  328.                 CALL PrintPaddle(TRUE)
  329.                 printOutBoard = TRUE
  330.             END IF
  331.             IF printOutBoard = TRUE THEN 'print the board to the screen
  332.                 CALL PrintBoard ' print the board to the screen
  333.                 printOutBoard = FALSE 'stop the board from being printed now
  334.             END IF
  335.             IF numberOfBricks = 0 THEN 'there are no bricks left on the board
  336.                 currentLevel = currentLevel + 1 'increment the current level
  337.                 activeLetter.letter = 0: activeLetter.x = 0: activeLetter.y = 0
  338.                 CALL PrintLevel(currentLevel) 'put the newest level on the board
  339.                 spaceToStart = FALSE 'the spacebar has not been pressed since the new level has been output
  340.                 score = score + 200 '200 points for finishing a level
  341.                 IF mute = -1 THEN PLAY successBeep '1 is mute, -1 is note muted
  342.             END IF
  343.             IF activeLetter.letter <> 0 THEN
  344.                 CALL PrintLetter(FALSE)
  345.                 activeLetter.y = activeLetter.y + 0.5
  346.                 CALL PrintLetter(TRUE)
  347.                 printOutBoard = TRUE
  348.             END IF
  349.         END IF
  350.         IF debugging$ = "C" THEN debugMode = TRUE
  351.         IF debugging$ = "O" THEN debugMode = FALSE
  352.         IF _KEYDOWN(32) = -1 THEN ' the spacebar has been pushed
  353.             spaceToStart = TRUE ' the spacebar has been pushed
  354.             printOutBoard = TRUE ' it is needed to print the board to the screen
  355.         END IF
  356.         _DELAY (delaySpeed) ' insert a delay to make the movement playable and visible
  357.         IF numberOfGuys = 0 THEN CALL EndOfGame
  358.         IF score MOD 750 = 0 AND score <> 0 THEN numberOfGuys = numberOfGuys + 1 ' new guy every 2,000 points
  359.         IF debugging$ = "+" THEN 'increase the game speed
  360.             delaySpeed = delaySpeed - 0.005
  361.             IF delaySpeed < 0 THEN delaySpeed = 0 'don't allow a negative delay
  362.         END IF
  363.         IF debugging$ = "-" THEN delaySpeed = delaySpeed + 0.005 'decrease the game speed
  364.         IF debugging$ = "m" OR debugging$ = "M" THEN mute = mute * -1 'turn mute on or off
  365.         IF debugging$ = "p" OR debugging$ = "P" THEN pause$ = INPUT$(1) 'pause the game
  366.         IF debugging$ = CHR$(27) THEN EXIT DO 'end the game and return to the main menu
  367.     LOOP
  368.  
  369. SUB EndOfGame
  370.     COLOR 15, 0
  371.     CLS
  372.     PRINT "Game over"
  373.     CALL P(FALSE)
  374.  
  375. SUB MoveBall (whichOne)
  376.     changeBallSomewhat = changeBallSomewhat + 1 'keep track of the number of times the ball has moved to occasionally nudge it
  377.     SELECT CASE ballDirection(whichOne)
  378.         CASE upAndRight
  379.             CALL MoveUpAndRight(whichOne)
  380.         CASE upAndLeft
  381.             CALL MoveUpAndLeft(whichOne)
  382.         CASE downAndRight
  383.             CALL MoveDownAndRight(whichOne)
  384.         CASE downAndLeft
  385.             CALL MoveDownAndLeft(whichOne)
  386.     END SELECT
  387.  
  388. FUNCTION Report (x, y) 'determine what element is at specified x, y location
  389.     'if color  12 then border, 1 then background, 15 then paddle, 11 ball, 9 bonus, else brick
  390.     rtn = -1 'initialize what should be returned
  391.     SELECT CASE board(x, y, 2)
  392.         CASE 12
  393.             rtn = theWall
  394.         CASE 1
  395.             rtn = theBackground
  396.         CASE 15
  397.             rtn = thePaddle
  398.         CASE 11
  399.             rtn = theBall
  400.         CASE 9
  401.             rtn = theBonus
  402.         CASE ELSE
  403.             rtn = theBrick
  404.     END SELECT
  405.     Report = rtn
  406.  
  407. SUB MoveUpAndRight (thisBall)
  408.     SELECT CASE Report(ball(thisBall).x + 1, ball(thisBall).y - 1) 'report one away from where the ball currently is
  409.         CASE theBackground, theBall ' move it even if both balls are in the same place
  410.             ball(thisBall).x = ball(thisBall).x + 1
  411.             ball(thisBall).y = ball(thisBall).y - 1
  412.             IF changeBallSomewhat MOD 100 = 0 AND ball(thisBall).x + 1 < 80 THEN ball(thisBall).x = ball(thisBall).x + 1
  413.         CASE theWall
  414.             IF mute = -1 THEN PLAY hitWallSound
  415.             IF ball(thisBall).x + 1 = 80 THEN
  416.                 'hit the right wall
  417.                 ballDirection(thisBall) = upAndLeft
  418.             ELSEIF ball(thisBall).y - 1 = 1 THEN
  419.                 'hit top wall
  420.                 ballDirection(thisBall) = downAndRight
  421.             END IF
  422.         CASE theBrick
  423.             IF mute = -1 THEN PLAY hitBrickSound
  424.             leftSideOfBrick = FindBrickLeft(ball(thisBall).x + 1)
  425.             vertOfBrick = FindBrickVertical(ball(thisBall).y - 1)
  426.             CALL PrintBrick(leftSideOfBrick, vertOfBrick, FALSE)
  427.             ballDirection(thisBall) = downAndRight
  428.     END SELECT
  429.  
  430. SUB MoveUpAndLeft (b)
  431.     SELECT CASE Report(ball(b).x - 1, ball(b).y - 1)
  432.         CASE theBackground, theBall, theBonus
  433.             ball(b).x = ball(b).x - 1
  434.             ball(b).y = ball(b).y - 1
  435.             IF changeBallSomewhat MOD 100 = 0 AND ball(b).x - 1 > 1 THEN ball(b).x = ball(b).x - 1
  436.         CASE theWall
  437.             IF mute = -1 THEN PLAY hitWallSound
  438.             IF ball(b).x - 1 = 1 THEN
  439.                 ballDirection(b) = upAndRight
  440.             ELSEIF ball(b).y - 1 = 1 THEN 'hit the top
  441.                 ballDirection(b) = downAndLeft
  442.             END IF
  443.         CASE theBrick
  444.             IF mute = -1 THEN PLAY hitBrickSound
  445.             leftSideOfBrick = FindBrickLeft(ball(b).x - 1)
  446.             vertOfBrick = FindBrickVertical(ball(b).y - 1)
  447.             CALL PrintBrick(leftSideOfBrick, vertOfBrick, FALSE)
  448.             ballDirection = downAndLeft
  449.     END SELECT
  450.  
  451. SUB MoveDownAndRight (var)
  452.     SELECT CASE Report(ball(var).x + 1, ball(var).y + 1)
  453.         CASE theBackground, theBall, theBonus
  454.             IF ball(var).y + 1 = 48 THEN
  455.                 IF debugMode = FALSE THEN
  456.                     CALL PrintBall(var, FALSE) 'remove the ball the fell from the screen
  457.                     IF activeBall <> 3 THEN 'activeBall is 1 or 2
  458.                         score = score - 50
  459.                         spaceToStart = FALSE
  460.                         CALL PrintPaddle(FALSE)
  461.                         paddleLength = 8
  462.                         paddleLeft = INT(RND * (72 - 2 + 1)) + 2
  463.                         activeBall = 1
  464.                         ball(activeBall).x = paddleLeft + 4: ball(activeBall).y = 47
  465.                         CALL PrintBall(activeBall, TRUE)
  466.                         CALL PrintPaddle(TRUE)
  467.                         ballDirection(activeBall) = INT(RND * 2) + 1
  468.                         IF mute = -1 THEN PLAY deathSound
  469.                         numberOfGuys = numberOfGuys - 1
  470.                         CALL PrintBoard
  471.                     ELSEIF activeBall = 3 THEN
  472.                         IF var = 1 THEN
  473.                             activeBall = 2
  474.                         ELSEIF var = 2 THEN
  475.                             activeBall = 1
  476.                         END IF
  477.                         ball(var).x = 0
  478.                         ball(var).y = 0
  479.                         COLOR 10, 0: LOCATE 10, 1
  480.                         PRINT "ball(var).x, ball(var).y"
  481.                         PRINT "ball(" + S$(var) + ").x, ball(+"; S$(var) + ").y"
  482.                         PRINT S$(ball(var).x) + ", " + S$(ball(var).y)
  483.                         PRINT "activeBall: " + S$(activeBall)
  484.                         CALL P(TRUE)
  485.                     ELSE
  486.                         LOCATE 40, 1: COLOR 15, 0: PRINT "MoveDownAndRight has active ball<>1, 2 or 3": CALL P(TRUE)
  487.                     END IF
  488.                 ELSE 'debug mode is on (true)
  489.                     IF mute = -1 THEN PLAY hitWallSound
  490.                     ballDirection(var) = upAndRight
  491.                     ball(var).x = ball(var).x + 1
  492.                     ball(var).y = ball(var).y - 1
  493.                     IF changeBallSomewhat MOD 100 = 0 AND ball(var).x + 1 < 80 THEN ball(var).x = ball(var).x + 1
  494.                 END IF
  495.             ELSE 'debug is on
  496.                 ball(var).x = ball(var).x + 1
  497.                 ball(var).y = ball(var).y + 1
  498.             END IF
  499.         CASE theWall
  500.             IF mute = -1 THEN PLAY hitWallSound
  501.             IF ball(var).x + 1 = 80 THEN ballDirection(var) = downAndLeft
  502.         CASE theBrick
  503.             IF mute = -1 THEN PLAY hitBrickSound
  504.             leftSideOfBrick = FindBrickLeft(ball(var).x + 1)
  505.             vertOfBrick = FindBrickVertical(ball(var).y + 1)
  506.             CALL PrintBrick(leftSideOfBrick, vertOfBrick, FALSE)
  507.             ballDirection(var) = upAndRight
  508.         CASE thePaddle
  509.             IF mute = -1 THEN PLAY hitPaddleSound
  510.             ballDirection(var) = upAndRight
  511.     END SELECT
  512.  
  513. SUB MoveDownAndLeft (i)
  514.     SELECT CASE Report(ball(i).x - 1, ball(i).y + 1)
  515.         CASE theBackground, theBall, theBonus
  516.             IF ball(i).y + 1 = 48 THEN
  517.                 IF debugMode = FALSE THEN
  518.                     CALL PrintBall(i, FALSE)
  519.                     IF activeBall <> 3 THEN 'only one ball was active
  520.                         score = score - 50
  521.                         spaceToStart = FALSE
  522.                         CALL PrintPaddle(FALSE)
  523.                         paddleLeft = INT(RND * (72 - 2% + 1)) + 2
  524.                         paddleLength = 8
  525.                         activeBall = 1
  526.                         ball(activeBall).x = paddleLeft + 4: ball(activeBall).y = 47
  527.                         CALL PrintBall(activeBall, TRUE)
  528.                         CALL PrintPaddle(TRUE)
  529.                         ballDirection(activeBall) = INT(RND * 2) + 1
  530.                         IF mute = -1 THEN PLAY deathSound
  531.                         numberOfGuys = numberOfGuys - 1
  532.                         CALL PrintBoard
  533.                     ELSE 'one ball fell off the screen
  534.                         IF i = 1 THEN
  535.                             activeBall = 2
  536.                         ELSEIF i = 2 THEN
  537.                             activeBall = 1
  538.                         END IF
  539.                         ball(i).x = 0
  540.                         ball(i).y = 0
  541.                     END IF
  542.                 ELSE 'in debug mode
  543.                     IF mute = -1 THEN PLAY hitWallSound
  544.                     ballDirection(i) = upAndLeft
  545.                     ball(i).x = ball(i).x - 1
  546.                     ball(i).y = ball(i).y - 1
  547.                     IF changeBallSomewhat MOD 100 = 0 AND ball(i).x - 1 > 1 THEN ball(i).x = ball(i).x + 1
  548.                 END IF
  549.             ELSE 'not at bottom of screen
  550.                 ball(i).x = ball(i).x - 1
  551.                 ball(i).y = ball(i).y + 1
  552.             END IF
  553.         CASE theWall
  554.             IF mute = -1 THEN PLAY hitWallSound
  555.             IF ball(i).x - 1 = 1 THEN ballDirection(i) = downAndRight
  556.         CASE theBrick
  557.             IF mute = -1 THEN PLAY hitBrickSound
  558.             leftSideOfBrick = FindBrickLeft(ball(i).x - 1)
  559.             vertOfBrick = FindBrickVertical(ball(i).y + 1)
  560.             CALL PrintBrick(leftSideOfBrick, vertOfBrick, FALSE)
  561.             ballDirection(i) = upAndLeft
  562.         CASE thePaddle
  563.             IF mute = -1 THEN PLAY hitPaddleSound
  564.             ballDirection(i) = upAndLeft
  565.     END SELECT
  566.  
  567. FUNCTION FindBrickLeft (x) 'this returns the x coordinate of the brick that was hit
  568.     rtn = 0
  569.     FOR cnt = 2 TO 79 STEP 6
  570.         IF cnt <= x AND x <= cnt + 5 THEN rtn = cnt
  571.     NEXT cnt
  572.     FindBrickLeft = rtn
  573.  
  574. FUNCTION FindBrickVertical (y)
  575.     rtn = 0
  576.     FOR cnt = 2 TO 47
  577.         IF cnt = y THEN rtn = cnt
  578.     NEXT
  579.     FindBrickVertical = rtn
  580.  
  581. SUB PrintBall (whichBall, onOrOff) 'put the ball on the board or remove it from the board to effect position change
  582.     IF onOrOff = TRUE THEN
  583.         useColor = 11
  584.     ELSEIF onOrOff = FALSE THEN
  585.         useColor = 1
  586.     END IF
  587.     CALL PlaceChar(ball(whichBall).x, ball(whichBall).y, 254, useColor)
  588.     CALL PrintBoard
  589.  
  590. SUB PrintPaddle (onOrOff)
  591.     IF onOrOff = TRUE THEN
  592.         theColor = 15
  593.     ELSEIF onOrOf = FALSE THEN
  594.         theColor = 1
  595.     END IF
  596.     IF paddleLeft < 2 THEN paddleLeft = 2
  597.     IF paddleLeft > 80 - paddleLength THEN paddleLeft = 80 - paddleLength
  598.     FOR across = 0 TO paddleLength - 1
  599.         LOCATE 48, INT(paddleLeft) + across: COLOR theColor: PRINT CHR$(219)
  600.         CALL PlaceChar(INT(paddleLeft) + across, 48, 219, theColor)
  601.     NEXT across
  602.  
  603. SUB PlaceChar (X, Y, char, clr) 'put the character ASCII with specified color on the board
  604.     board(X, Y, 1) = char 'character
  605.     board(X, Y, 2) = clr ' color
  606.  
  607. SUB PrintBoard 'print the current board configurationg to the screen and update the current stats displayed
  608.     FOR y = 2 TO 48: FOR x = 2 TO 79
  609.             this$ = CHR$(board(x, y, 1))
  610.             theColor = board(x, y, 2)
  611.             COLOR theColor, 1
  612.             LOCATE y, x
  613.             PRINT this$
  614.             IF BrickIsThere(x, y) = TRUE THEN
  615.                 xCo = FindBrickLeft(x)
  616.                 yCo = FindBrickVertical(y)
  617.                 CALL PrintBrick(xCo, yCo, TRUE)
  618.             END IF
  619.     NEXT x: NEXT y
  620.     LOCATE 1, 2: COLOR 10, 12
  621.     PRINT "  Level " + S$(currentLevel) + "       ";
  622.     PRINT "Men: " + S$(numberOfGuys) + "       ";
  623.     PRINT "Bricks remaining: " + S$(numberOfBricks) + "       ";
  624.     PRINT "Score: " + S$(score) + "    "
  625.  
  626. FUNCTION BrickIsThere (xCoord, yCoord)
  627.     x = xCoord: y = yCoord
  628.     rtn = FALSE
  629.     IF board(x, y, 2) <> 11 AND board(x, y, 2) <> 15 AND board(x, y, 2) <> 12 AND board(x, y, 2) <> 9 AND board(x, y, 2) <> 1 THEN rtn = TRUE
  630.     BrickIsThere = rtn
  631.  
  632. SUB CreationMain 'main subroutine for the level creation feature
  633.     penUp = TRUE
  634.     eraserOn = FALSE
  635.     currentColor = 0
  636.     brick.x = 2
  637.     brick.y = 2
  638.     FOR countX = 2 TO 79
  639.         FOR countY = 2 TO 46
  640.             creationBoard(countX, countY) = 1
  641.     NEXT: NEXT
  642.     CALL PrintBackdrop
  643.     CALL PrintCreationBoard
  644.     CALL PrintCreationBrick
  645.     printOutCurrentBoard = FALSE
  646.     DO
  647.         whichCommand$ = INKEY$
  648.         SELECT CASE whichCommand$
  649.             CASE "P", "p"
  650.                 IF penUp = TRUE THEN
  651.                     penUp = FALSE
  652.                     CALL PutBrickOnBoard
  653.                 ELSEIF penUp = FALSE AND eraserOn = FALSE THEN
  654.                     penUp = TRUE
  655.                 END IF
  656.                 CALL PrintBackdrop
  657.                 printOutCurrentBoard = TRUE
  658.             CASE "E", "e"
  659.                 IF eraserOn = FALSE THEN
  660.                     eraserOn = TRUE
  661.                     currentColor = 1
  662.                     penUp = FALSE
  663.                     CALL PutBrickOnBoard
  664.                 ELSEIF eraserOn = TRUE THEN
  665.                     eraserOn = FALSE
  666.                     currentColor = 0
  667.                     penUp = TRUE
  668.                 END IF
  669.                 printOutCurrentBoard = TRUE
  670.             CASE "C", "c" 'game uses 12, 15, 11, 1 and 9, 17
  671.                 IF currentColor = 0 THEN
  672.                     currentColor = 2
  673.                 ELSEIF currentColor = 8 THEN
  674.                     currentColor = 10
  675.                 ELSEIF currentColor = 10 THEN
  676.                     currentColor = 13
  677.                 ELSEIF currentColor = 14 THEN
  678.                     currentColor = 16
  679.                 ELSEIF currentColor = 16 THEN
  680.                     currentColor = 18
  681.                 ELSEIF currentColor < 31 THEN
  682.                     currentColor = currentColor + 1
  683.                 ELSEIF currentColor = 31 THEN
  684.                     currentColor = 0
  685.                 END IF
  686.                 printOutCurrentBoard = TRUE
  687.                 IF penUp = FALSE THEN CALL PutBrickOnBoard
  688.             CASE "A", "a"
  689.                 penUp = TRUE
  690.                 eraserOn = FALSE
  691.                 currentColor = 0
  692.                 FOR xCount = 2 TO 79
  693.                     FOR yCount = 2 TO 46
  694.                         creationBoard(xCount, yCount) = 1
  695.                 NEXT: NEXT
  696.                 printOutCurrentBoard = TRUE
  697.             CASE "s", "S"
  698.                 IF SaveBoard$ = "END" THEN EXIT DO
  699.             CASE CHR$(0) + "H" ' up
  700.                 IF brick.y > 2 THEN
  701.                     brick.y = brick.y - 1
  702.                     IF penUp = FALSE THEN CALL PutBrickOnBoard
  703.                     printOutCurrentBoard = TRUE
  704.                 END IF
  705.             CASE CHR$(0) + "K" ' left
  706.                 IF brick.x > 7 THEN
  707.                     brick.x = brick.x - 6
  708.                     IF penUp = FALSE THEN CALL PutBrickOnBoard
  709.                     printOutCurrentBoard = TRUE
  710.                 END IF
  711.             CASE CHR$(0) + "P" ' down
  712.                 IF brick.y < 47 THEN
  713.                     brick.y = brick.y + 1
  714.                     IF penUp = FALSE THEN CALL PutBrickOnBoard
  715.                     printOutCurrentBoard = TRUE
  716.                 END IF
  717.             CASE CHR$(0) + "M" ' right
  718.                 IF brick.x < 73 THEN
  719.                     brick.x = brick.x + 6
  720.                     IF penUp = FALSE THEN CALL PutBrickOnBoard
  721.                     printOutCurrentBoard = TRUE
  722.                 END IF
  723.             CASE CHR$(27)
  724.                 EXIT DO
  725.         END SELECT
  726.         IF printOutCurrentBoard = TRUE THEN
  727.             CALL PrintBackdrop
  728.             CALL PrintCreationBoard
  729.             CALL PrintCreationBrick
  730.             printOutCurrentBoard = FALSE
  731.         END IF
  732.     LOOP
  733.  
  734. FUNCTION SaveBoard$
  735.     COLOR 10, 0
  736.     CLS
  737.     hghstLvl = 0
  738.     IF _FILEEXISTS("Highest Level") THEN
  739.         OPEN "Highest Level" FOR INPUT AS #1
  740.         INPUT #1, hl$
  741.         highestLevel = VAL(hl$)
  742.         CLOSE #1
  743.         highestLevel = highestLevel + 1
  744.         OPEN "Highest Level" FOR OUTPUT AS #1
  745.         PRINT #1, S$(highestLevel)
  746.         CLOSE #1
  747.     ELSE
  748.         OPEN "Highest Level" FOR OUTPUT AS #1
  749.         PRINT #1, S$(1)
  750.         CLOSE #1
  751.         highestLevel = 1
  752.     END IF
  753.  
  754.     filename$ = "Level " + S$(highestLevel)
  755.     LOCATE 10, 10
  756.     PRINT "The game board has been saved as " + CHR$(34) + "Level " + S$(highestLevel) + CHR$(34)
  757.     PRINT
  758.     IF highestLevel > 1 THEN PRINT "It will automatically be loaded after Level " + S$(highestLevel - 1) + " is completed."
  759.     PRINT
  760.     OPEN filename$ FOR OUTPUT AS #1
  761.     FOR x = 2 TO 79
  762.         FOR y = 2 TO 46
  763.             COLOR 10, 0: LOCATE 15, 15: PRINT "Working"
  764.             stringOut$ = S$(creationBoard(x, y))
  765.             IF LEN(stringOut$) = 1 THEN stringOut$ = " " + stringOut$
  766.             PRINT #1, stringOut$
  767.             COLOR 0, 0: LOCATE 15, 15: PRINT "Working"
  768.     NEXT: NEXT
  769.     CLOSE #1
  770.     COLOR 10, 0
  771.     a$ = "Push " + CHR$(34) + "A" + CHR$(34) + " to make (a)nother level"
  772.     LOCATE 30, (80 - LEN(a$)) / 2
  773.     PRINT a$
  774.     b$ = "Push any other key to exit."
  775.     PRINT: PRINT
  776.     PRINT CenterText$(b$)
  777.     pause$ = INPUT$(1)
  778.     IF UCASE$(pause$) = "A" THEN
  779.         CALL CreationMain
  780.     ELSE
  781.         SaveBoard$ = "END"
  782.     END IF
  783.  
  784. SUB PutBrickOnBoard
  785.     FOR counting = 0 TO 5
  786.         creationBoard(brick.x + counting, brick.y) = currentColor
  787.     NEXT counting
  788.  
  789. SUB PrintCreationBrick
  790.     IF penUp = TRUE AND eraserOn = FALSE THEN
  791.         LOCATE brick.y, brick.x
  792.         COLOR 15, 1
  793.         PRINT CHR$(219)
  794.     ELSEIF penUp = FALSE AND eraserOn = TRUE THEN
  795.         LOCATE brick.y, brick.x
  796.         COLOR 7, 1
  797.         PRINT "-"
  798.     ELSE
  799.         LOCATE brick.y, brick.x
  800.         COLOR currentColor, 1
  801.         PRINT CHR$(219)
  802.     END IF
  803.     FOR count = 1 TO 5
  804.         LOCATE brick.y, brick.x + count
  805.         IF eraserOn = TRUE THEN
  806.             COLOR 7, 1
  807.             PRINT "-"
  808.         ELSE
  809.             COLOR currentColor, 1
  810.             PRINT CHR$(219)
  811.         END IF
  812.     NEXT
  813.  
  814.  
  815. SUB PrintCreationBoard
  816.     CALL PrintBackdrop
  817.     FOR y = 2 TO 46
  818.         FOR x = 2 TO 79
  819.             COLOR creationBoard(x, y), 1
  820.             LOCATE y, x
  821.             PRINT CHR$(219)
  822.     NEXT: NEXT
  823.  
  824. SUB PrintBackdrop
  825.     COLOR 1, 1: CLS
  826.     COLOR 12, 1
  827.     FOR x = 1 TO 80
  828.         LOCATE 1, x: PRINT CHR$(219)
  829.     NEXT
  830.     FOR y = 1 TO 48
  831.         LOCATE y, 1: PRINT CHR$(219)
  832.         LOCATE y, 80: PRINT CHR$(219)
  833.     NEXT
  834.     COLOR 14, 1
  835.     LOCATE 47, 3
  836.     PRINT "Use the Arrow Keys To Move      P - Pen ";
  837.     IF penUp = TRUE THEN
  838.         COLOR 10, 1
  839.         PRINT "up";
  840.         COLOR 14, 1
  841.         PRINT "/";
  842.         COLOR 7, 1
  843.         PRINT "down";
  844.     ELSE
  845.         COLOR 7, 1
  846.         PRINT "up";
  847.         COLOR 14, 1
  848.         PRINT "/";
  849.         COLOR 10, 1
  850.         PRINT "down";
  851.     END IF
  852.     PRINT "       ";
  853.     IF currentColor = 0 THEN
  854.         COLOR 0, 7
  855.     ELSE
  856.         COLOR currentColor, 0
  857.     END IF
  858.     PRINT "C - Cycle colors"
  859.     LOCATE 48, 2
  860.     COLOR 14, 1: PRINT "E - Eraser ";
  861.     'LOCATE 20, 20: COLOR 15, 0: PRINT "eraserOn = " + S$(eraserOn): CALL P
  862.     '    LOCATE 48, 26
  863.     IF eraserOn = TRUE THEN
  864.         COLOR 10, 1
  865.         PRINT "On";
  866.         COLOR 14, 1: PRINT "/";
  867.         COLOR 7, 1
  868.         PRINT "Off";
  869.     ELSE
  870.         COLOR 7, 1
  871.         PRINT "On";
  872.         COLOR 14, 1
  873.         PRINT "/";
  874.         COLOR 10, 1
  875.         PRINT "Off";
  876.     END IF
  877.     COLOR 14, 1
  878.     PRINT "     A - Clear All";
  879.     PRINT "     S - Save     [ESC] - End Without Save"
  880.     CALL PrintCreationBrick
  881.     '    LOCATE 45, 10: COLOR 10, 1: PRINT "eraserOn = " + S$(eraserOn)
  882.  
  883. SUB P (EndAllowed)
  884.     pause$ = INPUT$(1)
  885.     IF pause$ = CHR$(27) AND EndAllowed = TRUE THEN END
  886.  
  887. FUNCTION S$ (number)
  888.     S$ = LTRIM$(STR$(number))

Offline SpriggsySpriggs

  • QB64 Developer
  • Forum Resident
  • Posts: 1109
  • If you're API and you know it clap your hands
    • My GitHub
Re: Break Thru
« Reply #1 on: July 19, 2021, 02:50:29 PM »
That looks pretty nice!
If you're API and you know it clap your hands
My GitHub

Offline NOVARSEG

  • Forum Resident
  • Posts: 510
Re: Break Thru
« Reply #2 on: July 21, 2021, 03:13:00 AM »


Offline Jaze

  • Newbie
  • Posts: 59
Re: Break Thru
« Reply #3 on: July 21, 2021, 12:17:50 PM »
I must admit that Steve's version works better than mine but the video did give me an idea for an improvement. With my game you can hit the bricks from above, with his you can't. The trouble I ran into is the ball behaving erratically and destroying a lot of bricks when it should've been reflected downward. Easy enough edit. I'll look into it. Having the ball move at different angles is more difficult. Specifically when to decide the angle should change... hmm. Food for thought anyway.

Offline johnno56

  • Forum Resident
  • Posts: 1133
  • Live long and prosper.
Re: Break Thru
« Reply #4 on: July 21, 2021, 05:05:31 PM »
This is not my idea... but it's still cool...

Imagine the paddle divided into three equal areas. If the ball collides with the central area the reflection is equal amounts of DX and DY. if colliding with the left or right areas then increase/decrease DX by an amount that is not equal to DY... or something like that... It may require a little extra work with collision detection but shouldn't be too hard. I helped work on a breakout game for sdlbasic some years back... I will try to find it and locate the paddle deflection code... Fingers crossed...
Logic is the beginning of wisdom.

Offline bplus

  • Forum Resident
  • Posts: 7155
  • b = b + ...
Re: Break Thru
« Reply #5 on: July 21, 2021, 07:16:12 PM »
@johnno56 are you talking about my elliptical paddle you called a loaf of bread? Created in SdlBasic and converted to QB64.

Well at least that faux 3D game made to Wiki description for bricks and scoring none of this Screen 0 crap that only Pete can enjoy. ;-))

Update: I just checked, 315 lines, what's that other guy doing with all the extra lines?
« Last Edit: July 21, 2021, 07:48:50 PM by bplus »

Offline johnno56

  • Forum Resident
  • Posts: 1133
  • Live long and prosper.
Re: Break Thru
« Reply #6 on: July 21, 2021, 07:57:19 PM »
Now that you mention it... the 'loaf of bread' does sound familiar... Mmm... bread...  If memory serves correctly, I used that code in a 'minimalist' version of Bustout. Made the ball deflection a little more erratic... and each time the ball collided with the paddle, the velocity of the ball, would also change a little...
Logic is the beginning of wisdom.

Offline bplus

  • Forum Resident
  • Posts: 7155
  • b = b + ...
Re: Break Thru
« Reply #7 on: July 21, 2021, 08:01:46 PM »
Now that you mention it... the 'loaf of bread' does sound familiar... Mmm... bread...  If memory serves correctly, I used that code in a 'minimalist' version of Bustout. Made the ball deflection a little more erratic... and each time the ball collided with the paddle, the velocity of the ball, would also change a little...

Sure turn a game of skill into a game of luck :p  LOL

Offline johnno56

  • Forum Resident
  • Posts: 1133
  • Live long and prosper.
Re: Break Thru
« Reply #8 on: July 22, 2021, 10:07:49 AM »
I can work with luck... probably because I have only a little gaming skill... lol
Logic is the beginning of wisdom.