Advertisement
MegaLoler

Love Game Engine

Apr 9th, 2013
169
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. --[[
  2.  
  3. engine.lua
  4. Version: 1.3
  5.  
  6. Author: MegaLoler
  7. Email: megaloler9000@gmail.com
  8.  
  9. A game engine for Love that manages game scenes and entities.
  10.  
  11. If requires that you use the class.lua file:
  12. require("class.lua")
  13.  
  14. Make sure you have this in your code:
  15. require("engine.lua")
  16.  
  17. Create a game by creating a subclass of the Engine class.
  18. MyGame = engine.newClass(engine.Engine)
  19.  
  20. Define the setup method:
  21. function MyGame:setup()
  22.     -- Initalize your game here.
  23. end
  24.  
  25. Make sure to call the setGame function of your game class in your main.lua:
  26. MyGame:setGame()  -- This will make the game engine take over.
  27.  
  28. Create a scene by subclassing the Entity class:
  29. TestScene = newClass(engine.Entity)
  30.  
  31. Define the setup, update, draw, and any other methods that you wish:
  32. function TestScene:setup() ... end
  33. function TestScene:update(dt) ... end
  34. function TestScene:draw() ... end
  35.  
  36. Call the setScene method somewhere in your game's setup method to set the inital scene on launch:
  37. self:setScene(TestScene) -- Pass the class itself, not an instance of it
  38.  
  39. Add children entities to a scene or entity preferably in its setup method with the addChild method:
  40. local child = TestEntity:new(self.engine, self) -- Parameters are game engine and parent entity
  41. self:addChild(child)
  42.  
  43. --]]
  44.  
  45. require("class")
  46.  
  47. engine = {} -- Engine package
  48.  
  49. -- Love wrappers
  50.  
  51. function love.load()
  52.     engine.game:load()
  53. end
  54.  
  55. function love.quit()
  56.     engine.game:quit()
  57. end
  58.  
  59. function love.focus(f)
  60.     engine.game:focus(f)
  61. end
  62.  
  63. function love.keypressed(key, unicode)
  64.     engine.game:keypressed(key, unicode)
  65. end
  66.  
  67. function love.keyreleased(key)
  68.     engine.game:keyreleased(key)
  69. end
  70.  
  71. function love.mousepressed(x, y, button)
  72.     engine.game:mousepressed(x, y, button)
  73. end
  74.  
  75. function love.mousereleased(x, y, button)
  76.     engine.game:mousereleased(x, y, button)
  77. end
  78.  
  79. function love.update(dt)
  80.     engine.game:update(dt)
  81. end
  82.  
  83. function love.draw()
  84.     engine.game:draw()
  85. end
  86.  
  87. -- Engine class
  88.  
  89. engine.Engine = newClass()
  90.  
  91. function engine.Engine:init()
  92.     self:setSize()
  93.     self:setTitle()
  94.     self.focused = true
  95.     self.fading = false
  96.     self.fade = 0
  97.     self.fadeSpeed = 2
  98.     self:setFadeColor()
  99.     self:setScene(engine.Entity)
  100. end
  101.  
  102. -- Sets the engine subclass to load
  103.  
  104. function engine.Engine:setGame()
  105.     engine.game = self:new()
  106. end
  107.  
  108. -- Engine methods
  109.  
  110. function engine.Engine:setTitle(title)
  111.     self.title = title or "Game Engine"
  112.     love.graphics.setCaption(self.title)
  113. end
  114.  
  115. function engine.Engine:setSize(width, height)
  116.     self.width = width or 640
  117.     self.height = height or 480
  118.     love.graphics.setMode(self.width, self.height)
  119.     if self.scene then self:positionScene() end
  120. end
  121.  
  122. function engine.Engine:fadeToScene(scene, ...)
  123.     self.fadeTo = scene
  124.     self.fadeArgs = ...
  125.     self.fading = true
  126. end
  127.  
  128. function engine.Engine:setFadeColor(color)
  129.     self.fadeColor = color or {0, 0, 0}
  130. end
  131.  
  132. function engine.Engine:setScene(scene, ...)
  133.     if self.scene then self.scene:destroy() end
  134.     self.scene = scene:new(self)
  135.     self:positionScene()
  136.     self.scene:setup(...)
  137. end
  138.  
  139. function engine.Engine:toggleFullscreen()
  140.     love.graphics.toggleFullscreen()
  141. end
  142.  
  143. -- Wrapped Love functions
  144.  
  145. function engine.Engine:load()
  146.     self:setup()
  147. end
  148.  
  149. function engine.Engine:quit()
  150. end
  151.  
  152. function engine.Engine:focus(f)
  153.     self.focused = f
  154. end
  155.  
  156. function engine.Engine:keypressed(key, unicode)
  157.     self.scene:onkeypressed(key, unicode)
  158. end
  159.  
  160. function engine.Engine:keyreleased(key)
  161.     self.scene:onkeyreleased(key)
  162. end
  163.  
  164. function engine.Engine:mousepressed(x, y, button)
  165.     self.scene:onmousepressed(x, y, button)
  166. end
  167.  
  168. function engine.Engine:mousereleased(x, y, button)
  169.     self.scene:onmousereleased(x, y, button)
  170. end
  171.  
  172. function engine.Engine:update(dt)
  173.     if self.fading then
  174.         if self.fade >= 1 then
  175.             self.fade = 1
  176.             self.fading = false
  177.             self:setScene(self.fadeTo, self.fadeArgs)
  178.         else
  179.             self.fade = self.fade + self.fadeSpeed * dt
  180.             if self.fade > 1 then self.fade = 1 end
  181.         end
  182.     else
  183.         if self.fade <= 0 then
  184.             self.fade = 0
  185.         else
  186.             self.fade = self.fade - self.fadeSpeed * dt
  187.             if self.fade < 0 then self.fade = 0 end
  188.         end
  189.     end
  190.     self.scene:masterUpdate(dt)
  191. end
  192.  
  193. function engine.Engine:draw()
  194.     self.scene:render()
  195.     love.graphics.setCanvas()
  196.     self.scene:postRender()
  197.     self:drawFade()
  198. end
  199.  
  200. -- Private methods
  201.  
  202. function engine.Engine:positionScene()
  203.     self.scene:setPosition(self.width / 2, self.height / 2)
  204. end
  205.  
  206. function engine.Engine:drawFade()
  207.     love.graphics.setBlendMode("alpha")
  208.     love.graphics.setColor(self.fadeColor[1], self.fadeColor[2], self.fadeColor[3], (math.cos((1 - self.fade) * math.pi) + 1) * 127)
  209.     love.graphics.polygon("fill", 0, 0, self.width, 0, self.width, self.height, 0, self.height)
  210. end
  211.  
  212. -- Virtual methods
  213.  
  214. function engine.Engine:setup()
  215. end
  216.  
  217. -- Entity class
  218.  
  219. engine.Entity = newClass()
  220.  
  221. function engine.Entity:init(engine, container)
  222.     self.engine = engine
  223.     self.container = container
  224.     self:setPosition()
  225.     self:setSize()
  226.     self:setOrientation()
  227.     self:setScale()
  228.     self:setColor()
  229.     self.backgroundAlpha = 255
  230.     self.alpha = 255
  231.     self:setBackgroundColor()
  232.     self.children = {}
  233.     self.selectable = false
  234.     self.selected = false
  235.     self.clearCanvas = true
  236.     self.hasBackground = false
  237.     self.staticDrawing = true
  238.     self.refreshRequested = true
  239.     self.tick = 0
  240.     self.time = 0
  241. end
  242.  
  243. -- Entity methods
  244.  
  245. function engine.Entity:addChild(child, ...)
  246.     table.insert(self.children, child)
  247.     child:setup(...)
  248. end
  249.  
  250. function engine.Entity:removeChild(child)
  251.     table.remove(self.children, child)
  252.     child:destroy()
  253. end
  254.  
  255. function engine.Entity:refresh()
  256.     self.refreshRequested = true
  257. end
  258.  
  259. function engine.Entity:setColor(color)
  260.     self.color = color or {255, 255, 255}
  261. end
  262.  
  263. function engine.Entity:setBackgroundColor(color)
  264.     local r, g, b = love.graphics.getBackgroundColor()
  265.     self.backgroundColor = color or {r, g, b}
  266. end
  267.  
  268. function engine.Entity:setPosition(x, y)
  269.     local dx = self.engine.width / 2
  270.     local dy = self.engine.height / 2
  271.     if self.container then
  272.         dx = self.container.width / 2
  273.         dy = self.container.height / 2
  274.     end
  275.     self.x = x or dx
  276.     self.y = y or dy
  277. end
  278.  
  279. function engine.Entity:move(x, y)
  280.     self.x = self.x + x
  281.     self.y = self.y + y
  282. end
  283.  
  284. function engine.Entity:setOrigin(x, y)
  285.     self.originX = x or self.width / 2
  286.     self.originY = y or self.height / 2
  287. end
  288.  
  289. function engine.Entity:setOrientation(r)
  290.     self.orientation = r or 0
  291. end
  292.  
  293. function engine.Entity:setScale(x, y)
  294.     self.scaleX = x or 1
  295.     self.scaleY = y or 1
  296. end
  297.  
  298. function engine.Entity:setSize(width, height)
  299.     self.width = width or self.engine.width
  300.     self.height = height or self.engine.height
  301.     self.canvas = love.graphics.newCanvas(self.width, self.height)
  302.     self:setOrigin()
  303. end
  304.  
  305. function engine.Entity:masterUpdate(dt)
  306.     self.time = self.time + dt
  307.     for k, v in pairs(self.children) do
  308.         v:masterUpdate(dt)
  309.     end
  310.     self:update(dt)
  311.     self.tick = self.tick + 1
  312. end
  313.  
  314. function engine.Entity:render()
  315.     if not self.staticDrawing or self.refreshRequested then
  316.         self.refreshRequested = false
  317.         love.graphics.setCanvas(self.canvas)
  318.         if self.clearCanvas then self.canvas:clear() end
  319.         if self.hasBackground then
  320.             love.graphics.setColor(self.backgroundColor[1], self.backgroundColor[2], self.backgroundColor[3], self.backgroundAlpha)
  321.             love.graphics.setBlendMode("alpha")
  322.             love.graphics.polygon("fill", 0, 0, self.width, 0, self.width, self.height, 0, self.height)
  323.         end
  324.        
  325.         self:preDraw()
  326.        
  327.         for k, v in pairs(self.children) do
  328.             v:render()
  329.             love.graphics.setCanvas(self.canvas)
  330.             v:postRender()
  331.         end
  332.        
  333.         self:draw()
  334.     end
  335. end
  336.  
  337. function engine.Entity:postRender()
  338.     love.graphics.setBlendMode("alpha")
  339.     love.graphics.setColor(self.color[1], self.color[2], self.color[3], self.alpha)
  340.     love.graphics.drawq(self.canvas, love.graphics.newQuad(0, 0, self.width, self.height, self.width, self.height), self.x, self.y , self.orientation, self.scaleX, self.scaleY, self.originX, self.originY)
  341. end
  342.  
  343. function engine.Entity:onkeypressed(key, unicode)
  344.     self:keypressed(key, unicode)
  345.     if self.selectedChild then self.selectedChild:onkeypressed(key, unicode) end
  346. end
  347.  
  348. function engine.Entity:onkeyreleased(key)
  349.     self:keyreleased(key)
  350.     if self.selectedChild then self.selectedChild:onkeyreleased(key) end
  351. end
  352.  
  353. function engine.Entity:onmousepressed(x, y, button)
  354.     local oldSelectedChild = self.selectedChild
  355.     self:mousepressed(x, y, button)
  356.     if self.selectedChild then self.selectedChild.selected = false end
  357.     self.selectedChild = self:getChildAtLocation(x, y)
  358.     if self.selectedChild and not self.selectedChild.selectable then self.selectedChild = nil end
  359.     if self.selectedChild then
  360.         self.selectedChild.selected = true
  361.         x, y = self:localCoordsToChildCoords(x, y, self.selectedChild)
  362.         self.selectedChild:onmousepressed(x, y, button)
  363.     end
  364.     if self.selectedChild ~= oldSelectedChild then
  365.         if oldSelectedChild then oldSelectedChild:focus(false) end
  366.         if self.selectedChild then self.selectedChild:focus(true) end
  367.     end
  368. end
  369.  
  370. function engine.Entity:onmousereleased(x, y, button)
  371.     self:mousereleased(x, y, button)
  372.     if self.selectedChild then
  373.         x, y = self:localCoordsToChildCoords(x, y, self.selectedChild)
  374.         self.selectedChild:onmousereleased(x, y, button)
  375.         if self.selectedChild:inBounds(x, y) then self.selectedChild:mouseclicked(x, y, button) end
  376.     end
  377. end
  378.  
  379. -- Private methods
  380.  
  381. function engine.Entity:inBounds(x, y)
  382.     return x >= 0 and x < self.width and y >= 0 and y < self.height
  383. end
  384.  
  385. function engine.Entity:getChildAtLocation(x, y)
  386.     for i = 1, #self.children do
  387.         local child = self.children[#self.children - (i - 1)]
  388.         local cx, cy = self:localCoordsToChildCoords(x, y, child)
  389.         if child:inBounds(cx, cy) then return child end
  390.     end
  391. end
  392.  
  393. function engine.Entity:localCoordsToChildCoords(x, y, child)
  394.     x = (x - child.x) / child.scaleX
  395.     y = (y - child.y) / child.scaleY
  396.    
  397.     distance = math.sqrt((x * x) + (y * y))
  398.     angle = math.atan2(y, x) - child.orientation
  399.    
  400.     x = math.cos(angle) * distance
  401.     y = math.sin(angle) * distance
  402.    
  403.     x = x + child.originX
  404.     y = y + child.originY
  405.    
  406.     return x, y
  407. end
  408.  
  409. -- Virtual methods
  410.  
  411. function engine.Entity:setup(...)
  412. end
  413.  
  414. function engine.Entity:destroy()
  415. end
  416.  
  417. function engine.Entity:focus(f)
  418. end
  419.  
  420. function engine.Entity:keypressed(key, unicode)
  421. end
  422.  
  423. function engine.Entity:keyreleased(key)
  424. end
  425.  
  426. function engine.Entity:mousepressed(x, y, button)
  427. end
  428.  
  429. function engine.Entity:mousereleased(x, y, button)
  430. end
  431.  
  432. function engine.Entity:mouseclicked(x, y, button)
  433. end
  434.  
  435. function engine.Entity:update(dt)
  436. end
  437.  
  438. function engine.Entity:preDraw()
  439. end
  440.  
  441. function engine.Entity:draw()
  442. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement