diff --git a/imperium-porcorum.love/game/init.lua b/imperium-porcorum.love/game/init.lua index 0f71484..e0c0fb2 100644 --- a/imperium-porcorum.love/game/init.lua +++ b/imperium-porcorum.love/game/init.lua @@ -28,7 +28,7 @@ local Game = Object:extend() local PigManager = require "game.pigmanager" local Inventory = require "game.inventory" -local binser = require "libs.binser" +local binser = require "core.libs.binser" Game.gui = require "game.modules.gui" diff --git a/imperium-porcorum.love/libs/anim8.lua b/imperium-porcorum.love/libs/anim8.lua deleted file mode 100644 index 8fefe99..0000000 --- a/imperium-porcorum.love/libs/anim8.lua +++ /dev/null @@ -1,302 +0,0 @@ -local anim8 = { - _VERSION = 'anim8 v2.3.0', - _DESCRIPTION = 'An animation library for LÖVE', - _URL = 'https://github.com/kikito/anim8', - _LICENSE = [[ - MIT LICENSE - - Copyright (c) 2011 Enrique García Cota - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ]] -} - -local Grid = {} - -local _frames = {} - -local function assertPositiveInteger(value, name) - if type(value) ~= 'number' then error(("%s should be a number, was %q"):format(name, tostring(value))) end - if value < 1 then error(("%s should be a positive number, was %d"):format(name, value)) end - if value ~= math.floor(value) then error(("%s should be an integer, was %d"):format(name, value)) end -end - -local function createFrame(self, x, y) - local fw, fh = self.frameWidth, self.frameHeight - return love.graphics.newQuad( - self.left + (x-1) * fw + x * self.border, - self.top + (y-1) * fh + y * self.border, - fw, - fh, - self.imageWidth, - self.imageHeight - ) -end - -local function getGridKey(...) - return table.concat( {...} ,'-' ) -end - -local function getOrCreateFrame(self, x, y) - if x < 1 or x > self.width or y < 1 or y > self.height then - error(("There is no frame for x=%d, y=%d"):format(x, y)) - end - local key = self._key - _frames[key] = _frames[key] or {} - _frames[key][x] = _frames[key][x] or {} - _frames[key][x][y] = _frames[key][x][y] or createFrame(self, x, y) - return _frames[key][x][y] -end - -local function parseInterval(str) - if type(str) == "number" then return str,str,1 end - str = str:gsub('%s', '') -- remove spaces - local min, max = str:match("^(%d+)-(%d+)$") - assert(min and max, ("Could not parse interval from %q"):format(str)) - min, max = tonumber(min), tonumber(max) - local step = min <= max and 1 or -1 - return min, max, step -end - -function Grid:getFrames(...) - local result, args = {}, {...} - local minx, maxx, stepx, miny, maxy, stepy - - for i=1, #args, 2 do - minx, maxx, stepx = parseInterval(args[i]) - miny, maxy, stepy = parseInterval(args[i+1]) - for y = miny, maxy, stepy do - for x = minx, maxx, stepx do - result[#result+1] = getOrCreateFrame(self,x,y) - end - end - end - - return result -end - -local Gridmt = { - __index = Grid, - __call = Grid.getFrames -} - -local function newGrid(frameWidth, frameHeight, imageWidth, imageHeight, left, top, border) - assertPositiveInteger(frameWidth, "frameWidth") - assertPositiveInteger(frameHeight, "frameHeight") - assertPositiveInteger(imageWidth, "imageWidth") - assertPositiveInteger(imageHeight, "imageHeight") - - left = left or 0 - top = top or 0 - border = border or 0 - - local key = getGridKey(frameWidth, frameHeight, imageWidth, imageHeight, left, top, border) - - local grid = setmetatable( - { frameWidth = frameWidth, - frameHeight = frameHeight, - imageWidth = imageWidth, - imageHeight = imageHeight, - left = left, - top = top, - border = border, - width = math.floor(imageWidth/frameWidth), - height = math.floor(imageHeight/frameHeight), - _key = key - }, - Gridmt - ) - return grid -end - ------------------------------------------------------------ - -local Animation = {} - -local function cloneArray(arr) - local result = {} - for i=1,#arr do result[i] = arr[i] end - return result -end - -local function parseDurations(durations, frameCount) - local result = {} - if type(durations) == 'number' then - for i=1,frameCount do result[i] = durations end - else - local min, max, step - for key,duration in pairs(durations) do - assert(type(duration) == 'number', "The value [" .. tostring(duration) .. "] should be a number") - min, max, step = parseInterval(key) - for i = min,max,step do result[i] = duration end - end - end - - if #result < frameCount then - error("The durations table has length of " .. tostring(#result) .. ", but it should be >= " .. tostring(frameCount)) - end - - return result -end - -local function parseIntervals(durations) - local result, time = {0},0 - for i=1,#durations do - time = time + durations[i] - result[i+1] = time - end - return result, time -end - -local Animationmt = { __index = Animation } -local nop = function() end - -local function newAnimation(frames, durations, onLoop) - local td = type(durations); - if (td ~= 'number' or durations <= 0) and td ~= 'table' then - error("durations must be a positive number. Was " .. tostring(durations) ) - end - onLoop = onLoop or nop - durations = parseDurations(durations, #frames) - local intervals, totalDuration = parseIntervals(durations) - return setmetatable({ - frames = cloneArray(frames), - durations = durations, - intervals = intervals, - totalDuration = totalDuration, - onLoop = onLoop, - timer = 0, - position = 1, - status = "playing", - flippedH = false, - flippedV = false - }, - Animationmt - ) -end - -function Animation:clone() - local newAnim = newAnimation(self.frames, self.durations, self.onLoop) - newAnim.flippedH, newAnim.flippedV = self.flippedH, self.flippedV - return newAnim -end - -function Animation:flipH() - self.flippedH = not self.flippedH - return self -end - -function Animation:flipV() - self.flippedV = not self.flippedV - return self -end - -local function seekFrameIndex(intervals, timer) - local high, low, i = #intervals-1, 1, 1 - - while(low <= high) do - i = math.floor((low + high) / 2) - if timer > intervals[i+1] then low = i + 1 - elseif timer <= intervals[i] then high = i - 1 - else - return i - end - end - - return i -end - -function Animation:update(dt) - if self.status ~= "playing" then return end - - self.timer = self.timer + dt - local loops = math.floor(self.timer / self.totalDuration) - if loops ~= 0 then - self.timer = self.timer - self.totalDuration * loops - local f = type(self.onLoop) == 'function' and self.onLoop or self[self.onLoop] - f(self, loops) - end - - self.position = seekFrameIndex(self.intervals, self.timer) -end - -function Animation:pause() - self.status = "paused" -end - -function Animation:gotoFrame(position) - self.position = position - self.timer = self.intervals[self.position] -end - -function Animation:pauseAtEnd() - self.position = #self.frames - self.timer = self.totalDuration - self:pause() -end - -function Animation:pauseAtStart() - self.position = 1 - self.timer = 0 - self:pause() -end - -function Animation:resume() - self.status = "playing" -end - -function Animation:draw(image, x, y, r, sx, sy, ox, oy, kx, ky) - love.graphics.draw(image, self:getFrameInfo(x, y, r, sx, sy, ox, oy, kx, ky)) -end - -function Animation:getFrameInfo(x, y, r, sx, sy, ox, oy, kx, ky) - local frame = self.frames[self.position] - if self.flippedH or self.flippedV then - r,sx,sy,ox,oy,kx,ky = r or 0, sx or 1, sy or 1, ox or 0, oy or 0, kx or 0, ky or 0 - local _,_,w,h = frame:getViewport() - - if self.flippedH then - sx = sx * -1 - ox = w - ox - kx = kx * -1 - ky = ky * -1 - end - - if self.flippedV then - sy = sy * -1 - oy = h - oy - kx = kx * -1 - ky = ky * -1 - end - end - return frame, x, y, r, sx, sy, ox, oy, kx, ky -end - -function Animation:getDimensions() - local _,_,w,h = self.frames[self.position]:getViewport() - return w,h -end - ------------------------------------------------------------ - -anim8.newGrid = newGrid -anim8.newAnimation = newAnimation - -return anim8 diff --git a/imperium-porcorum.love/libs/assets/init.lua b/imperium-porcorum.love/libs/assets/init.lua deleted file mode 100644 index 0f3cf4d..0000000 --- a/imperium-porcorum.love/libs/assets/init.lua +++ /dev/null @@ -1,9 +0,0 @@ -local AssetManager = Object:extend() - -local SoundManager = "libs.assets.sfx" - -function AssetManager:new() - -end - -return AssetManager diff --git a/imperium-porcorum.love/libs/assets/sfx.lua b/imperium-porcorum.love/libs/assets/sfx.lua deleted file mode 100644 index 6a1dcbb..0000000 --- a/imperium-porcorum.love/libs/assets/sfx.lua +++ /dev/null @@ -1,12 +0,0 @@ -local SoundManager = Object:extend() -local SFX = Object:extend() - -function SoundManager:new() - self.datas = {} -end - -function SoundManager:addSFX() - self.datas = {} -end - -return SoundManager diff --git a/imperium-porcorum.love/libs/binser.lua b/imperium-porcorum.love/libs/binser.lua deleted file mode 100644 index 5aa1299..0000000 --- a/imperium-porcorum.love/libs/binser.lua +++ /dev/null @@ -1,687 +0,0 @@ --- binser.lua - ---[[ -Copyright (c) 2016 Calvin Rose - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -]] - -local assert = assert -local error = error -local select = select -local pairs = pairs -local getmetatable = getmetatable -local setmetatable = setmetatable -local tonumber = tonumber -local type = type -local loadstring = loadstring or load -local concat = table.concat -local char = string.char -local byte = string.byte -local format = string.format -local sub = string.sub -local dump = string.dump -local floor = math.floor -local frexp = math.frexp -local unpack = unpack or table.unpack - --- Lua 5.3 frexp polyfill --- From https://github.com/excessive/cpml/blob/master/modules/utils.lua -if not frexp then - local log, abs, floor = math.log, math.abs, math.floor - local log2 = log(2) - frexp = function(x) - if x == 0 then return 0, 0 end - local e = floor(log(abs(x)) / log2 + 1) - return x / 2 ^ e, e - end -end - --- NIL = 202 --- FLOAT = 203 --- TRUE = 204 --- FALSE = 205 --- STRING = 206 --- TABLE = 207 --- REFERENCE = 208 --- CONSTRUCTOR = 209 --- FUNCTION = 210 --- RESOURCE = 211 --- INT64 = 212 - -local mts = {} -local ids = {} -local serializers = {} -local deserializers = {} -local resources = {} -local resources_by_name = {} - -local function pack(...) - return {...}, select("#", ...) -end - -local function not_array_index(x, len) - return type(x) ~= "number" or x < 1 or x > len or x ~= floor(x) -end - -local function type_check(x, tp, name) - assert(type(x) == tp, - format("Expected parameter %q to be of type %q.", name, tp)) -end - -local bigIntSupport = false -local isInteger -if math.type then -- Detect Lua 5.3 - local mtype = math.type - bigIntSupport = loadstring[[ - local char = string.char - return function(n) - local nn = n < 0 and -(n + 1) or n - local b1 = nn // 0x100000000000000 - local b2 = nn // 0x1000000000000 % 0x100 - local b3 = nn // 0x10000000000 % 0x100 - local b4 = nn // 0x100000000 % 0x100 - local b5 = nn // 0x1000000 % 0x100 - local b6 = nn // 0x10000 % 0x100 - local b7 = nn // 0x100 % 0x100 - local b8 = nn % 0x100 - if n < 0 then - b1, b2, b3, b4 = 0xFF - b1, 0xFF - b2, 0xFF - b3, 0xFF - b4 - b5, b6, b7, b8 = 0xFF - b5, 0xFF - b6, 0xFF - b7, 0xFF - b8 - end - return char(212, b1, b2, b3, b4, b5, b6, b7, b8) - end]]() - isInteger = function(x) - return mtype(x) == 'integer' - end -else - isInteger = function(x) - return floor(x) == x - end -end - --- Copyright (C) 2012-2015 Francois Perrad. --- number serialization code modified from https://github.com/fperrad/lua-MessagePack --- Encode a number as a big-endian ieee-754 double, big-endian signed 64 bit integer, or a small integer -local function number_to_str(n) - if isInteger(n) then -- int - if n <= 100 and n >= -27 then -- 1 byte, 7 bits of data - return char(n + 27) - elseif n <= 8191 and n >= -8192 then -- 2 bytes, 14 bits of data - n = n + 8192 - return char(128 + (floor(n / 0x100) % 0x100), n % 0x100) - elseif bigIntSupport then - return bigIntSupport(n) - end - end - local sign = 0 - if n < 0.0 then - sign = 0x80 - n = -n - end - local m, e = frexp(n) -- mantissa, exponent - if m ~= m then - return char(203, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00) - elseif m == 1/0 then - if sign == 0 then - return char(203, 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00) - else - return char(203, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00) - end - end - e = e + 0x3FE - if e < 1 then -- denormalized numbers - m = m * 2 ^ (52 + e) - e = 0 - else - m = (m * 2 - 1) * 2 ^ 52 - end - return char(203, - sign + floor(e / 0x10), - (e % 0x10) * 0x10 + floor(m / 0x1000000000000), - floor(m / 0x10000000000) % 0x100, - floor(m / 0x100000000) % 0x100, - floor(m / 0x1000000) % 0x100, - floor(m / 0x10000) % 0x100, - floor(m / 0x100) % 0x100, - m % 0x100) -end - --- Copyright (C) 2012-2015 Francois Perrad. --- number deserialization code also modified from https://github.com/fperrad/lua-MessagePack -local function number_from_str(str, index) - local b = byte(str, index) - if b < 128 then - return b - 27, index + 1 - elseif b < 192 then - return byte(str, index + 1) + 0x100 * (b - 128) - 8192, index + 2 - end - local b1, b2, b3, b4, b5, b6, b7, b8 = byte(str, index + 1, index + 8) - if b == 212 then - local flip = b1 >= 128 - if flip then -- negative - b1, b2, b3, b4 = 0xFF - b1, 0xFF - b2, 0xFF - b3, 0xFF - b4 - b5, b6, b7, b8 = 0xFF - b5, 0xFF - b6, 0xFF - b7, 0xFF - b8 - end - local n = ((((((b1 * 0x100 + b2) * 0x100 + b3) * 0x100 + b4) * 0x100 + b5) * 0x100 + b6) * 0x100 + b7) * 0x100 + b8 - if flip then - return (-n) - 1, index + 9 - else - return n, index + 9 - end - end - local sign = b1 > 0x7F and -1 or 1 - local e = (b1 % 0x80) * 0x10 + floor(b2 / 0x10) - local m = ((((((b2 % 0x10) * 0x100 + b3) * 0x100 + b4) * 0x100 + b5) * 0x100 + b6) * 0x100 + b7) * 0x100 + b8 - local n - if e == 0 then - if m == 0 then - n = sign * 0.0 - else - n = sign * (m / 2 ^ 52) * 2 ^ -1022 - end - elseif e == 0x7FF then - if m == 0 then - n = sign * (1/0) - else - n = 0.0/0.0 - end - else - n = sign * (1.0 + m / 2 ^ 52) * 2 ^ (e - 0x3FF) - end - return n, index + 9 -end - -local types = {} - -types["nil"] = function(x, visited, accum) - accum[#accum + 1] = "\202" -end - -function types.number(x, visited, accum) - accum[#accum + 1] = number_to_str(x) -end - -function types.boolean(x, visited, accum) - accum[#accum + 1] = x and "\204" or "\205" -end - -function types.string(x, visited, accum) - local alen = #accum - if visited[x] then - accum[alen + 1] = "\208" - accum[alen + 2] = number_to_str(visited[x]) - else - visited[x] = visited.next - visited.next = visited.next + 1 - accum[alen + 1] = "\206" - accum[alen + 2] = number_to_str(#x) - accum[alen + 3] = x - end -end - -local function check_custom_type(x, visited, accum) - local res = resources[x] - if res then - accum[#accum + 1] = "\211" - types[type(res)](res, visited, accum) - return true - end - local mt = getmetatable(x) - local id = mt and ids[mt] - if id then - if x == visited.temp then - error("Infinite loop in constructor.") - end - visited.temp = x - accum[#accum + 1] = "\209" - types[type(id)](id, visited, accum) - local args, len = pack(serializers[id](x)) - accum[#accum + 1] = number_to_str(len) - for i = 1, len do - local arg = args[i] - types[type(arg)](arg, visited, accum) - end - visited[x] = visited.next - visited.next = visited.next + 1 - return true - end -end - -function types.userdata(x, visited, accum) - if visited[x] then - accum[#accum + 1] = "\208" - accum[#accum + 1] = number_to_str(visited[x]) - else - if check_custom_type(x, visited, accum) then return end - error("Cannot serialize this userdata.") - end -end - -function types.table(x, visited, accum) - if visited[x] then - accum[#accum + 1] = "\208" - accum[#accum + 1] = number_to_str(visited[x]) - else - if check_custom_type(x, visited, accum) then return end - visited[x] = visited.next - visited.next = visited.next + 1 - local xlen = #x - accum[#accum + 1] = "\207" - accum[#accum + 1] = number_to_str(xlen) - for i = 1, xlen do - local v = x[i] - types[type(v)](v, visited, accum) - end - local key_count = 0 - for k in pairs(x) do - if not_array_index(k, xlen) then - key_count = key_count + 1 - end - end - accum[#accum + 1] = number_to_str(key_count) - for k, v in pairs(x) do - if not_array_index(k, xlen) then - types[type(k)](k, visited, accum) - types[type(v)](v, visited, accum) - end - end - end -end - -types["function"] = function(x, visited, accum) - if visited[x] then - accum[#accum + 1] = "\208" - accum[#accum + 1] = number_to_str(visited[x]) - else - if check_custom_type(x, visited, accum) then return end - visited[x] = visited.next - visited.next = visited.next + 1 - local str = dump(x) - accum[#accum + 1] = "\210" - accum[#accum + 1] = number_to_str(#str) - accum[#accum + 1] = str - end -end - -types.cdata = function(x, visited, accum) - if visited[x] then - accum[#accum + 1] = "\208" - accum[#accum + 1] = number_to_str(visited[x]) - else - if check_custom_type(x, visited, #accum) then return end - error("Cannot serialize this cdata.") - end -end - -types.thread = function() error("Cannot serialize threads.") end - -local function deserialize_value(str, index, visited) - local t = byte(str, index) - if not t then return end - if t < 128 then - return t - 27, index + 1 - elseif t < 192 then - return byte(str, index + 1) + 0x100 * (t - 128) - 8192, index + 2 - elseif t == 202 then - return nil, index + 1 - elseif t == 203 then - return number_from_str(str, index) - elseif t == 204 then - return true, index + 1 - elseif t == 205 then - return false, index + 1 - elseif t == 206 then - local length, dataindex = deserialize_value(str, index + 1, visited) - local nextindex = dataindex + length - local substr = sub(str, dataindex, nextindex - 1) - visited[#visited + 1] = substr - return substr, nextindex - elseif t == 207 then - local count, nextindex = number_from_str(str, index + 1) - local ret = {} - visited[#visited + 1] = ret - for i = 1, count do - ret[i], nextindex = deserialize_value(str, nextindex, visited) - end - count, nextindex = number_from_str(str, nextindex) - for i = 1, count do - local k, v - k, nextindex = deserialize_value(str, nextindex, visited) - v, nextindex = deserialize_value(str, nextindex, visited) - ret[k] = v - end - return ret, nextindex - elseif t == 208 then - local ref, nextindex = number_from_str(str, index + 1) - return visited[ref], nextindex - elseif t == 209 then - local count - local name, nextindex = deserialize_value(str, index + 1, visited) - count, nextindex = number_from_str(str, nextindex) - local args = {} - for i = 1, count do - args[i], nextindex = deserialize_value(str, nextindex, visited) - end - local ret = deserializers[name](unpack(args)) - visited[#visited + 1] = ret - return ret, nextindex - elseif t == 210 then - local length, dataindex = deserialize_value(str, index + 1, visited) - local nextindex = dataindex + length - local ret = loadstring(sub(str, dataindex, nextindex - 1)) - visited[#visited + 1] = ret - return ret, nextindex - elseif t == 211 then - local res, nextindex = deserialize_value(str, index + 1, visited) - return resources_by_name[res], nextindex - elseif t == 212 then - return number_from_str(str, index) - else - error("Could not deserialize type byte " .. t .. ".") - end -end - -local function serialize(...) - local visited = {next = 1} - local accum = {} - for i = 1, select("#", ...) do - local x = select(i, ...) - types[type(x)](x, visited, accum) - end - return concat(accum) -end - -local function make_file_writer(file) - return setmetatable({}, { - __newindex = function(_, _, v) - file:write(v) - end - }) -end - -local function serialize_to_file(path, mode, ...) - local file, err = io.open(path, mode) - assert(file, err) - local visited = {next = 1} - local accum = make_file_writer(file) - for i = 1, select("#", ...) do - local x = select(i, ...) - types[type(x)](x, visited, accum) - end - -- flush the writer - file:flush() - file:close() -end - -local function writeFile(path, ...) - return serialize_to_file(path, "wb", ...) -end - -local function appendFile(path, ...) - return serialize_to_file(path, "ab", ...) -end - -local function deserialize(str, index) - assert(type(str) == "string", "Expected string to deserialize.") - local vals = {} - index = index or 1 - local visited = {} - local len = 0 - local val - while index do - val, index = deserialize_value(str, index, visited) - if index then - len = len + 1 - vals[len] = val - end - end - return vals, len -end - -local function deserializeN(str, n, index) - assert(type(str) == "string", "Expected string to deserialize.") - n = n or 1 - assert(type(n) == "number", "Expected a number for parameter n.") - assert(n > 0 and floor(n) == n, "N must be a poitive integer.") - local vals = {} - index = index or 1 - local visited = {} - local len = 0 - local val - while index and len < n do - val, index = deserialize_value(str, index, visited) - if index then - len = len + 1 - vals[len] = val - end - end - vals[len + 1] = index - return unpack(vals, 1, n + 1) -end - -local function readFile(path) - local file, err = io.open(path, "rb") - assert(file, err) - local str = file:read("*all") - file:close() - return deserialize(str) -end - -local function default_deserialize(metatable) - return function(...) - local ret = {} - for i = 1, select("#", ...), 2 do - ret[select(i, ...)] = select(i + 1, ...) - end - return setmetatable(ret, metatable) - end -end - -local function default_serialize(x) - assert(type(x) == "table", - "Default serialization for custom types only works for tables.") - local args = {} - local len = 0 - for k, v in pairs(x) do - args[len + 1], args[len + 2] = k, v - len = len + 2 - end - return unpack(args, 1, len) -end - --- Templating - -local function normalize_template(template) - local ret = {} - for i = 1, #template do - ret[i] = template[i] - end - local non_array_part = {} - -- The non-array part of the template (nested templates) have to be deterministic, so they are sorted. - -- This means that inherently non deterministicly sortable keys (tables, functions) should NOT be used - -- in templates. Looking for way around this. - for k in pairs(template) do - if not_array_index(k, #template) then - non_array_part[#non_array_part + 1] = k - end - end - table.sort(non_array_part) - for i = 1, #non_array_part do - local name = non_array_part[i] - ret[#ret + 1] = {name, normalize_template(template[name])} - end - return ret -end - -local function templatepart_serialize(part, argaccum, x, len) - local extras = {} - local extracount = 0 - for k, v in pairs(x) do - extras[k] = v - extracount = extracount + 1 - end - for i = 1, #part do - extracount = extracount - 1 - if type(part[i]) == "table" then - extras[part[i][1]] = nil - len = templatepart_serialize(part[i][2], argaccum, x[part[i][1]], len) - else - extras[part[i]] = nil - len = len + 1 - argaccum[len] = x[part[i]] - end - end - if extracount > 0 then - argaccum[len + 1] = extras - else - argaccum[len + 1] = nil - end - return len + 1 -end - -local function templatepart_deserialize(ret, part, values, vindex) - for i = 1, #part do - local name = part[i] - if type(name) == "table" then - local newret = {} - ret[name[1]] = newret - vindex = templatepart_deserialize(newret, name[2], values, vindex) - else - ret[name] = values[vindex] - vindex = vindex + 1 - end - end - local extras = values[vindex] - if extras then - for k, v in pairs(extras) do - ret[k] = v - end - end - return vindex + 1 -end - -local function template_serializer_and_deserializer(metatable, template) - return function(x) - argaccum = {} - local len = templatepart_serialize(template, argaccum, x, 0) - return unpack(argaccum, 1, len) - end, function(...) - local ret = {} - local len = select("#", ...) - local args = {...} - templatepart_deserialize(ret, template, args, 1) - return setmetatable(ret, metatable) - end -end - -local function register(metatable, name, serialize, deserialize) - name = name or metatable.name - serialize = serialize or metatable._serialize - deserialize = deserialize or metatable._deserialize - if not serialize then - if metatable._template then - local t = normalize_template(metatable._template) - serialize, deserialize = template_serializer_and_deserializer(metatable, t) - elseif not deserialize then - serialize = default_serialize - deserialize = default_deserialize(metatable) - else - serialize = metatable - end - end - type_check(metatable, "table", "metatable") - type_check(name, "string", "name") - type_check(serialize, "function", "serialize") - type_check(deserialize, "function", "deserialize") - assert(not ids[metatable], "Metatable already registered.") - assert(not mts[name], ("Name %q already registered."):format(name)) - mts[name] = metatable - ids[metatable] = name - serializers[name] = serialize - deserializers[name] = deserialize - return metatable -end - -local function unregister(item) - local name, metatable - if type(item) == "string" then -- assume name - name, metatable = item, mts[item] - else -- assume metatable - name, metatable = ids[item], item - end - type_check(name, "string", "name") - type_check(metatable, "table", "metatable") - mts[name] = nil - ids[metatable] = nil - serializers[name] = nil - deserializers[name] = nil - return metatable -end - -local function registerClass(class, name) - name = name or class.name - if class.__instanceDict then -- middleclass - register(class.__instanceDict, name) - else -- assume 30log or similar library - register(class, name) - end - return class -end - -local function registerResource(resource, name) - type_check(name, "string", "name") - assert(not resources[resource], - "Resource already registered.") - assert(not resources_by_name[name], - format("Resource %q already exists.", name)) - resources_by_name[name] = resource - resources[resource] = name - return resource -end - -local function unregisterResource(name) - type_check(name, "string", "name") - assert(resources_by_name[name], format("Resource %q does not exist.", name)) - local resource = resources_by_name[name] - resources_by_name[name] = nil - resources[resource] = nil - return resource -end - -return { - -- aliases - s = serialize, - d = deserialize, - dn = deserializeN, - r = readFile, - w = writeFile, - a = appendFile, - - serialize = serialize, - deserialize = deserialize, - deserializeN = deserializeN, - readFile = readFile, - writeFile = writeFile, - appendFile = appendFile, - register = register, - unregister = unregister, - registerResource = registerResource, - unregisterResource = unregisterResource, - registerClass = registerClass -} diff --git a/imperium-porcorum.love/libs/bump.lua b/imperium-porcorum.love/libs/bump.lua deleted file mode 100644 index 5626d4f..0000000 --- a/imperium-porcorum.love/libs/bump.lua +++ /dev/null @@ -1,775 +0,0 @@ -local bump = { - _VERSION = 'bump v3.1.7', - _URL = 'https://github.com/kikito/bump.lua', - _DESCRIPTION = 'A collision detection library for Lua', - _LICENSE = [[ - MIT LICENSE - - Copyright (c) 2014 Enrique García Cota - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ]] -} - ------------------------------------------- --- Auxiliary functions ------------------------------------------- -local DELTA = 1e-10 -- floating-point margin of error - -local abs, floor, ceil, min, max = math.abs, math.floor, math.ceil, math.min, math.max - -local function sign(x) - if x > 0 then return 1 end - if x == 0 then return 0 end - return -1 -end - -local function nearest(x, a, b) - if abs(a - x) < abs(b - x) then return a else return b end -end - -local function assertType(desiredType, value, name) - if type(value) ~= desiredType then - error(name .. ' must be a ' .. desiredType .. ', but was ' .. tostring(value) .. '(a ' .. type(value) .. ')') - end -end - -local function assertIsPositiveNumber(value, name) - if type(value) ~= 'number' or value <= 0 then - error(name .. ' must be a positive integer, but was ' .. tostring(value) .. '(' .. type(value) .. ')') - end -end - -local function assertIsRect(x,y,w,h) - assertType('number', x, 'x') - assertType('number', y, 'y') - assertIsPositiveNumber(w, 'w') - assertIsPositiveNumber(h, 'h') -end - -local defaultFilter = function() - return 'slide' -end - ------------------------------------------- --- Rectangle functions ------------------------------------------- - -local function rect_getNearestCorner(x,y,w,h, px, py) - return nearest(px, x, x+w), nearest(py, y, y+h) -end - --- This is a generalized implementation of the liang-barsky algorithm, which also returns --- the normals of the sides where the segment intersects. --- Returns nil if the segment never touches the rect --- Notice that normals are only guaranteed to be accurate when initially ti1, ti2 == -math.huge, math.huge -local function rect_getSegmentIntersectionIndices(x,y,w,h, x1,y1,x2,y2, ti1,ti2) - ti1, ti2 = ti1 or 0, ti2 or 1 - local dx, dy = x2-x1, y2-y1 - local nx, ny - local nx1, ny1, nx2, ny2 = 0,0,0,0 - local p, q, r - - for side = 1,4 do - if side == 1 then nx,ny,p,q = -1, 0, -dx, x1 - x -- left - elseif side == 2 then nx,ny,p,q = 1, 0, dx, x + w - x1 -- right - elseif side == 3 then nx,ny,p,q = 0, -1, -dy, y1 - y -- top - else nx,ny,p,q = 0, 1, dy, y + h - y1 -- bottom - end - - if p == 0 then - if q <= 0 then return nil end - else - r = q / p - if p < 0 then - if r > ti2 then return nil - elseif r > ti1 then ti1,nx1,ny1 = r,nx,ny - end - else -- p > 0 - if r < ti1 then return nil - elseif r < ti2 then ti2,nx2,ny2 = r,nx,ny - end - end - end - end - - return ti1,ti2, nx1,ny1, nx2,ny2 -end - --- Calculates the minkowsky difference between 2 rects, which is another rect -local function rect_getDiff(x1,y1,w1,h1, x2,y2,w2,h2) - return x2 - x1 - w1, - y2 - y1 - h1, - w1 + w2, - h1 + h2 -end - -local function rect_containsPoint(x,y,w,h, px,py) - return px - x > DELTA and py - y > DELTA and - x + w - px > DELTA and y + h - py > DELTA -end - -local function rect_isIntersecting(x1,y1,w1,h1, x2,y2,w2,h2) - return x1 < x2+w2 and x2 < x1+w1 and - y1 < y2+h2 and y2 < y1+h1 -end - -local function rect_getSquareDistance(x1,y1,w1,h1, x2,y2,w2,h2) - local dx = x1 - x2 + (w1 - w2)/2 - local dy = y1 - y2 + (h1 - h2)/2 - return dx*dx + dy*dy -end - -local function rect_detectCollision(x1,y1,w1,h1, x2,y2,w2,h2, goalX, goalY) - goalX = goalX or x1 - goalY = goalY or y1 - - local dx, dy = goalX - x1, goalY - y1 - local x,y,w,h = rect_getDiff(x1,y1,w1,h1, x2,y2,w2,h2) - - local overlaps, ti, nx, ny - - if rect_containsPoint(x,y,w,h, 0,0) then -- item was intersecting other - local px, py = rect_getNearestCorner(x,y,w,h, 0, 0) - local wi, hi = min(w1, abs(px)), min(h1, abs(py)) -- area of intersection - ti = -wi * hi -- ti is the negative area of intersection - overlaps = true - else - local ti1,ti2,nx1,ny1 = rect_getSegmentIntersectionIndices(x,y,w,h, 0,0,dx,dy, -math.huge, math.huge) - - -- item tunnels into other - if ti1 - and ti1 < 1 - and (abs(ti1 - ti2) >= DELTA) -- special case for rect going through another rect's corner - and (0 < ti1 + DELTA - or 0 == ti1 and ti2 > 0) - then - ti, nx, ny = ti1, nx1, ny1 - overlaps = false - end - end - - if not ti then return end - - local tx, ty - - if overlaps then - if dx == 0 and dy == 0 then - -- intersecting and not moving - use minimum displacement vector - local px, py = rect_getNearestCorner(x,y,w,h, 0,0) - if abs(px) < abs(py) then py = 0 else px = 0 end - nx, ny = sign(px), sign(py) - tx, ty = x1 + px, y1 + py - else - -- intersecting and moving - move in the opposite direction - local ti1, _ - ti1,_,nx,ny = rect_getSegmentIntersectionIndices(x,y,w,h, 0,0,dx,dy, -math.huge, 1) - if not ti1 then return end - tx, ty = x1 + dx * ti1, y1 + dy * ti1 - end - else -- tunnel - tx, ty = x1 + dx * ti, y1 + dy * ti - end - - return { - overlaps = overlaps, - ti = ti, - move = {x = dx, y = dy}, - normal = {x = nx, y = ny}, - touch = {x = tx, y = ty}, - itemRect = {x = x1, y = y1, w = w1, h = h1}, - otherRect = {x = x2, y = y2, w = w2, h = h2} - } -end - ------------------------------------------- --- Grid functions ------------------------------------------- - -local function grid_toWorld(cellSize, cx, cy) - return (cx - 1)*cellSize, (cy-1)*cellSize -end - -local function grid_toCell(cellSize, x, y) - return floor(x / cellSize) + 1, floor(y / cellSize) + 1 -end - --- grid_traverse* functions are based on "A Fast Voxel Traversal Algorithm for Ray Tracing", --- by John Amanides and Andrew Woo - http://www.cse.yorku.ca/~amana/research/grid.pdf --- It has been modified to include both cells when the ray "touches a grid corner", --- and with a different exit condition - -local function grid_traverse_initStep(cellSize, ct, t1, t2) - local v = t2 - t1 - if v > 0 then - return 1, cellSize / v, ((ct + v) * cellSize - t1) / v - elseif v < 0 then - return -1, -cellSize / v, ((ct + v - 1) * cellSize - t1) / v - else - return 0, math.huge, math.huge - end -end - -local function grid_traverse(cellSize, x1,y1,x2,y2, f) - local cx1,cy1 = grid_toCell(cellSize, x1,y1) - local cx2,cy2 = grid_toCell(cellSize, x2,y2) - local stepX, dx, tx = grid_traverse_initStep(cellSize, cx1, x1, x2) - local stepY, dy, ty = grid_traverse_initStep(cellSize, cy1, y1, y2) - local cx,cy = cx1,cy1 - - f(cx, cy) - - -- The default implementation had an infinite loop problem when - -- approaching the last cell in some occassions. We finish iterating - -- when we are *next* to the last cell - while abs(cx - cx2) + abs(cy - cy2) > 1 do - if tx < ty then - tx, cx = tx + dx, cx + stepX - f(cx, cy) - else - -- Addition: include both cells when going through corners - if tx == ty then f(cx + stepX, cy) end - ty, cy = ty + dy, cy + stepY - f(cx, cy) - end - end - - -- If we have not arrived to the last cell, use it - if cx ~= cx2 or cy ~= cy2 then f(cx2, cy2) end - -end - -local function grid_toCellRect(cellSize, x,y,w,h) - local cx,cy = grid_toCell(cellSize, x, y) - local cr,cb = ceil((x+w) / cellSize), ceil((y+h) / cellSize) - return cx, cy, cr - cx + 1, cb - cy + 1 -end - ------------------------------------------- --- Responses ------------------------------------------- - -local touch = function(world, col, x,y,w,h, goalX, goalY, filter) - return col.touch.x, col.touch.y, {}, 0 -end - -local cross = function(world, col, x,y,w,h, goalX, goalY, filter) - local cols, len = world:project(col.item, x,y,w,h, goalX, goalY, filter) - return goalX, goalY, cols, len -end - -local slide = function(world, col, x,y,w,h, goalX, goalY, filter) - goalX = goalX or x - goalY = goalY or y - - local tch, move = col.touch, col.move - local sx, sy = tch.x, tch.y - if move.x ~= 0 or move.y ~= 0 then - if col.normal.x == 0 then - sx = goalX - else - sy = goalY - end - end - - col.slide = {x = sx, y = sy} - - x,y = tch.x, tch.y - goalX, goalY = sx, sy - local cols, len = world:project(col.item, x,y,w,h, goalX, goalY, filter) - return goalX, goalY, cols, len -end - -local bounce = function(world, col, x,y,w,h, goalX, goalY, filter) - goalX = goalX or x - goalY = goalY or y - - local tch, move = col.touch, col.move - local tx, ty = tch.x, tch.y - - local bx, by = tx, ty - - if move.x ~= 0 or move.y ~= 0 then - local bnx, bny = goalX - tx, goalY - ty - if col.normal.x == 0 then bny = -bny else bnx = -bnx end - bx, by = tx + bnx, ty + bny - end - - col.bounce = {x = bx, y = by} - x,y = tch.x, tch.y - goalX, goalY = bx, by - - local cols, len = world:project(col.item, x,y,w,h, goalX, goalY, filter) - return goalX, goalY, cols, len -end - ------------------------------------------- --- World ------------------------------------------- - -local World = {} -local World_mt = {__index = World} - --- Private functions and methods - -local function sortByWeight(a,b) return a.weight < b.weight end - -local function sortByTiAndDistance(a,b) - if a.ti == b.ti then - local ir, ar, br = a.itemRect, a.otherRect, b.otherRect - local ad = rect_getSquareDistance(ir.x,ir.y,ir.w,ir.h, ar.x,ar.y,ar.w,ar.h) - local bd = rect_getSquareDistance(ir.x,ir.y,ir.w,ir.h, br.x,br.y,br.w,br.h) - return ad < bd - end - return a.ti < b.ti -end - -local function addItemToCell(self, item, cx, cy) - self.rows[cy] = self.rows[cy] or setmetatable({}, {__mode = 'v'}) - local row = self.rows[cy] - row[cx] = row[cx] or {itemCount = 0, x = cx, y = cy, items = setmetatable({}, {__mode = 'k'})} - local cell = row[cx] - self.nonEmptyCells[cell] = true - if not cell.items[item] then - cell.items[item] = true - cell.itemCount = cell.itemCount + 1 - end -end - -local function removeItemFromCell(self, item, cx, cy) - local row = self.rows[cy] - if not row or not row[cx] or not row[cx].items[item] then return false end - - local cell = row[cx] - cell.items[item] = nil - cell.itemCount = cell.itemCount - 1 - if cell.itemCount == 0 then - self.nonEmptyCells[cell] = nil - end - return true -end - -local function getDictItemsInCellRect(self, cl,ct,cw,ch) - local items_dict = {} - for cy=ct,ct+ch-1 do - local row = self.rows[cy] - if row then - for cx=cl,cl+cw-1 do - local cell = row[cx] - if cell and cell.itemCount > 0 then -- no cell.itemCount > 1 because tunneling - for item,_ in pairs(cell.items) do - items_dict[item] = true - end - end - end - end - end - - return items_dict -end - -local function getCellsTouchedBySegment(self, x1,y1,x2,y2) - - local cells, cellsLen, visited = {}, 0, {} - - grid_traverse(self.cellSize, x1,y1,x2,y2, function(cx, cy) - local row = self.rows[cy] - if not row then return end - local cell = row[cx] - if not cell or visited[cell] then return end - - visited[cell] = true - cellsLen = cellsLen + 1 - cells[cellsLen] = cell - end) - - return cells, cellsLen -end - -local function getInfoAboutItemsTouchedBySegment(self, x1,y1, x2,y2, filter) - local cells, len = getCellsTouchedBySegment(self, x1,y1,x2,y2) - local cell, rect, l,t,w,h, ti1,ti2, tii0,tii1 - local visited, itemInfo, itemInfoLen = {},{},0 - for i=1,len do - cell = cells[i] - for item in pairs(cell.items) do - if not visited[item] then - visited[item] = true - if (not filter or filter(item)) then - rect = self.rects[item] - l,t,w,h = rect.x,rect.y,rect.w,rect.h - - ti1,ti2 = rect_getSegmentIntersectionIndices(l,t,w,h, x1,y1, x2,y2, 0, 1) - if ti1 and ((0 < ti1 and ti1 < 1) or (0 < ti2 and ti2 < 1)) then - -- the sorting is according to the t of an infinite line, not the segment - tii0,tii1 = rect_getSegmentIntersectionIndices(l,t,w,h, x1,y1, x2,y2, -math.huge, math.huge) - itemInfoLen = itemInfoLen + 1 - itemInfo[itemInfoLen] = {item = item, ti1 = ti1, ti2 = ti2, weight = min(tii0,tii1)} - end - end - end - end - end - table.sort(itemInfo, sortByWeight) - return itemInfo, itemInfoLen -end - -local function getResponseByName(self, name) - local response = self.responses[name] - if not response then - error(('Unknown collision type: %s (%s)'):format(name, type(name))) - end - return response -end - - --- Misc Public Methods - -function World:addResponse(name, response) - self.responses[name] = response -end - -function World:project(item, x,y,w,h, goalX, goalY, filter) - assertIsRect(x,y,w,h) - - goalX = goalX or x - goalY = goalY or y - filter = filter or defaultFilter - - local collisions, len = {}, 0 - - local visited = {} - if item ~= nil then visited[item] = true end - - -- This could probably be done with less cells using a polygon raster over the cells instead of a - -- bounding rect of the whole movement. Conditional to building a queryPolygon method - local tl, tt = min(goalX, x), min(goalY, y) - local tr, tb = max(goalX + w, x+w), max(goalY + h, y+h) - local tw, th = tr-tl, tb-tt - - local cl,ct,cw,ch = grid_toCellRect(self.cellSize, tl,tt,tw,th) - - local dictItemsInCellRect = getDictItemsInCellRect(self, cl,ct,cw,ch) - - for other,_ in pairs(dictItemsInCellRect) do - if not visited[other] then - visited[other] = true - - local responseName = filter(item, other) - if responseName then - local ox,oy,ow,oh = self:getRect(other) - local col = rect_detectCollision(x,y,w,h, ox,oy,ow,oh, goalX, goalY) - - if col then - col.other = other - col.item = item - col.type = responseName - - len = len + 1 - collisions[len] = col - end - end - end - end - - table.sort(collisions, sortByTiAndDistance) - - return collisions, len -end - -function World:countCells() - local count = 0 - for _,row in pairs(self.rows) do - for _,_ in pairs(row) do - count = count + 1 - end - end - return count -end - -function World:hasItem(item) - return not not self.rects[item] -end - -function World:getItems() - local items, len = {}, 0 - for item,_ in pairs(self.rects) do - len = len + 1 - items[len] = item - end - return items, len -end - -function World:countItems() - local len = 0 - for _ in pairs(self.rects) do len = len + 1 end - return len -end - -function World:getRect(item) - local rect = self.rects[item] - if not rect then - error('Item ' .. tostring(item) .. ' must be added to the world before getting its rect. Use world:add(item, x,y,w,h) to add it first.') - end - return rect.x, rect.y, rect.w, rect.h -end - -function World:toWorld(cx, cy) - return grid_toWorld(self.cellSize, cx, cy) -end - -function World:toCell(x,y) - return grid_toCell(self.cellSize, x, y) -end - - ---- Query methods - -function World:queryRect(x,y,w,h, filter) - - assertIsRect(x,y,w,h) - - local cl,ct,cw,ch = grid_toCellRect(self.cellSize, x,y,w,h) - local dictItemsInCellRect = getDictItemsInCellRect(self, cl,ct,cw,ch) - - local items, len = {}, 0 - - local rect - for item,_ in pairs(dictItemsInCellRect) do - rect = self.rects[item] - if (not filter or filter(item)) - and rect_isIntersecting(x,y,w,h, rect.x, rect.y, rect.w, rect.h) - then - len = len + 1 - items[len] = item - end - end - - return items, len -end - -function World:queryPoint(x,y, filter) - local cx,cy = self:toCell(x,y) - local dictItemsInCellRect = getDictItemsInCellRect(self, cx,cy,1,1) - - local items, len = {}, 0 - - local rect - for item,_ in pairs(dictItemsInCellRect) do - rect = self.rects[item] - if (not filter or filter(item)) - and rect_containsPoint(rect.x, rect.y, rect.w, rect.h, x, y) - then - len = len + 1 - items[len] = item - end - end - - return items, len -end - -function World:querySegment(x1, y1, x2, y2, filter) - local itemInfo, len = getInfoAboutItemsTouchedBySegment(self, x1, y1, x2, y2, filter) - local items = {} - for i=1, len do - items[i] = itemInfo[i].item - end - return items, len -end - -function World:querySegmentWithCoords(x1, y1, x2, y2, filter) - local itemInfo, len = getInfoAboutItemsTouchedBySegment(self, x1, y1, x2, y2, filter) - local dx, dy = x2-x1, y2-y1 - local info, ti1, ti2 - for i=1, len do - info = itemInfo[i] - ti1 = info.ti1 - ti2 = info.ti2 - - info.weight = nil - info.x1 = x1 + dx * ti1 - info.y1 = y1 + dy * ti1 - info.x2 = x1 + dx * ti2 - info.y2 = y1 + dy * ti2 - end - return itemInfo, len -end - - ---- Main methods - -function World:add(item, x,y,w,h) - local rect = self.rects[item] - if rect then - error('Item ' .. tostring(item) .. ' added to the world twice.') - end - assertIsRect(x,y,w,h) - - self.rects[item] = {x=x,y=y,w=w,h=h} - - local cl,ct,cw,ch = grid_toCellRect(self.cellSize, x,y,w,h) - for cy = ct, ct+ch-1 do - for cx = cl, cl+cw-1 do - addItemToCell(self, item, cx, cy) - end - end - - return item -end - -function World:remove(item) - local x,y,w,h = self:getRect(item) - - self.rects[item] = nil - local cl,ct,cw,ch = grid_toCellRect(self.cellSize, x,y,w,h) - for cy = ct, ct+ch-1 do - for cx = cl, cl+cw-1 do - removeItemFromCell(self, item, cx, cy) - end - end -end - -function World:update(item, x2,y2,w2,h2) - local x1,y1,w1,h1 = self:getRect(item) - w2,h2 = w2 or w1, h2 or h1 - assertIsRect(x2,y2,w2,h2) - - if x1 ~= x2 or y1 ~= y2 or w1 ~= w2 or h1 ~= h2 then - - local cellSize = self.cellSize - local cl1,ct1,cw1,ch1 = grid_toCellRect(cellSize, x1,y1,w1,h1) - local cl2,ct2,cw2,ch2 = grid_toCellRect(cellSize, x2,y2,w2,h2) - - if cl1 ~= cl2 or ct1 ~= ct2 or cw1 ~= cw2 or ch1 ~= ch2 then - - local cr1, cb1 = cl1+cw1-1, ct1+ch1-1 - local cr2, cb2 = cl2+cw2-1, ct2+ch2-1 - local cyOut - - for cy = ct1, cb1 do - cyOut = cy < ct2 or cy > cb2 - for cx = cl1, cr1 do - if cyOut or cx < cl2 or cx > cr2 then - removeItemFromCell(self, item, cx, cy) - end - end - end - - for cy = ct2, cb2 do - cyOut = cy < ct1 or cy > cb1 - for cx = cl2, cr2 do - if cyOut or cx < cl1 or cx > cr1 then - addItemToCell(self, item, cx, cy) - end - end - end - - end - - local rect = self.rects[item] - rect.x, rect.y, rect.w, rect.h = x2,y2,w2,h2 - - end -end - -function World:move(item, goalX, goalY, filter) - local actualX, actualY, cols, len = self:check(item, goalX, goalY, filter) - - self:update(item, actualX, actualY) - - return actualX, actualY, cols, len -end - -function World:check(item, goalX, goalY, filter) - filter = filter or defaultFilter - - local visited = {[item] = true} - local visitedFilter = function(itm, other) - if visited[other] then return false end - return filter(itm, other) - end - - local cols, len = {}, 0 - - local x,y,w,h = self:getRect(item) - - local projected_cols, projected_len = self:project(item, x,y,w,h, goalX,goalY, visitedFilter) - - while projected_len > 0 do - local col = projected_cols[1] - len = len + 1 - cols[len] = col - - visited[col.other] = true - - local response = getResponseByName(self, col.type) - - goalX, goalY, projected_cols, projected_len = response( - self, - col, - x, y, w, h, - goalX, goalY, - visitedFilter - ) - end - - return goalX, goalY, cols, len -end - - --- Public library functions - -bump.newWorld = function(cellSize) - cellSize = cellSize or 64 - assertIsPositiveNumber(cellSize, 'cellSize') - local world = setmetatable({ - cellSize = cellSize, - rects = {}, - rows = {}, - nonEmptyCells = {}, - responses = {} - }, World_mt) - - world:addResponse('touch', touch) - world:addResponse('cross', cross) - world:addResponse('slide', slide) - world:addResponse('bounce', bounce) - - return world -end - -bump.rect = { - getNearestCorner = rect_getNearestCorner, - getSegmentIntersectionIndices = rect_getSegmentIntersectionIndices, - getDiff = rect_getDiff, - containsPoint = rect_containsPoint, - isIntersecting = rect_isIntersecting, - getSquareDistance = rect_getSquareDistance, - detectCollision = rect_detectCollision -} - -bump.responses = { - touch = touch, - cross = cross, - slide = slide, - bounce = bounce -} - -return bump diff --git a/imperium-porcorum.love/libs/cscreen.lua b/imperium-porcorum.love/libs/cscreen.lua deleted file mode 100644 index 579ea0d..0000000 --- a/imperium-porcorum.love/libs/cscreen.lua +++ /dev/null @@ -1,99 +0,0 @@ ---[[ -CScreen v1.3 by CodeNMore -A simple way to make resolution-independent Love2D games -Tested for LOVE 0.10.1 -See: https://github.com/CodeNMore/CScreen -Zlib License: -Copyright (c) 2016 CodeNMore -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from -the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: -1. The origin of this software must not be misrepresented; you must not -claim that you wrote the original software. If you use this software in -a product, an acknowledgment in the product documentation would be appreciated -but is not required. -2. Altered source versions must be plainly marked as such, and must not be -misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. ---]] - -local CScreen = {} -local rx, ry, ctr = 800, 600, true -local rxv, ryv, fsv, fsvr = 800, 600, 1.0, 1.0 -local tx, ty, rwf, rhf = 0, 0, 800, 600 -local cr, cg, cb, ca = 0, 0, 0, 255 - --- Initializes CScreen with the initial size values -function CScreen.init(tw, th, cntr) - rx = tw or 800 - ry = th or 600 - ctr = cntr or false - CScreen.update(love.graphics.getWidth(), love.graphics.getHeight()) -end - --- Draws letterbox borders -function CScreen.cease() - if ctr then - local pr, pg, pb, pa = love.graphics.getColor() - love.graphics.setColor(cr, cg, cb, ca) - love.graphics.scale(fsvr, fsvr) - - if tx ~= 0 then - love.graphics.rectangle("fill", -tx, 0, tx, rhf) - love.graphics.rectangle("fill", rxv, 0, tx, rhf) - elseif ty ~= 0 then - love.graphics.rectangle("fill", 0, -ty, rwf, ty) - love.graphics.rectangle("fill", 0, ryv, rwf, ty) - end - - love.graphics.setColor(pr, pg, pb, pa) - end -end - --- Scales and centers all graphics properly -function CScreen.apply() - if ctr then - love.graphics.translate(tx, ty) - end - love.graphics.scale(fsv, fsv) -end - --- Updates CScreen when the window size changes -function CScreen.update(w, h) - local sx = w / rx - local sy = h / ry - fsv = math.min(sx, sy) - fsvr = 1 / fsv - -- Centering - if ctr and fsv == sx then -- Vertically - tx = 0 - ty = (h / 2) - (ry * fsv / 2) - elseif ctr and fsv == sy then -- Horizontally - ty = 0 - tx = (w / 2) - (rx * fsv / 2) - end - -- Variable sets - rwf = w - rhf = h - rxv = rx * fsv - ryv = ry * fsv -end - --- Convert from window coordinates to target coordinates -function CScreen.project(x, y) - return math.floor((x - tx) / fsv), math.floor((y - ty) / fsv) -end - --- Change letterbox color -function CScreen.setColor(r, g, b, a) - cr = r - cg = g - cb = b - ca = a -end - --- Return the table for use -return CScreen diff --git a/imperium-porcorum.love/libs/hump/camera.lua b/imperium-porcorum.love/libs/hump/camera.lua deleted file mode 100644 index cb86a79..0000000 --- a/imperium-porcorum.love/libs/hump/camera.lua +++ /dev/null @@ -1,216 +0,0 @@ ---[[ -Copyright (c) 2010-2015 Matthias Richter - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -Except as contained in this notice, the name(s) of the above copyright holders -shall not be used in advertising or otherwise to promote the sale, use or -other dealings in this Software without prior written authorization. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -]]-- - -local _PATH = (...):match('^(.*[%./])[^%.%/]+$') or '' -local cos, sin = math.cos, math.sin - -local camera = {} -camera.__index = camera - --- Movement interpolators (for camera locking/windowing) -camera.smooth = {} - -function camera.smooth.none() - return function(dx,dy) return dx,dy end -end - -function camera.smooth.linear(speed) - assert(type(speed) == "number", "Invalid parameter: speed = "..tostring(speed)) - return function(dx,dy, s) - -- normalize direction - local d = math.sqrt(dx*dx+dy*dy) - local dts = math.min((s or speed) * love.timer.getDelta(), d) -- prevent overshooting the goal - if d > 0 then - dx,dy = dx/d, dy/d - end - - return dx*dts, dy*dts - end -end - -function camera.smooth.damped(stiffness) - assert(type(stiffness) == "number", "Invalid parameter: stiffness = "..tostring(stiffness)) - return function(dx,dy, s) - local dts = love.timer.getDelta() * (s or stiffness) - return dx*dts, dy*dts - end -end - - -local function new(x,y, zoom, rot, smoother) - x,y = x or love.graphics.getWidth()/2, y or love.graphics.getHeight()/2 - zoom = zoom or 1 - rot = rot or 0 - smoother = smoother or camera.smooth.none() -- for locking, see below - return setmetatable({x = x, y = y, scale = zoom, rot = rot, smoother = smoother}, camera) -end - -function camera:lookAt(x,y) - self.x, self.y = x, y - return self -end - -function camera:move(dx,dy) - self.x, self.y = self.x + dx, self.y + dy - return self -end - -function camera:position() - return self.x, self.y -end - -function camera:rotate(phi) - self.rot = self.rot + phi - return self -end - -function camera:rotateTo(phi) - self.rot = phi - return self -end - -function camera:zoom(mul) - self.scale = self.scale * mul - return self -end - -function camera:zoomTo(zoom) - self.scale = zoom - return self -end - -function camera:attach(x,y,w,h, noclip) - x,y = x or 0, y or 0 - w,h = w or love.graphics.getWidth(), h or love.graphics.getHeight() - - self._sx,self._sy,self._sw,self._sh = love.graphics.getScissor() - if not noclip then - love.graphics.setScissor(x,y,w,h) - end - - local cx,cy = x+w/2, y+h/2 - love.graphics.push() - love.graphics.translate(cx, cy) - love.graphics.scale(self.scale) - love.graphics.rotate(self.rot) - love.graphics.translate(-self.x, -self.y) -end - -function camera:detach() - love.graphics.pop() - love.graphics.setScissor(self._sx,self._sy,self._sw,self._sh) -end - -function camera:draw(...) - local x,y,w,h,noclip,func - local nargs = select("#", ...) - if nargs == 1 then - func = ... - elseif nargs == 5 then - x,y,w,h,func = ... - elseif nargs == 6 then - x,y,w,h,noclip,func = ... - else - error("Invalid arguments to camera:draw()") - end - - self:attach(x,y,w,h,noclip) - func() - self:detach() -end - --- world coordinates to camera coordinates -function camera:cameraCoords(x,y, ox,oy,w,h) - ox, oy = ox or 0, oy or 0 - w,h = w or love.graphics.getWidth(), h or love.graphics.getHeight() - - -- x,y = ((x,y) - (self.x, self.y)):rotated(self.rot) * self.scale + center - local c,s = cos(self.rot), sin(self.rot) - x,y = x - self.x, y - self.y - x,y = c*x - s*y, s*x + c*y - return x*self.scale + w/2 + ox, y*self.scale + h/2 + oy -end - --- camera coordinates to world coordinates -function camera:worldCoords(x,y, ox,oy,w,h) - ox, oy = ox or 0, oy or 0 - w,h = w or love.graphics.getWidth(), h or love.graphics.getHeight() - - -- x,y = (((x,y) - center) / self.scale):rotated(-self.rot) + (self.x,self.y) - local c,s = cos(-self.rot), sin(-self.rot) - x,y = (x - w/2 - ox) / self.scale, (y - h/2 - oy) / self.scale - x,y = c*x - s*y, s*x + c*y - return x+self.x, y+self.y -end - -function camera:mousePosition(ox,oy,w,h) - local mx,my = love.mouse.getPosition() - return self:worldCoords(mx,my, ox,oy,w,h) -end - --- camera scrolling utilities -function camera:lockX(x, smoother, ...) - local dx, dy = (smoother or self.smoother)(x - self.x, self.y, ...) - self.x = self.x + dx - return self -end - -function camera:lockY(y, smoother, ...) - local dx, dy = (smoother or self.smoother)(self.x, y - self.y, ...) - self.y = self.y + dy - return self -end - -function camera:lockPosition(x,y, smoother, ...) - return self:move((smoother or self.smoother)(x - self.x, y - self.y, ...)) -end - -function camera:lockWindow(x, y, x_min, x_max, y_min, y_max, smoother, ...) - -- figure out displacement in camera coordinates - x,y = self:cameraCoords(x,y) - local dx, dy = 0,0 - if x < x_min then - dx = x - x_min - elseif x > x_max then - dx = x - x_max - end - if y < y_min then - dy = y - y_min - elseif y > y_max then - dy = y - y_max - end - - -- transform displacement to movement in world coordinates - local c,s = cos(-self.rot), sin(-self.rot) - dx,dy = (c*dx - s*dy) / self.scale, (s*dx + c*dy) / self.scale - - -- move - self:move((smoother or self.smoother)(dx,dy,...)) -end - --- the module -return setmetatable({new = new, smooth = camera.smooth}, - {__call = function(_, ...) return new(...) end}) diff --git a/imperium-porcorum.love/libs/hump/class.lua b/imperium-porcorum.love/libs/hump/class.lua deleted file mode 100644 index 7d62707..0000000 --- a/imperium-porcorum.love/libs/hump/class.lua +++ /dev/null @@ -1,98 +0,0 @@ ---[[ -Copyright (c) 2010-2013 Matthias Richter - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -Except as contained in this notice, the name(s) of the above copyright holders -shall not be used in advertising or otherwise to promote the sale, use or -other dealings in this Software without prior written authorization. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -]]-- - -local function include_helper(to, from, seen) - if from == nil then - return to - elseif type(from) ~= 'table' then - return from - elseif seen[from] then - return seen[from] - end - - seen[from] = to - for k,v in pairs(from) do - k = include_helper({}, k, seen) -- keys might also be tables - if to[k] == nil then - to[k] = include_helper({}, v, seen) - end - end - return to -end - --- deeply copies `other' into `class'. keys in `other' that are already --- defined in `class' are omitted -local function include(class, other) - return include_helper(class, other, {}) -end - --- returns a deep copy of `other' -local function clone(other) - return setmetatable(include({}, other), getmetatable(other)) -end - -local function new(class) - -- mixins - class = class or {} -- class can be nil - local inc = class.__includes or {} - if getmetatable(inc) then inc = {inc} end - - for _, other in ipairs(inc) do - if type(other) == "string" then - other = _G[other] - end - include(class, other) - end - - -- class implementation - class.__index = class - class.init = class.init or class[1] or function() end - class.include = class.include or include - class.clone = class.clone or clone - - -- constructor call - return setmetatable(class, {__call = function(c, ...) - local o = setmetatable({}, c) - o:init(...) - return o - end}) -end - --- interface for cross class-system compatibility (see https://github.com/bartbes/Class-Commons). -if class_commons ~= false and not common then - common = {} - function common.class(name, prototype, parent) - return new{__includes = {prototype, parent}} - end - function common.instance(class, ...) - return class(...) - end -end - - --- the module -return setmetatable({new = new, include = include, clone = clone}, - {__call = function(_,...) return new(...) end}) diff --git a/imperium-porcorum.love/libs/hump/gamestate.lua b/imperium-porcorum.love/libs/hump/gamestate.lua deleted file mode 100644 index 4a42205..0000000 --- a/imperium-porcorum.love/libs/hump/gamestate.lua +++ /dev/null @@ -1,108 +0,0 @@ ---[[ -Copyright (c) 2010-2013 Matthias Richter - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -Except as contained in this notice, the name(s) of the above copyright holders -shall not be used in advertising or otherwise to promote the sale, use or -other dealings in this Software without prior written authorization. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -]]-- - -local function __NULL__() end - - -- default gamestate produces error on every callback -local state_init = setmetatable({leave = __NULL__}, - {__index = function() error("Gamestate not initialized. Use Gamestate.switch()") end}) -local stack = {state_init} -local initialized_states = setmetatable({}, {__mode = "k"}) -local state_is_dirty = true - -local GS = {} -function GS.new(t) return t or {} end -- constructor - deprecated! - -local function change_state(stack_offset, to, ...) - local pre = stack[#stack] - - -- initialize only on first call - ;(initialized_states[to] or to.init or __NULL__)(to) - initialized_states[to] = __NULL__ - - stack[#stack+stack_offset] = to - state_is_dirty = true - return (to.enter or __NULL__)(to, pre, ...) -end - -function GS.switch(to, ...) - assert(to, "Missing argument: Gamestate to switch to") - assert(to ~= GS, "Can't call switch with colon operator") - ;(stack[#stack].leave or __NULL__)(stack[#stack]) - return change_state(0, to, ...) -end - -function GS.push(to, ...) - assert(to, "Missing argument: Gamestate to switch to") - assert(to ~= GS, "Can't call push with colon operator") - return change_state(1, to, ...) -end - -function GS.pop(...) - assert(#stack > 1, "No more states to pop!") - local pre, to = stack[#stack], stack[#stack-1] - stack[#stack] = nil - ;(pre.leave or __NULL__)(pre) - state_is_dirty = true - return (to.resume or __NULL__)(to, pre, ...) -end - -function GS.current() - return stack[#stack] -end - --- fetch event callbacks from love.handlers -local all_callbacks = { 'draw', 'errhand', 'update' } -for k in pairs(love.handlers) do - all_callbacks[#all_callbacks+1] = k -end - -function GS.registerEvents(callbacks) - local registry = {} - callbacks = callbacks or all_callbacks - for _, f in ipairs(callbacks) do - registry[f] = love[f] or __NULL__ - love[f] = function(...) - registry[f](...) - return GS[f](...) - end - end -end - --- forward any undefined functions -setmetatable(GS, {__index = function(_, func) - -- call function only if at least one 'update' was called beforehand - -- (see issue #46) - if not state_is_dirty or func == 'update' then - state_is_dirty = false - return function(...) - return (stack[#stack][func] or __NULL__)(stack[#stack], ...) - end - end - return __NULL__ -end}) - -return GS diff --git a/imperium-porcorum.love/libs/hump/signal.lua b/imperium-porcorum.love/libs/hump/signal.lua deleted file mode 100644 index e204ca0..0000000 --- a/imperium-porcorum.love/libs/hump/signal.lua +++ /dev/null @@ -1,102 +0,0 @@ ---[[ -Copyright (c) 2012-2013 Matthias Richter - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -Except as contained in this notice, the name(s) of the above copyright holders -shall not be used in advertising or otherwise to promote the sale, use or -other dealings in this Software without prior written authorization. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -]]-- - -local Registry = {} -Registry.__index = function(self, key) - return Registry[key] or (function() - local t = {} - rawset(self, key, t) - return t - end)() -end - -function Registry:register(s, f) - self[s][f] = f - return f -end - -function Registry:emit(s, ...) - for f in pairs(self[s]) do - f(...) - end -end - -function Registry:remove(s, ...) - local f = {...} - for i = 1,select('#', ...) do - self[s][f[i]] = nil - end -end - -function Registry:clear(...) - local s = {...} - for i = 1,select('#', ...) do - self[s[i]] = {} - end -end - -function Registry:emitPattern(p, ...) - for s in pairs(self) do - if s:match(p) then self:emit(s, ...) end - end -end - -function Registry:registerPattern(p, f) - for s in pairs(self) do - if s:match(p) then self:register(s, f) end - end - return f -end - -function Registry:removePattern(p, ...) - for s in pairs(self) do - if s:match(p) then self:remove(s, ...) end - end -end - -function Registry:clearPattern(p) - for s in pairs(self) do - if s:match(p) then self[s] = {} end - end -end - --- instancing -function Registry.new() - return setmetatable({}, Registry) -end - --- default instance -local default = Registry.new() - --- module forwards calls to default instance -local module = {} -for k in pairs(Registry) do - if k ~= "__index" then - module[k] = function(...) return default[k](default, ...) end - end -end - -return setmetatable(module, {__call = Registry.new}) diff --git a/imperium-porcorum.love/libs/hump/timer.lua b/imperium-porcorum.love/libs/hump/timer.lua deleted file mode 100644 index 5b4e515..0000000 --- a/imperium-porcorum.love/libs/hump/timer.lua +++ /dev/null @@ -1,210 +0,0 @@ ---[[ -Copyright (c) 2010-2013 Matthias Richter - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -Except as contained in this notice, the name(s) of the above copyright holders -shall not be used in advertising or otherwise to promote the sale, use or -other dealings in this Software without prior written authorization. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -]]-- - -local Timer = {} -Timer.__index = Timer - -local function _nothing_() end - -function Timer:update(dt) - local to_remove = {} - - for handle in pairs(self.functions) do - -- handle: { - -- time = , - -- after = , - -- during = , - -- limit = , - -- count = , - -- } - - handle.time = handle.time + dt - handle.during(dt, math.max(handle.limit - handle.time, 0)) - - while handle.time >= handle.limit and handle.count > 0 do - if handle.after(handle.after) == false then - handle.count = 0 - break - end - handle.time = handle.time - handle.limit - handle.count = handle.count - 1 - end - - if handle.count == 0 then - table.insert(to_remove, handle) - end - end - - for i = 1, #to_remove do - self.functions[to_remove[i]] = nil - end -end - -function Timer:during(delay, during, after) - local handle = { time = 0, during = during, after = after or _nothing_, limit = delay, count = 1 } - self.functions[handle] = true - return handle -end - -function Timer:after(delay, func) - return self:during(delay, _nothing_, func) -end - -function Timer:every(delay, after, count) - local count = count or math.huge -- exploit below: math.huge - 1 = math.huge - local handle = { time = 0, during = _nothing_, after = after, limit = delay, count = count } - self.functions[handle] = true - return handle -end - -function Timer:cancel(handle) - self.functions[handle] = nil -end - -function Timer:clear() - self.functions = {} -end - -function Timer:script(f) - local co = coroutine.wrap(f) - co(function(t) - self:after(t, co) - coroutine.yield() - end) -end - -Timer.tween = setmetatable({ - -- helper functions - out = function(f) -- 'rotates' a function - return function(s, ...) return 1 - f(1-s, ...) end - end, - chain = function(f1, f2) -- concatenates two functions - return function(s, ...) return (s < .5 and f1(2*s, ...) or 1 + f2(2*s-1, ...)) * .5 end - end, - - -- useful tweening functions - linear = function(s) return s end, - quad = function(s) return s*s end, - cubic = function(s) return s*s*s end, - quart = function(s) return s*s*s*s end, - quint = function(s) return s*s*s*s*s end, - sine = function(s) return 1-math.cos(s*math.pi/2) end, - expo = function(s) return 2^(10*(s-1)) end, - circ = function(s) return 1 - math.sqrt(1-s*s) end, - - back = function(s,bounciness) - bounciness = bounciness or 1.70158 - return s*s*((bounciness+1)*s - bounciness) - end, - - bounce = function(s) -- magic numbers ahead - local a,b = 7.5625, 1/2.75 - return math.min(a*s^2, a*(s-1.5*b)^2 + .75, a*(s-2.25*b)^2 + .9375, a*(s-2.625*b)^2 + .984375) - end, - - elastic = function(s, amp, period) - amp, period = amp and math.max(1, amp) or 1, period or .3 - return (-amp * math.sin(2*math.pi/period * (s-1) - math.asin(1/amp))) * 2^(10*(s-1)) - end, -}, { - --- register new tween -__call = function(tween, self, len, subject, target, method, after, ...) - -- recursively collects fields that are defined in both subject and target into a flat list - local function tween_collect_payload(subject, target, out) - for k,v in pairs(target) do - local ref = subject[k] - assert(type(v) == type(ref), 'Type mismatch in field "'..k..'".') - if type(v) == 'table' then - tween_collect_payload(ref, v, out) - else - local ok, delta = pcall(function() return (v-ref)*1 end) - assert(ok, 'Field "'..k..'" does not support arithmetic operations') - out[#out+1] = {subject, k, delta} - end - end - return out - end - - method = tween[method or 'linear'] -- see __index - local payload, t, args = tween_collect_payload(subject, target, {}), 0, {...} - - local last_s = 0 - return self:during(len, function(dt) - t = t + dt - local s = method(math.min(1, t/len), unpack(args)) - local ds = s - last_s - last_s = s - for _, info in ipairs(payload) do - local ref, key, delta = unpack(info) - ref[key] = ref[key] + delta * ds - end - end, after) -end, - --- fetches function and generated compositions for method `key` -__index = function(tweens, key) - if type(key) == 'function' then return key end - - assert(type(key) == 'string', 'Method must be function or string.') - if rawget(tweens, key) then return rawget(tweens, key) end - - local function construct(pattern, f) - local method = rawget(tweens, key:match(pattern)) - if method then return f(method) end - return nil - end - - local out, chain = rawget(tweens,'out'), rawget(tweens,'chain') - return construct('^in%-([^-]+)$', function(...) return ... end) - or construct('^out%-([^-]+)$', out) - or construct('^in%-out%-([^-]+)$', function(f) return chain(f, out(f)) end) - or construct('^out%-in%-([^-]+)$', function(f) return chain(out(f), f) end) - or error('Unknown interpolation method: ' .. key) -end}) - --- Timer instancing -function Timer.new() - return setmetatable({functions = {}, tween = Timer.tween}, Timer) -end - --- default instance -local default = Timer.new() - --- module forwards calls to default instance -local module = {} -for k in pairs(Timer) do - if k ~= "__index" then - module[k] = function(...) return default[k](default, ...) end - end -end -module.tween = setmetatable({}, { - __index = Timer.tween, - __newindex = function(k,v) Timer.tween[k] = v end, - __call = function(t, ...) return default:tween(...) end, -}) - -return setmetatable(module, {__call = Timer.new}) diff --git a/imperium-porcorum.love/libs/hump/vector-light.lua b/imperium-porcorum.love/libs/hump/vector-light.lua deleted file mode 100644 index fc47a13..0000000 --- a/imperium-porcorum.love/libs/hump/vector-light.lua +++ /dev/null @@ -1,172 +0,0 @@ ---[[ -Copyright (c) 2012-2013 Matthias Richter - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -Except as contained in this notice, the name(s) of the above copyright holders -shall not be used in advertising or otherwise to promote the sale, use or -other dealings in this Software without prior written authorization. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -]]-- - -local sqrt, cos, sin, atan2 = math.sqrt, math.cos, math.sin, math.atan2 - -local function str(x,y) - return "("..tonumber(x)..","..tonumber(y)..")" -end - -local function mul(s, x,y) - return s*x, s*y -end - -local function div(s, x,y) - return x/s, y/s -end - -local function add(x1,y1, x2,y2) - return x1+x2, y1+y2 -end - -local function sub(x1,y1, x2,y2) - return x1-x2, y1-y2 -end - -local function permul(x1,y1, x2,y2) - return x1*x2, y1*y2 -end - -local function dot(x1,y1, x2,y2) - return x1*x2 + y1*y2 -end - -local function det(x1,y1, x2,y2) - return x1*y2 - y1*x2 -end - -local function eq(x1,y1, x2,y2) - return x1 == x2 and y1 == y2 -end - -local function lt(x1,y1, x2,y2) - return x1 < x2 or (x1 == x2 and y1 < y2) -end - -local function le(x1,y1, x2,y2) - return x1 <= x2 and y1 <= y2 -end - -local function len2(x,y) - return x*x + y*y -end - -local function len(x,y) - return sqrt(x*x + y*y) -end - -local function fromPolar(angle, radius) - return cos(angle)*radius, sin(angle)*radius -end - -local function toPolar(x, y) - return atan2(y,x), len(x,y) -end - -local function dist2(x1,y1, x2,y2) - return len2(x1-x2, y1-y2) -end - -local function dist(x1,y1, x2,y2) - return len(x1-x2, y1-y2) -end - -local function normalize(x,y) - local l = len(x,y) - if l > 0 then - return x/l, y/l - end - return x,y -end - -local function rotate(phi, x,y) - local c, s = cos(phi), sin(phi) - return c*x - s*y, s*x + c*y -end - -local function perpendicular(x,y) - return -y, x -end - -local function project(x,y, u,v) - local s = (x*u + y*v) / (u*u + v*v) - return s*u, s*v -end - -local function mirror(x,y, u,v) - local s = 2 * (x*u + y*v) / (u*u + v*v) - return s*u - x, s*v - y -end - --- ref.: http://blog.signalsondisplay.com/?p=336 -local function trim(maxLen, x, y) - local s = maxLen * maxLen / len2(x, y) - s = s > 1 and 1 or math.sqrt(s) - return x * s, y * s -end - -local function angleTo(x,y, u,v) - if u and v then - return atan2(y, x) - atan2(v, u) - end - return atan2(y, x) -end - --- the module -return { - str = str, - - fromPolar = fromPolar, - toPolar = toPolar, - - -- arithmetic - mul = mul, - div = div, - add = add, - sub = sub, - permul = permul, - dot = dot, - det = det, - cross = det, - - -- relation - eq = eq, - lt = lt, - le = le, - - -- misc operations - len2 = len2, - len = len, - dist2 = dist2, - dist = dist, - normalize = normalize, - rotate = rotate, - perpendicular = perpendicular, - project = project, - mirror = mirror, - trim = trim, - angleTo = angleTo, -} diff --git a/imperium-porcorum.love/libs/hump/vector.lua b/imperium-porcorum.love/libs/hump/vector.lua deleted file mode 100644 index 14775f3..0000000 --- a/imperium-porcorum.love/libs/hump/vector.lua +++ /dev/null @@ -1,199 +0,0 @@ ---[[ -Copyright (c) 2010-2013 Matthias Richter - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -Except as contained in this notice, the name(s) of the above copyright holders -shall not be used in advertising or otherwise to promote the sale, use or -other dealings in this Software without prior written authorization. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -]]-- - -local assert = assert -local sqrt, cos, sin, atan2 = math.sqrt, math.cos, math.sin, math.atan2 - -local vector = {} -vector.__index = vector - -local function new(x,y) - return setmetatable({x = x or 0, y = y or 0}, vector) -end -local zero = new(0,0) - -local function fromPolar(angle, radius) - return new(cos(angle) * radius, sin(angle) * radius) -end - -local function isvector(v) - return type(v) == 'table' and type(v.x) == 'number' and type(v.y) == 'number' -end - -function vector:clone() - return new(self.x, self.y) -end - -function vector:unpack() - return self.x, self.y -end - -function vector:__tostring() - return "("..tonumber(self.x)..","..tonumber(self.y)..")" -end - -function vector.__unm(a) - return new(-a.x, -a.y) -end - -function vector.__add(a,b) - assert(isvector(a) and isvector(b), "Add: wrong argument types ( expected)") - return new(a.x+b.x, a.y+b.y) -end - -function vector.__sub(a,b) - assert(isvector(a) and isvector(b), "Sub: wrong argument types ( expected)") - return new(a.x-b.x, a.y-b.y) -end - -function vector.__mul(a,b) - if type(a) == "number" then - return new(a*b.x, a*b.y) - elseif type(b) == "number" then - return new(b*a.x, b*a.y) - else - assert(isvector(a) and isvector(b), "Mul: wrong argument types ( or expected)") - return a.x*b.x + a.y*b.y - end -end - -function vector.__div(a,b) - assert(isvector(a) and type(b) == "number", "wrong argument types (expected / )") - return new(a.x / b, a.y / b) -end - -function vector.__eq(a,b) - return a.x == b.x and a.y == b.y -end - -function vector.__lt(a,b) - return a.x < b.x or (a.x == b.x and a.y < b.y) -end - -function vector.__le(a,b) - return a.x <= b.x and a.y <= b.y -end - -function vector.permul(a,b) - assert(isvector(a) and isvector(b), "permul: wrong argument types ( expected)") - return new(a.x*b.x, a.y*b.y) -end - -function vector:toPolar() - return new(atan2(self.x, self.y), self:len()) -end - -function vector:len2() - return self.x * self.x + self.y * self.y -end - -function vector:len() - return sqrt(self.x * self.x + self.y * self.y) -end - -function vector.dist(a, b) - assert(isvector(a) and isvector(b), "dist: wrong argument types ( expected)") - local dx = a.x - b.x - local dy = a.y - b.y - return sqrt(dx * dx + dy * dy) -end - -function vector.dist2(a, b) - assert(isvector(a) and isvector(b), "dist: wrong argument types ( expected)") - local dx = a.x - b.x - local dy = a.y - b.y - return (dx * dx + dy * dy) -end - -function vector:normalizeInplace() - local l = self:len() - if l > 0 then - self.x, self.y = self.x / l, self.y / l - end - return self -end - -function vector:normalized() - return self:clone():normalizeInplace() -end - -function vector:rotateInplace(phi) - local c, s = cos(phi), sin(phi) - self.x, self.y = c * self.x - s * self.y, s * self.x + c * self.y - return self -end - -function vector:rotated(phi) - local c, s = cos(phi), sin(phi) - return new(c * self.x - s * self.y, s * self.x + c * self.y) -end - -function vector:perpendicular() - return new(-self.y, self.x) -end - -function vector:projectOn(v) - assert(isvector(v), "invalid argument: cannot project vector on " .. type(v)) - -- (self * v) * v / v:len2() - local s = (self.x * v.x + self.y * v.y) / (v.x * v.x + v.y * v.y) - return new(s * v.x, s * v.y) -end - -function vector:mirrorOn(v) - assert(isvector(v), "invalid argument: cannot mirror vector on " .. type(v)) - -- 2 * self:projectOn(v) - self - local s = 2 * (self.x * v.x + self.y * v.y) / (v.x * v.x + v.y * v.y) - return new(s * v.x - self.x, s * v.y - self.y) -end - -function vector:cross(v) - assert(isvector(v), "cross: wrong argument types ( expected)") - return self.x * v.y - self.y * v.x -end - --- ref.: http://blog.signalsondisplay.com/?p=336 -function vector:trimInplace(maxLen) - local s = maxLen * maxLen / self:len2() - s = (s > 1 and 1) or math.sqrt(s) - self.x, self.y = self.x * s, self.y * s - return self -end - -function vector:angleTo(other) - if other then - return atan2(self.y, self.x) - atan2(other.y, other.x) - end - return atan2(self.y, self.x) -end - -function vector:trimmed(maxLen) - return self:clone():trimInplace(maxLen) -end - - --- the module -return setmetatable({new = new, fromPolar = fromPolar, isvector = isvector, zero = zero}, - {__call = function(_, ...) return new(...) end}) diff --git a/imperium-porcorum.love/libs/lovebird.lua b/imperium-porcorum.love/libs/lovebird.lua deleted file mode 100644 index 8b296eb..0000000 --- a/imperium-porcorum.love/libs/lovebird.lua +++ /dev/null @@ -1,737 +0,0 @@ --- --- lovebird --- --- Copyright (c) 2017 rxi --- --- This library is free software; you can redistribute it and/or modify it --- under the terms of the MIT license. See LICENSE for details. --- - -local socket = require "socket" - -local lovebird = { _version = "0.4.3" } - -lovebird.loadstring = loadstring or load -lovebird.inited = false -lovebird.host = "*" -lovebird.buffer = "" -lovebird.lines = {} -lovebird.connections = {} -lovebird.pages = {} - -lovebird.wrapprint = true -lovebird.timestamp = true -lovebird.allowhtml = false -lovebird.echoinput = true -lovebird.port = 8000 -lovebird.whitelist = { "127.0.0.1" } -lovebird.maxlines = 200 -lovebird.updateinterval = .5 - - -lovebird.pages["index"] = [[ - - - - - - - - lovebird - - - - -
-
-
-
-
- -
-
-
-
-
-
-
-
- - - -]] - - -lovebird.pages["buffer"] = [[ ]] - - -lovebird.pages["env.json"] = [[ - -{ - "valid": true, - "path": "", - "vars": [ - - { - "key": "", - "value": , - "type": "", - }, - - ] -} -]] - - - -function lovebird.init() - -- Init server - lovebird.server = assert(socket.bind(lovebird.host, lovebird.port)) - lovebird.addr, lovebird.port = lovebird.server:getsockname() - lovebird.server:settimeout(0) - -- Wrap print - lovebird.origprint = print - if lovebird.wrapprint then - local oldprint = print - print = function(...) - oldprint(...) - lovebird.print(...) - end - end - -- Compile page templates - for k, page in pairs(lovebird.pages) do - lovebird.pages[k] = lovebird.template(page, "lovebird, req", - "pages." .. k) - end - lovebird.inited = true -end - - -function lovebird.template(str, params, chunkname) - params = params and ("," .. params) or "" - local f = function(x) return string.format(" echo(%q)", x) end - str = ("?>"..str.."(.-)<%?lua", f) - str = "local echo " .. params .. " = ..." .. str - local fn = assert(lovebird.loadstring(str, chunkname)) - return function(...) - local output = {} - local echo = function(str) table.insert(output, str) end - fn(echo, ...) - return table.concat(lovebird.map(output, tostring)) - end -end - - -function lovebird.map(t, fn) - local res = {} - for k, v in pairs(t) do res[k] = fn(v) end - return res -end - - -function lovebird.trace(...) - local str = "[lovebird] " .. table.concat(lovebird.map({...}, tostring), " ") - print(str) - if not lovebird.wrapprint then lovebird.print(str) end -end - - -function lovebird.unescape(str) - local f = function(x) return string.char(tonumber("0x"..x)) end - return (str:gsub("%+", " "):gsub("%%(..)", f)) -end - - -function lovebird.parseurl(url) - local res = {} - res.path, res.search = url:match("/([^%?]*)%??(.*)") - res.query = {} - for k, v in res.search:gmatch("([^&^?]-)=([^&^#]*)") do - res.query[k] = lovebird.unescape(v) - end - return res -end - - -local htmlescapemap = { - ["<"] = "<", - ["&"] = "&", - ['"'] = """, - ["'"] = "'", -} - -function lovebird.htmlescape(str) - return ( str:gsub("[<&\"']", htmlescapemap) ) -end - - -function lovebird.truncate(str, len) - if #str <= len then - return str - end - return str:sub(1, len - 3) .. "..." -end - - -function lovebird.compare(a, b) - local na, nb = tonumber(a), tonumber(b) - if na then - if nb then return na < nb end - return false - elseif nb then - return true - end - return tostring(a) < tostring(b) -end - - -function lovebird.checkwhitelist(addr) - if lovebird.whitelist == nil then return true end - for _, a in pairs(lovebird.whitelist) do - local ptn = "^" .. a:gsub("%.", "%%."):gsub("%*", "%%d*") .. "$" - if addr:match(ptn) then return true end - end - return false -end - - -function lovebird.clear() - lovebird.lines = {} - lovebird.buffer = "" -end - - -function lovebird.pushline(line) - line.time = os.time() - line.count = 1 - table.insert(lovebird.lines, line) - if #lovebird.lines > lovebird.maxlines then - table.remove(lovebird.lines, 1) - end - lovebird.recalcbuffer() -end - - -function lovebird.recalcbuffer() - local function doline(line) - local str = line.str - if not lovebird.allowhtml then - str = lovebird.htmlescape(line.str):gsub("\n", "
") - end - if line.type == "input" then - str = '' .. str .. '' - else - if line.type == "error" then - str = '! ' .. str - str = '' .. str .. '' - end - if line.count > 1 then - str = '' .. line.count .. ' ' .. str - end - if lovebird.timestamp then - str = os.date('%H:%M:%S ', line.time) .. - str - end - end - return str - end - lovebird.buffer = table.concat(lovebird.map(lovebird.lines, doline), "
") -end - - -function lovebird.print(...) - local t = {} - for i = 1, select("#", ...) do - table.insert(t, tostring(select(i, ...))) - end - local str = table.concat(t, " ") - local last = lovebird.lines[#lovebird.lines] - if last and str == last.str then - -- Update last line if this line is a duplicate of it - last.time = os.time() - last.count = last.count + 1 - lovebird.recalcbuffer() - else - -- Create new line - lovebird.pushline({ type = "output", str = str }) - end -end - - -function lovebird.onerror(err) - lovebird.pushline({ type = "error", str = err }) - if lovebird.wrapprint then - lovebird.origprint("[lovebird] ERROR: " .. err) - end -end - - -function lovebird.onrequest(req, client) - local page = req.parsedurl.path - page = page ~= "" and page or "index" - -- Handle "page not found" - if not lovebird.pages[page] then - return "HTTP/1.1 404\r\nContent-Length: 8\r\n\r\nBad page" - end - -- Handle page - local str - xpcall(function() - local data = lovebird.pages[page](lovebird, req) - local contenttype = "text/html" - if string.match(page, "%.json$") then - contenttype = "application/json" - end - str = "HTTP/1.1 200 OK\r\n" .. - "Content-Type: " .. contenttype .. "\r\n" .. - "Content-Length: " .. #data .. "\r\n" .. - "\r\n" .. data - end, lovebird.onerror) - return str -end - - -function lovebird.receive(client, pattern) - while 1 do - local data, msg = client:receive(pattern) - if not data then - if msg == "timeout" then - -- Wait for more data - coroutine.yield(true) - else - -- Disconnected -- yielding nil means we're done - coroutine.yield(nil) - end - else - return data - end - end -end - - -function lovebird.send(client, data) - local idx = 1 - while idx < #data do - local res, msg = client:send(data, idx) - if not res and msg == "closed" then - -- Handle disconnect - coroutine.yield(nil) - else - idx = idx + res - coroutine.yield(true) - end - end -end - - -function lovebird.onconnect(client) - -- Create request table - local requestptn = "(%S*)%s*(%S*)%s*(%S*)" - local req = {} - req.socket = client - req.addr, req.port = client:getsockname() - req.request = lovebird.receive(client, "*l") - req.method, req.url, req.proto = req.request:match(requestptn) - req.headers = {} - while 1 do - local line, msg = lovebird.receive(client, "*l") - if not line or #line == 0 then break end - local k, v = line:match("(.-):%s*(.*)$") - req.headers[k] = v - end - if req.headers["Content-Length"] then - req.body = lovebird.receive(client, req.headers["Content-Length"]) - end - -- Parse body - req.parsedbody = {} - if req.body then - for k, v in req.body:gmatch("([^&]-)=([^&^#]*)") do - req.parsedbody[k] = lovebird.unescape(v) - end - end - -- Parse request line's url - req.parsedurl = lovebird.parseurl(req.url) - -- Handle request; get data to send and send - local data = lovebird.onrequest(req) - lovebird.send(client, data) - -- Clear up - client:close() -end - - -function lovebird.update() - if not lovebird.inited then lovebird.init() end - -- Handle new connections - while 1 do - -- Accept new connections - local client = lovebird.server:accept() - if not client then break end - client:settimeout(0) - local addr = client:getsockname() - if lovebird.checkwhitelist(addr) then - -- Connection okay -- create and add coroutine to set - local conn = coroutine.wrap(function() - xpcall(function() lovebird.onconnect(client) end, function() end) - end) - lovebird.connections[conn] = true - else - -- Reject connection not on whitelist - lovebird.trace("got non-whitelisted connection attempt: ", addr) - client:close() - end - end - -- Handle existing connections - for conn in pairs(lovebird.connections) do - -- Resume coroutine, remove if it has finished - local status = conn() - if status == nil then - lovebird.connections[conn] = nil - end - end -end - - -return lovebird diff --git a/imperium-porcorum.love/libs/sti/graphics.lua b/imperium-porcorum.love/libs/sti/graphics.lua deleted file mode 100644 index 1d73379..0000000 --- a/imperium-porcorum.love/libs/sti/graphics.lua +++ /dev/null @@ -1,128 +0,0 @@ -local lg = love.graphics -local graphics = { isCreated = lg and true or false } - -function graphics.newSpriteBatch(...) - if graphics.isCreated then - return lg.newSpriteBatch(...) - end -end - -function graphics.newCanvas(...) - if graphics.isCreated then - return lg.newCanvas(...) - end -end - -function graphics.newImage(...) - if graphics.isCreated then - return lg.newImage(...) - end -end - -function graphics.newQuad(...) - if graphics.isCreated then - return lg.newQuad(...) - end -end - -function graphics.getCanvas(...) - if graphics.isCreated then - return lg.getCanvas(...) - end -end - -function graphics.setCanvas(...) - if graphics.isCreated then - return lg.setCanvas(...) - end -end - -function graphics.clear(...) - if graphics.isCreated then - return lg.clear(...) - end -end - -function graphics.push(...) - if graphics.isCreated then - return lg.push(...) - end -end - -function graphics.origin(...) - if graphics.isCreated then - return lg.origin(...) - end -end - -function graphics.scale(...) - if graphics.isCreated then - return lg.scale(...) - end -end - -function graphics.translate(...) - if graphics.isCreated then - return lg.translate(...) - end -end - -function graphics.pop(...) - if graphics.isCreated then - return lg.pop(...) - end -end - -function graphics.draw(...) - if graphics.isCreated then - return lg.draw(...) - end -end - -function graphics.rectangle(...) - if graphics.isCreated then - return lg.rectangle(...) - end -end - -function graphics.getColor(...) - if graphics.isCreated then - return lg.getColor(...) - end -end - -function graphics.setColor(...) - if graphics.isCreated then - return lg.setColor(...) - end -end - -function graphics.line(...) - if graphics.isCreated then - return lg.line(...) - end -end - -function graphics.polygon(...) - if graphics.isCreated then - return lg.polygon(...) - end -end - -function graphics.getWidth() - if graphics.isCreated then - return lg.getWidth() - end - - return 0 -end - -function graphics.getHeight() - if graphics.isCreated then - return lg.getHeight() - end - - return 0 -end - -return graphics diff --git a/imperium-porcorum.love/libs/sti/init.lua b/imperium-porcorum.love/libs/sti/init.lua deleted file mode 100644 index de1bd16..0000000 --- a/imperium-porcorum.love/libs/sti/init.lua +++ /dev/null @@ -1,1485 +0,0 @@ ---- Simple and fast Tiled map loader and renderer. --- @module sti --- @author Landon Manning --- @copyright 2016 --- @license MIT/X11 - -local STI = { - _LICENSE = "MIT/X11", - _URL = "https://github.com/karai17/Simple-Tiled-Implementation", - _VERSION = "0.18.2.1", - _DESCRIPTION = "Simple Tiled Implementation is a Tiled Map Editor library designed for the *awesome* LÖVE framework.", - cache = {} -} -STI.__index = STI - -local cwd = (...):gsub('%.init$', '') .. "." -local utils = require(cwd .. "utils") -local ceil = math.ceil -local floor = math.floor -local lg = require(cwd .. "graphics") -local Map = {} -Map.__index = Map - -local function new(map, plugins, ox, oy) - local dir = "" - - if type(map) == "table" then - map = setmetatable(map, Map) - else - -- Check for valid map type - local ext = map:sub(-4, -1) - assert(ext == ".lua", string.format( - "Invalid file type: %s. File must be of type: lua.", - ext - )) - - -- Get directory of map - dir = map:reverse():find("[/\\]") or "" - if dir ~= "" then - dir = map:sub(1, 1 + (#map - dir)) - end - - -- Load map - map = setmetatable(assert(love.filesystem.load(map))(), Map) - end - - map:init(dir, plugins, ox, oy) - - return map -end - ---- Instance a new map. --- @param map Path to the map file or the map table itself --- @param plugins A list of plugins to load --- @param ox Offset of map on the X axis (in pixels) --- @param oy Offset of map on the Y axis (in pixels) --- @return table The loaded Map -function STI.__call(_, map, plugins, ox, oy) - return new(map, plugins, ox, oy) -end - ---- Flush image cache. -function STI:flush() - self.cache = {} -end - ---- Map object - ---- Instance a new map --- @param path Path to the map file --- @param plugins A list of plugins to load --- @param ox Offset of map on the X axis (in pixels) --- @param oy Offset of map on the Y axis (in pixels) -function Map:init(path, plugins, ox, oy) - if type(plugins) == "table" then - self:loadPlugins(plugins) - end - - self:resize() - self.objects = {} - self.tiles = {} - self.tileInstances = {} - self.drawRange = { - sx = 1, - sy = 1, - ex = self.width, - ey = self.height, - } - self.offsetx = ox or 0 - self.offsety = oy or 0 - - self.freeBatchSprites = {} - setmetatable(self.freeBatchSprites, { __mode = 'k' }) - - -- Set tiles, images - local gid = 1 - for i, tileset in ipairs(self.tilesets) do - assert(tileset.image, "STI does not support Tile Collections.\nYou need to create a Texture Atlas.") - - -- Cache images - if lg.isCreated then - local formatted_path = utils.format_path(path .. tileset.image) - - if not STI.cache[formatted_path] then - utils.fix_transparent_color(tileset, formatted_path) - utils.cache_image(STI, formatted_path, tileset.image) - else - tileset.image = STI.cache[formatted_path] - end - end - - gid = self:setTiles(i, tileset, gid) - end - - -- Set layers - for _, layer in ipairs(self.layers) do - self:setLayer(layer, path) - end -end - ---- Load plugins --- @param plugins A list of plugins to load -function Map:loadPlugins(plugins) - for _, plugin in ipairs(plugins) do - local pluginModulePath = cwd .. 'plugins.' .. plugin - local ok, pluginModule = pcall(require, pluginModulePath) - if ok then - for k, func in pairs(pluginModule) do - if not self[k] then - self[k] = func - end - end - end - end -end - ---- Create Tiles --- @param index Index of the Tileset --- @param tileset Tileset data --- @param gid First Global ID in Tileset --- @return number Next Tileset's first Global ID -function Map:setTiles(index, tileset, gid) - local quad = lg.newQuad - local imageW = tileset.imagewidth - local imageH = tileset.imageheight - local tileW = tileset.tilewidth - local tileH = tileset.tileheight - local margin = tileset.margin - local spacing = tileset.spacing - local w = utils.get_tiles(imageW, tileW, margin, spacing) - local h = utils.get_tiles(imageH, tileH, margin, spacing) - - for y = 1, h do - for x = 1, w do - local id = gid - tileset.firstgid - local quadX = (x - 1) * tileW + margin + (x - 1) * spacing - local quadY = (y - 1) * tileH + margin + (y - 1) * spacing - local properties, terrain, animation, objectGroup - - for _, tile in pairs(tileset.tiles) do - if tile.id == id then - properties = tile.properties - animation = tile.animation - objectGroup = tile.objectGroup - - if tile.terrain then - terrain = {} - - for i = 1, #tile.terrain do - terrain[i] = tileset.terrains[tile.terrain[i] + 1] - end - end - end - end - - local tile = { - id = id, - gid = gid, - tileset = index, - quad = quad( - quadX, quadY, - tileW, tileH, - imageW, imageH - ), - properties = properties or {}, - terrain = terrain, - animation = animation, - objectGroup = objectGroup, - frame = 1, - time = 0, - width = tileW, - height = tileH, - sx = 1, - sy = 1, - r = 0, - offset = tileset.tileoffset, - } - - self.tiles[gid] = tile - gid = gid + 1 - end - end - - return gid -end - ---- Create Layers --- @param layer Layer data --- @param path (Optional) Path to an Image Layer's image -function Map:setLayer(layer, path) - if layer.encoding then - if layer.encoding == "base64" then - assert(require "ffi", "Compressed maps require LuaJIT FFI.\nPlease Switch your interperator to LuaJIT or your Tile Layer Format to \"CSV\".") - local fd = love.data.decode("string", "base64", layer.data) - - if not layer.compression then - layer.data = utils.get_decompressed_data(fd) - else - assert(love.data.decompress, "zlib and gzip compression require LOVE 11.0+.\nPlease set your Tile Layer Format to \"Base64 (uncompressed)\" or \"CSV\".") - - if layer.compression == "zlib" then - local data = love.data.decompress("string", "zlib", fd) - layer.data = utils.get_decompressed_data(data) - end - - if layer.compression == "gzip" then - local data = love.data.decompress("string", "gzip", fd) - layer.data = utils.get_decompressed_data(data) - end - end - end - end - - layer.x = (layer.x or 0) + layer.offsetx + self.offsetx - layer.y = (layer.y or 0) + layer.offsety + self.offsety - layer.update = function() end - - if layer.type == "tilelayer" then - self:setTileData(layer) - self:setSpriteBatches(layer) - layer.draw = function() self:drawTileLayer(layer) end - elseif layer.type == "objectgroup" then - self:setObjectData(layer) - self:setObjectCoordinates(layer) - self:setObjectSpriteBatches(layer) - layer.draw = function() self:drawObjectLayer(layer) end - elseif layer.type == "imagelayer" then - layer.draw = function() self:drawImageLayer(layer) end - - if layer.image ~= "" then - local formatted_path = utils.format_path(path .. layer.image) - if not STI.cache[formatted_path] then - utils.cache_image(STI, formatted_path) - end - - layer.image = STI.cache[formatted_path] - layer.width = layer.image:getWidth() - layer.height = layer.image:getHeight() - end - end - - self.layers[layer.name] = layer -end - ---- Add Tiles to Tile Layer --- @param layer The Tile Layer -function Map:setTileData(layer) - local i = 1 - local map = {} - - for y = 1, layer.height do - map[y] = {} - for x = 1, layer.width do - local gid = layer.data[i] - - if gid > 0 then - map[y][x] = self.tiles[gid] or self:setFlippedGID(gid) - end - - i = i + 1 - end - end - - layer.data = map -end - ---- Add Objects to Layer --- @param layer The Object Layer -function Map:setObjectData(layer) - for _, object in ipairs(layer.objects) do - object.layer = layer - self.objects[object.id] = object - end -end - ---- Correct position and orientation of Objects in an Object Layer --- @param layer The Object Layer -function Map:setObjectCoordinates(layer) - for _, object in ipairs(layer.objects) do - local x = layer.x + object.x - local y = layer.y + object.y - local w = object.width - local h = object.height - local r = object.rotation - local cos = math.cos(math.rad(r)) - local sin = math.sin(math.rad(r)) - - if object.shape == "rectangle" and not object.gid then - object.rectangle = {} - - local vertices = { - { x=x, y=y }, - { x=x + w, y=y }, - { x=x + w, y=y + h }, - { x=x, y=y + h }, - } - - for _, vertex in ipairs(vertices) do - vertex.x, vertex.y = utils.rotate_vertex(self, vertex, x, y, cos, sin) - table.insert(object.rectangle, { x = vertex.x, y = vertex.y }) - end - elseif object.shape == "ellipse" then - object.ellipse = {} - local vertices = utils.convert_ellipse_to_polygon(x, y, w, h) - - for _, vertex in ipairs(vertices) do - vertex.x, vertex.y = utils.rotate_vertex(self, vertex, x, y, cos, sin) - table.insert(object.ellipse, { x = vertex.x, y = vertex.y }) - end - elseif object.shape == "polygon" then - for _, vertex in ipairs(object.polygon) do - vertex.x = vertex.x + x - vertex.y = vertex.y + y - vertex.x, vertex.y = utils.rotate_vertex(self, vertex, x, y, cos, sin) - end - elseif object.shape == "polyline" then - for _, vertex in ipairs(object.polyline) do - vertex.x = vertex.x + x - vertex.y = vertex.y + y - vertex.x, vertex.y = utils.rotate_vertex(self, vertex, x, y, cos, sin) - end - end - end -end - ---- Convert tile location to tile instance location --- @param layer Tile layer --- @param tile Tile --- @param x Tile location on X axis (in tiles) --- @param y Tile location on Y axis (in tiles) --- @return number Tile instance location on X axis (in pixels) --- @return number Tile instance location on Y axis (in pixels) -function Map:getLayerTilePosition(layer, tile, x, y) - local tileW = self.tilewidth - local tileH = self.tileheight - local tileX, tileY - - if self.orientation == "orthogonal" then - local tileset = self.tilesets[tile.tileset] - tileX = (x - 1) * tileW + tile.offset.x - tileY = (y - 0) * tileH + tile.offset.y - tileset.tileheight - tileX, tileY = utils.compensate(tile, tileX, tileY, tileW, tileH) - elseif self.orientation == "isometric" then - tileX = (x - y) * (tileW / 2) + tile.offset.x + layer.width * tileW / 2 - self.tilewidth / 2 - tileY = (x + y - 2) * (tileH / 2) + tile.offset.y - else - local sideLen = self.hexsidelength or 0 - if self.staggeraxis == "y" then - if self.staggerindex == "odd" then - if y % 2 == 0 then - tileX = (x - 1) * tileW + tileW / 2 + tile.offset.x - else - tileX = (x - 1) * tileW + tile.offset.x - end - else - if y % 2 == 0 then - tileX = (x - 1) * tileW + tile.offset.x - else - tileX = (x - 1) * tileW + tileW / 2 + tile.offset.x - end - end - - local rowH = tileH - (tileH - sideLen) / 2 - tileY = (y - 1) * rowH + tile.offset.y - else - if self.staggerindex == "odd" then - if x % 2 == 0 then - tileY = (y - 1) * tileH + tileH / 2 + tile.offset.y - else - tileY = (y - 1) * tileH + tile.offset.y - end - else - if x % 2 == 0 then - tileY = (y - 1) * tileH + tile.offset.y - else - tileY = (y - 1) * tileH + tileH / 2 + tile.offset.y - end - end - - local colW = tileW - (tileW - sideLen) / 2 - tileX = (x - 1) * colW + tile.offset.x - end - end - - return tileX, tileY -end - ---- Place new tile instance --- @param layer Tile layer --- @param tile Tile --- @param number Tile location on X axis (in tiles) --- @param number Tile location on Y axis (in tiles) -function Map:addNewLayerTile(layer, tile, x, y) - local tileset = tile.tileset - local image = self.tilesets[tile.tileset].image - - layer.batches[tileset] = layer.batches[tileset] - or lg.newSpriteBatch(image, layer.width * layer.height) - - local batch = layer.batches[tileset] - local tileX, tileY = self:getLayerTilePosition(layer, tile, x, y) - - local tab = { - layer = layer, - gid = tile.gid, - x = tileX, - y = tileY, - r = tile.r, - oy = 0 - } - - if batch then - tab.batch = batch - tab.id = batch:add(tile.quad, tileX, tileY, tile.r, tile.sx, tile.sy) - end - - self.tileInstances[tile.gid] = self.tileInstances[tile.gid] or {} - table.insert(self.tileInstances[tile.gid], tab) -end - ---- Batch Tiles in Tile Layer for improved draw speed --- @param layer The Tile Layer -function Map:setSpriteBatches(layer) - layer.batches = {} - - if self.orientation == "orthogonal" or self.orientation == "isometric" then - local startX = 1 - local startY = 1 - local endX = layer.width - local endY = layer.height - local incrementX = 1 - local incrementY = 1 - - -- Determine order to add tiles to sprite batch - -- Defaults to right-down - if self.renderorder == "right-up" then - startX, endX, incrementX = startX, endX, 1 - startY, endY, incrementY = endY, startY, -1 - elseif self.renderorder == "left-down" then - startX, endX, incrementX = endX, startX, -1 - startY, endY, incrementY = startY, endY, 1 - elseif self.renderorder == "left-up" then - startX, endX, incrementX = endX, startX, -1 - startY, endY, incrementY = endY, startY, -1 - end - - for y = startY, endY, incrementY do - for x = startX, endX, incrementX do - local tile = layer.data[y][x] - - if tile then - self:addNewLayerTile(layer, tile, x, y) - end - end - end - else - local sideLen = self.hexsidelength or 0 - - if self.staggeraxis == "y" then - for y = 1, layer.height do - for x = 1, layer.width do - local tile = layer.data[y][x] - - if tile then - self:addNewLayerTile(layer, tile, x, y) - end - end - end - else - local i = 0 - local _x - - if self.staggerindex == "odd" then - _x = 1 - else - _x = 2 - end - - while i < layer.width * layer.height do - for _y = 1, layer.height + 0.5, 0.5 do - local y = floor(_y) - - for x = _x, layer.width, 2 do - i = i + 1 - local tile = layer.data[y][x] - - if tile then - self:addNewLayerTile(layer, tile, x, y) - end - end - - if _x == 1 then - _x = 2 - else - _x = 1 - end - end - end - end - end -end - ---- Batch Tiles in Object Layer for improved draw speed --- @param layer The Object Layer -function Map:setObjectSpriteBatches(layer) - local newBatch = lg.newSpriteBatch - local tileW = self.tilewidth - local tileH = self.tileheight - local batches = {} - - if layer.draworder == "topdown" then - table.sort(layer.objects, function(a, b) - return a.y + a.height < b.y + b.height - end) - end - - for _, object in ipairs(layer.objects) do - if object.gid then - local tile = self.tiles[object.gid] or self:setFlippedGID(object.gid) - local tileset = tile.tileset - local image = self.tilesets[tile.tileset].image - - batches[tileset] = batches[tileset] or newBatch(image) - - local sx = object.width / tile.width - local sy = object.height / tile.height - - local batch = batches[tileset] - local tileX = object.x + tile.offset.x - local tileY = object.y + tile.offset.y - tile.height * sy - local tileR = math.rad(object.rotation) - local oy = 0 - - -- Compensation for scale/rotation shift - if tile.sx == 1 and tile.sy == 1 then - if tileR ~= 0 then - tileY = tileY + tileH - oy = tileH - end - else - if tile.sx < 0 then tileX = tileX + tileW end - if tile.sy < 0 then tileY = tileY + tileH end - if tileR > 0 then tileX = tileX + tileW end - if tileR < 0 then tileY = tileY + tileH end - end - - local tab = { - layer = layer, - gid = tile.gid, - x = tileX, - y = tileY, - r = tileR, - oy = oy - } - - if batch then - tab.batch = batch - tab.id = batch:add(tile.quad, tileX, tileY, tileR, tile.sx * sx, tile.sy * sy, 0, oy) - end - - self.tileInstances[tile.gid] = self.tileInstances[tile.gid] or {} - table.insert(self.tileInstances[tile.gid], tab) - end - end - - layer.batches = batches -end - ---- Create a Custom Layer to place userdata in (such as player sprites) --- @param name Name of Custom Layer --- @param index Draw order within Layer stack --- @return table Custom Layer -function Map:addCustomLayer(name, index) - index = index or #self.layers + 1 - local layer = { - type = "customlayer", - name = name, - visible = true, - opacity = 1, - properties = {}, - } - - function layer.draw() end - function layer.update() end - - table.insert(self.layers, index, layer) - self.layers[name] = self.layers[index] - - return layer -end - ---- Convert another Layer into a Custom Layer --- @param index Index or name of Layer to convert --- @return table Custom Layer -function Map:convertToCustomLayer(index) - local layer = assert(self.layers[index], "Layer not found: " .. index) - - layer.type = "customlayer" - layer.x = nil - layer.y = nil - layer.width = nil - layer.height = nil - layer.encoding = nil - layer.data = nil - layer.objects = nil - layer.image = nil - - function layer.draw() end - function layer.update() end - - return layer -end - ---- Remove a Layer from the Layer stack --- @param index Index or name of Layer to convert -function Map:removeLayer(index) - local layer = assert(self.layers[index], "Layer not found: " .. index) - - if type(index) == "string" then - for i, l in ipairs(self.layers) do - if l.name == index then - table.remove(self.layers, i) - self.layers[index] = nil - break - end - end - else - local name = self.layers[index].name - table.remove(self.layers, index) - self.layers[name] = nil - end - - -- Remove tile instances - if layer.batches then - for _, batch in pairs(layer.batches) do - self.freeBatchSprites[batch] = nil - end - - for _, tiles in pairs(self.tileInstances) do - for i = #tiles, 1, -1 do - local tile = tiles[i] - if tile.layer == layer then - table.remove(tiles, i) - end - end - end - end - - -- Remove objects - if layer.objects then - for i, object in pairs(self.objects) do - if object.layer == layer then - self.objects[i] = nil - end - end - end -end - ---- Animate Tiles and update every Layer --- @param dt Delta Time -function Map:update(dt) - for _, tile in pairs(self.tiles) do - local update = false - - if tile.animation then - tile.time = tile.time + dt * 1000 - - while tile.time > tonumber(tile.animation[tile.frame].duration) do - update = true - tile.time = tile.time - tonumber(tile.animation[tile.frame].duration) - tile.frame = tile.frame + 1 - - if tile.frame > #tile.animation then tile.frame = 1 end - end - - if update and self.tileInstances[tile.gid] then - for _, j in pairs(self.tileInstances[tile.gid]) do - local t = self.tiles[tonumber(tile.animation[tile.frame].tileid) + self.tilesets[tile.tileset].firstgid] - j.batch:set(j.id, t.quad, j.x, j.y, j.r, tile.sx, tile.sy, 0, j.oy) - end - end - end - end - - for _, layer in ipairs(self.layers) do - layer:update(dt) - end -end - ---- Draw every Layer --- @param tx Translate on X --- @param ty Translate on Y --- @param sx Scale on X --- @param sy Scale on Y -function Map:draw(tx, ty, sx, sy) - local current_canvas = lg.getCanvas() - lg.setCanvas(self.canvas) - lg.clear() - - -- Scale map to 1.0 to draw onto canvas, this fixes tearing issues - -- Map is translated to correct position so the right section is drawn - lg.push() - lg.origin() - lg.translate(math.floor(tx or 0), math.floor(ty or 0)) - - for _, layer in ipairs(self.layers) do - if layer.visible and layer.opacity > 0 then - self:drawLayer(layer) - end - end - - lg.pop() - - -- Draw canvas at 0,0; this fixes scissoring issues - -- Map is scaled to correct scale so the right section is shown - lg.push() - lg.origin() - lg.scale(sx or 1, sy or sx or 1) - - lg.setCanvas(current_canvas) - lg.draw(self.canvas) - - lg.pop() -end - ---- Draw an individual Layer --- @param layer The Layer to draw -function Map.drawLayer(_, layer) - local r,g,b,a = lg.getColor() - lg.setColor(r, g, b, a * layer.opacity) - layer:draw() - lg.setColor(r,g,b,a) -end - ---- Default draw function for Tile Layers --- @param layer The Tile Layer to draw -function Map:drawTileLayer(layer) - if type(layer) == "string" or type(layer) == "number" then - layer = self.layers[layer] - end - - assert(layer.type == "tilelayer", "Invalid layer type: " .. layer.type .. ". Layer must be of type: tilelayer") - - for _, batch in pairs(layer.batches) do - lg.draw(batch, floor(layer.x), floor(layer.y)) - end -end - ---- Default draw function for Object Layers --- @param layer The Object Layer to draw -function Map:drawObjectLayer(layer) - if type(layer) == "string" or type(layer) == "number" then - layer = self.layers[layer] - end - - assert(layer.type == "objectgroup", "Invalid layer type: " .. layer.type .. ". Layer must be of type: objectgroup") - - local line = { 160, 160, 160, 255 * layer.opacity } - local fill = { 160, 160, 160, 255 * layer.opacity * 0.5 } - local r,g,b,a = lg.getColor() - local reset = { r, g, b, a * layer.opacity } - - local function sortVertices(obj) - local vertex = {} - - for _, v in ipairs(obj) do - table.insert(vertex, v.x) - table.insert(vertex, v.y) - end - - return vertex - end - - local function drawShape(obj, shape) - local vertex = sortVertices(obj) - - if shape == "polyline" then - lg.setColor(line) - lg.line(vertex) - return - elseif shape == "polygon" then - lg.setColor(fill) - if not love.math.isConvex(vertex) then - local triangles = love.math.triangulate(vertex) - for _, triangle in ipairs(triangles) do - lg.polygon("fill", triangle) - end - else - lg.polygon("fill", vertex) - end - else - lg.setColor(fill) - lg.polygon("fill", vertex) - end - - lg.setColor(line) - lg.polygon("line", vertex) - end - - for _, object in ipairs(layer.objects) do - if object.shape == "rectangle" and not object.gid then - drawShape(object.rectangle, "rectangle") - elseif object.shape == "ellipse" then - drawShape(object.ellipse, "ellipse") - elseif object.shape == "polygon" then - drawShape(object.polygon, "polygon") - elseif object.shape == "polyline" then - drawShape(object.polyline, "polyline") - end - end - - lg.setColor(reset) - for _, batch in pairs(layer.batches) do - lg.draw(batch, 0, 0) - end - lg.setColor(r,g,b,a) -end - ---- Default draw function for Image Layers --- @param layer The Image Layer to draw -function Map:drawImageLayer(layer) - if type(layer) == "string" or type(layer) == "number" then - layer = self.layers[layer] - end - - assert(layer.type == "imagelayer", "Invalid layer type: " .. layer.type .. ". Layer must be of type: imagelayer") - - if layer.image ~= "" then - lg.draw(layer.image, layer.x, layer.y) - end -end - ---- Resize the drawable area of the Map --- @param w The new width of the drawable area (in pixels) --- @param h The new Height of the drawable area (in pixels) -function Map:resize(w, h) - if lg.isCreated then - w = w or lg.getWidth() - h = h or lg.getHeight() - - self.canvas = lg.newCanvas(w, h) - self.canvas:setFilter("nearest", "nearest") - end -end - ---- Create flipped or rotated Tiles based on bitop flags --- @param gid The flagged Global ID --- @return table Flipped Tile -function Map:setFlippedGID(gid) - local bit31 = 2147483648 - local bit30 = 1073741824 - local bit29 = 536870912 - local flipX = false - local flipY = false - local flipD = false - local realgid = gid - - if realgid >= bit31 then - realgid = realgid - bit31 - flipX = not flipX - end - - if realgid >= bit30 then - realgid = realgid - bit30 - flipY = not flipY - end - - if realgid >= bit29 then - realgid = realgid - bit29 - flipD = not flipD - end - - local tile = self.tiles[realgid] - local data = { - id = tile.id, - gid = gid, - tileset = tile.tileset, - frame = tile.frame, - time = tile.time, - width = tile.width, - height = tile.height, - offset = tile.offset, - quad = tile.quad, - properties = tile.properties, - terrain = tile.terrain, - animation = tile.animation, - sx = tile.sx, - sy = tile.sy, - r = tile.r, - } - - if flipX then - if flipY and flipD then - data.r = math.rad(-90) - data.sy = -1 - elseif flipY then - data.sx = -1 - data.sy = -1 - elseif flipD then - data.r = math.rad(90) - else - data.sx = -1 - end - elseif flipY then - if flipD then - data.r = math.rad(-90) - else - data.sy = -1 - end - elseif flipD then - data.r = math.rad(90) - data.sy = -1 - end - - self.tiles[gid] = data - - return self.tiles[gid] -end - ---- Get custom properties from Layer --- @param layer The Layer --- @return table List of properties -function Map:getLayerProperties(layer) - local l = self.layers[layer] - - if not l then - return {} - end - - return l.properties -end - ---- Get custom properties from Tile --- @param layer The Layer that the Tile belongs to --- @param x The X axis location of the Tile (in tiles) --- @param y The Y axis location of the Tile (in tiles) --- @return table List of properties -function Map:getTileProperties(layer, x, y) - local tile = self.layers[layer].data[y][x] - - if not tile then - return {} - end - - return tile.properties -end - ---- Get custom properties from Object --- @param layer The Layer that the Object belongs to --- @param object The index or name of the Object --- @return table List of properties -function Map:getObjectProperties(layer, object) - local o = self.layers[layer].objects - - if type(object) == "number" then - o = o[object] - else - for _, v in ipairs(o) do - if v.name == object then - o = v - break - end - end - end - - if not o then - return {} - end - - return o.properties -end - ---- Change a tile in a layer to another tile --- @param layer The Layer that the Tile belongs to --- @param x The X axis location of the Tile (in tiles) --- @param y The Y axis location of the Tile (in tiles) --- @param gid The gid of the new tile -function Map:setLayerTile(layer, x, y, gid) - layer = self.layers[layer] - - layer.data[y] = layer.data[y] or {} - local tile = layer.data[y][x] - local instance - if tile then - local tileX, tileY = self:getLayerTilePosition(layer, tile, x, y) - for _, inst in pairs(self.tileInstances[tile.gid]) do - if inst.x == tileX and inst.y == tileY then - instance = inst - break - end - end - end - - if tile == self.tiles[gid] then - return - end - - tile = self.tiles[gid] - - if instance then - self:swapTile(instance, tile) - else - self:addNewLayerTile(layer, tile, x, y) - end - layer.data[y][x] = tile -end - ---- Swap a tile in a spritebatch --- @param instance The current Instance object we want to replace --- @param tile The Tile object we want to use --- @return none -function Map:swapTile(instance, tile) - -- Update sprite batch - if instance.batch then - if tile then - instance.batch:set( - instance.id, - tile.quad, - instance.x, - instance.y, - tile.r, - tile.sx, - tile.sy - ) - else - instance.batch:set( - instance.id, - instance.x, - instance.y, - 0, - 0) - - self.freeBatchSprites[instance.batch] = - self.freeBatchSprites[instance.batch] or {} - - table.insert(self.freeBatchSprites[instance.batch], instance) - end - end - - -- Remove old tile instance - for i, ins in ipairs(self.tileInstances[instance.gid]) do - if ins.batch == instance.batch and ins.id == instance.id then - table.remove(self.tileInstances[instance.gid], i) - break - end - end - - -- Add new tile instance - if tile then - self.tileInstances[tile.gid] = self.tileInstances[tile.gid] or {} - - local freeBatchSprites = self.freeBatchSprites[instance.batch] - local newInstance - if freeBatchSprites and #freeBatchSprites > 0 then - newInstance = freeBatchSprites[#freeBatchSprites] - freeBatchSprites[#freeBatchSprites] = nil - else - newInstance = {} - end - - newInstance.layer = instance.layer - newInstance.batch = instance.batch - newInstance.id = instance.id - newInstance.gid = tile.gid or 0 - newInstance.x = instance.x - newInstance.y = instance.y - newInstance.r = tile.r or 0 - newInstance.oy = tile.r ~= 0 and tile.height or 0 - table.insert(self.tileInstances[tile.gid], newInstance) - end -end - ---- Convert tile location to pixel location --- @param x The X axis location of the point (in tiles) --- @param y The Y axis location of the point (in tiles) --- @return number The X axis location of the point (in pixels) --- @return number The Y axis location of the point (in pixels) -function Map:convertTileToPixel(x,y) - if self.orientation == "orthogonal" then - local tileW = self.tilewidth - local tileH = self.tileheight - return - x * tileW, - y * tileH - elseif self.orientation == "isometric" then - local mapH = self.height - local tileW = self.tilewidth - local tileH = self.tileheight - local offsetX = mapH * tileW / 2 - return - (x - y) * tileW / 2 + offsetX, - (x + y) * tileH / 2 - elseif self.orientation == "staggered" or - self.orientation == "hexagonal" then - local tileW = self.tilewidth - local tileH = self.tileheight - local sideLen = self.hexsidelength or 0 - - if self.staggeraxis == "x" then - return - x * tileW, - ceil(y) * (tileH + sideLen) + (ceil(y) % 2 == 0 and tileH or 0) - else - return - ceil(x) * (tileW + sideLen) + (ceil(x) % 2 == 0 and tileW or 0), - y * tileH - end - end -end - ---- Convert pixel location to tile location --- @param x The X axis location of the point (in pixels) --- @param y The Y axis location of the point (in pixels) --- @return number The X axis location of the point (in tiles) --- @return number The Y axis location of the point (in tiles) -function Map:convertPixelToTile(x, y) - if self.orientation == "orthogonal" then - local tileW = self.tilewidth - local tileH = self.tileheight - return - x / tileW, - y / tileH - elseif self.orientation == "isometric" then - local mapH = self.height - local tileW = self.tilewidth - local tileH = self.tileheight - local offsetX = mapH * tileW / 2 - return - y / tileH + (x - offsetX) / tileW, - y / tileH - (x - offsetX) / tileW - elseif self.orientation == "staggered" then - local staggerX = self.staggeraxis == "x" - local even = self.staggerindex == "even" - - local function topLeft(x, y) - if staggerX then - if ceil(x) % 2 == 1 and even then - return x - 1, y - else - return x - 1, y - 1 - end - else - if ceil(y) % 2 == 1 and even then - return x, y - 1 - else - return x - 1, y - 1 - end - end - end - - local function topRight(x, y) - if staggerX then - if ceil(x) % 2 == 1 and even then - return x + 1, y - else - return x + 1, y - 1 - end - else - if ceil(y) % 2 == 1 and even then - return x + 1, y - 1 - else - return x, y - 1 - end - end - end - - local function bottomLeft(x, y) - if staggerX then - if ceil(x) % 2 == 1 and even then - return x - 1, y + 1 - else - return x - 1, y - end - else - if ceil(y) % 2 == 1 and even then - return x, y + 1 - else - return x - 1, y + 1 - end - end - end - - local function bottomRight(x, y) - if staggerX then - if ceil(x) % 2 == 1 and even then - return x + 1, y + 1 - else - return x + 1, y - end - else - if ceil(y) % 2 == 1 and even then - return x + 1, y + 1 - else - return x, y + 1 - end - end - end - - local tileW = self.tilewidth - local tileH = self.tileheight - - if staggerX then - x = x - (even and tileW / 2 or 0) - else - y = y - (even and tileH / 2 or 0) - end - - local halfH = tileH / 2 - local ratio = tileH / tileW - local referenceX = ceil(x / tileW) - local referenceY = ceil(y / tileH) - local relativeX = x - referenceX * tileW - local relativeY = y - referenceY * tileH - - if (halfH - relativeX * ratio > relativeY) then - return topLeft(referenceX, referenceY) - elseif (-halfH + relativeX * ratio > relativeY) then - return topRight(referenceX, referenceY) - elseif (halfH + relativeX * ratio < relativeY) then - return bottomLeft(referenceX, referenceY) - elseif (halfH * 3 - relativeX * ratio < relativeY) then - return bottomRight(referenceX, referenceY) - end - - return referenceX, referenceY - elseif self.orientation == "hexagonal" then - local staggerX = self.staggeraxis == "x" - local even = self.staggerindex == "even" - local tileW = self.tilewidth - local tileH = self.tileheight - local sideLenX = 0 - local sideLenY = 0 - - if staggerX then - sideLenX = self.hexsidelength - x = x - (even and tileW or (tileW - sideLenX) / 2) - else - sideLenY = self.hexsidelength - y = y - (even and tileH or (tileH - sideLenY) / 2) - end - - local colW = ((tileW - sideLenX) / 2) + sideLenX - local rowH = ((tileH - sideLenY) / 2) + sideLenY - local referenceX = ceil(x) / (colW * 2) - local referenceY = ceil(y) / (rowH * 2) - local relativeX = x - referenceX * colW * 2 - local relativeY = y - referenceY * rowH * 2 - local centers - - if staggerX then - local left = sideLenX / 2 - local centerX = left + colW - local centerY = tileH / 2 - - centers = { - { x = left, y = centerY }, - { x = centerX, y = centerY - rowH }, - { x = centerX, y = centerY + rowH }, - { x = centerX + colW, y = centerY }, - } - else - local top = sideLenY / 2 - local centerX = tileW / 2 - local centerY = top + rowH - - centers = { - { x = centerX, y = top }, - { x = centerX - colW, y = centerY }, - { x = centerX + colW, y = centerY }, - { x = centerX, y = centerY + rowH } - } - end - - local nearest = 0 - local minDist = math.huge - - local function len2(ax, ay) - return ax * ax + ay * ay - end - - for i = 1, 4 do - local dc = len2(centers[i].x - relativeX, centers[i].y - relativeY) - - if dc < minDist then - minDist = dc - nearest = i - end - end - - local offsetsStaggerX = { - { x = 0, y = 0 }, - { x = 1, y = -1 }, - { x = 1, y = 0 }, - { x = 2, y = 0 }, - } - - local offsetsStaggerY = { - { x = 0, y = 0 }, - { x = -1, y = 1 }, - { x = 0, y = 1 }, - { x = 0, y = 2 }, - } - - local offsets = staggerX and offsetsStaggerX or offsetsStaggerY - - return - referenceX + offsets[nearest].x, - referenceY + offsets[nearest].y - end -end - ---- A list of individual layers indexed both by draw order and name --- @table Map.layers --- @see TileLayer --- @see ObjectLayer --- @see ImageLayer --- @see CustomLayer - ---- A list of individual tiles indexed by Global ID --- @table Map.tiles --- @see Tile --- @see Map.tileInstances - ---- A list of tile instances indexed by Global ID --- @table Map.tileInstances --- @see TileInstance --- @see Tile --- @see Map.tiles - ---- A list of no-longer-used batch sprites, indexed by batch ---@table Map.freeBatchSprites - ---- A list of individual objects indexed by Global ID --- @table Map.objects --- @see Object - ---- @table TileLayer --- @field name The name of the layer --- @field x Position on the X axis (in pixels) --- @field y Position on the Y axis (in pixels) --- @field width Width of layer (in tiles) --- @field height Height of layer (in tiles) --- @field visible Toggle if layer is visible or hidden --- @field opacity Opacity of layer --- @field properties Custom properties --- @field data A tileWo dimensional table filled with individual tiles indexed by [y][x] (in tiles) --- @field update Update function --- @field draw Draw function --- @see Map.layers --- @see Tile - ---- @table ObjectLayer --- @field name The name of the layer --- @field x Position on the X axis (in pixels) --- @field y Position on the Y axis (in pixels) --- @field visible Toggle if layer is visible or hidden --- @field opacity Opacity of layer --- @field properties Custom properties --- @field objects List of objects indexed by draw order --- @field update Update function --- @field draw Draw function --- @see Map.layers --- @see Object - ---- @table ImageLayer --- @field name The name of the layer --- @field x Position on the X axis (in pixels) --- @field y Position on the Y axis (in pixels) --- @field visible Toggle if layer is visible or hidden --- @field opacity Opacity of layer --- @field properties Custom properties --- @field image Image to be drawn --- @field update Update function --- @field draw Draw function --- @see Map.layers - ---- Custom Layers are used to place userdata such as sprites within the draw order of the map. --- @table CustomLayer --- @field name The name of the layer --- @field x Position on the X axis (in pixels) --- @field y Position on the Y axis (in pixels) --- @field visible Toggle if layer is visible or hidden --- @field opacity Opacity of layer --- @field properties Custom properties --- @field update Update function --- @field draw Draw function --- @see Map.layers --- @usage --- -- Create a Custom Layer --- local spriteLayer = map:addCustomLayer("Sprite Layer", 3) --- --- -- Add data to Custom Layer --- spriteLayer.sprites = { --- player = { --- image = lg.newImage("assets/sprites/player.png"), --- x = 64, --- y = 64, --- r = 0, --- } --- } --- --- -- Update callback for Custom Layer --- function spriteLayer:update(dt) --- for _, sprite in pairs(self.sprites) do --- sprite.r = sprite.r + math.rad(90 * dt) --- end --- end --- --- -- Draw callback for Custom Layer --- function spriteLayer:draw() --- for _, sprite in pairs(self.sprites) do --- local x = math.floor(sprite.x) --- local y = math.floor(sprite.y) --- local r = sprite.r --- lg.draw(sprite.image, x, y, r) --- end --- end - ---- @table Tile --- @field id Local ID within Tileset --- @field gid Global ID --- @field tileset Tileset ID --- @field quad Quad object --- @field properties Custom properties --- @field terrain Terrain data --- @field animation Animation data --- @field frame Current animation frame --- @field time Time spent on current animation frame --- @field width Width of tile --- @field height Height of tile --- @field sx Scale value on the X axis --- @field sy Scale value on the Y axis --- @field r Rotation of tile (in radians) --- @field offset Offset drawing position --- @field offset.x Offset value on the X axis --- @field offset.y Offset value on the Y axis --- @see Map.tiles - ---- @table TileInstance --- @field batch Spritebatch the Tile Instance belongs to --- @field id ID within the spritebatch --- @field gid Global ID --- @field x Position on the X axis (in pixels) --- @field y Position on the Y axis (in pixels) --- @see Map.tileInstances --- @see Tile - ---- @table Object --- @field id Global ID --- @field name Name of object (non-unique) --- @field shape Shape of object --- @field x Position of object on X axis (in pixels) --- @field y Position of object on Y axis (in pixels) --- @field width Width of object (in pixels) --- @field height Heigh tof object (in pixels) --- @field rotation Rotation of object (in radians) --- @field visible Toggle if object is visible or hidden --- @field properties Custom properties --- @field ellipse List of verticies of specific shape --- @field rectangle List of verticies of specific shape --- @field polygon List of verticies of specific shape --- @field polyline List of verticies of specific shape --- @see Map.objects - -return setmetatable({}, STI) diff --git a/imperium-porcorum.love/libs/sti/plugins/box2d.lua b/imperium-porcorum.love/libs/sti/plugins/box2d.lua deleted file mode 100644 index 6d2e1b4..0000000 --- a/imperium-porcorum.love/libs/sti/plugins/box2d.lua +++ /dev/null @@ -1,303 +0,0 @@ ---- Box2D plugin for STI --- @module box2d --- @author Landon Manning --- @copyright 2017 --- @license MIT/X11 - -local utils = require((...):gsub('plugins.box2d', 'utils')) -local lg = require((...):gsub('plugins.box2d', 'graphics')) - -return { - box2d_LICENSE = "MIT/X11", - box2d_URL = "https://github.com/karai17/Simple-Tiled-Implementation", - box2d_VERSION = "2.3.2.6", - box2d_DESCRIPTION = "Box2D hooks for STI.", - - --- Initialize Box2D physics world. - -- @param world The Box2D world to add objects to. - box2d_init = function(map, world) - assert(love.physics, "To use the Box2D plugin, please enable the love.physics module.") - - local body = love.physics.newBody(world, map.offsetx, map.offsety) - local collision = { - body = body, - } - - local function addObjectToWorld(objshape, vertices, userdata, object) - local shape - - if objshape == "polyline" then - if #vertices == 4 then - shape = love.physics.newEdgeShape(unpack(vertices)) - else - shape = love.physics.newChainShape(false, unpack(vertices)) - end - else - shape = love.physics.newPolygonShape(unpack(vertices)) - end - - local currentBody = body - - if userdata.properties.dynamic == true then - currentBody = love.physics.newBody(world, map.offsetx, map.offsety, 'dynamic') - end - - local fixture = love.physics.newFixture(currentBody, shape) - - fixture:setUserData(userdata) - - -- Set some custom properties from userdata (or use default set by box2d) - fixture:setFriction(userdata.properties.friction or 0.2) - fixture:setRestitution(userdata.properties.restitution or 0.0) - fixture:setSensor(userdata.properties.sensor or false) - fixture:setFilterData(userdata.properties.categories or 1, - userdata.properties.mask or 65535, - userdata.properties.group or 0) - - local obj = { - object = object, - body = currentBody, - shape = shape, - fixture = fixture, - } - - table.insert(collision, obj) - end - - local function getPolygonVertices(object) - local vertices = {} - for _, vertex in ipairs(object.polygon) do - table.insert(vertices, vertex.x) - table.insert(vertices, vertex.y) - end - - return vertices - end - - local function calculateObjectPosition(object, tile) - local o = { - shape = object.shape, - x = (object.dx or object.x) + map.offsetx, - y = (object.dy or object.y) + map.offsety, - w = object.width, - h = object.height, - polygon = object.polygon or object.polyline or object.ellipse or object.rectangle - } - - local userdata = { - object = o, - properties = object.properties - } - - if o.shape == "rectangle" then - o.r = object.rotation or 0 - local cos = math.cos(math.rad(o.r)) - local sin = math.sin(math.rad(o.r)) - local oy = 0 - - if object.gid then - local tileset = map.tilesets[map.tiles[object.gid].tileset] - local lid = object.gid - tileset.firstgid - local t = {} - - -- This fixes a height issue - o.y = o.y + map.tiles[object.gid].offset.y - oy = tileset.tileheight - - for _, tt in ipairs(tileset.tiles) do - if tt.id == lid then - t = tt - break - end - end - - if t.objectGroup then - for _, obj in ipairs(t.objectGroup.objects) do - -- Every object in the tile - calculateObjectPosition(obj, object) - end - - return - else - o.w = map.tiles[object.gid].width - o.h = map.tiles[object.gid].height - end - end - - o.polygon = { - { x=o.x+0, y=o.y+0 }, - { x=o.x+o.w, y=o.y+0 }, - { x=o.x+o.w, y=o.y+o.h }, - { x=o.x+0, y=o.y+o.h } - } - - for _, vertex in ipairs(o.polygon) do - vertex.x, vertex.y = utils.rotate_vertex(map, vertex, o.x, o.y, cos, sin, oy) - end - - local vertices = getPolygonVertices(o) - addObjectToWorld(o.shape, vertices, userdata, tile or object) - elseif o.shape == "ellipse" then - if not o.polygon then - o.polygon = utils.convert_ellipse_to_polygon(o.x, o.y, o.w, o.h) - end - local vertices = getPolygonVertices(o) - local triangles = love.math.triangulate(vertices) - - for _, triangle in ipairs(triangles) do - addObjectToWorld(o.shape, triangle, userdata, tile or object) - end - elseif o.shape == "polygon" then - local vertices = getPolygonVertices(o) - local triangles = love.math.triangulate(vertices) - - for _, triangle in ipairs(triangles) do - addObjectToWorld(o.shape, triangle, userdata, tile or object) - end - elseif o.shape == "polyline" then - local vertices = getPolygonVertices(o) - addObjectToWorld(o.shape, vertices, userdata, tile or object) - end - end - - for _, tile in pairs(map.tiles) do - if map.tileInstances[tile.gid] then - for _, instance in ipairs(map.tileInstances[tile.gid]) do - -- Every object in every instance of a tile - if tile.objectGroup then - for _, object in ipairs(tile.objectGroup.objects) do - if object.properties.collidable == true then - object.dx = instance.x + object.x - object.dy = instance.y + object.y - calculateObjectPosition(object, instance) - end - end - end - - -- Every instance of a tile - if tile.properties.collidable == true then - local object = { - shape = "rectangle", - x = instance.x, - y = instance.y, - width = map.tilewidth, - height = map.tileheight, - properties = tile.properties - } - - calculateObjectPosition(object, instance) - end - end - end - end - - for _, layer in ipairs(map.layers) do - -- Entire layer - if layer.properties.collidable == true then - if layer.type == "tilelayer" then - for gid, tiles in pairs(map.tileInstances) do - local tile = map.tiles[gid] - local tileset = map.tilesets[tile.tileset] - - for _, instance in ipairs(tiles) do - if instance.layer == layer then - local object = { - shape = "rectangle", - x = instance.x, - y = instance.y, - width = tileset.tilewidth, - height = tileset.tileheight, - properties = tile.properties - } - - calculateObjectPosition(object, instance) - end - end - end - elseif layer.type == "objectgroup" then - for _, object in ipairs(layer.objects) do - calculateObjectPosition(object) - end - elseif layer.type == "imagelayer" then - local object = { - shape = "rectangle", - x = layer.x or 0, - y = layer.y or 0, - width = layer.width, - height = layer.height, - properties = layer.properties - } - - calculateObjectPosition(object) - end - end - - -- Individual objects - if layer.type == "objectgroup" then - for _, object in ipairs(layer.objects) do - if object.properties.collidable == true then - calculateObjectPosition(object) - end - end - end - end - - map.box2d_collision = collision - end, - - --- Remove Box2D fixtures and shapes from world. - -- @param index The index or name of the layer being removed - box2d_removeLayer = function(map, index) - local layer = assert(map.layers[index], "Layer not found: " .. index) - local collision = map.box2d_collision - - -- Remove collision objects - for i = #collision, 1, -1 do - local obj = collision[i] - - if obj.object.layer == layer then - obj.fixture:destroy() - table.remove(collision, i) - end - end - end, - - --- Draw Box2D physics world. - -- @param tx Translate on X - -- @param ty Translate on Y - -- @param sx Scale on X - -- @param sy Scale on Y - box2d_draw = function(map, tx, ty, sx, sy) - local collision = map.box2d_collision - - lg.push() - lg.scale(sx or 1, sy or sx or 1) - lg.translate(math.floor(tx or 0), math.floor(ty or 0)) - - for _, obj in ipairs(collision) do - local points = {obj.body:getWorldPoints(obj.shape:getPoints())} - local shape_type = obj.shape:getType() - - if shape_type == "edge" or shape_type == "chain" then - love.graphics.line(points) - elseif shape_type == "polygon" then - love.graphics.polygon("line", points) - else - error("sti box2d plugin does not support "..shape_type.." shapes") - end - end - - lg.pop() - end, -} - ---- Custom Properties in Tiled are used to tell this plugin what to do. --- @table Properties --- @field collidable set to true, can be used on any Layer, Tile, or Object --- @field sensor set to true, can be used on any Tile or Object that is also collidable --- @field dynamic set to true, can be used on any Tile or Object --- @field friction can be used to define the friction of any Object --- @field restitution can be used to define the restitution of any Object --- @field categories can be used to set the filter Category of any Object --- @field mask can be used to set the filter Mask of any Object --- @field group can be used to set the filter Group of any Object diff --git a/imperium-porcorum.love/libs/sti/plugins/bump.lua b/imperium-porcorum.love/libs/sti/plugins/bump.lua deleted file mode 100644 index d69ff26..0000000 --- a/imperium-porcorum.love/libs/sti/plugins/bump.lua +++ /dev/null @@ -1,194 +0,0 @@ ---- Bump.lua plugin for STI --- @module bump.lua --- @author David Serrano (BobbyJones|FrenchFryLord) --- @copyright 2016 --- @license MIT/X11 - -local lg = require((...):gsub('plugins.bump', 'graphics')) - -return { - bump_LICENSE = "MIT/X11", - bump_URL = "https://github.com/karai17/Simple-Tiled-Implementation", - bump_VERSION = "3.1.6.1", - bump_DESCRIPTION = "Bump hooks for STI.", - - --- Adds each collidable tile to the Bump world. - -- @param world The Bump world to add objects to. - -- @return collidables table containing the handles to the objects in the Bump world. - bump_init = function(map, world) - local collidables = {} - - for _, tileset in ipairs(map.tilesets) do - for _, tile in ipairs(tileset.tiles) do - local gid = tileset.firstgid + tile.id - - if map.tileInstances[gid] then - for _, instance in ipairs(map.tileInstances[gid]) do - -- Every object in every instance of a tile - if tile.objectGroup then - for _, object in ipairs(tile.objectGroup.objects) do - if object.properties.collidable == true then - local t = { - name = object.name, - type = object.type, - x = instance.x + map.offsetx + object.x, - y = instance.y + map.offsety + object.y, - width = object.width, - height = object.height, - layer = instance.layer, - properties = object.properties - - } - - world:add(t, t.x, t.y, t.width, t.height) - table.insert(collidables, t) - end - end - end - - -- Every instance of a tile - if tile.properties and tile.properties.collidable == true then - local t = { - x = instance.x + map.offsetx, - y = instance.y + map.offsety, - width = map.tilewidth, - height = map.tileheight, - layer = instance.layer, - properties = tile.properties - } - - world:add(t, t.x, t.y, t.width, t.height) - table.insert(collidables, t) - end - end - end - end - end - - for _, layer in ipairs(map.layers) do - -- Entire layer - if layer.properties.collidable == true then - if layer.type == "tilelayer" then - for y, tiles in ipairs(layer.data) do - for x, tile in pairs(tiles) do - - if tile.objectGroup then - for _, object in ipairs(tile.objectGroup.objects) do - if object.properties.collidable == true then - local t = { - name = object.name, - type = object.type, - x = ((x-1) * map.tilewidth + tile.offset.x + map.offsetx) + object.x, - y = ((y-1) * map.tileheight + tile.offset.y + map.offsety) + object.y, - width = object.width, - height = object.height, - layer = layer, - properties = object.properties - } - - world:add(t, t.x, t.y, t.width, t.height) - table.insert(collidables, t) - end - end - end - - - local t = { - x = (x-1) * map.tilewidth + tile.offset.x + map.offsetx, - y = (y-1) * map.tileheight + tile.offset.y + map.offsety, - width = tile.width, - height = tile.height, - layer = layer, - properties = tile.properties - } - - world:add(t, t.x, t.y, t.width, t.height) - table.insert(collidables, t) - end - end - elseif layer.type == "imagelayer" then - world:add(layer, layer.x, layer.y, layer.width, layer.height) - table.insert(collidables, layer) - end - end - - -- individual collidable objects in a layer that is not "collidable" - -- or whole collidable objects layer - if layer.type == "objectgroup" then - for _, obj in ipairs(layer.objects) do - if layer.properties.collidable == true or obj.properties.collidable == true then - if obj.shape == "rectangle" then - local t = { - name = obj.name, - type = obj.type, - x = obj.x + map.offsetx, - y = obj.y + map.offsety, - width = obj.width, - height = obj.height, - layer = layer, - properties = obj.properties - } - - if obj.gid then - t.y = t.y - obj.height - end - - world:add(t, t.x, t.y, t.width, t.height) - table.insert(collidables, t) - end -- TODO implement other object shapes? - end - end - end - - end - map.bump_collidables = collidables - end, - - --- Remove layer - -- @param index to layer to be removed - -- @param world bump world the holds the tiles - -- @param tx Translate on X --- @param ty Translate on Y --- @param sx Scale on X --- @param sy Scale on Y - bump_removeLayer = function(map, index, world) - local layer = assert(map.layers[index], "Layer not found: " .. index) - local collidables = map.bump_collidables - - -- Remove collision objects - for i = #collidables, 1, -1 do - local obj = collidables[i] - - if obj.layer == layer - and ( - layer.properties.collidable == true - or obj.properties.collidable == true - ) then - world:remove(obj) - table.remove(collidables, i) - end - end - end, - - --- Draw bump collisions world. - -- @param world bump world holding the tiles geometry - -- @param tx Translate on X - -- @param ty Translate on Y - -- @param sx Scale on X - -- @param sy Scale on Y - bump_draw = function(map, world, tx, ty, sx, sy) - lg.push() - lg.scale(sx or 1, sy or sx or 1) - lg.translate(math.floor(tx or 0), math.floor(ty or 0)) - - for _, collidable in pairs(map.bump_collidables) do - lg.rectangle("line", world:getRect(collidable)) - end - - lg.pop() - end -} - ---- Custom Properties in Tiled are used to tell this plugin what to do. --- @table Properties --- @field collidable set to true, can be used on any Layer, Tile, or Object diff --git a/imperium-porcorum.love/libs/sti/utils.lua b/imperium-porcorum.love/libs/sti/utils.lua deleted file mode 100644 index 9f8839a..0000000 --- a/imperium-porcorum.love/libs/sti/utils.lua +++ /dev/null @@ -1,206 +0,0 @@ --- Some utility functions that shouldn't be exposed. -local utils = {} - --- https://github.com/stevedonovan/Penlight/blob/master/lua/pl/path.lua#L286 -function utils.format_path(path) - local np_gen1,np_gen2 = '[^SEP]+SEP%.%.SEP?','SEP+%.?SEP' - local np_pat1, np_pat2 = np_gen1:gsub('SEP','/'), np_gen2:gsub('SEP','/') - local k - - repeat -- /./ -> / - path,k = path:gsub(np_pat2,'/') - until k == 0 - - repeat -- A/../ -> (empty) - path,k = path:gsub(np_pat1,'') - until k == 0 - - if path == '' then path = '.' end - - return path -end - --- Compensation for scale/rotation shift -function utils.compensate(tile, tileX, tileY, tileW, tileH) - local compx = 0 - local compy = 0 - - if tile.sx < 0 then compx = tileW end - if tile.sy < 0 then compy = tileH end - - if tile.r > 0 then - tileX = tileX + tileH - compy - tileY = tileY + tileH + compx - tileW - elseif tile.r < 0 then - tileX = tileX + compy - tileY = tileY - compx + tileH - else - tileX = tileX + compx - tileY = tileY + compy - end - - return tileX, tileY -end - --- Cache images in main STI module -function utils.cache_image(sti, path, image) - image = image or love.graphics.newImage(path) - image:setFilter("nearest", "nearest") - sti.cache[path] = image -end - --- We just don't know. -function utils.get_tiles(imageW, tileW, margin, spacing) - imageW = imageW - margin - local n = 0 - - while imageW >= tileW do - imageW = imageW - tileW - if n ~= 0 then imageW = imageW - spacing end - if imageW >= 0 then n = n + 1 end - end - - return n -end - --- Decompress tile layer data -function utils.get_decompressed_data(data) - local ffi = require "ffi" - local d = {} - local decoded = ffi.cast("uint32_t*", data) - - for i = 0, data:len() / ffi.sizeof("uint32_t") do - table.insert(d, tonumber(decoded[i])) - end - - return d -end - --- Convert a Tiled ellipse object to a LOVE polygon -function utils.convert_ellipse_to_polygon(x, y, w, h, max_segments) - local ceil = math.ceil - local cos = math.cos - local sin = math.sin - - local function calc_segments(segments) - local function vdist(a, b) - local c = { - x = a.x - b.x, - y = a.y - b.y, - } - - return c.x * c.x + c.y * c.y - end - - segments = segments or 64 - local vertices = {} - - local v = { 1, 2, ceil(segments/4-1), ceil(segments/4) } - - local m - if love and love.physics then - m = love.physics.getMeter() - else - m = 32 - end - - for _, i in ipairs(v) do - local angle = (i / segments) * math.pi * 2 - local px = x + w / 2 + cos(angle) * w / 2 - local py = y + h / 2 + sin(angle) * h / 2 - - table.insert(vertices, { x = px / m, y = py / m }) - end - - local dist1 = vdist(vertices[1], vertices[2]) - local dist2 = vdist(vertices[3], vertices[4]) - - -- Box2D threshold - if dist1 < 0.0025 or dist2 < 0.0025 then - return calc_segments(segments-2) - end - - return segments - end - - local segments = calc_segments(max_segments) - local vertices = {} - - table.insert(vertices, { x = x + w / 2, y = y + h / 2 }) - - for i = 0, segments do - local angle = (i / segments) * math.pi * 2 - local px = x + w / 2 + cos(angle) * w / 2 - local py = y + h / 2 + sin(angle) * h / 2 - - table.insert(vertices, { x = px, y = py }) - end - - return vertices -end - -function utils.rotate_vertex(map, vertex, x, y, cos, sin) - if map.orientation == "isometric" then - x, y = utils.convert_isometric_to_screen(map, x, y) - vertex.x, vertex.y = utils.convert_isometric_to_screen(map, vertex.x, vertex.y) - end - - vertex.x = vertex.x - x - vertex.y = vertex.y - y - - return - x + cos * vertex.x - sin * vertex.y, - y + sin * vertex.x + cos * vertex.y -end - ---- Project isometric position to cartesian position -function utils.convert_isometric_to_screen(map, x, y) - local mapH = map.height - local tileW = map.tilewidth - local tileH = map.tileheight - local tileX = x / tileH - local tileY = y / tileH - local offsetX = mapH * tileW / 2 - - return - (tileX - tileY) * tileW / 2 + offsetX, - (tileX + tileY) * tileH / 2 -end - -function utils.hex_to_color(hex) - if hex:sub(1, 1) == "#" then - hex = hex:sub(2) - end - - return { - r = tonumber(hex:sub(1, 2), 16) / 255, - g = tonumber(hex:sub(3, 4), 16) / 255, - b = tonumber(hex:sub(5, 6), 16) / 255 - } -end - -function utils.pixel_function(_, _, r, g, b, a) - local mask = utils._TC - - if r == mask.r and - g == mask.g and - b == mask.b then - return r, g, b, 0 - end - - return r, g, b, a -end - -function utils.fix_transparent_color(tileset, path) - local image_data = love.image.newImageData(path) - tileset.image = love.graphics.newImage(image_data) - - if tileset.transparentcolor then - utils._TC = utils.hex_to_color(tileset.transparentcolor) - - image_data:mapPixel(utils.pixel_function) - tileset.image = love.graphics.newImage(image_data) - end -end - -return utils diff --git a/imperium-porcorum.love/modules/menus/flowbox.lua b/imperium-porcorum.love/modules/menus/flowbox.lua deleted file mode 100644 index 6074d98..0000000 --- a/imperium-porcorum.love/modules/menus/flowbox.lua +++ /dev/null @@ -1,160 +0,0 @@ -FlowBox = Menu:extend() - -function FlowBox:new(x,y,w,h,slots_hor,slots_vert) - ListBox.super.new(self, x, y, w, h) - self.slots = slots_hor * slots_vert - self.slots_hor = slots_hor - self.slots_vert = slots_vert - self.begin = 1 - self.widgetsH = math.floor( self.h / slots_vert ) - self.widgetsW = math.floor( self.w / slots_hor ) - self.h = slots_vert * self.widgetsH -- On fait en sorte que la hauteur - self.w = slots_hor * self.widgetsW -- et la largeur - -- soit un multiple du nombre de slot et de leur dimensions -end - -function FlowBox:update(dt) - local col, line = self:getCoord(self.selected) - local begincol, beginline = self:getCoord(self.begin) - - if line < beginline then - beginline = line - end - - if line > beginline + self.slots_vert - 1 then - beginline = line - self.slots_vert + 1 - end - - if beginline < 0 then - beginline = 0 - end - - self.begin = beginline * self.slots_hor + 1 -end - -function FlowBox:getCoord(id_selected) - id_selected = id_selected - 1 -- On simplifie les calcul en prenant 0 comme départ - local line, col - line = math.floor(id_selected / self.slots_hor) - col = id_selected - (line * self.slots_hor) - return col, line -end - -function FlowBox:moveCursor(new_col, new_line) - local col, line = self:getCoord(self.selected) - local lastcol, lastline = self:getCoord(#self.listWidget) - - - if new_line < 0 then - new_line = lastline - end - - if new_line > lastline then - new_line = 0 - end - - if (new_line == lastline) then - if new_col < 0 then - new_col = lastcol - end - - if new_col > lastcol then - if (line == lastline) then - new_col = 0 - else - new_col = lastcol - end - end - else - if new_col < 0 then - new_col = self.slots_hor - 1 - end - - if new_col == self.slots_hor then - new_col = 0 - end - end - - self.selected = (new_line * self.slots_hor) + new_col + 1 -end - -function FlowBox:keyreleased(key, code) - local col, line = self:getCoord(self.selected) - if key == 'left' then - self:moveCursor(col - 1, line) - end - - if key == 'right' then - self:moveCursor(col + 1, line) - end - - if key == 'up' then - self:moveCursor(col, line - 1) - end - - if key == 'down' then - self:moveCursor(col, line + 1) - end - - if key == "A" then - self.listWidget[self.selected]:action() - end -end - -function FlowBox:mousemoved(x, y) - local col, line = self:getCoord(self.selected) - local begincol, beginline = self:getCoord(self.begin) - local newcol, newline - - newline = beginline + math.floor(y / self.widgetsH) - newcol = math.floor(x / self.widgetsW) - self.selected = (newline * self.slots_hor) + newcol + 1 - - if self.selected < 1 then - self.selected = 1 - end - if self.selected > #self.listWidget then - self.selected = #self.listWidget - end -end - -function FlowBox:mousepressed(x, y, button, isTouch) - local col, line = self:getCoord(self.selected) - local begincol, beginline = self:getCoord(self.begin) - local newline, newcol - - newline = beginline + math.floor(y / self.widgetsH) - newcol = math.floor(x / self.widgetsW) - self.selected = (newline * self.slots_hor) + newcol + 1 - - if self.selected < 1 then - self.selected = 1 - end - if self.selected > #self.listWidget then - self.selected = #self.listWidget - end - - if #self.listWidget > 0 then - self.listWidget[self.selected]:action() - end -end - -function FlowBox:draw() - local widgety = self.y - local widgetx = self.x - for i,v in ipairs(self.listWidget) do - if (i >= self.begin) and (i < self.begin + self.slots) then - v:draw(widgetx, widgety, self.widgetsW, self.widgetsH) - if self.selected == i and self.focus == true then - v:drawSelected(widgetx, widgety, self.widgetsW, self.widgetsH) - else - v:draw(widgetx, widgety, self.widgetsW, self.widgetsH) - end - widgetx = widgetx + self.widgetsW - if widgetx == (self.x + self.w) then - widgetx = self.x - widgety = widgety + self.widgetsH - end - end - end -end diff --git a/imperium-porcorum.love/modules/menus/grid.lua b/imperium-porcorum.love/modules/menus/grid.lua deleted file mode 100644 index ee57746..0000000 --- a/imperium-porcorum.love/modules/menus/grid.lua +++ /dev/null @@ -1,227 +0,0 @@ -GridBox = Menu:extend() - -function GridBox:new(x,y,w,h,slots_hor,slots_vert) - ListBox.super.new(self, x, y, w, h) - self.slots = slots_hor * slots_vert - self.slots_hor = slots_hor - self.slots_vert = slots_vert - self.begin = 1 - self.widgetsH = math.floor( self.h / slots_vert ) - self.widgetsW = math.floor( self.w / slots_hor ) - self.h = slots_vert * self.widgetsH -- On fait en sorte que la hauteur - self.w = slots_hor * self.widgetsW -- et la largeur - -- soit un multiple du nombre de slot et de leur dimensions - self.cursor = {} - self.cursor.x = 0 - self.cursor.y = 0 - - -- La gridbox possède la particularité de pouvoir fusioner des slots, on fait - -- donc une liste de slots disponibles, qui serviront par la suite. - self.listSlot = {} - for i= 1, self.slots do - self.listSlot[i] = {} - self.listSlot[i].sizeH = 1 - self.listSlot[i].sizeW = 1 - self.listSlot[i].isSlave = 0 - self.listSlot[i].widgetID = i - end -end - -function GridBox:update(dt) - self.begin = 1 - local slotID = self:getSlotbyCoord(self.cursor.x, self.cursor.y) - if self.listSlot[slotID].isSlave > 0 then - slotID = self.listSlot[slotID].isSlave - end - self.selected = self.listSlot[slotID].widgetID - self.cursor.x, self.cursor.y = self:getCoord(slotID) -end - -function GridBox:regenSlots() - local widgetID = 1 - for i,v in ipairs(self.listSlot) do - if v.isSlave == 0 and (widgetID <= #self.listWidget) then - self.listSlot[i].widgetID = widgetID - widgetID = widgetID + 1 - end - end -end - -function GridBox:addCol(slotID) - local col, line = self:getCoord(slotID) - if (col + self.listSlot[slotID].sizeW + 1) <= self.slots_hor then - slotSlave = slotID + self.listSlot[slotID].sizeW - for i = 1, self.listSlot[slotID].sizeH do - self.listSlot[slotSlave + ((i-1)* self.slots_hor)].isSlave = slotID - end - self.listSlot[slotID].sizeW = self.listSlot[slotID].sizeW + 1 - end -end - -function GridBox:addLine(slotID) - local col, line = self:getCoord(slotID) - if (line + self.listSlot[slotID].sizeH + 1) <= self.slots_vert then - slotSlave = slotID + (self.listSlot[slotID].sizeH * self.slots_hor) - for i = 1, self.listSlot[slotID].sizeW do - self.listSlot[slotSlave + (i-1)].isSlave = slotID - end - self.listSlot[slotID].sizeH = self.listSlot[slotID].sizeH + 1 - end -end - -function GridBox:getCoord(id_selected) - id_selected = id_selected - 1 -- On simplifie les calcul en prenant 0 comme départ - local line, col - line = math.floor(id_selected / self.slots_hor) - col = id_selected - (line * self.slots_hor) - return col, line -end - -function GridBox:getSlotbyCoord(col, line) - return (line * self.slots_hor) + col + 1 -end - -function GridBox:getSlot(widgetID) - local slotID - for i,v in ipairs(self.listSlot) do - if v.widgetID == widgetID then - return i - end - end - return 0 -end - -function GridBox:moveCursor(newcol, newline) - local col, line = self.cursor.x, self.cursor.y - local relcol, relline = newcol - col, newline - line - self.cursor.x, self.cursor.y = newcol, newline - - while self.cursor.y < 0 do - self.cursor.y = self.cursor.y + self.slots_vert - end - - while self.cursor.x < 0 do - self.cursor.x = self.cursor.x + self.slots_hor - end - - while self.cursor.y >= self.slots_vert do - self.cursor.y = self.cursor.y - self.slots_vert - end - - while self.cursor.x >= self.slots_hor do - self.cursor.x = self.cursor.x - self.slots_hor - end - previousSlot = self:getSlotbyCoord(col, line) - newSlot = self:getSlotbyCoord(self.cursor.x, self.cursor.y) - - if (self.listSlot[newSlot].isSlave > 0) or (self.listSlot[newSlot].widgetID > #self.listWidget) then - if (self.listSlot[newSlot].isSlave == previousSlot) or (self.listSlot[newSlot].widgetID > #self.listWidget) then - self:moveCursor(self.cursor.x + relcol, self.cursor.y + relline) - end - end - -end - -function GridBox:keyreleased(key, code) - slotID = self:getSlot(self.selected) - local col, line = self.cursor.x, self.cursor.y - if key == 'left' then - --self:moveCol(-1) - self:moveCursor(col - 1, line) - end - - if key == 'right' then - --self:moveCol(1) - self:moveCursor(col + 1, line) - end - - if key == 'up' then - self:moveCursor(col, line - 1) - end - - if key == 'down' then - self:moveCursor(col, line + 1) - end - - if key == "A" and self.selected <= #self.listWidget then - self.listWidget[self.selected]:action() - end -end - -function GridBox:mousemoved(x, y) - local col, line = self:getCoord(self.selected) - local begincol, beginline = self:getCoord(self.begin) - local newcol, newline - local newselect, slotID - - newline = beginline + math.floor(y / self.widgetsH) - newcol = math.floor(x / self.widgetsW) - self.cursor.x = newcol - self.cursor.y = newline - - if self.selected < 1 then - self.selected = 1 - end - if self.selected > #self.listWidget then - self.selected = #self.listWidget - end - -end - -function GridBox:mousepressed(x, y, button, isTouch) - local col, line = self:getCoord(self.selected) - local begincol, beginline = self:getCoord(self.begin) - local newcol, newline - local newselect, slotID - - newline = beginline + math.floor(y / self.widgetsH) - newcol = math.floor(x / self.widgetsW) - newselect = (newline * self.slots_hor) + newcol + 1 - - if self.listSlot[newselect].isSlave > 0 then - slotID = self.listSlot[newselect].isSlave - else - slotID = newselect - end - - self.selected = self.listSlot[slotID].widgetID - - if #self.listWidget > 0 and self.selected > 1 and self.selected <= #self.listWidget then - self.listWidget[self.selected]:action() - end -end - -function GridBox:draw() - local widgety = self.y - local widgetx = self.x - - self:regenSlots() -- On reget les slots au cas où :p - for i,v in ipairs(self.listSlot) do - if (v.isSlave == 0) and (v.widgetID <= #self.listWidget) then - --self.listWidget[v.widgetID]:draw(widgetx, widgety, self.widgetsW * v.sizeW, self.widgetsH * v.sizeH) - if self.selected == v.widgetID and self.focus == true then - self.listWidget[v.widgetID]:drawSelected(widgetx, widgety, self.widgetsW * v.sizeW, self.widgetsH * v.sizeH) - else - self.listWidget[v.widgetID]:draw(widgetx, widgety, self.widgetsW * v.sizeW, self.widgetsH * v.sizeH) - end - end - if (v.isSlave > 0) and false then - love.graphics.setColor(255,255,255,128) - love.graphics.rectangle("fill", widgetx, widgety, self.widgetsW, self.widgetsH) - end - local col, line = self:getCoord(i) - - if (col == self.cursor.x) and (line == self.cursor.y) and false then - love.graphics.setColor(255,255,0,128) - love.graphics.rectangle("fill", widgetx, widgety, self.widgetsW, self.widgetsH) - end - - --love.graphics.setColor(0,0,0,10) - --love.graphics.rectangle("line", widgetx, widgety, self.widgetsW, self.widgetsH) - widgetx = widgetx + self.widgetsW - if widgetx == (self.x + self.w) then - widgetx = self.x - widgety = widgety + self.widgetsH - end - end -end diff --git a/imperium-porcorum.love/modules/menus/init.lua b/imperium-porcorum.love/modules/menus/init.lua deleted file mode 100644 index bcfdc7c..0000000 --- a/imperium-porcorum.love/modules/menus/init.lua +++ /dev/null @@ -1,86 +0,0 @@ -MenuController = Object:extend() - -require "modules.menus.menu" -require "modules.menus.widgets" -require "modules.menus.listbox" -require "modules.menus.flowbox" -require "modules.menus.grid" -require "modules.menus.textmenu" - - -function MenuController:new() - self.menus = {} -end - -function MenuController:reset() - self.menus = {} -end - -function MenuController:addMenu(menu) - table.insert(self.menus, menu) -end - -function MenuController:update() - self:clear() - for i,v in ipairs(self.menus) do - v.id = i - v:update(dt) - v:updateWidgets(dt) - end -end - -function MenuController:clear() - -- On retire les entitées marquées comme supprimées - for i,v in ipairs(self.menus) do - if (v.destroyed == true) then - table.remove(self.menus, i) - end - end -end - -function MenuController:updateList() - for i,v in ipairs(self.menus) do - v.id = i - end -end - -function MenuController:keyreleased(key, code) - for i,v in ipairs(self.menus) do - if v.focus == true then - v:keyreleased(key, code) - end - end -end - -function MenuController:mousemoved(x, y, dx, dy) - for i,v in ipairs(self.menus) do - if (x > v.x) and (x < v.x + v.w) and (y > v.y) and (y < v.y + v.h) then - v:mousemoved(x - v.x, y - v.y) - for j,u in ipairs(self.menus) do - u.focus = false - end - v.focus = true - end - end -end - -function MenuController:mousepressed( x, y, button, istouch ) - for i,v in ipairs(self.menus) do - if (x > v.x) and (x < v.x + v.w) and (y > v.y) and (y < v.y + v.h) then - v:mousepressed(x - v.x, y - v.y, button, istouch ) - for j,u in ipairs(self.menus) do - u.focus = false - end - v.focus = true - end - end -end - -function MenuController:draw(dt) -- On dessine les entitées - for i,v in ipairs(self.menus) do - v.id = i - v:draw(dt) - end -end - -return MenuController diff --git a/imperium-porcorum.love/modules/menus/listbox.lua b/imperium-porcorum.love/modules/menus/listbox.lua deleted file mode 100644 index fdba4a8..0000000 --- a/imperium-porcorum.love/modules/menus/listbox.lua +++ /dev/null @@ -1,77 +0,0 @@ -ListBox = Menu:extend() - -function ListBox:new(x,y,w,h,slots) - ListBox.super.new(self, x, y, w, h) - self.slots = slots - self.begin = 1 - self.widgetsH = math.floor( self.h / slots ) - self.h = slots * self.widgetsH -- On fait en sorte que la hauteur - -- soit un multiple du nombre de slot et de leur hauteur -end - -function ListBox:update(dt) - if self.selected < self.begin then - self.begin = self.selected - end - if self.selected > self.begin + self.slots - 1 then - self.begin = self.selected - self.slots + 1 - end - - if self.begin < 1 then - self.begin = 1 - end -end - -function ListBox:keyreleased(key, code) - - if key == 'up' then - self:moveCursor(self.selected - 1) - end - - if key == 'down' then - self:moveCursor(self.selected + 1) - end - - if key == "A" then - self.listWidget[self.selected]:action() - end - -end - -function ListBox:mousemoved(x, y) - self.selected = self.begin + math.floor(y / self.widgetsH) - if self.selected < 1 then - self.selected = 1 - end - if self.selected > #self.listWidget then - self.selected = #self.listWidget - end -end - -function ListBox:mousepressed(x, y, button, isTouch) - self.selected = self.begin + math.floor(y / self.widgetsH) - if self.selected < 1 then - self.selected = 1 - end - if self.selected > #self.listWidget then - self.selected = #self.listWidget - end - if #self.listWidget > 0 then - self.listWidget[self.selected]:action() - end -end - -function ListBox:draw() - local widgety = self.y - for i,v in ipairs(self.listWidget) do - if (i >= self.begin) and (i < self.begin + self.slots) then - v:draw(self.x, widgety, self.w, self.widgetsH) - if self.selected == i and self.focus == true then - v:drawSelected(self.x, widgety, self.w, self.widgetsH) - else - v:draw(self.x, widgety, self.w, self.widgetsH) - end - widgety = widgety + self.widgetsH - end - end -end diff --git a/imperium-porcorum.love/modules/menus/menu.lua b/imperium-porcorum.love/modules/menus/menu.lua deleted file mode 100644 index c14c495..0000000 --- a/imperium-porcorum.love/modules/menus/menu.lua +++ /dev/null @@ -1,97 +0,0 @@ -Menu = Object:extend() - -function Menu:new(x,y,w,h) - self.x = x - self.y = y - self.w = w - self.h = h - self.listWidget = {} - self.selected = 0 - self.selectedPrevious = 0 - - self.destroyed = false - self.focus = false - self.cancel = 0 - self.virtualpad = vpad() -end - -function Menu:setLastWidgetCancel() - self.cancel = #self.listWidget -end - -function Menu:cancelAction() - if (self.cancel ~= 0) then - self.listWidget[self.cancel]:action() - end -end - -function Menu:update(dt) - -- Cette fonction ne contient rien par défaut -end - -function Menu:empty() - self.listWidget = {} - self.cancel = 0 -end - -function Menu:resize(x,y,w,h) - self.x = x - self.y = y - self.w = w - self.h = h -end - -function Menu:destroy() - self.destroyed = true -end - -function Menu:draw() - -- Cette fonction ne contient rien par défaut -end - -function Menu:keyreleased(key, code) - -- Cette fonction ne contient rien par défaut -end - -function Menu:mousemoved(x, y) - -- Cette fonction ne contient rien par défaut -end - -function Menu:mousepressed( x, y, button, istouch ) - -- Cette fonction ne contient rien par défaut -end - -function Menu:addWidget(newwidget) - if #self.listWidget == 0 then - self.selected = 1 - end - table.insert(self.listWidget, newwidget) -end - -function Menu:updateWidgets(dt) - self:clearWidgets() - for i,v in ipairs(self.listWidget) do - v.id = i - v:update(dt) - end -end - -function Menu:clearWidgets() -- On retire les widgets marquées comme supprimées - for i,v in ipairs(self.listWidget) do - if (v.destroyed == true) then - table.remove(self.listWidget, i) - end - end -end - -function Menu:moveCursor(new_selected) - if new_selected < 1 then - self.selected = #self.listWidget + new_selected - else - if new_selected > #self.listWidget then - self.selected = new_selected - #self.listWidget - else - self.selected = new_selected - end - end -end diff --git a/imperium-porcorum.love/modules/menus/textmenu.lua b/imperium-porcorum.love/modules/menus/textmenu.lua deleted file mode 100644 index 696f260..0000000 --- a/imperium-porcorum.love/modules/menus/textmenu.lua +++ /dev/null @@ -1,111 +0,0 @@ -TextMenu = Menu:extend() - -function TextMenu:new(x, y, font, slots) - TextMenu.super.new(self, x, y, 0, 0) - self.font = assets:getFont(font) - self.center = false - self.widgetsH = self.font:getHeight() - self.slots = slots - self.h = self.widgetsH * self.slots - self.begin = 1 - self.fixedWidth = false -end - -function TextMenu:centerText(width) - self.fixedWidth = true - self.center = true - self.w = width -end - -function TextMenu:update(dt) - if (self.fixedWidth == false) then - self:getWidth() - end - - if self.selected < self.begin then - self.begin = self.selected - end - if self.selected > self.begin + self.slots - 1 then - self.begin = self.selected - self.slots + 1 - end - - if self.begin < 1 then - self.begin = 1 - end -end - -function TextMenu:getWidth() - local width = self.w - - - for i,v in ipairs(self.listWidget) do - local stringWidth = self.font:getWidth(v.label) - width = math.max(stringWidth, width) - end - - self.w = width -end - -function TextMenu:keyreleased(key, code) - key = self.virtualpad:translateAction(1, key) - - if key == 'up' then - self:moveCursor(self.selected - 1) - end - - if key == 'down' then - self:moveCursor(self.selected + 1) - end - - if key == "A" then - self.listWidget[self.selected]:action() - end - - if key == "B" then - self:cancelAction() - end - -end - -function TextMenu:mousemoved(x, y) - self.selected = self.begin + math.floor(y / self.widgetsH) - if self.selected < 1 then - self.selected = 1 - end - if self.selected > #self.listWidget then - self.selected = #self.listWidget - end -end - -function TextMenu:mousepressed(x, y, button, isTouch) - self.selected = self.begin + math.floor(y / self.widgetsH) - if self.selected < 1 then - self.selected = 1 - end - if self.selected > #self.listWidget then - self.selected = #self.listWidget - end - if #self.listWidget > 0 then - self.listWidget[self.selected]:action() - end -end - -function TextMenu:draw() - local widgety = self.y - self.font:set() - for i,v in ipairs(self.listWidget) do - if (i >= self.begin) and (i < self.begin + self.slots) then - if self.selected == i and self.focus == true then - love.graphics.setColor(85, 170, 255) - else - utils.graphics.resetColor() - end - if (self.center) then - love.graphics.printf(v.label, self.x, widgety, self.w, "center") - else - love.graphics.print(v.label, self.x, widgety) - end - widgety = widgety + self.widgetsH - end - end -end diff --git a/imperium-porcorum.love/modules/menus/widgets/init.lua b/imperium-porcorum.love/modules/menus/widgets/init.lua deleted file mode 100644 index c174954..0000000 --- a/imperium-porcorum.love/modules/menus/widgets/init.lua +++ /dev/null @@ -1,114 +0,0 @@ -Widget = Object:extend() -DummyWidget = Widget:extend() - -function Widget:new() - self.destroyed = false - self.selectable = false - self.selection_margin = 0 - self.margin = 2 - self.label = "" -end - -function Widget:selectAction() - -- Do nothing -end - -function DummyWidget:new() - DummyWidget.super.new(self) - self.r = love.math.random(128) - self.g = love.math.random(128) - self.b = love.math.random(128) - self.selectable = true - self.label = "DUMMY WIDGET (see modules.menus.widget)" -end - -function DummyWidget:draw(x, y, w, h) - x = x + self.margin - y = y + self.margin - w = w - self.margin * 2 - h = h - self.margin * 2 - - love.graphics.setColor(self.r,self.g,self.b,70) - love.graphics.rectangle("fill", x, y, w, h) - love.graphics.setColor(self.r,self.g,self.b) - love.graphics.rectangle("line", x, y, w, h) -end - -function Widget:drawSelected(x,y,w,h) - self:draw(x, y, w, h) - x = x + self.selection_margin - y = y + self.selection_margin - w = w - self.selection_margin * 2 - h = h - self.selection_margin * 2 - - love.graphics.setColor(0,0,0) - love.graphics.rectangle("fill", x, y, 4, 8) - love.graphics.rectangle("fill", x, y, 8, 4) - - love.graphics.rectangle("fill", x + w, y, -4, 8) - love.graphics.rectangle("fill", x + w, y, -8, 4) - - love.graphics.rectangle("fill", x, y + h, 4, -8) - love.graphics.rectangle("fill", x, y + h, 8, -4) - - love.graphics.rectangle("fill", x + w, y + h, -4, -8) - love.graphics.rectangle("fill", x + w, y + h, -8, -4) - - love.graphics.setColor(255,255,255) - love.graphics.rectangle("fill", x + 1, y + 1, 2, 6) - love.graphics.rectangle("fill", x + 1, y + 1, 6, 2) - - love.graphics.rectangle("fill", x + w - 1, y + 1, -2, 6) - love.graphics.rectangle("fill", x + w - 1, y + 1, -6, 2) - - love.graphics.rectangle("fill", x + 1, y + h - 1, 2, -6) - love.graphics.rectangle("fill", x + 1, y + h - 1, 6, -2) - - love.graphics.rectangle("fill", x + w - 1, y + h - 1, -2, -6) - love.graphics.rectangle("fill", x + w - 1, y + h - 1, -6, -2) - -end - -function Widget:draw(x, y, w, h) -end - -function Widget:update(dt) - -- N/A -end - -function Widget:action() - self:destroy() -end - -function Widget:destroy() - self.destroyed = true -end - -function drawWidget_selected(x, y, w, h) - love.graphics.setColor(0,0,0) - love.graphics.rectangle("fill", x, y, 4, 8) - love.graphics.rectangle("fill", x, y, 8, 4) - - love.graphics.rectangle("fill", x + w, y, -4, 8) - love.graphics.rectangle("fill", x + w, y, -8, 4) - - love.graphics.rectangle("fill", x, y + h, 4, -8) - love.graphics.rectangle("fill", x, y + h, 8, -4) - - love.graphics.rectangle("fill", x + w, y + h, -4, -8) - love.graphics.rectangle("fill", x + w, y + h, -8, -4) - - love.graphics.setColor(255,255,255) - love.graphics.rectangle("fill", x + 1, y + 1, 2, 6) - love.graphics.rectangle("fill", x + 1, y + 1, 6, 2) - - love.graphics.rectangle("fill", x + w - 1, y + 1, -2, 6) - love.graphics.rectangle("fill", x + w - 1, y + 1, -6, 2) - - love.graphics.rectangle("fill", x + 1, y + h - 1, 2, -6) - love.graphics.rectangle("fill", x + 1, y + h - 1, 6, -2) - - love.graphics.rectangle("fill", x + w - 1, y + h - 1, -2, -6) - love.graphics.rectangle("fill", x + w - 1, y + h - 1, -6, -2) - -end diff --git a/imperium-porcorum.love/modules/savegame/init.lua b/imperium-porcorum.love/modules/savegame/init.lua deleted file mode 100644 index fd6a523..0000000 --- a/imperium-porcorum.love/modules/savegame/init.lua +++ /dev/null @@ -1,60 +0,0 @@ -Savegame = Object:extend() - -local binser = require "libs.binser" - -require "modules.savegame.pigs" - -function Savegame:new(filename) - self:reset() -end - -function Savegame:init(filename) - self:reset() - self.name = filename - self.slot = 1 -- le slot 0 signifie qu'on ne peut pas sauvegarder. -end - -function Savegame:reload() - self:read(self.name) -end - -function Savegame:getSaveFile(saveslot, absolute) - local dir = "" - if absolute then - dir = love.filesystem.getSaveDirectory() .. "/" - if not love.filesystem.exists(dir) then - love.filesystem.createDirectory( "" ) - end - end - - local filepath = dir .. "save" .. saveslot .. ".save" - - return filepath -end - -function Savegame:read() - if self.slot > 0 then - filepath = self:getSaveFile(self.slot, true) - if love.filesystem.exists("save" .. self.slot .. ".save") then - local loadedDatas = binser.readFile(filepath) - self.data = loadedDatas[1] - else - end - end -end - -function Savegame:write() - if self.slot > 0 then - filepath = self:getSaveFile(self.slot, true) - binser.writeFile(filepath, self.data) - end -end - -function Savegame:reset() - self.name = "" - self.data = {} - self.slot = 1 - self:resetPigs() -end - -return Savegame diff --git a/imperium-porcorum.love/modules/savegame/keyboard.lua b/imperium-porcorum.love/modules/savegame/keyboard.lua deleted file mode 100644 index f9f156f..0000000 --- a/imperium-porcorum.love/modules/savegame/keyboard.lua +++ /dev/null @@ -1,9 +0,0 @@ -local defaultKeyboard = require "datas.keyboard" - -function Savegame:initKeyboard() - self.save.keyboard = defaultKeyboard -end - -function Savegame:getKeyboard(playerID) - return self.save.keyboard[playerID] -end diff --git a/imperium-porcorum.love/scenes/levels/camera.lua b/imperium-porcorum.love/scenes/levels/camera.lua deleted file mode 100644 index aab661a..0000000 --- a/imperium-porcorum.love/scenes/levels/camera.lua +++ /dev/null @@ -1,153 +0,0 @@ -local CameraSystem = Object:extend() -local Camera = require "libs.hump.camera" - --- INIT FUNCTIONS --- Initialize the camera system - -function CameraSystem:new(scene, x, y) - self.scene = scene - self.world = scene.world - self.view = Camera(x, y, 1, 0, true) - - local width, height, flags = love.window.getMode( ) - self.screenWidth = width - self.screenHeight = height - self.viewWidth, self.viewHeight = core.screen:getDimensions() - - self.resolution = self.screenWidth / self.viewWidth - self:limit() -end - --- WRAPPER and UTILS --- Access data from the camera - -function CameraSystem:floorCoord() - self.view.x, self.view.y = utils.math.floorCoord(self.view.x, self.view.y) -end - -function CameraSystem:getCoord() - local camx, camy, camh, camw - camx = self.view.x - (self.viewWidth/2) - camy = self.view.y - (self.viewHeight/2) - - camw = self.viewWidth - camh = self.viewHeight - return camx, camy, camw, camh -end - -function CameraSystem:getScale() - return self.view.scale -end - -function CameraSystem:getScreenCoord() - local camx, camy, camh, camw - camx = self.view.x - (self.screenWidth/2) - camy = self.view.y - (self.screenHeight/2) - - camw = self.screenWidth - camh = self.screenHeight - return camx, camy, camw, camh -end - -function CameraSystem:worldCoord(x, y, ox, oy, w, h) - ox, oy = ox or 0, oy or 0 - w,h = w or love.graphics.getWidth(), h or love.graphics.getHeight() - return self.view:worldCoords(x, y, ox, oy, w, h) -end - -function CameraSystem:cameraCoords(x, y) - return self.view:cameraCoords(x, y, ox, oy, w, h) -end - -function CameraSystem:getVisibleEntities() - local camx, camy, camw, camh = self:getScreenCoord() - local visibleThings, len = self.world:queryRect(camx-64, camy-64, camw+128, camh+128) - return visibleThings, len -end - -function CameraSystem:isInsideView(x, y, w, h, border) - local camx, camy, camw, camh = self:getCoord() - local border = border or 0 - if (x + w + border >= camx) and (x < camx + camw + border) - and (y + h + border >= camy) and (y < camy + camh + border) then - return true - else - return false - end -end - -function CameraSystem:attach() - self.view:attach() -end - -function CameraSystem:detach() - self.view:detach() -end - --- UPDATE and MOVE functions --- Move and update the camera system - -function CameraSystem:update(dt) - self:followPlayer(self.scene.playermanager.activePlayer) - self:limit() - self:floorCoord() -end - -function CameraSystem:followPlayer(id) - local player = self.scene.playermanager:getPlayerByID(id) - - if (player ~= nil) then - local playx, playy = utils.math.floorCoord(player.center.x, - player.center.y) - - local camx, camy = self.view.x + (self.viewWidth/2), - self.view.y + (self.viewHeight/2) - - - playx, playy = self:cameraCoords(playx, playy) - playx = playx - (self.viewWidth/2) - playy = playy - (self.viewHeight/2) - - if (math.abs(playx) > 8) then - camx = camx + (playx - (8*utils.math.sign(playx))) - end - - if (playy > 16) then - camy = camy + (playy - 16) - elseif (playy < -64) then - camy = camy + (playy + 64) - end - - self.view.x, self.view.y = camx - (self.viewWidth/2), - camy - (self.viewHeight/2) - end -end - -function CameraSystem:move(x, y) - self.view.x = x - self.view.y = y - - self:limit() -end - -function CameraSystem:limit() - local camx, camy = self.view.x, self.view.y - local camMinX, camMinY = (self.screenWidth/2), (self.screenHeight/2) - - local camMaxX, camMaxY = self.world:getDimensions() - - if (self.resolution == 1) then - camMaxX, camMaxY = camMaxX - camMinX, camMaxY - camMinY - end - - - camx = math.max(camx, camMinX) - camx = math.min(camx, camMaxX) - - camy = math.max(camy, camMinY) - camy = math.min(camy, camMaxY) - - self.view.x, self.view.y = camx, camy -end - -return CameraSystem diff --git a/imperium-porcorum.love/scenes/levels/players.lua b/imperium-porcorum.love/scenes/levels/players.lua deleted file mode 100644 index 059bb8a..0000000 --- a/imperium-porcorum.love/scenes/levels/players.lua +++ /dev/null @@ -1,92 +0,0 @@ -local PlayerManager = Object:extend() -local Obj = require "scenes.levels.entities" - -function PlayerManager:new(scene) - self.scene = scene - self.players = {} - self.startx, self.starty = self.scene.world:getStartPosition() -end - --- PLAYER FUNCTIONS --- Handle virtual players - --- TODO: Gérer la manière dont le joueur va avoir une équipe de cochons - -function PlayerManager:addPlayer(pigID) - -- Enregistrer le joueur n'est pas le rajouter à une liste des objets qui existe, - -- mais juste insérer ses informations les plus importantes afin d'aider le jeu - -- à pouvoir le reconstruire. - local play = {} - play.pigID = pigID - play.isDead = 0 - - table.insert(self.players, play) -end - -function PlayerManager:spawnPlayer(playerID) - local play = self.players[playerID] - --Obj.Player(self.scene.world, self.startx, self.starty, playerID) - --self.activePlayer = playerID -end - -function PlayerManager:getPlayers() - local itemList = self.scene.world:getActors() - local playerList = {} - - for i,v in ipairs(itemList) do - if (v.playerID > 0) then - table.insert(playerList, v) - end - end - - return playerList -end - -function PlayerManager:getPlayerByID(id) - local itemList = self.scene.world:getActors() - local player - - if (id == nil) then - return nil - --error("You must have an ID to search") - end - - for i,v in ipairs(itemList) do - if (v.playerID == id) then - player = v - end - end - - return player -end - -function PlayerManager:playerExist(id) - return (self.players[id] ~= nil) -end - -function PlayerManager:playerHaveObject(id) - player = self:getPlayerByID(id) - - if (player == nil) then - return false - else - return true - end -end - --- UPDATE FUNCTIONS --- Update the death timer and respawn the player when it's done - -function PlayerManager:update(dt) - -end - --- DRAW FUNCTIONS --- Functions made to draw the HUD - -function PlayerManager:drawHUD(dt) - - -end - -return PlayerManager diff --git a/imperium-porcorum.love/scenes/levels/world.lua b/imperium-porcorum.love/scenes/levels/world.lua index f6a944a..737448f 100644 --- a/imperium-porcorum.love/scenes/levels/world.lua +++ b/imperium-porcorum.love/scenes/levels/world.lua @@ -1,10 +1,6 @@ local World2D = require "core.modules.world.world2D" local World = World2D:extend() -local Obj = require "scenes.levels.entities" - -local Sti = require "libs.sti" - -- INIT FUNCTIONS -- All functions to init the world and the map