Guest User

Tetracraft

a guest
Jun 25th, 2025
58
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 25.76 KB | None | 0 0
  1. local pixelbox = {initialized=false,shared_data={},internal={}}
  2.  
  3. pixelbox.url     = "https://pixels.devvie.cc"
  4. pixelbox.license = [[MIT License
  5.  
  6. Copyright (c) 2024 9551Dev
  7.  
  8. Permission is hereby granted, free of charge, to any person obtaining a copy
  9. of this software and associated documentation files (the "Software"), to deal
  10. in the Software without restriction, including without limitation the rights
  11. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12. copies of the Software, and to permit persons to whom the Software is
  13. furnished to do so, subject to the following conditions:
  14.  
  15. The above copyright notice and this permission notice shall be included in all
  16. copies or substantial portions of the Software.
  17.  
  18. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  21. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  24. SOFTWARE.
  25. ]]
  26.  
  27. local box_object = {}
  28.  
  29. local to_blit = {}
  30. local t_cat   = table.concat
  31.  
  32. local function generate_lookups()
  33.     for i = 0, 15 do
  34.         to_blit[2^i] = ("%x"):format(i)
  35.     end
  36. end
  37.  
  38. pixelbox.internal.to_blit_lookup   = to_blit
  39. pixelbox.internal.generate_lookups = generate_lookups
  40.  
  41. function pixelbox.make_canvas_scanline(y_coord)
  42.     return setmetatable({},{__newindex=function(self,key,value)
  43.         if type(key) == "number" and key%1 ~= 0 then
  44.             error(("Tried to write a float pixel. x:%s y:%s"):format(key,y_coord),2)
  45.         else rawset(self,key,value) end
  46.     end})
  47. end
  48.  
  49. function pixelbox.make_canvas(source_table)
  50.     local dummy_OOB = pixelbox.make_canvas_scanline("NONE")
  51.     local dummy_mt  = getmetatable(dummy_OOB)
  52.  
  53.     function dummy_mt.tostring() return "pixelbox_dummy_oob" end
  54.  
  55.     return setmetatable(source_table or {},{__index=function(_,key)
  56.         if type(key) == "number" and key%1 ~= 0 then
  57.             error(("Tried to write float scanline. y:%s"):format(key),2)
  58.         end
  59.  
  60.         return dummy_OOB
  61.     end})
  62. end
  63.  
  64. function pixelbox.setup_canvas(box,canvas_blank,color,keep_existing)
  65.     for y=1,box.height do
  66.  
  67.         local scanline
  68.         if not rawget(canvas_blank,y) then
  69.             scanline = pixelbox.make_canvas_scanline(y)
  70.  
  71.             rawset(canvas_blank,y,scanline)
  72.         else
  73.             scanline = canvas_blank[y]
  74.         end
  75.  
  76.         for x=1,box.width do
  77.             if not (scanline[x] and keep_existing) then
  78.                 scanline[x] = color
  79.             end
  80.         end
  81.     end
  82.  
  83.     return canvas_blank
  84. end
  85.  
  86. function pixelbox.restore(box,color,keep_existing)
  87.     if not keep_existing then
  88.         local new_canvas = pixelbox.setup_canvas(box,pixelbox.make_canvas(),color)
  89.  
  90.         box.canvas = new_canvas
  91.         box.CANVAS = new_canvas
  92.     else
  93.         pixelbox.setup_canvas(box,box.canvas,color,true)
  94.     end
  95. end
  96.  
  97. local string_rep = string.rep
  98. function box_object:render()
  99.     local term = self.term
  100.     local blit_line,set_cursor = term.blit,term.setCursorPos
  101.  
  102.     local canv = self.canvas
  103.  
  104.     local fg_line_1,bg_line_1 = {},{}
  105.     local fg_line_2,bg_line_2 = {},{}
  106.  
  107.     local width,height = self.width,self.height
  108.  
  109.     local even_char_line = string_rep("\131",width)
  110.     local odd_char_line  = string_rep("\143",width)
  111.  
  112.     local sy = 0
  113.     for y=1,height,3 do
  114.         sy = sy + 2
  115.         local layer_1 = canv[y]
  116.         local layer_2 = canv[y+1]
  117.         local layer_3 = canv[y+2]
  118.  
  119.         local n = 1
  120.         for x=1,width do
  121.             local color1 = layer_1[x]
  122.             local color2 = layer_2[x]
  123.             local color3 = layer_3[x]
  124.  
  125.             fg_line_1  [n] = to_blit[color1]
  126.             bg_line_1  [n] = to_blit[color2]
  127.             fg_line_2  [n] = to_blit[color2 or color2]
  128.             bg_line_2  [n] = to_blit[color3 or color2]
  129.  
  130.             n = n + 1
  131.         end
  132.  
  133.         set_cursor(1,sy-1)
  134.         blit_line(odd_char_line,
  135.             t_cat(fg_line_1,""),
  136.             t_cat(bg_line_1,"")
  137.         )
  138.  
  139.         set_cursor(1,sy)
  140.         blit_line(even_char_line,
  141.             t_cat(fg_line_2,""),
  142.             t_cat(bg_line_2,"")
  143.         )
  144.     end
  145. end
  146.  
  147. function box_object:clear(color)
  148.     pixelbox.restore(self,to_blit[color or ""] and color or self.background,false)
  149. end
  150.  
  151. function box_object:set_pixel(x,y,color)
  152.     self.canvas[y][x] = color
  153. end
  154.  
  155. function box_object:set_canvas(canvas)
  156.     self.canvas = canvas
  157.     self.CANVAS = canvas
  158. end
  159.  
  160. function box_object:resize(w,h,color)
  161.     self.term_width  = w
  162.     self.term_height = h
  163.     self.width  = w*2
  164.     self.height = h*3
  165.  
  166.     pixelbox.restore(self,color or self.background,true)
  167. end
  168.  
  169. function pixelbox.module_error(module,str,level,supress_error)
  170.     level = level or 1
  171.  
  172.     if module.__contact and not supress_error then
  173.         local _,err_msg = pcall(error,str,level+2)
  174.         printError(err_msg)
  175.         error((module.__report_msg or "\nReport module issue at:\n-> __contact"):gsub("[%w_]+",module),0)
  176.     elseif not supress_error then
  177.         error(str,level+1)
  178.     end
  179. end
  180.  
  181. function box_object:load_module(modules)
  182.     for k,module in ipairs(modules or {}) do
  183.         local module_data = {
  184.             __author     = module.author,
  185.             __name       = module.name,
  186.             __contact    = module.contact,
  187.             __report_msg = module.report_msg
  188.         }
  189.  
  190.         local module_fields,magic_methods = module.init(self,module_data,pixelbox,pixelbox.shared_data,pixelbox.initialized,modules)
  191.  
  192.         magic_methods    = magic_methods or {}
  193.         module_data.__fn = module_fields
  194.  
  195.  
  196.         if self.modules[module.id] and not modules.force then
  197.             pixelbox.module_error(module_data,("Module ID conflict: %q"):format(module.id),2,modules.supress)
  198.         else
  199.             self.modules[module.id] = module_data
  200.             if magic_methods.verified_load then
  201.                 magic_methods.verified_load()
  202.             end
  203.         end
  204.  
  205.         for fn_name in pairs(module_fields) do
  206.             if self.modules.module_functions[fn_name] and not modules.force then
  207.                 pixelbox.module_error(module_data,("Module %q tried to register already existing element: %q"):format(module.id,fn_name),2,modules.supress)
  208.             else
  209.                 self.modules.module_functions[fn_name] = {
  210.                     id   = module.id,
  211.                     name = fn_name
  212.                 }
  213.             end
  214.         end
  215.     end
  216. end
  217.  
  218. function pixelbox.new(terminal,bg,modules)
  219.     local box = {
  220.         modules = {module_functions={}}
  221.     }
  222.  
  223.     box.background = bg or terminal.getBackgroundColor()
  224.  
  225.     local w,h = terminal.getSize()
  226.     box.term  = terminal
  227.  
  228.     setmetatable(box,{__index = function(self,key)
  229.         local module_fn = rawget(box.modules.module_functions,key)
  230.         if module_fn then
  231.             return box.modules[module_fn.id].__fn[module_fn.name]
  232.         end
  233.  
  234.         return rawget(box_object,key)
  235.     end})
  236.  
  237.     box.__bixelbox_lite = true
  238.  
  239.     box.term_width  = w
  240.     box.term_height = h
  241.     box.width       = w
  242.     box.height      = math.ceil(h * (3/2))
  243.  
  244.     pixelbox.restore(box,box.background)
  245.  
  246.     if type(modules) == "table" then
  247.         box:load_module(modules)
  248.     end
  249.  
  250.     if not pixelbox.initialized then
  251.         generate_lookups()
  252.  
  253.         pixelbox.initialized = true
  254.     end
  255.  
  256.     return box
  257. end
  258.  
  259.  
  260.  
  261. local termWidth,termHeight = term.getSize()
  262. local lockStart = nil
  263. local lockDelay = 0.25 -- seconds
  264. local keysDown = {}
  265. local gameWindow = window.create(
  266.                                     term.current(),
  267.                                     2,
  268.                                     3,
  269.                                     12,
  270.                                     18
  271.                                 )
  272. local infoWindow = window.create(
  273.                                                         term.current(),
  274.                                                         1,
  275.                                                         21,
  276.                                                         termWidth,
  277.                                                         50
  278.                                                     )
  279. local nextPieceWindow = window.create(
  280.                                     term.current(),
  281.                                     16,
  282.                                     8,
  283.                                     4,
  284.                                     6
  285.                                 )
  286.                                
  287. local heldPieceWindow = window.create(
  288.                                     term.current(),
  289.                                     16,
  290.                                     15,
  291.                                     4,
  292.                                     3
  293.                                 )
  294. local pieces =  {
  295.                     straight = {
  296.                                 color = colors.cyan,
  297.                                 {{0,1},{1,1},{2,1},{3,1}},
  298.                                 {{2,0},{2,1},{2,2},{2,3}},
  299.                                 {{0,2},{1,2},{2,2},{3,2}},
  300.                                 {{1,0},{1,1},{1,2},{1,3}},
  301.                                 {{0,1},{1,1},{2,1},{3,1}}},
  302.                                
  303.                                
  304.                     jShape = {
  305.                                 color = colors.blue,
  306.                                 {{0,0},{0,1},{1,1},{2,1}},
  307.                                 {{1,0},{2,0},{1,1},{1,2}},
  308.                                 {{0,1},{1,1},{2,1},{2,2}},
  309.                                 {{1,0},{1,1},{0,2},{1,2}},
  310.                                 {{0,0},{0,1},{1,1},{2,1}}},
  311.                                
  312.                     lShape = {
  313.                                 color = colors.orange,
  314.                                 {{2,0},{0,1},{1,1},{2,1}},
  315.                                 {{1,0},{1,1},{1,2},{2,2}},
  316.                                 {{0,1},{1,1},{2,1},{0,2}},
  317.                                 {{0,0},{1,0},{1,1},{1,2}},
  318.                                 {{2,0},{0,1},{1,1},{2,1}}},
  319.                                
  320.                     square = {
  321.                                 color = colors.yellow,
  322.                                 {{1,0},{2,0},{1,1},{2,1}},
  323.                                 {{1,0},{2,0},{1,1},{2,1}},
  324.                                 {{1,0},{2,0},{1,1},{2,1}},
  325.                                 {{1,0},{2,0},{1,1},{2,1}},
  326.                                 {{1,0},{2,0},{1,1},{2,1}}},
  327.                                
  328.                     sShape = {
  329.                                 color = colors.lime,
  330.                                 {{1,0},{2,0},{0,1},{1,1}},
  331.                                 {{1,0},{1,1},{2,1},{2,2}},
  332.                                 {{1,1},{2,1},{0,2},{1,2}},
  333.                                 {{0,0},{0,1},{1,1},{1,2}},
  334.                                 {{1,0},{2,0},{0,1},{1,1}}},
  335.                                
  336.                     tShape = {
  337.                                 color = colors.purple,
  338.                                 {{1,0},{0,1},{1,1},{2,1}},
  339.                                 {{1,0},{1,1},{2,1},{1,2}},
  340.                                 {{0,1},{1,1},{2,1},{1,2}},
  341.                                 {{1,0},{0,1},{1,1},{1,2}},
  342.                                 {{1,0},{0,1},{1,1},{2,1}}},
  343.                    
  344.                     zShape = {
  345.                                 color = colors.red,
  346.                                 {{0,0},{1,0},{1,1},{2,1}},
  347.                                 {{2,0},{1,1},{2,1},{1,2}},
  348.                                 {{0,1},{1,1},{1,2},{2,2}},
  349.                                 {{1,0},{0,1},{1,1},{0,2}},
  350.                                 {{0,0},{1,0},{1,1},{2,1}}},
  351.                                
  352.                 }      
  353. local wallKickLTable =  {
  354.                             {{0,0},{-2,0},{1,0},{-2,1},{1,-2}},
  355.                             {{0,0},{-1,0},{2,0},{-1,-2},{2,1}},
  356.                             {{0,0},{2,0},{-1,0},{2,-1},{-1,2}},
  357.                             {{0,0},{1,0},{-2,0},{1,2},{-2,-1}},
  358.                             {{0,0},{-2,0},{1,0},{-2,1},{1,-2}}
  359.                         }
  360. local wallKickOther =   {
  361.                             {{0,0},{-1,0},{-1,-1},{0,2},{-1,2}},
  362.                             {{0,0},{1,0},{1,1},{0,-2},{1,-2}},
  363.                             {{0,0},{1,0},{1,-1},{0,2},{1,2}},
  364.                             {{0,0},{-1,0},{-1,1},{0,-2},{-1,-2}},
  365.                             {{0,0},{-1,0},{-1,-1},{0,2},{-1,2}}
  366.  
  367.                         }
  368. local player =  {
  369.                 x = 5,
  370.                 y = 2,
  371.                 rotation = 1,
  372.                 score = 0,
  373.                 currentPiece = "straight",
  374.                 frameCounter = 0,
  375.                 speed = 16,
  376.                 linesCleared = 0,
  377.                 gameEnded = false,
  378.                 level = 0,
  379.                 allowSwap = true
  380.                 }
  381. local bag = {}
  382. local bagInitialized = bagInitialized or false
  383.  
  384. local box = pixelbox.new(gameWindow)
  385. local nextPieceBox = pixelbox.new(nextPieceWindow)
  386. local heldPieceBox = pixelbox.new(heldPieceWindow)
  387.  
  388. local function printToInfo(msg)  
  389.     infoWindow.setBackgroundColor(colors.black)
  390.     infoWindow.setTextColor(colors.white)
  391.     local terminal = term.current()
  392.     term.redirect(infoWindow)
  393.     print(msg)
  394.     term.redirect(terminal)
  395. end
  396.  
  397. function newCurrentPiece()
  398.   -- All seven tetromino names
  399.   local pieceTypes = {
  400.     "straight", "square", "tShape",
  401.     "jShape",    "lShape",   "sShape", "zShape"
  402.   }
  403.  
  404.   -- Fisher–Yates shuffle
  405.   local function shuffle(t)
  406.     for i = #t, 2, -1 do
  407.       local j = math.random(i)
  408.       t[i], t[j] = t[j], t[i]
  409.     end
  410.   end
  411.  
  412.   -- Append one shuffled septet to bag
  413.   local function refillBag()
  414.     -- build a fresh septet
  415.     local septet = {}
  416.     for _, p in ipairs(pieceTypes) do
  417.       septet[#septet + 1] = p
  418.     end
  419.     shuffle(septet)
  420.     -- append it
  421.     for _, p in ipairs(septet) do
  422.       bag[#bag + 1] = p
  423.     end
  424.   end
  425.  
  426.   -- On first ever call, seed two septets (14 pieces total)
  427.   if not bagInitialized then
  428.     refillBag()
  429.     refillBag()
  430.     bagInitialized = true
  431.   end
  432.  
  433.   -- Maintain at least a full septet in reserve
  434.   if #bag <= 7 then
  435.     refillBag()
  436.   end
  437.  
  438.   -- Pull the next piece from the front, shifting all others down
  439.   local nextPiece = bag[1]
  440.   table.remove(bag, 1)
  441.  
  442.   return nextPiece
  443. end
  444.  
  445. local function drawTetromino(x,y,name,rotation,arguments)
  446.     if arguments == "clear" then
  447.         for i = 1,4 do
  448.             box:set_pixel(pieces[name][rotation][i][1] + x,pieces[name][rotation][i][2] + y,colors.black)
  449.         end
  450.     elseif arguments == "ghost" then
  451.         for i = 1,4 do
  452.             box:set_pixel(pieces[name][rotation][i][1] + x,pieces[name][rotation][i][2] + y,colors.gray)
  453.         end
  454.     elseif arguments == "collision" then
  455.         local collides = false
  456.         for i = 1,4 do
  457.             if box.canvas[y + pieces[name][rotation][i][2]][x + pieces[name][rotation][i][1]] ~= colors.black then
  458.                 collides = true
  459.             end
  460.         end
  461.        
  462.         return collides
  463.        
  464.     else
  465.         for i = 1,4 do
  466.             box:set_pixel(pieces[name][rotation][i][1] + x,pieces[name][rotation][i][2] + y,pieces[name].color)
  467.         end        
  468.     end
  469. end
  470.  
  471. local function drawNextPieces(x,y,name)
  472.  
  473.     for i = 1,4 do
  474.         nextPieceBox:set_pixel(pieces[name][1][i][1] + x,pieces[name][1][i][2] + y,pieces[name].color)
  475.     end        
  476.    
  477. end
  478.  
  479. local function drawHeldPiece(x,y,name)
  480.     if name then
  481.         for i = 1,4 do
  482.             heldPieceBox:set_pixel(pieces[name][1][i][1] + x,pieces[name][1][i][2] + y,pieces[name].color)
  483.         end        
  484.     end
  485. end
  486.  
  487. local function rotatePiece(x,y,name,currentRotation)
  488.     drawTetromino(player.x,player.y,player.currentPiece,player.rotation,"clear")
  489.    
  490.     if name == "straight" then
  491.         for i = 1,5 do
  492.             if drawTetromino(x + wallKickLTable[currentRotation][i][1],y + wallKickLTable[currentRotation][i][2],name,currentRotation + 1, "collision") == false then
  493.                 if player.rotation == 4 then
  494.                     player.rotation = 1
  495.                 else
  496.                     player.rotation = player.rotation + 1
  497.                 end
  498.                
  499.                 if lockStart then lockStart = os.clock() end
  500.                 player.x = player.x + wallKickLTable[currentRotation][i][1]
  501.                 player.y = player.y + wallKickLTable[currentRotation][i][2]
  502.                 break
  503.             end
  504.         end
  505.     else
  506.         for i = 1,5 do
  507.             if drawTetromino(x + wallKickOther[currentRotation][i][1],y + wallKickOther[currentRotation][i][2],name,currentRotation + 1, "collision") == false then
  508.                 if player.rotation == 4 then
  509.                     player.rotation = 1
  510.                 else
  511.                     player.rotation = player.rotation + 1
  512.                 end
  513.                
  514.                 if lockStart then lockStart = os.clock() end
  515.                 player.x = player.x + wallKickOther[currentRotation][i][1]
  516.                 player.y = player.y + wallKickOther[currentRotation][i][2]
  517.                 break
  518.             end
  519.         end    
  520.     end
  521. end
  522.  
  523. local function moveLeft()
  524.     if drawTetromino(player.x - 1,player.y,player.currentPiece,player.rotation, "collision") == false then
  525.         player.x = player.x - 1
  526.         if lockStart then lockStart = os.clock() end
  527.     end
  528. end
  529.  
  530. local function moveRight()
  531.     if drawTetromino(player.x + 1,player.y,player.currentPiece,player.rotation, "collision") == false then
  532.         player.x = player.x + 1
  533.         if lockStart then lockStart = os.clock() end
  534.     end
  535. end
  536.  
  537. local function clearCheck()
  538.  
  539.     -- Iterate bottom-up so collapsing doesn’t skip rows
  540.     local y = 25
  541.     local clearedLines = 0
  542.     while y >= 2 do
  543.         -- Check if row y is full
  544.         local isFull = true
  545.         for x = 2, 11 do
  546.             if box.canvas[y][x] == colors.black then
  547.                 isFull = false
  548.                 break
  549.             end
  550.         end
  551.  
  552.         if isFull then
  553.             player.linesCleared = player.linesCleared + 1
  554.             clearedLines = clearedLines + 1
  555.             -- Pull every row above y down by one
  556.             for pullY = y, 2, -1 do
  557.                 for x = 2, 11 do
  558.                     box.canvas[pullY][x] = box.canvas[pullY - 1][x]
  559.                 end
  560.             end
  561.  
  562.             -- Clear the new top row
  563.             for x = 2, 11 do
  564.                 box.canvas[1][x] = colors.black
  565.             end
  566.  
  567.             -- Stay on this y to re-check the row that just shifted into place
  568.         else
  569.             y = y - 1
  570.         end
  571.     end
  572.    
  573.     if clearedLines == 1 then
  574.         player.score = player.score + ((player.level + 1) * 40)
  575.     elseif clearedLines == 2 then
  576.         player.score = player.score + ((player.level + 1) * 100)
  577.     elseif clearedLines == 3 then
  578.         player.score = player.score + ((player.level + 1) * 300)
  579.     elseif clearedLines == 4 then
  580.         player.score = player.score + ((player.level + 1) * 1200)
  581.     end
  582.    
  583.     if clearedLines > 0 then
  584.         if math.floor(player.linesCleared / 10) > player.level then
  585.             player.level = player.level + 1
  586.            
  587.             if player.level == 1 then
  588.                 player.speed = 15
  589.             elseif player.level == 2 then
  590.                 player.speed = 13
  591.             elseif player.level == 3 then
  592.                 player.speed = 11
  593.             elseif player.level == 4 then
  594.                 player.speed = 9
  595.             elseif player.level == 5 then
  596.                 player.speed = 8
  597.             elseif player.level == 6 then
  598.                 player.speed = 6
  599.             elseif player.level == 7 then
  600.                 player.speed = 4
  601.             elseif player.level == 8 then
  602.                 player.speed = 3
  603.             elseif player.level == 9 then
  604.                 player.speed = 3
  605.             elseif player.level == 10 then
  606.                 player.speed = 2
  607.             elseif player.level == 11 then
  608.                 player.speed = 2
  609.             elseif player.level == 12 then
  610.                 player.speed = 1
  611.             end
  612.            
  613.         end
  614.     end
  615.    
  616. end
  617.  
  618. local function moveDown()
  619.     if not drawTetromino(player.x, player.y + 1, player.currentPiece, player.rotation, "collision") then
  620.         if player.frameCounter > player.speed or keysDown[keys.s] or keysDown[keys.down] then
  621.             player.y = player.y + 1
  622.             player.frameCounter = 0
  623.         end
  624.        
  625.         lockStart = nil -- cancel lock delay if rising
  626.         if keysDown[keys.s] or keysDown[keys.down] then
  627.             player.score = player.score + 1
  628.         end
  629.     else
  630.         if lockStart == nil then
  631.             lockStart = os.clock()
  632.         elseif os.clock() - lockStart >= lockDelay then
  633.             -- Lock piece
  634.             drawTetromino(player.x, player.y, player.currentPiece, player.rotation)
  635.             player.x = 5
  636.             player.y = 2
  637.             player.rotation = 1
  638.             player.currentPiece = newCurrentPiece()
  639.             player.gameEnded = drawTetromino(player.x, player.y, player.currentPiece, player.rotation,"collision")
  640.             lockStart = nil
  641.             clearCheck()
  642.             player.allowSwap = true
  643.         end
  644.     end
  645. end
  646.  
  647. for x = 1,box.width do
  648.     for y = 1,box.height do
  649.         if (x+y) % 2 == 0 and (x < 2 or x > 11 or y > 25) and y ~= 27 then
  650.             box:set_pixel(x,y,colors.lightGray)
  651.         elseif (x < 2 or x > 11 or y > 25) and y ~= 27 then
  652.             box:set_pixel(x,y,colors.gray)
  653.         end
  654.     end
  655. end
  656.  
  657. local function getUserInput()
  658.  
  659.     local event, key = os.pullEvent()
  660.    
  661.     if event == "key" then keysDown[key] = true
  662.     elseif event == "key_up" then keysDown[key] = false rollLock = true
  663.     elseif event == "timer" and key == timer then
  664.         timer = os.startTimer(0.05)
  665.         player.frameCounter = player.frameCounter + 1
  666.         drawTetromino(player.x,player.y,player.currentPiece,player.rotation,"clear")
  667.  
  668.         moveDown()
  669.  
  670.         if (keysDown[keys.w] or keysDown[keys.up]) and rollLock then
  671.             rotatePiece(player.x,player.y,player.currentPiece,player.rotation)
  672.             rollLock = false
  673.         end
  674.         if (keysDown[keys.d] or keysDown[keys.right]) then
  675.             moveRight()
  676.         end
  677.         if (keysDown[keys.a] or keysDown[keys.left]) then
  678.             moveLeft()
  679.         end
  680.         if keysDown[keys.space] and rollLock then
  681.             rollLock = false
  682.             local yUntilDrop = 0
  683.             repeat
  684.                 yUntilDrop = yUntilDrop + 1
  685.             until drawTetromino(player.x,player.y + yUntilDrop,player.currentPiece,player.rotation,"collision")
  686.             player.y = player.y + yUntilDrop - 1
  687.             player.score = player.score + (yUntilDrop-1)*2
  688.         end
  689.         if (keysDown[keys.e] or keysDown[keys.enter]) and player.allowSwap then
  690.             player.allowSwap = false
  691.  
  692.             player.x, player.y, player.rotation = 5, 2, 1
  693.  
  694.             local temp = player.currentPiece
  695.             if player.heldPiece then
  696.                 player.currentPiece = player.heldPiece
  697.             else
  698.                 player.currentPiece = newCurrentPiece()
  699.             end
  700.             player.heldPiece = temp
  701.         end
  702.        
  703.         local yUntilDrop = 0
  704.         repeat
  705.             yUntilDrop = yUntilDrop + 1
  706.         until drawTetromino(player.x,player.y + yUntilDrop,player.currentPiece,player.rotation,"collision")
  707.        
  708.         drawTetromino(player.x,player.y + yUntilDrop - 1,player.currentPiece,player.rotation,"ghost")
  709.         drawTetromino(player.x,player.y,player.currentPiece,player.rotation)
  710.        
  711.         box:render()
  712.         drawTetromino(player.x,player.y + yUntilDrop - 1,player.currentPiece,player.rotation,"clear")
  713.     end
  714. end
  715.  
  716. highScore = 7384
  717.  
  718. local function start()
  719.     term.setBackgroundColor(colors.black)
  720.     term.clear()
  721.    
  722.     term.setCursorPos(5,1)
  723.     term.write("LINES:     TOP SCORE:")
  724.     term.setCursorPos(16,2)
  725.     term.write(highScore)
  726.     term.setCursorPos(18,4)
  727.     term.write("SCORE")
  728.     term.setCursorPos(16,7)
  729.     term.write("NEXT:")
  730.     term.setCursorPos(16,14)
  731.     term.write("HELD:")
  732.     term.setCursorPos(16,18)
  733.     term.write("LEVEL:")
  734.    
  735.     timer = os.startTimer(0.05)
  736.     player.currentPiece = newCurrentPiece()
  737.    
  738.     while true do
  739.        
  740.         if player.gameEnded == true then
  741.             break
  742.         end
  743.        
  744.         getUserInput()
  745.         infoWindow.clear()
  746.         infoWindow.setCursorPos(1,1)
  747.         term.setCursorPos(7,2)
  748.         term.write(player.linesCleared)
  749.         term.setCursorPos(16,5)
  750.         term.write(player.score)
  751.        
  752.         nextPieceBox:clear()
  753.         drawNextPieces(1,1,bag[1])
  754.         drawNextPieces(1,4,bag[2])
  755.         drawNextPieces(1,7,bag[3])
  756.         nextPieceBox:render()
  757.        
  758.         heldPieceBox:clear()
  759.         drawHeldPiece(1,1,player.heldPiece)
  760.         heldPieceBox:render()
  761.        
  762.         term.setCursorPos(16,19)
  763.         term.write(player.level)
  764.        
  765.     end
  766. end
  767.  
  768. start()
  769.  
  770. term.clear()
  771. term.setCursorPos(1,1)
  772.  
  773. if player.score > highScore then
  774.     local path = shell.resolve("tetris.lua")
  775.     local file = fs.open(path, "r")
  776.     local lines = {}
  777.  
  778.     while true do
  779.         local line = file.readLine()
  780.         if line == nil then break end
  781.         table.insert(lines, line)
  782.     end
  783.     file.close()
  784.  
  785.     for i, line in ipairs(lines) do
  786.         if line:match("^highScore%s*=%s*%d+") then
  787.             lines[i] = "highScore = " .. tostring(player.score)
  788.             break
  789.         end
  790.     end
  791.  
  792.     file = fs.open(path, "w")
  793.     for _, line in ipairs(lines) do
  794.         file.writeLine(line)
  795.     end
  796.     file.close()
  797.    
  798.     print("NEW HIGH SCORE:")
  799.     print(highScore)
  800.    
  801. else
  802.     print("YOUR SCORE:")
  803.     print(player.score)
  804. end
Advertisement
Add Comment
Please, Sign In to add comment