Advertisement
nonogamer9

nono2048 2! (ComputerCraft Port)

Oct 1st, 2024 (edited)
63
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 12.56 KB | Gaming | 0 0
  1. local board = {}
  2. local size = 4
  3. local score = 0
  4. local highScore = 0
  5. local width, height = term.getSize()
  6. local t = 0
  7. local gameOver = false
  8. local won = false
  9. local isMonochrome = false
  10.  
  11. local speaker = peripheral.find("speaker")
  12.  
  13. local function playSound(instrument, volume, pitch)
  14.     if speaker then
  15.         speaker.playNote(instrument, volume, pitch)
  16.     end
  17. end
  18.  
  19. local requiredColors = {"gray", "lightBlue", "cyan", "blue", "green", "lime", "yellow", "orange", "red", "magenta", "purple", "pink", "white", "black", "lightGray"}
  20. for _, color in ipairs(requiredColors) do
  21.     if not colors[color] then
  22.         error("Required color not available: " .. color)
  23.     end
  24. end
  25.  
  26. local tileColors = {
  27.     [0] = colors.gray,
  28.     [2] = colors.lightBlue,
  29.     [4] = colors.cyan,
  30.     [8] = colors.blue,
  31.     [16] = colors.green,
  32.     [32] = colors.lime,
  33.     [64] = colors.yellow,
  34.     [128] = colors.orange,
  35.     [256] = colors.red,
  36.     [512] = colors.magenta,
  37.     [1024] = colors.purple,
  38.     [2048] = colors.pink
  39. }
  40.  
  41. local monochromeColors = {
  42.     [0] = colors.gray,
  43.     [2] = colors.lightGray,
  44.     [4] = colors.white,
  45.     [8] = colors.white,
  46.     [16] = colors.lightGray,
  47.     [32] = colors.lightGray,
  48.     [64] = colors.gray,
  49.     [128] = colors.gray,
  50.     [256] = colors.black,
  51.     [512] = colors.black,
  52.     [1024] = colors.black,
  53.     [2048] = colors.black
  54. }
  55.  
  56. local shadowColors = {
  57.     [0] = colors.lightGray,
  58.     [2] = colors.blue,
  59.     [4] = colors.blue,
  60.     [8] = colors.black,
  61.     [16] = colors.blue,
  62.     [32] = colors.green,
  63.     [64] = colors.orange,
  64.     [128] = colors.red,
  65.     [256] = colors.magenta,
  66.     [512] = colors.purple,
  67.     [1024] = colors.black,
  68.     [2048] = colors.magenta
  69. }
  70.  
  71. local monochromeShadowColors = {
  72.     [0] = colors.lightGray,
  73.     [2] = colors.gray,
  74.     [4] = colors.gray,
  75.     [8] = colors.lightGray,
  76.     [16] = colors.lightGray,
  77.     [32] = colors.gray,
  78.     [64] = colors.gray,
  79.     [128] = colors.black,
  80.     [256] = colors.black,
  81.     [512] = colors.black,
  82.     [1024] = colors.black,
  83.     [2048] = colors.black
  84. }
  85.  
  86. local rainbowColors = {
  87.     colors.red,
  88.     colors.orange,
  89.     colors.yellow,
  90.     colors.lime,
  91.     colors.cyan,
  92.     colors.blue,
  93.     colors.purple
  94. }
  95.  
  96. local tileWidth = 5
  97. local tileHeight = 3
  98. local boardWidth = size * tileWidth + (size - 1)
  99. local boardHeight = size * tileHeight + (size - 1)
  100. local startX = math.floor((width - boardWidth) / 2)
  101. local startY = math.floor((height - boardHeight) / 2)
  102.  
  103. local buffer = {}
  104. for y = 1, height do
  105.     buffer[y] = {}
  106.     for x = 1, width do
  107.         buffer[y][x] = {
  108.             char = " ",
  109.             textColor = colors.white,
  110.             backgroundColor = colors.black
  111.         }
  112.     end
  113. end
  114.  
  115. local function setBufferPixel(x, y, char, textColor, backgroundColor)
  116.     if x >= 1 and x <= width and y >= 1 and y <= height then
  117.         if not buffer[y] then
  118.             buffer[y] = {}
  119.         end
  120.         buffer[y][x] = {
  121.             char = char or " ",
  122.             textColor = textColor or colors.white,
  123.             backgroundColor = backgroundColor or colors.black
  124.         }
  125.     end
  126. end
  127.  
  128. local function writeToBuffer(x, y, text, textColor, backgroundColor)
  129.     for i = 1, #text do
  130.         setBufferPixel(x + i - 1, y, text:sub(i, i), textColor, backgroundColor)
  131.     end
  132. end
  133.  
  134. local particles = {}
  135.  
  136. local function createParticles(x, y, value)
  137.     for i = 1, 10 do
  138.         table.insert(particles, {
  139.             x = x + math.random() * tileWidth,
  140.             y = y + math.random() * tileHeight,
  141.             dx = (math.random() - 0.5) * 2,
  142.             dy = (math.random() - 0.5) * 2,
  143.             life = 10,
  144.             color = isMonochrome and monochromeColors[value] or tileColors[value] or colors.white
  145.         })
  146.     end
  147. end
  148.  
  149. local function updateParticles()
  150.     for i = #particles, 1, -1 do
  151.         local p = particles[i]
  152.         p.x = p.x + p.dx
  153.         p.y = p.y + p.dy
  154.         p.life = p.life - 1
  155.         if p.life <= 0 then
  156.             table.remove(particles, i)
  157.         end
  158.     end
  159. end
  160.  
  161. local function drawParticles()
  162.     for _, p in ipairs(particles) do
  163.         setBufferPixel(math.floor(p.x), math.floor(p.y), "•", p.color, colors.black)
  164.     end
  165. end
  166.  
  167. local function newBoard()
  168.     board = {}
  169.     for i = 1, size do
  170.         board[i] = {}
  171.         for j = 1, size do
  172.             board[i][j] = {value = 0, mergeEffect = 0}
  173.         end
  174.     end
  175.     score = 0
  176.     gameOver = false
  177.     won = false
  178. end
  179.  
  180. local function addTile()
  181.     local emptyCells = {}
  182.     for i = 1, size do
  183.         for j = 1, size do
  184.             if board[i][j].value == 0 then
  185.                 table.insert(emptyCells, {i, j})
  186.             end
  187.         end
  188.     end
  189.     if #emptyCells > 0 then
  190.         local cell = emptyCells[math.random(#emptyCells)]
  191.         board[cell[1]][cell[2]].value = math.random() < 0.9 and 2 or 4
  192.     end
  193. end
  194.  
  195. local function drawPlasma()
  196.     for y = 1, height do
  197.         for x = 1, width do
  198.             local v = math.sin(x * 0.1 + t) + math.sin(y * 0.1 + t) +
  199.                       math.sin((x + y) * 0.1 + t) + math.sin(math.sqrt(x^2 + y^2) * 0.1 + t)
  200.             v = (v + 4) / 8
  201.             local color = math.floor(v * 15) + 1
  202.             if isMonochrome then
  203.                 color = math.floor(v * 3) + colors.black
  204.             end
  205.             setBufferPixel(x, y, " ", colors.white, color)
  206.         end
  207.     end
  208.     t = t + 0.1
  209. end
  210.  
  211. local function drawTile(x, y, tileData)
  212.     local value = tileData.value
  213.     local color = isMonochrome and monochromeColors[value] or tileColors[value] or colors.white
  214.     local shadowColor = isMonochrome and monochromeShadowColors[value] or shadowColors[value] or colors.gray
  215.    
  216.     if tileData.mergeEffect > 0 then
  217.         color = isMonochrome and colors.white or colors.white
  218.         tileData.mergeEffect = tileData.mergeEffect - 1
  219.     end
  220.    
  221.     for i = 1, tileHeight do
  222.         setBufferPixel(x + tileWidth, y + i, " ", colors.black, shadowColor)
  223.     end
  224.     for j = 1, tileWidth do
  225.         setBufferPixel(x + j, y + tileHeight, " ", colors.black, shadowColor)
  226.     end
  227.    
  228.     for i = 0, tileHeight - 1 do
  229.         for j = 0, tileWidth - 1 do
  230.             setBufferPixel(x + j, y + i, " ", colors.black, color)
  231.         end
  232.     end
  233.    
  234.     if value > 0 then
  235.         local valueStr = tostring(value)
  236.         local xOffset = math.floor(tileWidth/2 - #valueStr/2)
  237.         writeToBuffer(x + xOffset, y + math.floor(tileHeight/2), valueStr, colors.black, color)
  238.     end
  239. end
  240.  
  241. local function drawBoard()
  242.     for i = 1, size do
  243.         for j = 1, size do
  244.             local x = startX + (j - 1) * (tileWidth + 1)
  245.             local y = startY + (i - 1) * (tileHeight + 1)
  246.             drawTile(x, y, board[i][j])
  247.         end
  248.     end
  249. end
  250.  
  251. local function drawUI()
  252.     writeToBuffer(2, height - 1, "Score: " .. score, colors.white, colors.black)
  253.     writeToBuffer(width - 15, height - 1, "High Score: " .. highScore, colors.white, colors.black)
  254. end
  255.  
  256. local logoOffset = 0
  257. local function drawLogo()
  258.     local gameTitle = "nono2048 2!"
  259.     local logoY = height
  260.     for i = 1, #gameTitle do
  261.         local colorIndex = ((i-1 + logoOffset) % #rainbowColors) + 1
  262.         local color = isMonochrome and colors.white or rainbowColors[colorIndex]
  263.         setBufferPixel(math.floor((width - #gameTitle) / 2) + i - 1, logoY, gameTitle:sub(i,i), color, colors.black)
  264.     end
  265.     logoOffset = (logoOffset + 1) % #rainbowColors
  266. end
  267.  
  268. local function checkGameOver()
  269.     for i = 1, size do
  270.         for j = 1, size do
  271.             if board[i][j].value == 0 then
  272.                 return false
  273.             end
  274.             if i < size and board[i][j].value == board[i+1][j].value then
  275.                 return false
  276.             end
  277.             if j < size and board[i][j].value == board[i][j+1].value then
  278.                 return false
  279.             end
  280.         end
  281.     end
  282.     return true
  283. end
  284.  
  285. local function moveTiles(direction)
  286.     local moved = false
  287.     local function shiftTile(i, j, di, dj)
  288.         while i + di >= 1 and i + di <= size and j + dj >= 1 and j + dj <= size do
  289.             if board[i + di][j + dj].value == 0 then
  290.                 board[i + di][j + dj].value = board[i][j].value
  291.                 board[i][j].value = 0
  292.                 i, j = i + di, j + dj
  293.                 moved = true
  294.             elseif board[i + di][j + dj].value == board[i][j].value then
  295.                 board[i + di][j + dj].value = board[i + di][j + dj].value * 2
  296.                 board[i + di][j + dj].mergeEffect = 5
  297.                 score = score + board[i + di][j + dj].value
  298.                 board[i][j].value = 0
  299.                 moved = true
  300.                 local x = startX + (j + dj - 1) * (tileWidth + 1)
  301.                 local y = startY + (i + di - 1) * (tileHeight + 1)
  302.                 createParticles(x, y, board[i + di][j + dj].value)
  303.                 playSound("bit", 3, 1)
  304.                 if board[i + di][j + dj].value == 2048 then
  305.                     won = true
  306.                 end
  307.                 break
  308.             else
  309.                 break
  310.             end
  311.         end
  312.     end
  313.  
  314.     if direction == "up" then
  315.         for j = 1, size do
  316.             for i = 2, size do
  317.                 if board[i][j].value ~= 0 then
  318.                     shiftTile(i, j, -1, 0)
  319.                 end
  320.             end
  321.         end
  322.     elseif direction == "down" then
  323.         for j = 1, size do
  324.             for i = size - 1, 1, -1 do
  325.                 if board[i][j].value ~= 0 then
  326.                     shiftTile(i, j, 1, 0)
  327.                 end
  328.             end
  329.         end
  330.     elseif direction == "left" then
  331.         for i = 1, size do
  332.             for j = 2, size do
  333.                 if board[i][j].value ~= 0 then
  334.                     shiftTile(i, j, 0, -1)
  335.                 end
  336.             end
  337.         end
  338.     elseif direction == "right" then
  339.         for i = 1, size do
  340.             for j = size - 1, 1, -1 do
  341.                 if board[i][j].value ~= 0 then
  342.                     shiftTile(i, j, 0, 1)
  343.                 end
  344.             end
  345.         end
  346.     end
  347.     return moved
  348. end
  349.  
  350. local function swapBuffers()
  351.     for y = 1, height do
  352.         for x = 1, width do
  353.             local pixel = buffer[y][x]
  354.             term.setCursorPos(x, y)
  355.             term.setTextColor(pixel.textColor)
  356.             term.setBackgroundColor(pixel.backgroundColor)
  357.             term.write(pixel.char)
  358.         end
  359.     end
  360. end
  361.  
  362. local function updateDisplay()
  363.     drawPlasma()
  364.     drawBoard()
  365.     updateParticles()
  366.     drawParticles()
  367.     drawUI()
  368.     drawLogo()
  369.    
  370.     if gameOver then
  371.         writeToBuffer(width/2 - 4, height/2, "Game Over!", colors.red, colors.black)
  372.     elseif won then
  373.         writeToBuffer(width/2 - 7, height/2, "You've won! 2048!", colors.green, colors.black)
  374.     end
  375.    
  376.     swapBuffers()
  377. end
  378.  
  379. local asciiLogo = [[
  380.                                        __
  381.                  ___ ___ ___ ___    ___|  |
  382.  ___ ___ ___ ___|_  |   | | | . |  |_  |  |
  383. |   | . |   | . |  _| | |_  | . |  |  _|__|
  384. |_|_|___|_|_|___|___|___| |_|___|  |___|__|
  385. ]]
  386.  
  387. term.clear()
  388. term.setCursorPos(1, 1)
  389. print(asciiLogo)
  390. print("\nWelcome to nono2048 2!")
  391. print("Press 'c' for color mode or 'm' for monochrome mode.")
  392.  
  393. local event, key
  394. repeat
  395.     event, key = os.pullEvent("key")
  396. until key == keys.c or key == keys.m
  397.  
  398. isMonochrome = (key == keys.m)
  399.  
  400. newBoard()
  401. addTile()
  402. addTile()
  403.  
  404. local updateTimer = os.startTimer(0.05)
  405.  
  406. while true do
  407.     local event, param = os.pullEventRaw()
  408.    
  409.     if event == "timer" and param == updateTimer then
  410.         updateDisplay()
  411.         updateTimer = os.startTimer(0.05)
  412.     elseif event == "key" then
  413.         local moved = false
  414.        
  415.         if param == keys.up then
  416.             moved = moveTiles("up")
  417.         elseif param == keys.down then
  418.             moved = moveTiles("down")
  419.         elseif param == keys.left then
  420.             moved = moveTiles("left")
  421.         elseif param == keys.right then
  422.             moved = moveTiles("right")
  423.         elseif param == keys.q then
  424.             break
  425.         elseif param == keys.r then
  426.             newBoard()
  427.             addTile()
  428.             addTile()
  429.             gameOver = false
  430.             particles = {}
  431.         end
  432.        
  433.         if moved then
  434.             addTile()
  435.             if score > highScore then
  436.                 highScore = score
  437.             end
  438.             gameOver = checkGameOver()
  439.             if gameOver then
  440.                 playSound("bass", 3, 0)
  441.             end
  442.         end
  443.     elseif event == "terminate" then
  444.         break
  445.     end
  446. end
  447.  
  448. term.setBackgroundColor(colors.black)
  449. term.clear()
  450. term.setCursorPos(1, 1)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement