Advertisement
MegaLoler

Love Game Engine

Apr 8th, 2013
178
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. --[[
  2.  
  3. engine.lua
  4. Version: 1.2
  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 = 1
  97.     self.fadeSpeed = 0.5
  98.     self.fadeColor = {255, 255, 255}
  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:setScene(scene, ...)
  129.     if self.scene then self.scene:destroy() end
  130.     self.scene = scene:new(self)
  131.     self:positionScene()
  132.     self.scene:setup(...)
  133. end
  134.  
  135. function engine.Engine:toggleFullscreen()
  136.     love.graphics.toggleFullscreen()
  137. end
  138.  
  139. -- Wrapped Love functions
  140.  
  141. function engine.Engine:load()
  142.     self:setup()
  143. end
  144.  
  145. function engine.Engine:quit()
  146. end
  147.  
  148. function engine.Engine:focus(f)
  149.     self.focused = f
  150. end
  151.  
  152. function engine.Engine:keypressed(key, unicode)
  153.     self.scene:onkeypressed(key, unicode)
  154. end
  155.  
  156. function engine.Engine:keyreleased(key)
  157.     self.scene:onkeyreleased(key)
  158. end
  159.  
  160. function engine.Engine:mousepressed(x, y, button)
  161.     self.scene:onmousepressed(x, y, button)
  162. end
  163.  
  164. function engine.Engine:mousereleased(x, y, button)
  165.     self.scene:onmousereleased(x, y, button)
  166. end
  167.  
  168. function engine.Engine:update(dt)
  169.     if self.fading then
  170.         if self.fade >= 1 then
  171.             self.fade = 1
  172.             self.fading = false
  173.             self:setScene(self.fadeTo, self.fadeArgs)
  174.         else
  175.             self.fade = self.fade + self.fadeSpeed * dt
  176.             if self.fade > 1 then self.fade = 1 end
  177.         end
  178.     else
  179.         if self.fade <= 0 then
  180.             self.fade = 0
  181.         else
  182.             self.fade = self.fade - self.fadeSpeed * dt
  183.             if self.fade < 0 then self.fade = 0 end
  184.         end
  185.     end
  186.     self.scene:masterUpdate(dt)
  187. end
  188.  
  189. function engine.Engine:draw()
  190.     self.scene:render()
  191.     love.graphics.setCanvas()
  192.     self.scene:postRender()
  193.     self:drawFade()
  194. end
  195.  
  196. -- Private methods
  197.  
  198. function engine.Engine:positionScene()
  199.     self.scene:setPosition(self.width / 2, self.height / 2)
  200. end
  201.  
  202. function engine.Engine:drawFade()
  203.     love.graphics.setBlendMode("alpha")
  204.     love.graphics.setColor(self.fadeColor[1], self.fadeColor[2], self.fadeColor[3], (math.cos((1 - self.fade) * math.pi) + 1) * 127)
  205.     love.graphics.polygon("fill", 0, 0, self.width, 0, self.width, self.height, 0, self.height)
  206. end
  207.  
  208. -- Virtual methods
  209.  
  210. function engine.Engine:setup()
  211. end
  212.  
  213. -- Entity class
  214.  
  215. engine.Entity = newClass()
  216.  
  217. function engine.Entity:init(engine, container)
  218.     self.engine = engine
  219.     self.container = container
  220.     self:setSize()
  221.     self:setPosition()
  222.     self:setOrientation()
  223.     self:setScale()
  224.     self:setColor()
  225.     self.backgroundAlpha = 255
  226.     self.alpha = 255
  227.     self:setBackgroundColor()
  228.     self.children = {}
  229.     self.selectable = false
  230.     self.selected = false
  231.     self.clearCanvas = true
  232.     self.hasBackground = false
  233.     self.staticDrawing = true
  234.     self.refreshRequested = true
  235. end
  236.  
  237. -- Entity methods
  238.  
  239. function engine.Entity:addChild(child, ...)
  240.     table.insert(self.children, child)
  241.     child:setup(...)
  242. end
  243.  
  244. function engine.Entity:removeChild(child)
  245.     table.remove(self.children, child)
  246.     child:destroy()
  247. end
  248.  
  249. function engine.Entity:refresh()
  250.     self.refreshRequested = true
  251. end
  252.  
  253. function engine.Entity:setColor(color)
  254.     self.color = color or {255, 255, 255}
  255. end
  256.  
  257. function engine.Entity:setBackgroundColor(color)
  258.     local r, g, b = love.graphics.getBackgroundColor()
  259.     self.backgroundColor = color or {r, g, b}
  260. end
  261.  
  262. function engine.Entity:setPosition(x, y)
  263.     local dx = self.engine.width / 2
  264.     local dy = self.engine.height / 2
  265.     if self.container then
  266.         dx = self.container.width / 2
  267.         dy = self.container.height / 2
  268.     end
  269.     self.x = x or dx
  270.     self.y = y or dy
  271. end
  272.  
  273. function engine.Entity:move(x, y)
  274.     self.x = self.x + x
  275.     self.y = self.y + y
  276. end
  277.  
  278. function engine.Entity:setOrientation(r)
  279.     self.orientation = r or 0
  280. end
  281.  
  282. function engine.Entity:setScale(x, y)
  283.     self.scaleX = x or 1
  284.     self.scaleY = y or 1
  285. end
  286.  
  287. function engine.Entity:setSize(width, height)
  288.     self.width = width or self.engine.width
  289.     self.height = height or self.engine.height
  290.     self.canvas = love.graphics.newCanvas(self.width, self.height)
  291. end
  292.  
  293. function engine.Entity:masterUpdate(dt)
  294.     for k, v in pairs(self.children) do
  295.         v:masterUpdate(dt)
  296.     end
  297.     self:update(dt)
  298. end
  299.  
  300. function engine.Entity:render()
  301.     if not self.staticDrawing or self.refreshRequested then
  302.         self.refreshRequested = false
  303.         love.graphics.setCanvas(self.canvas)
  304.         if self.clearCanvas then self.canvas:clear() end
  305.         if self.hasBackground then
  306.             love.graphics.setColor(self.backgroundColor[1], self.backgroundColor[2], self.backgroundColor[3], self.backgroundAlpha)
  307.             love.graphics.setBlendMode("alpha")
  308.             love.graphics.polygon("fill", 0, 0, self.width, 0, self.width, self.height, 0, self.height)
  309.         end
  310.        
  311.         self:preDraw()
  312.        
  313.         for k, v in pairs(self.children) do
  314.             v:render()
  315.             love.graphics.setCanvas(self.canvas)
  316.             v:postRender()
  317.         end
  318.        
  319.         self:draw()
  320.     end
  321. end
  322.  
  323. function engine.Entity:postRender()
  324.     love.graphics.setBlendMode("alpha")
  325.     love.graphics.setColor(self.color[1], self.color[2], self.color[3], self.alpha)
  326.     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)
  327. end
  328.  
  329. function engine.Entity:onkeypressed(key, unicode)
  330.     self:keypressed(key, unicode)
  331.     if self.selectedChild then self.selectedChild:onkeypressed(key, unicode) end
  332. end
  333.  
  334. function engine.Entity:onkeyreleased(key)
  335.     self:keyreleased(key)
  336.     if self.selectedChild then self.selectedChild:onkeyreleased(key) end
  337. end
  338.  
  339. function engine.Entity:onmousepressed(x, y, button)
  340.     local oldSelectedChild = self.selectedChild
  341.     self:mousepressed(x, y, button)
  342.     if self.selectedChild then self.selectedChild.selected = false end
  343.     self.selectedChild = self:getChildAtLocation(x, y)
  344.     if self.selectedChild and not self.selectedChild.selectable then self.selectedChild = nil end
  345.     if self.selectedChild then
  346.         self.selectedChild.selected = true
  347.         x, y = self:localCoordsToChildCoords(x, y, self.selectedChild)
  348.         self.selectedChild:onmousepressed(x, y, button)
  349.     end
  350.     if self.selectedChild ~= oldSelectedChild then
  351.         if oldSelectedChild then oldSelectedChild:focus(false) end
  352.         if self.selectedChild then self.selectedChild:focus(true) end
  353.     end
  354. end
  355.  
  356. function engine.Entity:onmousereleased(x, y, button)
  357.     self:mousereleased(x, y, button)
  358.     if self.selectedChild then
  359.         x, y = self:localCoordsToChildCoords(x, y, self.selectedChild)
  360.         self.selectedChild:onmousereleased(x, y, button)
  361.         if self.selectedChild:inBounds(x, y) then self.selectedChild:mouseclicked(x, y, button) end
  362.     end
  363. end
  364.  
  365. -- Private methods
  366.  
  367. function engine.Entity:inBounds(x, y)
  368.     return x >= 0 and x < self.width and y >= 0 and y < self.height
  369. end
  370.  
  371. function engine.Entity:getChildAtLocation(x, y)
  372.     for i = 1, #self.children do
  373.         local child = self.children[#self.children - (i - 1)]
  374.         local cx, cy = self:localCoordsToChildCoords(x, y, child)
  375.         if child:inBounds(cx, cy) then return child end
  376.     end
  377. end
  378.  
  379. function engine.Entity:localCoordsToChildCoords(x, y, child)
  380.     x = (x - child.x) / child.scaleX
  381.     y = (y - child.y) / child.scaleY
  382.    
  383.     distance = math.sqrt((x * x) + (y * y))
  384.     angle = math.atan2(y, x) - child.orientation
  385.    
  386.     x = math.cos(angle) * distance
  387.     y = math.sin(angle) * distance
  388.    
  389.     x = x + child.width / 2
  390.     y = y + child.height / 2
  391.    
  392.     return x, y
  393. end
  394.  
  395. -- Virtual methods
  396.  
  397. function engine.Entity:setup(...)
  398. end
  399.  
  400. function engine.Entity:destroy()
  401. end
  402.  
  403. function engine.Entity:focus(f)
  404. end
  405.  
  406. function engine.Entity:keypressed(key, unicode)
  407. end
  408.  
  409. function engine.Entity:keyreleased(key)
  410. end
  411.  
  412. function engine.Entity:mousepressed(x, y, button)
  413. end
  414.  
  415. function engine.Entity:mousereleased(x, y, button)
  416. end
  417.  
  418. function engine.Entity:mouseclicked(x, y, button)
  419. end
  420.  
  421. function engine.Entity:update(dt)
  422. end
  423.  
  424. function engine.Entity:preDraw()
  425. end
  426.  
  427. function engine.Entity:draw()
  428. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement