Advertisement
Jummit

Fruit collecting game

Mar 16th, 2018
317
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 10.63 KB | None | 0 0
  1. width, height = term.getSize()
  2.  
  3. local arguments = {...}
  4. if arguments and arguments[1] then
  5.   local outputPath = arguments[2] or arguments[1]..".pin"
  6.   local gameFile = fs.open(arguments[1], "r")
  7.   local game = gameFile:readAll()
  8.   gameFile.close()
  9.   local engineFile = fs.open("engine", "r")
  10.   local engine = engineFile.readAll()
  11.   engineFile.close()
  12.  
  13.   local outputFile = fs.open(outputPath, "w")
  14.   outputFile.write(engine)
  15.   outputFile.write("\n\nengine=getfenv()\n-- Game Code")
  16.   outputFile.write(game)
  17.   outputFile.close()
  18.   print("Exported game "..arguments[1].." to "..outputPath.." successfully")
  19. end
  20.  
  21. -- EVENT HANDLER MODULE
  22. mouse = {x = 0, y = 0}
  23. keyboard = {lastChar = ""}
  24. eventHandler = {
  25.   mouse_click = function(button, x, y)
  26.     mouse.x, mouse.y = x, y
  27.     mouse.isDown = true
  28.   end,
  29.   mouse_up = function(button, x, y)
  30.     mouse.x, mouse.y = x, y
  31.     mouse.isDown = false
  32.     mouse.isDragged = false
  33.   end,
  34.   mouse_drag = function(button, x, y)
  35.     mouse.x, mouse.y = x, y
  36.     mouse.isDown = true
  37.     mouse.dragX, mouse.dragY = x, y
  38.   end,
  39.  
  40.   key = function(key)
  41.     keyboard[keys.getName(key)] = true
  42.   end,
  43.   key_up = function(key)
  44.     keyboard[keys.getName(key)] = false
  45.   end,
  46.   char = function(char)
  47.     keyboard.lastChar = char
  48.     keyboard.newChar = true
  49.   end
  50. }
  51.  
  52. -- DYNAMIC LIGHT MODULE
  53. dynamicLight = {}
  54. dynamicLight.positions = {
  55.   [0] = {0, -1}, {1, 1}, {1, 0}, {1, -1}, {0, -1}, {-1, -1}, {-1, 0}, {-1, 1}, {0, 1}
  56. }
  57. dynamicLight.lightPixel = function(self, x, y)
  58.   local degree = math.deg(math.atan2(self.lightSource.x-x, self.lightSource.y-y))+180
  59.   local eightDegree = math.floor(degree/45)
  60.  
  61.   local tileX, tileY = x-dynamicLight.positions[eightDegree][1], y-dynamicLight.positions[eightDegree][2]
  62.   if not (self.light[tileX] and self[tileX] and self[tileX][tileY]) then return end
  63.   if self[tileX] and self[x] then
  64.     if self.light[tileX][tileY] == true and not self[tileX][tileY].solid then
  65.       self.light[x][y] = true
  66.     else
  67.       self.light[x][y] = false
  68.     end
  69.   end
  70. end
  71.  
  72.  
  73. -- ELEMENT MODULE
  74. moveTo = function(self, tilemap, xmove, ymove)
  75.   local canMove = true
  76.   for x = 1, self.w do
  77.     for y = 1, self.h do
  78.       local moveToX = self.x+xmove+y-1
  79.       local moveToY = self.y+ymove+y-1
  80.       if moveToX < 1 or moveToX > width or moveToY < 1 or moveToY > height then canMove = false end
  81.       local tile = tilemap:getTile(moveToX, moveToY)
  82.       if (not tile) or tile.solid then canMove = false end
  83.     end
  84.   end
  85.   if canMove then
  86.     self.x = self.x + xmove
  87.     self.y = self.y + ymove
  88.   end
  89. end
  90. isBoxClicked = function(box)
  91.   return mouse.isDown and box.x<=mouse.x and box.y<=mouse.y and box.x+box.w>mouse.x and box.y+box.h>mouse.y
  92. end
  93. newElement = function(elementTab)
  94.   return function(tab)
  95.     return setmetatable(
  96.       tab,
  97.       {
  98.         __index = elementTab
  99.       }
  100.     )
  101.   end
  102. end
  103. elements = {
  104.   tilemap = newElement({
  105.     generated = false,
  106.     getTile = function(self, x, y)
  107.       if self[x] then
  108.         return self[x][y]
  109.       else
  110.         return {}
  111.       end
  112.     end,
  113.     setTile = function(self, x, y, tile)
  114.       if not self[x] then self[x] = {} end
  115.       self[x][y] = self.tileset[tile]
  116.       self[x][y].tile = tile
  117.     end,
  118.     setRectangle = function(self, rx, ry, w, h, tile)
  119.       for x = rx, rx+w do
  120.         for y = ry, ry+h do
  121.           self:setTile(x, y, tile)
  122.         end
  123.       end
  124.     end,
  125.     [1] = {},
  126.     light = {},
  127.     lightUpdateTime = 7,
  128.     DRAW = function(self)
  129.       for y = 1, #self[1] do
  130.         term.setCursorPos(1, y)
  131.         for x = 1, #self do
  132.           local tile = self[x][y]
  133.           if tile then
  134.             if self.dynamicLight and not tile.solid and not self.light[x][y] then
  135.               term.setBackgroundColor(colors.black)
  136.               term.write(" ")
  137.             else
  138.               term.setBackgroundColor(tile.bc)
  139.               term.setTextColor(tile.tc)
  140.               term.write(tile.char)
  141.             end
  142.           else
  143.             term.write(" ")
  144.           end
  145.         end
  146.       end
  147.     end,
  148.     UPDATE = function(self)
  149.       if self.generate and not self.generated then
  150.         self:generate()
  151.         self.generated = true
  152.         if self.dynamicLight then
  153.           for x = 1, #self do
  154.             self.light[x] = {}
  155.           end
  156.         end
  157.       end
  158.       if self.dynamicLight then
  159.         for x = 1, 3 do
  160.           for y = 1, 3 do
  161.             if self.light[self.lightSource.x+x-2] then
  162.               self.light[self.lightSource.x+x-2][self.lightSource.y+y-2] = true
  163.             end
  164.           end
  165.         end
  166.  
  167.         for i = 1, self.lightUpdateTime do
  168.           for x = 1, #self do
  169.             for y = 1, #self[1] do
  170.               dynamicLight.lightPixel(self, x, y)
  171.             end
  172.           end
  173.         end
  174.       end
  175.     end
  176.   }),
  177.   button = newElement({
  178.     UPDATE = function(self)
  179.       if isBoxClicked(self) then
  180.         if not self.clicked and self.clickedFunction then self:clickedFunction() end
  181.         self.clicked = true
  182.       else
  183.         self.clicked = false
  184.       end
  185.     end,
  186.     DRAW = function(self)
  187.       if self.clicked then
  188.         term.setBackgroundColor(colors.white)
  189.         term.setTextColor(colors.lightGray)
  190.       else
  191.         term.setBackgroundColor(colors.lightGray)
  192.         term.setTextColor(colors.gray)
  193.       end
  194.       paintutils.drawFilledBox(self.x, self.y, self.w+self.x-1, self.h+self.y-1)
  195.       term.setCursorPos(self.x+self.w/2-#self.label/2, self.y+self.h/2)
  196.       term.write(self.label)
  197.     end
  198.   }),
  199.   sprite = newElement({
  200.     path = "",
  201.     DRAW = function(self)
  202.       if not self.image then
  203.         self.image = paintutils.loadImage(self.path)
  204.         self.w = #self.image[1]
  205.         self.h = #self.image
  206.       end
  207.       paintutils.drawImage(self.image, self.x, self.y)
  208.     end
  209.   }),
  210.   template = newElement({
  211.     UPDATE = function(self)
  212.     end,
  213.     DRAW = function(self)
  214.     end
  215.   }),
  216. }
  217.  
  218.  
  219. -- LIFECYCLE FUNCTIONS
  220. lastUpdate = os.clock()
  221. runProtected = function(func)
  222.   local succ, mess = pcall(func)
  223.   if not succ then
  224.     quit(mess)
  225.   end
  226. end
  227. update = function(elements, wantedDt, func)
  228.   runProtected(function()
  229.   local timer = os.startTimer(wantedDt)
  230.   local event, var1, var2, var3 = os.pullEventRaw()
  231.   if event == "terminate" then quit(true) end
  232.   os.cancelTimer(timer)
  233.  
  234.   if event ~= "mouse_drag" then mouse.isDragged = false end
  235.   if event ~= "char" then keyboard.newChar = false end
  236.   if eventHandler[event] then eventHandler[event](var1, var2, var3) end
  237.  
  238.   if os.clock()-lastUpdate >= wantedDt then
  239.     for elementName, element in pairs(elements) do
  240.       if element.UPDATE then
  241.         element:UPDATE()
  242.       end
  243.       if element.update then
  244.         element:update()
  245.       end
  246.     end
  247.     if func then func() end
  248.     lastUpdate = os.clock()
  249.   end
  250.   end)
  251. end
  252. buffer = window.create(term.current(), 1, 1, width, height)
  253. draw = function(elements, func)
  254.   runProtected(function()
  255.   buffer.setVisible(false)
  256.   local oldterm = term.redirect(buffer)
  257.   term.setBackgroundColor(colors.black)
  258.   term.clear()
  259.   for elementName, element in pairs(elements) do
  260.     if element.DRAW then
  261.       element:DRAW()
  262.     end
  263.     if element.draw then
  264.       element:draw()
  265.     end
  266.   end
  267.   if func then func() end
  268.   buffer.setVisible(true)
  269.   term.redirect(oldterm)
  270.   end)
  271. end
  272. quit = function(hard)
  273.   buffer.setVisible(true)
  274.   term.setBackgroundColor(colors.black)
  275.   term.setTextColor(colors.yellow)
  276.   term.clear()
  277.   term.setCursorPos(1, 1)
  278.   print("Thanks for using the Pinwyn Game Engine by Jummit!")
  279.   if type(hard) == "string" then
  280.     print("The game crashed! Here is the error:")
  281.     term.setTextColor(colors.red)
  282.     print(hard)
  283.   elseif hard then
  284.     print("The game was forcefully closed")
  285.   else
  286.     print("The game was closed without any errors")
  287.   end
  288.   error()
  289. end
  290.  
  291. engine=getfenv()
  292. -- Game Codeos.loadAPI("engine")
  293.  
  294. elements = {
  295.   player = {
  296.     fruits = 0,
  297.     path = "player.nfp",
  298.     x = 5, y = 5, w = 1, h = 1,
  299.     moves = {
  300.       up =  {0, -1},
  301.       down= {0,  1},
  302.       left= {-1, 0},
  303.       right={1,  0}
  304.     },
  305.     draw = function(self)
  306.       term.setBackgroundColor(colors.lightBlue)
  307.       term.setTextColor(colors.blue)
  308.       term.setCursorPos(1, 1)
  309.       term.write("Fruits collected: "..self.fruits)
  310.       paintutils.drawPixel(self.x, self.y, colors.blue)
  311.     end,
  312.     update = function(self)
  313.       for key, move in pairs(self.moves) do
  314.         if engine.keyboard[key] then
  315.           engine.moveTo(self, elements.tilemap, move[1], move[2])
  316.         end
  317.       end
  318.       elements.tilemap.lightSource.x = self.x
  319.       elements.tilemap.lightSource.y = self.y
  320.       if elements.tilemap[self.x] and elements.tilemap[self.x][self.y].tile == "fruit" then
  321.         elements.tilemap:setTile(self.x, self.y, "floor")
  322.         self.fruits = self.fruits + 1
  323.         while true do
  324.           local fx, fy = math.random(1, engine.width), math.random(1, engine.height)
  325.           if elements.tilemap:getTile(fx, fy).tile == "floor" then
  326.             elements.tilemap:setTile(fx, fy, "fruit")
  327.             break
  328.           end
  329.         end
  330.       end
  331.     end
  332.   },
  333.   --[[cow = {
  334.     x = 5, y = 10, w = 1, h = 1, move = {1, 0}, isMoving = true,
  335.     draw = function(self)
  336.       paintutils.drawPixel(self.x, self.y, colors.black)
  337.     end,
  338.     update = function(self)
  339.       if math.random(1, 10) == 1 then self.isMoving = not self.isMoving end
  340.       if math.random(1, 10) == 1 then self.move[math.random(1, 2)] = math.random(0, 1) end
  341.     end
  342.   },]]
  343.   tilemap = engine.elements.tilemap({
  344.     dynamicLight = false,
  345.     lightUpdateTime=1,
  346.     lightSource = {x=3, y=3},
  347.     tileset = {
  348.       floor = {bc=colors.green,tc=colors.gray,char=" "},
  349.       grass = {bc=colors.green,tc=colors.lime,char="\""},
  350.       wall = {bc=colors.gray,tc=colors.lightGray,char=" ",solid=true},
  351.       fruit = {bc=colors.red,tc=colors.orange,char="o",solid=false}
  352.     },
  353.     generate = function(self)
  354.       elements.tilemap:setRectangle(1, 1, engine.width, engine.height, "floor")
  355.       for x = 1, 20 do
  356.         self:setTile(math.random(1, engine.width), math.random(1, engine.height), "fruit")
  357.       end
  358.       for x = 1, #self do
  359.         for y = 1, #self[x] do
  360.           if math.random(1, 10) == 1 then
  361.             self:setTile(x, y, "grass")
  362.           end
  363.         end
  364.       end
  365.       for i = 1, 10 do
  366.         elements.tilemap:setRectangle(math.random(1, engine.width-4), math.random(1, engine.height-3), 3, 2, "wall")
  367.       end
  368.     end
  369.   })
  370. }
  371.  
  372. while not exit do
  373.   engine.update(elements, 0.06, function()
  374.     if engine.keyboard.q then exit = true end
  375.   end)
  376.   engine.draw(elements)
  377. end
  378. engine.quit()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement