Advertisement
massacring

plinko

Jan 5th, 2025 (edited)
45
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 14.64 KB | None | 0 0
  1. local Ball = require("Ball")
  2. local Button = require("Button")
  3. local Commons = require("Commons")
  4. local cashout = require('cashout')
  5. local monitor = peripheral.find("monitor")
  6. local speaker = peripheral.find("speaker")
  7.  
  8. -- Declares my own colors
  9. local m_colors = {
  10.     white = colors.white,
  11.     black = colors.black,
  12.     gray = colors.gray,
  13.     lightGray = colors.lightGray,
  14.     orange = colors.orange,
  15.     darkOrange = colors.magenta,
  16.     yellow = colors.yellow,
  17.     lightYellow = colors.lightBlue,
  18.     lime = colors.lime,
  19.     green = colors.green,
  20.     red = colors.red,
  21.     darkRed = colors.pink,
  22.     darkGray = colors.brown,
  23.     purple = colors.purple,
  24.     darkGold = colors.cyan,
  25.     lightGold = colors.blue
  26. }
  27.  
  28. monitor.setBackgroundColor(m_colors.black)
  29. monitor.clear()
  30. local window = window.create(monitor, 1, 1, 80, 38)
  31. local gameSpeed = 0.05
  32. local maxBalls = 5
  33. local width, height = window.getSize()
  34. local defaultBackgroundColor = m_colors.lightGray
  35. local defaultTextColor = m_colors.white
  36. local pinColor = m_colors.white
  37. local shadowColor = m_colors.gray
  38. local ballColor = m_colors.darkGray
  39. local scoreboardColor = m_colors.purple
  40. local scoreboardTitleColor = m_colors.darkGray
  41. local pinAreas = {}
  42. local balls = {}
  43. local cashoutButton = {}
  44.  
  45. -- key (x) = value ({key (y) = value (color)})
  46. local backgroundColorMap = {}
  47. local foregroundColorMap = {}
  48.  
  49. local goals = {
  50.     l_green = {startPos = 2, value = 33, primaryColor = m_colors.lime, secondaryColor = m_colors.green},
  51.     l_lightYellow = {startPos = 8, value = 11, primaryColor = m_colors.lightYellow, secondaryColor = m_colors.yellow},
  52.     l_yellow = {startPos = 14, value = 4, primaryColor = m_colors.yellow, secondaryColor = m_colors.lightYellow},
  53.     l_orange = {startPos = 20, value = 2, primaryColor = m_colors.orange, secondaryColor = m_colors.darkOrange},
  54.     l_darkOrange = {startPos = 26, value = 1.5, primaryColor = m_colors.darkOrange, secondaryColor = m_colors.orange},
  55.     l_red = {startPos = 32, value = 0.6, primaryColor = m_colors.red, secondaryColor = m_colors.darkRed},
  56.     c_darkRed = {startPos = 38, value = 0.3, primaryColor = m_colors.darkRed, secondaryColor = m_colors.red},
  57.     r_red = {startPos = 44, value = 0.6, primaryColor = m_colors.red, secondaryColor = m_colors.darkRed},
  58.     r_darkOrange = {startPos = 50, value = 1.5, primaryColor = m_colors.darkOrange, secondaryColor = m_colors.orange},
  59.     r_orange = {startPos = 56, value = 2, primaryColor = m_colors.orange, secondaryColor = m_colors.darkOrange},
  60.     r_yellow = {startPos = 62, value = 4, primaryColor = m_colors.yellow, secondaryColor = m_colors.lightYellow},
  61.     r_lightYellow = {startPos = 68, value = 11, primaryColor = m_colors.lightYellow, secondaryColor = m_colors.yellow},
  62.     r_green = {startPos = 74, value = 33, primaryColor = m_colors.lime, secondaryColor = m_colors.green},
  63. }
  64.  
  65.  
  66. local function clear()
  67.     window.setBackgroundColor(defaultBackgroundColor)
  68.     window.setTextColor(defaultTextColor)
  69.     window.clear()
  70.     window.setCursorPos(1,1)
  71. end
  72.  
  73. -- Changes the default palette
  74. local function setPalatte()
  75.     window.setPaletteColor(colors.orange, 0xDD9D54) -- new orange
  76.     window.setPaletteColor(colors.magenta, 0xD98752) -- secondare orange
  77.     window.setPaletteColor(colors.yellow, 0xECDC5B) -- new yellow
  78.     window.setPaletteColor(colors.lightBlue, 0xE3EA5B) -- secondary yellow
  79.     window.setPaletteColor(colors.lime, 0xA0CA55) -- new lime
  80.     window.setPaletteColor(colors.pink, 0xB73535) -- secondary red
  81.     window.setPaletteColor(colors.brown, 0x4C4C4C) -- dark (old) gray
  82.     window.setPaletteColor(colors.gray, 0x727272) -- new gray
  83.     window.setPaletteColor(colors.cyan, 0xE1B156) -- dark gold
  84.     window.setPaletteColor(colors.blue, 0xE8C958) -- light gold
  85. end
  86.  
  87. local function drawDot(x,y,color, isForeground)
  88.     window.setCursorPos(x,y)
  89.     window.setBackgroundColor(color)
  90.     window.write(" ")
  91.     if isForeground then
  92.         foregroundColorMap[x] = foregroundColorMap[x] or {}
  93.         foregroundColorMap[x][y] = color
  94.     else
  95.         backgroundColorMap[x] = backgroundColorMap[x] or {}
  96.         backgroundColorMap[x][y] = color
  97.     end
  98.    
  99. end
  100.  
  101. local function drawSquare(x, y, span, length, color, isForeground)
  102.     window.setCursorPos(x,y)
  103.     window.setBackgroundColor(color)
  104.     for row = 1, length, 1 do
  105.         window.setCursorPos(x,y+row-1)
  106.         window.write(string.rep(" ", span))
  107.         for column = 1, span, 1 do
  108.             local storeX = x+column-1
  109.             local storeY = y+row-1
  110.             if isForeground then
  111.                 foregroundColorMap[storeX] = foregroundColorMap[storeX] or {}
  112.                 foregroundColorMap[storeX][storeY] = color
  113.             else
  114.                 backgroundColorMap[storeX] = backgroundColorMap[storeX] or {}
  115.                 backgroundColorMap[storeX][storeY] = color
  116.             end
  117.         end
  118.     end
  119. end
  120.  
  121. local function write(text, x, y, textColor, backGroundColor, isForeground)
  122.     backGroundColor = backGroundColor or defaultBackgroundColor
  123.     textColor = textColor or defaultTextColor
  124.     window.setCursorPos(x,y)
  125.     window.setBackgroundColor(backGroundColor)
  126.     window.setTextColor(textColor)
  127.     window.write(text)
  128.     for column = 1, string.len(text), 1 do
  129.         local storeX = x+column-1
  130.         if isForeground then
  131.             foregroundColorMap[storeX] = foregroundColorMap[storeX] or {}
  132.             foregroundColorMap[storeX][y] = backGroundColor
  133.         else
  134.             backgroundColorMap[storeX] = backgroundColorMap[storeX] or {}
  135.             backgroundColorMap[storeX][y] = backGroundColor
  136.         end
  137.     end
  138. end
  139.  
  140. local function generatePin(x, y)
  141.     local area = {}
  142.     for column = 1, 2, 1 do
  143.         table.insert(area, {x = x+column, y = y})
  144.     end
  145.     table.insert(pinAreas, area)
  146. end
  147.  
  148. local function generateAllPins()
  149.     local midPoint = width / 2
  150.  
  151.     for row = 1,34,3 do
  152.         if row == 1 then goto continue end
  153.         for column = 1,(row/3)+1,1 do
  154.             local x = (midPoint - (row - 1) + (column*6) - 6) - 1
  155.             local y = row - 2
  156.             generatePin(x, y)
  157.         end
  158.         ::continue::
  159.     end
  160. end
  161.  
  162. local function drawAllPins()
  163.     for _, area in pairs(pinAreas) do
  164.         for _, coord in pairs(area) do
  165.             drawDot(coord.x+1, coord.y+1, shadowColor)
  166.             drawDot(coord.x+1, coord.y+2, shadowColor)
  167.             drawDot(coord.x, coord.y, pinColor, true)
  168.             drawDot(coord.x, coord.y+1, pinColor, true)
  169.         end
  170.     end
  171. end
  172.  
  173. local function drawGoal(x, y, text, primaryColor, secondaryColor, textColor)
  174.     drawSquare(x, y, 6, 3, primaryColor, true)
  175.     drawSquare(x+1, y+1, 4, 1, secondaryColor, true)
  176.     window.setCursorPos(x+1, y+1)
  177.     window.setTextColor(textColor)
  178.     window.write(text)
  179. end
  180.  
  181. local function drawAllGoals()
  182.     local y = height-3
  183.     local textColor = m_colors.darkGray
  184.     for _, goal in pairs(goals) do
  185.         local text = tostring(goal.value)
  186.         drawGoal(goal.startPos, y, " "..text, goal.primaryColor, goal.secondaryColor, textColor)
  187.     end
  188. end
  189.  
  190. local function drawScoreboard()
  191.     local scoreTitle = "Score:"
  192.     local scoreText = tostring(Commons.Score:getScore())
  193.     local scoreTextLen = string.len(scoreText) + 2
  194.     if scoreTextLen < 9 then scoreTextLen = 9 end
  195.     local startX = width - 2 - scoreTextLen
  196.  
  197.     window.setTextColor(m_colors.white)
  198.     drawSquare(startX+1, 4, scoreTextLen, 3, shadowColor)
  199.     drawSquare(startX, 3, scoreTextLen, 3, scoreboardColor, true)
  200.     window.setCursorPos(startX+1, 4)
  201.     window.write(scoreText)
  202.     drawSquare(startX+1, 2, 6, 1, scoreboardTitleColor, true)
  203.     window.setCursorPos(startX+1, 2)
  204.     window.write(scoreTitle)
  205. end
  206.  
  207. local function debugColorMaps()
  208.     clear()
  209.     for column, rows in pairs(backgroundColorMap) do
  210.         for row, _ in pairs(rows) do
  211.             window.setCursorPos(column,row)
  212.             window.setBackgroundColor(m_colors.lime)
  213.             window.write(" ")
  214.         end
  215.     end
  216.     for column, rows in pairs(foregroundColorMap) do
  217.         for row, _ in pairs(rows) do
  218.             window.setCursorPos(column,row)
  219.             window.setBackgroundColor(m_colors.purple)
  220.             window.write(" ")
  221.         end
  222.     end
  223. end
  224.  
  225. local function drawScreen()
  226.     clear()
  227.     drawAllPins()
  228.     drawAllGoals()
  229.     drawScoreboard()
  230.     drawSquare(cashoutButton.x+1, cashoutButton.y+1, cashoutButton.width, cashoutButton.height, shadowColor)
  231.     cashoutButton:displayOnScreen(drawSquare, write)
  232.     --debugColorMaps()
  233. end
  234.  
  235. local function spawnBall()
  236.     local ball = Ball.new(math.random(37, 45), 0, ballColor, foregroundColorMap, backgroundColorMap)
  237.     table.insert(balls, ball)
  238. end
  239.  
  240. local function endRun()
  241.     clear()
  242.     cashout()
  243.     os.reboot()
  244. end
  245.  
  246. local function createCashoutButton()
  247.     local label = "Cash out!"
  248.     local labelLength = string.len(label)
  249.     local x = width - labelLength - 3
  250.     local y = 8
  251.     local span = labelLength
  252.     local length = 1
  253.     local labelPad = 0
  254.     local backgroundColorNormal = m_colors.darkGold
  255.     local borderColorNormal = m_colors.orange
  256.     local textColorNormal = m_colors.white
  257.     cashoutButton = Button.new(label, endRun, x, y, span, length, labelPad, backgroundColorNormal, borderColorNormal, textColorNormal)
  258. end
  259.  
  260. local function init()
  261.     monitor.setTextScale(0.5)
  262.     setPalatte()
  263.     generateAllPins()
  264.     createCashoutButton()
  265.     drawScreen()
  266. end
  267.  
  268. -- Returns "right" around one in 'i' times, otherwise returns "left".
  269. local function calculateStep(i)
  270.     return (math.random(i) % i == 0) and "right" or "left"
  271. end
  272.  
  273. local function checkPinCollision(coord)
  274.     coord.x = coord.x or 0
  275.     coord.y = coord.y or 0
  276.     for _, area in pairs(pinAreas) do
  277.         for _, pinCoord in pairs(area) do
  278.             local result = coord.x == pinCoord.x and coord.y == pinCoord.y
  279.             if result then return true end
  280.         end
  281.     end
  282.     return false
  283. end
  284.  
  285. local function moveHorizontally(ball, direction, velocity)
  286.     local directionalVelocity = ((direction == "right") and 1 or -1)
  287.     for i = 1,velocity,1 do
  288.         ball:move(window, 1 * directionalVelocity, 0, defaultBackgroundColor)
  289.         local result = ball:checkBelowBall(checkPinCollision)
  290.         if not (result.left_collided or result.right_collided) and i ~= 1 then
  291.             ball:move(window, 0, 1, defaultBackgroundColor)
  292.         end
  293.         if i == velocity then return end
  294.         sleep(gameSpeed)
  295.     end
  296. end
  297.  
  298. local function calculateGoalPos(ball)
  299.     local x = ball.x
  300.     local midPoint = width / 2
  301.     local difference = midPoint - x
  302.     local result
  303.  
  304.     if (difference >= 0 and difference < 2)
  305.     or (difference <= 0 and difference > -3) then
  306.         return "c_darkRed"
  307.     elseif (difference > 0 and difference < 8)
  308.     or (difference < 0 and difference > -9) then
  309.         result = ((difference > 0) and "l_" or "r_") .. "red"
  310.     elseif (difference > 0 and difference < 14)
  311.     or (difference < 0 and difference > -15) then
  312.         result = ((difference > 0) and "l_" or "r_") .. "darkOrange"
  313.     elseif (difference > 0 and difference < 20)
  314.     or (difference < 0 and difference > -21) then
  315.         result = ((difference > 0) and "l_" or "r_") .. "orange"
  316.     elseif (difference > 0 and difference < 26)
  317.     or (difference < 0 and difference > -27) then
  318.         result = ((difference > 0) and "l_" or "r_") .. "yellow"
  319.     elseif (difference > 0 and difference < 32)
  320.     or (difference < 0 and difference > -33) then
  321.         result = ((difference > 0) and "l_" or "r_") .. "lightYellow"
  322.     else
  323.         result = ((difference > 0) and "l_" or "r_") .. "green"
  324.     end
  325.     return result
  326. end
  327.  
  328. local function calculateReward(ball)
  329.     local goal = calculateGoalPos(ball)
  330.     local multiplier = goals[goal].value
  331.     Commons.Score:updateScore(math.ceil(Commons.Score:getScore() * multiplier))
  332.     drawScoreboard()
  333. end
  334.  
  335. local function countBalls()
  336.     local count = 0
  337.     for _, ball in pairs(balls) do
  338.         if ball ~= nil then count = count + 1 end
  339.     end
  340.     return count
  341. end
  342.  
  343. local function playPinDing(direction)
  344.     local leftPitches = {0, 12, 24}
  345.     local rightPitches = {6, 18}
  346.     local pitch = (direction == "right") and rightPitches[math.random(#rightPitches)] or leftPitches[math.random(#leftPitches)]
  347.     speaker.playNote("pling", 1, pitch)
  348. end
  349.  
  350. local function playEndDing()
  351.     speaker.playNote("pling", 1, 10)
  352.     sleep(0.05)
  353.     speaker.playNote("pling", 1, 11)
  354.     sleep(0.05)
  355.     speaker.playNote("pling", 1, 13)
  356. end
  357.  
  358. local function tick()
  359.     while true do
  360.         for _, ball in pairs(balls) do
  361.             local result = ball:checkBelowBall(checkPinCollision)
  362.             if result.left_collided or result.right_collided then
  363.                 if result.left_collided and result.right_collided then
  364.                     local direction = calculateStep(2)
  365.                     local velocity = math.random(2, 4)
  366.                     moveHorizontally(ball, direction, velocity)
  367.                     playPinDing(direction)
  368.                 else
  369.                     local direction = result.left_collided and "right" or "left"
  370.                     local velocity = math.random(3)
  371.                     moveHorizontally(ball, direction, velocity)
  372.                     playPinDing(direction)
  373.                 end
  374.             else
  375.                 ball:move(window, 0, 1, defaultBackgroundColor)
  376.             end
  377.                 if ball.y >= height-3 then
  378.                 ball:move(window, 0, -1, defaultBackgroundColor)
  379.                 calculateReward(ball)
  380.                 ball:clear(window, defaultBackgroundColor)
  381.                 balls[_] = nil
  382.                 drawAllGoals()
  383.                 playEndDing()
  384.             end
  385.         end
  386.         sleep(gameSpeed)
  387.     end
  388. end
  389.  
  390. local function events()
  391.     sleep(0.5)
  392.     while true do
  393.         local eventData = {os.pullEvent()}
  394.         local event = eventData[1]
  395.         if event == "key_up" and eventData[2] == keys.q then
  396.             return
  397.         elseif event == "monitor_touch" then
  398.             local x, y = eventData[3], eventData[4]
  399.             if cashoutButton:collides(x, y) then
  400.                 cashoutButton.clickEvent()
  401.                 return
  402.             else
  403.                 local ballCount = countBalls()
  404.                 if Commons.Score:getScore() * (0.3 ^ (ballCount+1)) < 1.0
  405.                 then print("Out of coin!")
  406.                 elseif (ballCount >= maxBalls)
  407.                 then print("Too many balls!")
  408.                 else spawnBall() end
  409.             end
  410.             sleep(0.1)
  411.         end
  412.     end
  413. end
  414.  
  415. local function runGame()
  416.     parallel.waitForAny(tick, events)
  417. end
  418.  
  419. return { init = init, drawScreen = drawScreen, runGame = runGame }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement