Advertisement
faubiguy

Tetro

Oct 22nd, 2012
463
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 11.15 KB | None | 0 0
  1. -- Declarations
  2.  
  3. local updateLines
  4. local turnTransition
  5. local getSpritePixelData
  6. local constructSpriteColor
  7. local gameLoop
  8. local exited = false
  9. local replay = false
  10. local showControls
  11. local mainMenu
  12. local currentPiece
  13. local nextPiece
  14. local nextPieceSprite
  15. local currentSprite
  16. local downTimer
  17. local pieceActive
  18. local currentRotation
  19. local lines
  20. --local fallenPieces
  21. local fallenPieceSprite
  22. local timer
  23. local running
  24. local interval
  25.  
  26. -- Initialization
  27.  
  28. term.clear()
  29. term.setCursorPos(1,1)
  30.  
  31. if not term.isColor() then
  32.     print("This game requires and advanced computer to play")
  33.     return
  34. end
  35.  
  36. local function installAPI(name, code) -- Uses code from pastebin program
  37.     if not fs.exists(name) then
  38.         print(fs.getName(name).." API not found. Attempting to download...")
  39.         local response = http.get(
  40.             "http://pastebin.com/raw.php?i="..textutils.urlEncode( code )
  41.             )
  42.            
  43.         if response then
  44.            
  45.             local sResponse = response.readAll()
  46.             response.close()
  47.            
  48.             local file = fs.open( name, "w" )
  49.             file.write( sResponse )
  50.             file.close()
  51.             print("Download successful")
  52.         else
  53.             print("Unable to connect to pastebin.com\nAPI download failed")
  54.             return false
  55.         end
  56.     end
  57.     getfenv(os.loadAPI).print = function() end
  58.     local success = os.loadAPI(name)
  59.     getfenv(os.loadAPI).print = print
  60.     if not success then
  61.         print(fs.getName(name).." API failed to load.")
  62.         return false
  63.     end
  64.     return true
  65. end
  66.  
  67. installAPI("CGE", "r2UReK1M")
  68. installAPI("menu", "UgMUtQGU")
  69.  
  70. local width, height = term.getSize()
  71. local offset = math.floor((width-14)/2)
  72.  
  73. local wall = {}
  74. for _=1,height do
  75.     table.insert(wall, "||")
  76. end
  77.  
  78. local wall1 = CGE.constructSprite(0, 0, wall, "wall1")
  79. local wall2 = CGE.constructSprite(12, 0, wall, "wall2")
  80. CGE.addSprites({wall1, wall2})
  81.  
  82. local floor = CGE.constructSprite(1, height, {string.rep("-", 12)}, "floor")
  83. local ceiling  = CGE.constructSprite(1, -1, {string.rep("-", 12)}, "ceiling")
  84. CGE.addSprite(floor)
  85. CGE.addSprite(ceiling)
  86.  
  87. -- Sprites
  88.  
  89. local sprites = {
  90.     {{"&c&c&c&c"}, {"&c", "&c", "&c", "&c"}},
  91.     {{"&e&e", "&e&e"}},
  92.     {{"&1&1&1", "  &1"}, {" &1", " &1", "&1&1"}, {"&1", "&1&1&1"}, {"&1&1", "&1", "&1"}},
  93.     {{"&6&6&6", "&6"}, {"&6&6", " &6", " &6"}, {"  &6", "&6&6&6"}, {"&6", "&6", "&6&6"}},
  94.     {{" &5&5", "&5&5"}, {"&5", "&5&5", " &5"}},
  95.     {{"&3&3&3", " &3"}, {" &3", "&3&3", " &3"}, {" &3", "&3&3&3"}, {"&3", "&3&3", "&3"}},
  96.     {{"&a&a", " &a&a"}, {" &a", "&a&a", "&a"}}
  97. }
  98.  
  99. local offsets = {
  100.     {{1,-2},{-1,2}},
  101.     {{0,0}},
  102.     {{1,-1},{-1,0},{1,0},{-1,1}},
  103.     {{1,-1},{-1,0},{1,0},{-1,1}},
  104.     {{1,0},{-1,0}},
  105.     {{1,-1},{-1,0},{1,0},{-1,1}},
  106.     {{1,-1},{-1,1}}
  107. }
  108.  
  109. -- Variable preparation
  110.  
  111. local function resetVars()
  112.     nextPiece = math.random(1, 7)
  113.     nextPieceSprite = constructSpriteColor(18, 4, sprites[nextPiece][1], "nextPieceSprite")
  114.     pieceActive = false
  115.     currentRotation = 0
  116.     lines = 0
  117.     fallenPieces = {}
  118.     running = true
  119.     interval = 0.5
  120.     for _=1,height do
  121.         table.insert(fallenPieces, {})
  122.     end
  123.     do
  124.         local preSprite = {}
  125.         for _,line in ipairs(fallenPieces) do
  126.             local stringLine = ""
  127.             for i=1,10 do
  128.                 stringLine = stringLine .. (line[i] or " ")
  129.             end
  130.             table.insert(preSprite, stringLine)
  131.         end
  132.         fallenPieceSprite = constructSpriteColor(2, 0, preSprite, "fallenPieceSprite")
  133.         CGE.addSprite(fallenPieceSprite)
  134.     end
  135.     for _=1,height do
  136.     table.insert(fallenPieces, {})
  137.     end
  138.     do
  139.         local preSprite = {}
  140.         for _,line in ipairs(fallenPieces) do
  141.             local stringLine = ""
  142.             for i=1,10 do
  143.                 stringLine = stringLine .. (line[i] or " ")
  144.             end
  145.             table.insert(preSprite, stringLine)
  146.         end
  147.         fallenPieceSprite = constructSpriteColor(2, 0, preSprite, "fallenPieceSprite")
  148.         CGE.addSprite(fallenPieceSprite)
  149.     end
  150. end
  151.  
  152. local controls = {
  153. [keys.down] = function()
  154.     if not downTimer then
  155.         local movedSprite = CGE.moveSprite(currentSprite, 0, 1)
  156.         if CGE.checkCollision(movedSprite, {fallenPieceSprite, floor}) then
  157.             turnTransition()
  158.         else
  159.             CGE.changeSprite(currentSprite, movedSprite)
  160.             currentSprite = CGE.getSprite("currentSprite")
  161.             downTimer = os.startTimer(0.1)
  162.         end
  163.     end
  164. end,
  165. [keys.up] = function()
  166.     currentRotation = (currentRotation+1) % #sprites[currentPiece]
  167.     local posX, posY = unpack(CGE.getSpriteBounds(currentSprite))
  168.     offY, offX = unpack(offsets[currentPiece][currentRotation+1])
  169.     local rotatedSprite = constructSpriteColor(posX + offX - 1, posY + offY - 1, sprites[currentPiece][currentRotation+1], "currentSprite")
  170.     if not CGE.checkCollision(rotatedSprite, {wall1, wall2, fallenPieceSprite, floor}) then
  171.         CGE.changeSprite(currentSprite, rotatedSprite)
  172.         currentSprite = CGE.getSprite("currentSprite")
  173.     end
  174. end,
  175. [keys.left] = function()
  176.     if not pieceActive then return end
  177.     local movedSprite = CGE.moveSprite(currentSprite, -1, 0)
  178.     if not CGE.checkCollision(movedSprite, {wall1, wall2, fallenPieceSprite}) then CGE.changeSprite(currentSprite, movedSprite) end
  179.     currentSprite = CGE.getSprite("currentSprite")
  180. end,
  181. [keys.right] = function()
  182.     if not pieceActive then return end
  183.     local movedSprite = CGE.moveSprite(currentSprite, 1, 0)
  184.     if not CGE.checkCollision(movedSprite, {wall1, wall2, fallenPieceSprite}) then CGE.changeSprite(currentSprite, movedSprite) end
  185.     currentSprite = CGE.getSprite("currentSprite")
  186. end,
  187. [keys.space] = function()
  188.     local wOffset = math.floor((width-15)/2)
  189.     local hOffset = math.floor((height-9)/2)
  190.     local pauseText = {
  191.     "===============",
  192.     "| Game Paused |",
  193.     "| ----------- |",
  194.     "| Press SPACE |",
  195.     "| To Continue |",
  196.     "| ----------- |",
  197.     "| Press CTRL  |",
  198.     "|   To Quit   |",
  199.     "==============="
  200.     }
  201.     for line = 1, 9 do
  202.         term.setCursorPos(wOffset+1, hOffset+line)
  203.         term.write(pauseText[line])
  204.     end
  205.     while true do
  206.         local e,p = os.pullEvent()
  207.         if e == "key" then
  208.             if p == keys.space then break
  209.             elseif p == keys.leftCtrl or p == keys.rightCtrl then running = false break end
  210.         elseif e == "timer" and p == timer then
  211.             timer = os.startTimer(interval)
  212.         end
  213.     end
  214. end
  215. }
  216.  
  217. -- Redraw
  218.  
  219. local function redraw()
  220.     term.clear()
  221.     local nextOffset = offset + 16
  222.     term.setCursorPos(nextOffset, 2)
  223.     term.write("Next Piece:")
  224.     CGE.deleteSprite(nextPieceSprite)
  225.     nextPieceSprite = constructSpriteColor(18, 4, sprites[nextPiece][1], "nextPieceSprite")
  226.     CGE.addSprite(nextPieceSprite)
  227.     CGE.colorDraw(offset, 0)
  228.     term.setCursorPos(2,2)
  229.     term.write("Lines: "..lines)
  230.    
  231. end
  232.  
  233. -- Other Functions
  234.  
  235. function updateLines()
  236.     if CGE.checkCollision(currentSprite, {ceiling}) then running = false return end
  237.     pixels = getSpritePixelData(currentSprite)
  238.     for _,pixel in ipairs(pixels) do
  239.         local x, y = tonumber(pixel[1])-2, tonumber(pixel[2])
  240.         fallenPieces[y][x] = pixel[3]
  241.     end
  242.     local lineCount = #fallenPieces
  243.     local insertCount = 0
  244.     for line=lineCount,1,-1 do
  245.         local lineFound = true
  246.         local pieceLine = fallenPieces[line]
  247.             local space = false
  248.             for i=1,10 do
  249.                 if not pieceLine[i] then
  250.                     lineFound = false
  251.                     break
  252.                 end
  253.             end
  254.         if lineFound then
  255.             local pieceLine = fallenPieces[line]
  256.             table.remove(fallenPieces, line)
  257.             lines = lines + 1
  258.             insertCount = insertCount + 1
  259.         end
  260.     end
  261.     for _=1,insertCount do
  262.         table.insert(fallenPieces, 1, {})
  263.     end
  264. end
  265.  
  266. function turnTransition()
  267.     pieceActive = false
  268.     updateLines()
  269.     CGE.deleteSprite(currentSprite)
  270.     local preSprite = {}
  271.     for _,line in ipairs(fallenPieces) do
  272.         local stringLine = ""
  273.         for i=1,10 do
  274.             stringLine = stringLine .. (line[i] or " ")
  275.         end
  276.         table.insert(preSprite, stringLine)
  277.     end
  278.     CGE.deleteSprite(fallenPieceSprite)
  279.     fallenPieceSprite = constructSpriteColor(2, 0, preSprite, "fallenPieceSprite")
  280.     CGE.addSprite(fallenPieceSprite)
  281. end
  282.  
  283. function constructSpriteColor(sx, sy, stable, name, maxani)
  284.     if maxani == nil then maxani = 1 end
  285.     local nsprite = {}
  286.     local cur = 1
  287.     for i,v in ipairs(stable) do
  288.         local y = i
  289.         local line = v
  290.         local x = 1
  291.         local offsetX = 1
  292.         while x <= string.len(line) do
  293.             local type = string.sub(line, x, x)
  294.             if type ~= " " then
  295.                 if type == "&" then type = string.sub(line, x, x+1); x = x + 1 end
  296.                 nsprite[cur] = (sx+offsetX)..":"..(sy+y)..":"..type..":"..name..":"..maxani..":"..(1)..":".."0,0,0"
  297.                 cur = cur + 1
  298.             end
  299.             x = x + 1
  300.             offsetX = offsetX + 1
  301.         end
  302.     end
  303.     return nsprite
  304. end
  305.  
  306. function getSpritePixelData(sprite)
  307.     local ttable = {}
  308.     for i,v in ipairs(sprite) do
  309.         local splt = CGE.split(v, ":")
  310.         ttable[#ttable + 1] = {splt[1], splt[2], splt[3]}
  311.     end
  312.     return ttable
  313. end
  314.  
  315. local function main()
  316.     while not exited do
  317.         mainMenu:display(false, true)
  318.     end
  319. end
  320.  
  321. function showControls()
  322.     term.clear()
  323.     term.setCursorPos(1,1)
  324.     print("Right/left - Move piece right/left")
  325.     print("Up - Rotate piece")
  326.     print("Space - Pause")
  327.     print("Down - Move piece down")
  328.     print("\nPress any key to return to menu")
  329.     while true do
  330.         local e,p = os.pullEvent("key")
  331.         if p ~= 1 then break end
  332.     end
  333. end
  334.  
  335. -- Game Loop
  336.  
  337. function gameLoop()
  338.     resetVars()
  339.     term.clear()
  340.     timer = os.startTimer(interval)
  341.  
  342.     while running do
  343.         local event,p1 = os.pullEvent()
  344.         if event == "timer" and p1 == timer then
  345.             if not pieceActive then
  346.                 currentPiece = nextPiece
  347.                 nextPiece = math.random(1, 7)
  348.                 currentRotation = 0
  349.                 currentSprite = constructSpriteColor(2, -1, sprites[currentPiece][currentRotation+1], "currentSprite")
  350.                 CGE.addSprite(currentSprite)
  351.                 pieceActive = true
  352.             else
  353.                 local movedSprite = CGE.moveSprite(currentSprite, 0, 1)
  354.                 if CGE.checkCollision(movedSprite, {fallenPieceSprite, floor}) then
  355.                     turnTransition()
  356.                 else
  357.                     CGE.changeSprite(currentSprite, movedSprite)
  358.                     currentSprite = CGE.getSprite("currentSprite")
  359.                 end
  360.             end
  361.             redraw()
  362.             timer = os.startTimer(interval)
  363.         elseif event == "timer" and p1 == downTimer then
  364.             downTimer = nil
  365.         elseif event == "key" and controls[p1] then
  366.             controls[p1]()
  367.             redraw()
  368.         end
  369.     end
  370.     CGE.deleteSprite(currentSprite)
  371.     CGE.deleteSprite(fallenPieceSprite)
  372.     CGE.deleteSprite(nextPieceSprite)
  373.    
  374.     local wOffset = math.floor((width-16)/2)
  375.     local hOffset = math.floor((height-8)/2)
  376.     local score = tostring(lines)
  377.     local pauseText = {
  378.     "================",
  379.     "|  Game Over!  |",
  380.     "| ------------ |",
  381.     "| Lines: "..score..string.rep(" ", 5-score:len()).." |",
  382.     "| ------------ |",
  383.     "| Press Space  |",
  384.     "| To Continue  |",
  385.     "================"
  386.     }
  387.     for line = 1, 8 do
  388.         term.setCursorPos(wOffset+1, hOffset+line)
  389.         term.write(pauseText[line])
  390.     end
  391.     while true do
  392.         local e,p = os.pullEvent("key")
  393.         if e == "key" and p == keys.space then break end
  394.     end
  395.    
  396.     replayMenu:display(false, true)
  397.    
  398.     if replay then
  399.         resetVars()
  400.         return gameLoop()
  401.     end
  402. end
  403.  
  404. -- Menus
  405.  
  406. mainMenu = menu.create("Tetro")
  407. mainMenu:addOption("Play", gameLoop)
  408. mainMenu:addOption("Controls", showControls)
  409. mainMenu:addOption("Exit", function() exited = true end)
  410.  
  411. replayMenu = menu.create("Play again?")
  412. replayMenu:addOption("Yes", function() replay = true end)
  413. replayMenu:addOption("Exit Tetro", function() replay = false; exited = true end)
  414. replayMenu:addOption("Back to Main Menu", function() replay = false; exited = false end)
  415.  
  416. -- Other Stuff
  417.  
  418. main()
  419.  
  420. for _,sprite in pairs(CGE.getSprites()) do
  421.     CGE.deleteSprite(sprite)
  422. end
  423.  
  424. term.clear()
  425. term.setCursorPos(1,1)
  426. print("Thank you for playing Tetro")
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement