From d8ad342739d96b9c8180ae3b8cf482e085f17b9c Mon Sep 17 00:00:00 2001 From: Tim Anema Date: Mon, 8 Nov 2021 16:36:38 -0500 Subject: [PATCH] fixing light in the main list --- README.md | 16 +- examples/animation.lua | 5 +- examples/complex.lua | 3 - examples/short.lua | 15 +- examples/simple_tiled_impl.lua | 13 +- examples/vendor/list.lua | 193 +++++++++++++++++ main.lua | 375 +++++---------------------------- 7 files changed, 265 insertions(+), 355 deletions(-) create mode 100644 examples/vendor/list.lua diff --git a/README.md b/README.md index aabf2c5..795ec6e 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,14 @@ # light_world.lua - This is the light modeling done by Priorblue [here](https://bitbucket.org/PriorBlue/love2d-light-and-shadow-engine), -only it has been largely refactored and edited to allow for scaling and proper translation. + This is the light modeling done by Priorblue [here](https://bitbucket.org/PriorBlue/love2d-light-and-shadow-engine), +only it has been largely refactored and edited to allow for scaling and proper translation. *Supports love 11.2(master branch), 0.10.1(commit 414b9b74c0eb95bfb8b5e26a11caf2b32beccca0) - + ## Installation - + Copy and rename the lib folder into your project. - + ## How to use ```lua @@ -37,7 +37,7 @@ function love.draw() end ``` -For more information please check out the [wiki](https://github.com/tanema/light_world.lua/wiki) and see the examples directory to see how it is fully used. This project can be run with love to see the demonstrations in action. +For more information please check out the [wiki](https://github.com/tanema/light_world.lua/wiki) and see the examples directory to see how it is fully used. This project can be run with love to see the demonstrations in action. ### Gamera & HUMP There are example in the example directory how to use both of these with the library. @@ -61,14 +61,14 @@ There are example in the example directory how to use both of these with the lib * chromatic aberration [Preview](http://onepixelahead.de/love2d_polyshadow16.gif) * postshader with many included postshaders, plus easy to extend * animations in tandem with normal maps thanks to [anim8](https://github.com/kikito/anim8) - + ## License A License has been included in this project ## Contributors - Jon @xiejiangzhi -- Brandon Blanker Lim-it @flamendless +- Brandon Blanker Lim-it @flamendless - @Azorlogh - Gustavo Kishima @gukiboy - Rose L. Liverman @TangentFoxy diff --git a/examples/animation.lua b/examples/animation.lua index e1f3e31..f38a281 100644 --- a/examples/animation.lua +++ b/examples/animation.lua @@ -1,11 +1,8 @@ -- Example: Animation Example local LightWorld = require "lib" local anim8 = require 'lib.anim8' -local ProFi = require 'examples.vendor.ProFi' function love.load() - ProFi:start() - x, y, z, scale = 0, 0, 1, 1 -- load images image = love.graphics.newImage("examples/gfx/scott_pilgrim.png") @@ -83,7 +80,7 @@ function love.draw() love.graphics.setColor(255, 255, 255) love.graphics.rectangle("fill", -x/scale, -y/scale, love.graphics.getWidth()/scale, love.graphics.getHeight()/scale) animation:drawAnimation() - + animation2:draw(image, 200, 30) end) love.graphics.pop() diff --git a/examples/complex.lua b/examples/complex.lua index 9c1f483..2afeaef 100644 --- a/examples/complex.lua +++ b/examples/complex.lua @@ -1,6 +1,5 @@ -- Example: Complex Example local LightWorld = require "lib" -local ProFi = require 'examples.vendor.ProFi' function initScene() -- physic world @@ -30,8 +29,6 @@ function initScene() end function love.load() - ProFi:start() - love.graphics.setBackgroundColor(0, 0, 0) love.graphics.setDefaultFilter("nearest", "nearest") diff --git a/examples/short.lua b/examples/short.lua index 581509a..e88dc1c 100644 --- a/examples/short.lua +++ b/examples/short.lua @@ -1,10 +1,7 @@ -- Example: Short Example local LightWorld = require "lib" -local ProFi = require 'examples.vendor.ProFi' function love.load() - ProFi:start() - testShader = 0 x = 0 y = 0 @@ -34,9 +31,9 @@ function love.load() rectangleTest = lightWorld:newRectangle(512, 512, 64, 64) local px, py, pw, ph = 100, 200, 20, 50 polygonTest = lightWorld:newPolygon( - px, py, - px+pw, py, - px+pw, py+ph, + px, py, + px+pw, py, + px+pw, py+ph, px-50, py+ph) imageTest = lightWorld:newImage(image, 64, 64, 24, 6) @@ -104,7 +101,7 @@ function love.update(dt) x = x + dt * 200 end - + if love.keyboard.isDown("k") then polygonTest:move(0, -(dt * 200)) elseif love.keyboard.isDown("j") then @@ -124,7 +121,7 @@ function love.update(dt) if love.keyboard.isDown("s") then polygonTest:rotate(0.05) elseif love.keyboard.isDown("d") then - polygonTest:rotate(-0.05) + polygonTest:rotate(-0.05) end if love.keyboard.isDown("-") then @@ -132,7 +129,7 @@ function love.update(dt) elseif love.keyboard.isDown("=") then scale = scale + 0.01 end - + colorAberration = math.max(0.0, colorAberration - dt * 10.0) if colorAberration > 0.0 then lightWorld.post_shader:addEffect("blur", 2.0, 2.0) diff --git a/examples/simple_tiled_impl.lua b/examples/simple_tiled_impl.lua index 95005c2..3ef06bd 100644 --- a/examples/simple_tiled_impl.lua +++ b/examples/simple_tiled_impl.lua @@ -1,11 +1,8 @@ -- Example: STI Example local LightWorld = require "lib" local sti = require 'examples.vendor.sti' -local ProFi = require 'examples.vendor.ProFi' function love.load() - ProFi:start() - x = 0 y = 0 z = 1 @@ -26,13 +23,13 @@ function love.load() -- walls lightWorld:newRectangle(400, 32, 800, 64):setNormalMap(image_normal, 800, 64) - lightWorld:newRectangle(32, 272, 64, 416):setNormalMap(image_normal, 64, 416) - lightWorld:newRectangle(400, 464, 800, 32):setNormalMap(image_normal, 800, 32) - lightWorld:newRectangle(784, 272, 32, 416):setNormalMap(image_normal, 32, 416) + lightWorld:newRectangle(32, 272, 64, 416):setNormalMap(image_normal, 64, 416) + lightWorld:newRectangle(400, 464, 800, 32):setNormalMap(image_normal, 800, 32) + lightWorld:newRectangle(784, 272, 32, 416):setNormalMap(image_normal, 32, 416) --blocks - lightWorld:newRectangle(224, 256, 128, 124):setNormalMap(image_normal, 128, 124) - lightWorld:newRectangle(592, 224, 224, 64):setNormalMap(image_normal, 224, 64) + lightWorld:newRectangle(224, 256, 128, 124):setNormalMap(image_normal, 128, 124) + lightWorld:newRectangle(592, 224, 224, 64):setNormalMap(image_normal, 224, 64) end function love.update(dt) diff --git a/examples/vendor/list.lua b/examples/vendor/list.lua new file mode 100644 index 0000000..e97f4a4 --- /dev/null +++ b/examples/vendor/list.lua @@ -0,0 +1,193 @@ +local List = {} + +function inside(mx, my, x, y, w, h) + return mx >= x and mx <= (x+w) and my >= y and my <= (y+h) +end + +function List:new() + o = {} + setmetatable(o, self) + self.__index = self + + o.items = {} + o.files = {} + + o.x = 50 + o.y = 70 + + o.width = 400 + o.height = 500 + + o.item_height = 23 + o.sum_item_height = 0 + + o.bar_size = 20 + o.bar_pos = 0 + o.bar_max_pos = 0 + o.bar_width = 15 + o.bar_lock = nil + + return o +end + +function List:add(item, file) + table.insert(self.items, item) + table.insert(self.files, file) + self.items.n = #self.items + self.bar_pos = 0 + local num_items = (self.height/self.item_height) + local ratio = num_items/self.items.n + self.bar_size = self.height * ratio + self.bar_max_pos = self.height - self.bar_size - 3 + self.sum_item_height = (self.item_height+1) * self.items.n + 2 +end + +function List:hasBar() + return self.sum_item_height > self.height +end + +function List:getBarRatio() + return self.bar_pos/self.bar_max_pos +end + +function List:getOffset() + local ratio = self.bar_pos/self.bar_max_pos + return math.floor((self.sum_item_height-self.height)*ratio + 0.5) +end + +function List:update(dt) + if self.bar_lock then + local dy = math.floor(love.mouse.getY()-self.bar_lock.y+0.5) + self.bar_pos = self.bar_pos + dy + + if self.bar_pos < 0 then + self.bar_pos = 0 + elseif self.bar_pos > self.bar_max_pos then + self.bar_pos = self.bar_max_pos + end + + self.bar_lock.y = love.mouse.getY() + end +end + +function List:mousepressed(mx, my, b) + if self:hasBar() then + if b == 1 then + local x, y, w, h = self:getBarRect() + if inside(mx, my, x, y, w, h) then + self.bar_lock = { x = mx, y = my } + end + end + + local per_pixel = (self.sum_item_height-self.height)/self.bar_max_pos + local bar_pixel_dt = math.floor(((self.item_height)*3)/per_pixel + 0.5) + + if b == "wd" then + self.bar_pos = self.bar_pos + bar_pixel_dt + if self.bar_pos > self.bar_max_pos then + self.bar_pos = self.bar_max_pos + end + elseif b == "wu" then + self.bar_pos = self.bar_pos - bar_pixel_dt + if self.bar_pos < 0 then + self.bar_pos = 0 + end + end + end + + if b == 1 and inside(mx, my, self.x+2, self.y+1, self.width-3, self.height-3) then + local tx, ty = mx-self.x, my + self:getOffset() - self.y + local index = math.floor((ty/self.sum_item_height)*self.items.n) + local i = self.items[index+1] + local f = self.files[index+1] + if f then + exf.start(i, f) + end + end +end + +function List:mousereleased(x, y, b) + if self:hasBar() then + if b == 1 then + self.bar_lock = nil + end + end +end + +function List:getBarRect() + return self.x+self.width+2, self.y+1+self.bar_pos, + self.bar_width-3, self.bar_size +end + +function List:getItemRect(i) + return self.x+2, self.y+((self.item_height+1)*(i-1)+1)-self:getOffset(), + self.width-3, self.item_height +end + +function List:draw() + love.graphics.setLineWidth(2) + love.graphics.setLineStyle("rough") + love.graphics.setFont(self.font) + + love.graphics.setColor(48/255, 156/255, 225 / 255) + + local mx, my = love.mouse.getPosition() + + -- Get interval to display. + local start_i = math.floor( self:getOffset()/(self.item_height+1) ) + 1 + local end_i = start_i+math.floor( self.height/(self.item_height+1) ) + 1 + + if end_i > self.items.n then + end_i = self.items.n + end + + love.graphics.setScissor(self.x, self.y, self.width, self.height) + + -- Items. + for i = start_i,end_i do + local x, y, w, h = self:getItemRect(i) + local hover = inside(mx, my, x, y, w, h) + + if hover then + love.graphics.setColor(0, 0, 0, 127/255) + else + love.graphics.setColor(0, 0, 0, 63/255) + end + + love.graphics.rectangle("fill", x+1, y+i+1, w-3, h) + + if hover then + love.graphics.setColor(1, 1, 1, 1) + else + love.graphics.setColor(1, 1, 1, 127/255) + end + + local e_id = string.sub(self.items[i], 1, 5) + local e_rest = string.sub(self.items[i], 5) + + love.graphics.print(e_id, x+10, y+i+6) --Updated y placement -- Used to change position of Example IDs + love.graphics.print(e_rest, x+50, y+i+6) --Updated y placement -- Used to change position of Example Titles + end + + love.graphics.setScissor() + + -- Bar. + if self:hasBar() then + local x, y, w, h = self:getBarRect() + local hover = inside(mx, my, x, y, w, h) + + if hover or self.bar_lock then + love.graphics.setColor(0, 0, 0, 127/255) + else + love.graphics.setColor(0, 0, 0, 63/255) + end + love.graphics.rectangle("fill", x, y, w, h) + end + + -- Border. + love.graphics.setColor(0, 0, 0, 63/255) + love.graphics.rectangle("line", self.x+self.width, self.y, self.bar_width, self.height) + love.graphics.rectangle("line", self.x, self.y, self.width, self.height) +end + +return List diff --git a/main.lua b/main.lua index feeca4f..1eaf9c1 100644 --- a/main.lua +++ b/main.lua @@ -8,10 +8,10 @@ require "lib/postshader" local LightWorld = require "lib" local ProFi = require 'examples.vendor.ProFi' +local List = require 'examples.vendor.list' exf = {} exf.current = nil - exf.available = {} function love.load() @@ -24,7 +24,7 @@ function love.load() -- Find available demos. local files = love.filesystem.getDirectoryItems("examples") - local n = 0 + local n = 0 for i, v in ipairs(files) do is_file = (love.filesystem.getInfo("examples/".. v ).type == "file") @@ -37,135 +37,21 @@ function love.load() local s, e, c = string.find(contents, "Example: ([%a%p ]-)[\r\n]") file:close(file) if not c then c = "Untitled" end - local title = exf.getn(n) .. " " .. c .. " (" .. v .. ")" + local title = string.format("%04d", n) .. " " .. c .. " (" .. v .. ")" exf.list:add(title, v) end end - exf.list:done() - exf.resume() + exf.load() end -function love.update(dt) end -function love.draw() end -function love.keypressed(k) end -function love.keyreleased(k) end -function love.mousepressed(x, y, b) end -function love.mousereleased(x, y, b) end function exf.empty() end +function exf.keypressed(k) end +function exf.keyreleased(k) end +function exf.mousepressed(x, y, b) exf.list:mousepressed(x, y, b) end +function exf.mousereleased(x, y, b) exf.list:mousereleased(x, y, b) end -function exf.update(dt) - exf.list:update(dt) - lightMouse:setPosition(love.mouse.getX(), love.mouse.getY()) -end - -function exf.draw() - lightWorld:draw(function() - love.graphics.setBackgroundColor(0, 0, 0) - - love.graphics.setColor(48/255, 156/255, 225/255) - love.graphics.rectangle("fill", 0, 0, love.graphics.getWidth(), love.graphics.getHeight()) - - love.graphics.setColor(1, 1, 1, 191/255) - love.graphics.setFont(exf.bigfont) - love.graphics.print("Examples:", 50, 50) - - love.graphics.setFont(exf.smallfont) - love.graphics.print("Browse and click on the example you \nwant to run. To return the the example \nselection screen, press escape.", 500, 80) - - exf.list:draw() - - love.graphics.setColor(1, 1, 1) - love.graphics.draw(exf.bigball, 800 - 128, 600 - 128, love.timer.getTime(), 1, 1, exf.bigball:getWidth() * 0.5, exf.bigball:getHeight() * 0.5) - end) -end - -function exf.keypressed(k) -end - -function exf.keyreleased(k) -end - -function exf.mousepressed(x, y, b) - exf.list:mousepressed(x, y, b) -end - -function exf.mousereleased(x, y, b) - exf.list:mousereleased(x, y, b) -end - -function exf.getn(n) - local s = "" - n = tonumber(n) - local r = n - if r <= 0 then error("Example IDs must be bigger than 0. (Got: " .. r .. ")") end - if r >= 10000 then error("Example IDs must be less than 10000. (Got: " .. r .. ")") end - while r < 1000 do - s = s .. "0" - r = r * 10 - end - s = s .. n - return s -end - -function exf.intable(t, e) - for k, v in ipairs(t) do - if v == e then return true end - end - return false -end - -function exf.start(item, file) - local e_id = string.sub(item, 1, 4) - local e_rest = string.sub(item, 5) - local unused1, unused2, n = string.find(item, "(%s)%.lua") - - if exf.intable(exf.available, file) then - if not love.filesystem.getInfo("examples/" .. file) then - print("Could not load game .. " .. file) - else - - -- Clear all callbacks. - love.load = exf.empty - love.update = exf.empty - love.draw = exf.empty - love.keypressed = exf.empty - love.keyreleased = exf.empty - love.mousepressed = exf.empty - love.mousereleased = exf.empty - - love.filesystem.load("examples/" .. file)() - exf.clear() - - --love.window.setTitle(e_rest) - - -- Redirect keypress - local o_keypressed = love.keypressed - love.keypressed = - function(k) - if k == "escape" then - exf.resume() - end - o_keypressed(k) - end - - love.load() - end - else - print("Example ".. e_id .. " does not exist.") - end -end - -function exf.clear() - love.graphics.setBackgroundColor(0,0,0) - love.graphics.setColor(1, 1, 1) - love.graphics.setLineWidth(1) - love.graphics.setLineStyle("smooth") - love.graphics.setBlendMode("alpha") - love.mouse.setVisible(true) -end - -function exf.resume() +function exf.load() ProFi:stop() ProFi:writeReport( 'light_world_profiling_report.txt' ) @@ -180,220 +66,63 @@ function exf.resume() love.mouse.setVisible(true) love.window.setTitle("LOVE Example Browser") - -- create light world - lightWorld = LightWorld({ - ambient = {127/255, 127/255, 127/255} - }) - - -- create light - lightMouse = lightWorld:newLight(0, 0, 1, 127/255, 63/255, 500) - lightMouse:setSmooth(2) - - -- create shadow bodys - circleTest = lightWorld:newCircle(800 - 128, 600 - 128, exf.bigball:getWidth()*0.5) + lightWorld = LightWorld({ambient = {0.49, 0.49, 0.49}}) + lightMouse = lightWorld:newLight(20, 20, 1, 0.49, 0.24, 500) + lightMouse:setSmooth(2) + circleTest = lightWorld:newCircle(800 - 128, 600 - 128, exf.bigball:getWidth()*0.5) end -function inside(mx, my, x, y, w, h) - return mx >= x and mx <= (x+w) and my >= y and my <= (y+h) +function exf.update(dt) + exf.list:update(dt) + lightMouse:setPosition(love.mouse.getX(), love.mouse.getY()) + lightWorld:update(dt) end +function exf.draw() + lightWorld:draw(function() + love.graphics.setBackgroundColor(0, 0, 0) ----------------------- --- List object ----------------------- + love.graphics.setColor(0.18, 0.61, 1) + love.graphics.rectangle("fill", 0, 0, love.graphics.getWidth(), love.graphics.getHeight()) -List = {} + love.graphics.setColor(1, 1, 1, 1) + love.graphics.setFont(exf.bigfont) + love.graphics.print("Examples:", 50, 30) -function List:new() - o = {} - setmetatable(o, self) - self.__index = self + love.graphics.setFont(exf.smallfont) + love.graphics.print("Browse and click on the example you \nwant to run. To return the the example \nselection screen, press escape.", 500, 80) - o.items = {} - o.files = {} + exf.list:draw() - o.x = 50 - o.y = 70 - - o.width = 400 - o.height = 500 - - o.item_height = 23 - o.sum_item_height = 0 - - o.bar_size = 20 - o.bar_pos = 0 - o.bar_max_pos = 0 - o.bar_width = 15 - o.bar_lock = nil - - return o + love.graphics.setColor(1, 1, 1) + love.graphics.draw(exf.bigball, 800 - 128, 600 - 128, love.timer.getTime()/5, 1, 1, exf.bigball:getWidth() * 0.5, exf.bigball:getHeight() * 0.5) + end) end -function List:add(item, file) - table.insert(self.items, item) - table.insert(self.files, file) -end +function exf.start(item, file) + love.load = exf.empty + love.update = exf.empty + love.draw = exf.empty + love.keypressed = exf.empty + love.keyreleased = exf.empty + love.mousepressed = exf.empty + love.mousereleased = exf.empty -function List:done() - self.items.n = #self.items + love.filesystem.load("examples/" .. file)() + love.graphics.setBackgroundColor(0,0,0) + love.graphics.setColor(1, 1, 1) + love.graphics.setLineWidth(1) + love.graphics.setLineStyle("smooth") + love.graphics.setBlendMode("alpha") + love.mouse.setVisible(true) - -- Recalc bar size. - self.bar_pos = 0 - - local num_items = (self.height/self.item_height) - local ratio = num_items/self.items.n - self.bar_size = self.height * ratio - self.bar_max_pos = self.height - self.bar_size - 3 - - -- Calculate height of everything. - self.sum_item_height = (self.item_height+1) * self.items.n + 2 -end - -function List:hasBar() - return self.sum_item_height > self.height -end - -function List:getBarRatio() - return self.bar_pos/self.bar_max_pos -end - -function List:getOffset() - local ratio = self.bar_pos/self.bar_max_pos - return math.floor((self.sum_item_height-self.height)*ratio + 0.5) -end - -function List:update(dt) - if self.bar_lock then - local dy = math.floor(love.mouse.getY()-self.bar_lock.y+0.5) - self.bar_pos = self.bar_pos + dy - - if self.bar_pos < 0 then - self.bar_pos = 0 - elseif self.bar_pos > self.bar_max_pos then - self.bar_pos = self.bar_max_pos - end - - self.bar_lock.y = love.mouse.getY() - end -end - -function List:mousepressed(mx, my, b) - if self:hasBar() then - if b == 1 then - local x, y, w, h = self:getBarRect() - if inside(mx, my, x, y, w, h) then - self.bar_lock = { x = mx, y = my } - end - end - - local per_pixel = (self.sum_item_height-self.height)/self.bar_max_pos - local bar_pixel_dt = math.floor(((self.item_height)*3)/per_pixel + 0.5) - - if b == "wd" then - self.bar_pos = self.bar_pos + bar_pixel_dt - if self.bar_pos > self.bar_max_pos then - self.bar_pos = self.bar_max_pos - end - elseif b == "wu" then - self.bar_pos = self.bar_pos - bar_pixel_dt - if self.bar_pos < 0 then - self.bar_pos = 0 - end - end - end - - if b == 1 and inside(mx, my, self.x+2, self.y+1, self.width-3, self.height-3) then - local tx, ty = mx-self.x, my + self:getOffset() - self.y - local index = math.floor((ty/self.sum_item_height)*self.items.n) - local i = self.items[index+1] - local f = self.files[index+1] - if f then - exf.start(i, f) + local o_keypressed = love.keypressed + love.keypressed = function(k) + if k == "escape" then + exf.load() end - end -end - -function List:mousereleased(x, y, b) - if self:hasBar() then - if b == 1 then - self.bar_lock = nil - end - end -end - -function List:getBarRect() - return self.x+self.width+2, self.y+1+self.bar_pos, - self.bar_width-3, self.bar_size -end - -function List:getItemRect(i) - return self.x+2, self.y+((self.item_height+1)*(i-1)+1)-self:getOffset(), - self.width-3, self.item_height -end - -function List:draw() - love.graphics.setLineWidth(2) - love.graphics.setLineStyle("rough") - love.graphics.setFont(self.font) - - love.graphics.setColor(48/255, 156/255, 225 / 255) - - local mx, my = love.mouse.getPosition() - - -- Get interval to display. - local start_i = math.floor( self:getOffset()/(self.item_height+1) ) + 1 - local end_i = start_i+math.floor( self.height/(self.item_height+1) ) + 1 - - if end_i > self.items.n then - end_i = self.items.n + o_keypressed(k) end - love.graphics.setScissor(self.x, self.y, self.width, self.height) - - -- Items. - for i = start_i,end_i do - local x, y, w, h = self:getItemRect(i) - local hover = inside(mx, my, x, y, w, h) - - if hover then - love.graphics.setColor(0, 0, 0, 127/255) - else - love.graphics.setColor(0, 0, 0, 63/255) - end - - love.graphics.rectangle("fill", x+1, y+i+1, w-3, h) - - if hover then - love.graphics.setColor(1, 1, 1, 1) - else - love.graphics.setColor(1, 1, 1, 127/255) - end - - local e_id = string.sub(self.items[i], 1, 5) - local e_rest = string.sub(self.items[i], 5) - - love.graphics.print(e_id, x+10, y+i+6) --Updated y placement -- Used to change position of Example IDs - love.graphics.print(e_rest, x+50, y+i+6) --Updated y placement -- Used to change position of Example Titles - end - - love.graphics.setScissor() - - -- Bar. - if self:hasBar() then - local x, y, w, h = self:getBarRect() - local hover = inside(mx, my, x, y, w, h) - - if hover or self.bar_lock then - love.graphics.setColor(0, 0, 0, 127/255) - else - love.graphics.setColor(0, 0, 0, 63/255) - end - love.graphics.rectangle("fill", x, y, w, h) - end - - -- Border. - love.graphics.setColor(0, 0, 0, 63/255) - love.graphics.rectangle("line", self.x+self.width, self.y, self.bar_width, self.height) - love.graphics.rectangle("line", self.x, self.y, self.width, self.height) + love.load() end