Advertisement
MegaLoler

Love Game Engine

Apr 8th, 2013
95
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. --[[
  2.  
  3. engine.lua
  4. Version: 1.1
  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. --]]
  40.  
  41. require("class")
  42.  
  43. engine = {} -- Engine package
  44.  
  45. -- Love wrappers
  46.  
  47. function love.load()
  48.     engine.game:load()
  49. end
  50.  
  51. function love.quit()
  52.     engine.game:quit()
  53. end
  54.  
  55. function love.focus(f)
  56.     engine.game:focus(f)
  57. end
  58.  
  59. function love.keypressed(key, unicode)
  60.     engine.game:keypressed(key, unicode)
  61. end
  62.  
  63. function love.keyreleased(key)
  64.     engine.game:keyreleased(key)
  65. end
  66.  
  67. function love.mousepressed(x, y, button)
  68.     engine.game:mousepressed(x, y, button)
  69. end
  70.  
  71. function love.mousereleased(x, y, button)
  72.     engine.game:mousereleased(x, y, button)
  73. end
  74.  
  75. function love.update(dt)
  76.     engine.game:update(dt)
  77. end
  78.  
  79. function love.draw()
  80.     engine.game:draw()
  81. end
  82.  
  83. -- Engine class
  84.  
  85. engine.Engine = newClass()
  86.  
  87. function engine.Engine:init()
  88.     self:setSize()
  89.     self:setTitle()
  90.     self.focused = true
  91.     self.fading = false
  92.     self.fade = 1
  93.     self.fadeSpeed = 0.5
  94.     self.fadeColor = {255, 255, 255}
  95.     self:setScene(engine.Entity)
  96. end
  97.  
  98. -- Sets the engine subclass to load
  99.  
  100. function engine.Engine:setGame()
  101.     engine.game = self:new()
  102. end
  103.  
  104. -- Engine methods
  105.  
  106. function engine.Engine:setTitle(title)
  107.     self.title = title or "Game Engine"
  108.     love.graphics.setCaption(self.title)
  109. end
  110.  
  111. function engine.Engine:setSize(width, height)
  112.     self.width = width or 640
  113.     self.height = height or 480
  114.     love.graphics.setMode(self.width, self.height)
  115.     if self.scene then self:positionScene() end
  116. end
  117.  
  118. function engine.Engine:fadeToScene(scene, ...)
  119.     self.fadeTo = scene
  120.     self.fadeArgs = ...
  121.     self.fading = true
  122. end
  123.  
  124. function engine.Engine:setScene(scene, ...)
  125.     if self.scene then self.scene:destroy() end
  126.     self.scene = scene:new(self)
  127.     self:positionScene()
  128.     self.scene:setup(...)
  129. end
  130.  
  131. function engine.Engine:toggleFullscreen()
  132.     love.graphics.toggleFullscreen()
  133. end
  134.  
  135. -- Wrapped Love functions
  136.  
  137. function engine.Engine:load()
  138.     self:setup()
  139. end
  140.  
  141. function engine.Engine:quit()
  142. end
  143.  
  144. function engine.Engine:focus(f)
  145.     self.focused = f
  146. end
  147.  
  148. function engine.Engine:keypressed(key, unicode)
  149.     self.scene:onkeypressed(key, unicode)
  150. end
  151.  
  152. function engine.Engine:keyreleased(key)
  153.     self.scene:onkeyreleased(key)
  154. end
  155.  
  156. function engine.Engine:mousepressed(x, y, button)
  157.     self.scene:onmousepressed(x, y, button)
  158. end
  159.  
  160. function engine.Engine:mousereleased(x, y, button)
  161.     self.scene:onmousereleased(x, y, button)
  162. end
  163.  
  164. function engine.Engine:update(dt)
  165.     if self.fading then
  166.         if self.fade >= 1 then
  167.             self.fade = 1
  168.             self.fading = false
  169.             self:setScene(self.fadeTo, self.fadeArgs)
  170.         else
  171.             self.fade = self.fade + self.fadeSpeed * dt
  172.             if self.fade > 1 then self.fade = 1 end
  173.         end
  174.     else
  175.         if self.fade <= 0 then
  176.             self.fade = 0
  177.         else
  178.             self.fade = self.fade - self.fadeSpeed * dt
  179.             if self.fade < 0 then self.fade = 0 end
  180.         end
  181.     end
  182.     self.scene:masterUpdate(dt)
  183. end
  184.  
  185. function engine.Engine:draw()
  186.     self.scene:render()
  187.     love.graphics.setCanvas()
  188.     self.scene:postRender()
  189.     self:drawFade()
  190. end
  191.  
  192. -- Private methods
  193.  
  194. function engine.Engine:positionScene()
  195.     self.scene:setPosition(self.width / 2, self.height / 2)
  196. end
  197.  
  198. function engine.Engine:drawFade()
  199.     love.graphics.setBlendMode("alpha")
  200.     love.graphics.setColor(self.fadeColor[1], self.fadeColor[2], self.fadeColor[3], (math.cos((1 - self.fade) * math.pi) + 1) * 127)
  201.     love.graphics.polygon("fill", 0, 0, self.width, 0, self.width, self.height, 0, self.height)
  202. end
  203.  
  204. -- Virtual methods
  205.  
  206. function engine.Engine:setup()
  207. end
  208.  
  209. -- Entity class
  210.  
  211. engine.Entity = newClass()
  212.  
  213. function engine.Entity:init(engine)
  214.     self.engine = engine
  215.     self:setSize()
  216.     self:setPosition()
  217.     self:setOrientation()
  218.     self:setScale()
  219.     self:setColor()
  220.     self.children = {}
  221.     self.selectable = false
  222.     self.selected = false
  223. end
  224.  
  225. function engine.Entity:addChild(child, ...)
  226.     table.insert(self.children, child)
  227.     child:setup(...)
  228. end
  229.  
  230. function engine.Entity:removeChild(child)
  231.     table.remove(self.children, child)
  232.     child:destroy()
  233. end
  234.  
  235. function engine.Entity:setColor(color)
  236.     self.color = color or {255, 255, 255}
  237. end
  238.  
  239. function engine.Entity:setPosition(x, y)
  240.     self.x = x or 0
  241.     self.y = y or 0
  242. end
  243.  
  244. function engine.Entity:setOrientation(r)
  245.     self.orientation = r or 0
  246. end
  247.  
  248. function engine.Entity:setScale(x, y)
  249.     self.scaleX = x or 1
  250.     self.scaleY = y or 1
  251. end
  252.  
  253. function engine.Entity:setSize(width, height)
  254.     self.width = width or self.engine.width
  255.     self.height = height or self.engine.height
  256.     self.canvas = love.graphics.newCanvas(self.width, self.height)
  257. end
  258.  
  259. function engine.Entity:masterUpdate(dt)
  260.     for k, v in pairs(self.children) do
  261.         v:masterUpdate(dt)
  262.     end
  263.     self:update(dt)
  264. end
  265.  
  266. function engine.Entity:render()
  267.     love.graphics.setCanvas(self.canvas)
  268.     love.graphics.setColor(love.graphics.getBackgroundColor())
  269.     love.graphics.setBlendMode("alpha")
  270.     love.graphics.polygon("fill", 0, 0, self.width, 0, self.width, self.height, 0, self.height)
  271.    
  272.     self:preDraw()
  273.    
  274.     for k, v in pairs(self.children) do
  275.         v:render()
  276.         love.graphics.setCanvas(self.canvas)
  277.         v:postRender()
  278.     end
  279.    
  280.     self:draw()
  281. end
  282.  
  283. function engine.Entity:postRender()
  284.     love.graphics.setBlendMode("alpha")
  285.     love.graphics.setColor(self.color[1], self.color[2], self.color[3])
  286.     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.width / 2, self.height / 2)
  287. end
  288.  
  289. function engine.Entity:onkeypressed(key, unicode)
  290.     self:keypressed(key, unicode)
  291.     if self.selectedChild then self.selectedChild:onkeypressed(key, unicode) end
  292. end
  293.  
  294. function engine.Entity:onkeyreleased(key)
  295.     self:keyreleased(key)
  296.     if self.selectedChild then self.selectedChild:onkeyreleased(key) end
  297. end
  298.  
  299. function engine.Entity:onmousepressed(x, y, button)
  300.     self:mousepressed(x, y, button)
  301.     if self.selectedChild then self.selectedChild.selected = false end
  302.     self.selectedChild = self:getChildAtLocation(x, y)
  303.     if self.selectedChild and not self.selectedChild.selectable then self.selectedChild = nil end
  304.     if self.selectedChild then
  305.         self.selectedChild.selected = true
  306.         x, y = self:localCoordsToChildCoords(x, y, self.selectedChild)
  307.         self.selectedChild:onmousepressed(x, y, button)
  308.     end
  309. end
  310.  
  311. function engine.Entity:onmousereleased(x, y, button)
  312.     self:mousereleased(x, y, button)
  313.     if self.selectedChild then
  314.         x, y = self:localCoordsToChildCoords(x, y, self.selectedChild)
  315.         self.selectedChild:onmousereleased(x, y, button)
  316.     end
  317. end
  318.  
  319. -- Private methods
  320.  
  321. function engine.Entity:inBounds(x, y)
  322.     return x >= 0 and x < self.width and y >= 0 and y < self.height
  323. end
  324.  
  325. function engine.Entity:getChildAtLocation(x, y)
  326.     for i = 1, #self.children do
  327.         local child = self.children[#self.children - (i - 1)]
  328.         local cx, cy = self:localCoordsToChildCoords(x, y, child)
  329.         if child:inBounds(cx, cy) then return child end
  330.     end
  331. end
  332.  
  333. function engine.Entity:localCoordsToChildCoords(x, y, child)
  334.     x = (x - child.x) / child.scaleX
  335.     y = (y - child.y) / child.scaleY
  336.    
  337.     distance = math.sqrt((x * x) + (y * y))
  338.     angle = math.atan2(y, x) - child.orientation
  339.    
  340.     x = math.cos(angle) * distance
  341.     y = math.sin(angle) * distance
  342.    
  343.     x = x + child.width / 2
  344.     y = y + child.height / 2
  345.    
  346.     return x, y
  347. end
  348.  
  349. -- Virtual methods
  350.  
  351. function engine.Entity:setup(...)
  352. end
  353.  
  354. function engine.Entity:destroy()
  355. end
  356.  
  357. function engine.Entity:keypressed(key, unicode)
  358. end
  359.  
  360. function engine.Entity:keyreleased(key)
  361. end
  362.  
  363. function engine.Entity:mousepressed(x, y, button)
  364. end
  365.  
  366. function engine.Entity:mousereleased(x, y, button)
  367. end
  368.  
  369. function engine.Entity:update(dt)
  370. end
  371.  
  372. function engine.Entity:preDraw()
  373. end
  374.  
  375. function engine.Entity:draw()
  376. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement