MegaLoler

Love Game Engine

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