]> git.mcshandy.xyz Git - sumeriangame/commitdiff
TREEE MEANS STOP collision
authorLobster <kevmuri14@gmail.com>
Sun, 25 Jan 2026 18:29:11 +0000 (13:29 -0500)
committerLobster <kevmuri14@gmail.com>
Sun, 25 Jan 2026 18:29:11 +0000 (13:29 -0500)
main/collision.lua [new file with mode: 0644]
main/main.lua
main/player.lua [new file with mode: 0644]
main/plugin/windfield/init.lua [deleted file]
main/plugin/windfield/mlib/Changes.txt [deleted file]
main/plugin/windfield/mlib/LICENSE.md [deleted file]
main/plugin/windfield/mlib/README.md [deleted file]
main/plugin/windfield/mlib/mlib.lua [deleted file]
main/tiled/Sample_fantasy.tsx
main/tiled/test_1.lua
main/tiled/test_1.tmx

diff --git a/main/collision.lua b/main/collision.lua
new file mode 100644 (file)
index 0000000..94562cd
--- /dev/null
@@ -0,0 +1,26 @@
+-- collision.lua
+
+local collision = {}
+
+-- Check if a tile at grid position is collidable
+-- I think we can check tiles and objects for custom props using this for things like interactables too
+function collision.is_tile_collidable(map, x, y)
+
+  -- Get all layers and check if there are walls
+  for _, layer in ipairs(map.layers) do
+    if layer.type == 'tilelayer' then
+      local properties = map:getTileProperties(layer.name, x, y)
+      if properties and properties.wall then
+        return true
+      end
+    end
+  end
+  return false
+end
+
+-- Convert world coordinates to tile coordinates
+function collision.world_to_tile(map, wx, wy)
+  return math.floor(wx / map.tilewidth) + 1, math.floor(wy / map.tileheight) + 1
+end
+
+return collision
index 14a59207ce20f2d6c81ef0f6ed7dd8b24b666e30..4791cdceed994196734a2782043397f2816e251e 100644 (file)
@@ -2,22 +2,17 @@
 
 -- Plugins
 local sti  = require('plugin/sti')
-local wf = require('plugin/windfield')
-local lovebird = require('plugin/lovebird')
+local lovebird = require('plugin/lovebird') -- Debugging tool http://127.0.0.1:8000
 
 -- Modules
 local conf = require('conf')
 local assets = require('assets')
-local utils = require('utils')
-local vector = require('vector')
+local player_module = require('player')
 
 local active_map = nil
-local world = nil
 player = nil
 local tx, ty
 
-local world = wf.newWorld(0, 0)
-
 function love.load()
                love.graphics.setFont(assets.get_font('Cuneiform36'))
     love.audio.play(assets.get_source('intro'))
@@ -28,15 +23,7 @@ function love.load()
     end
 
     player = assets.get_object('Player')
-    player.keyreleased = function(self, key)
-      if key == 'q' then love.event.quit(0) end
-      for k,v in pairs(conf.player_keymap) do
-        if key == k and (v.control == conf.ControlType.Movement) then
-          self.vec.heading = v.heading
-          self.vec.speed = v.speed
-        end
-      end
-    end
+    player_module.init_controls(player, active_map)
 
     tx = 0
     ty = 0
@@ -44,9 +31,7 @@ end
 
 function love.update(dt)
   lovebird.update()
-
   active_map:update(dt)
-  world:update(dt)
 end
 
 function love.keypressed(key)
@@ -59,5 +44,4 @@ end
 function love.draw()
   active_map:draw(tx, ty, 2.0)
   love.graphics.print(IntroMessage, math.floor((conf.window.width/16) * 1), math.floor((conf.window.height/16) * 1))
-  world:draw()
 end
diff --git a/main/player.lua b/main/player.lua
new file mode 100644 (file)
index 0000000..9041579
--- /dev/null
@@ -0,0 +1,42 @@
+-- player.lua
+
+local conf = require('conf')
+local vector = require('vector')
+local collision = require('collision')
+
+local player_module = {}
+
+function player_module.init_controls(player_obj, active_map)
+  player_obj.keyreleased = function(self, key)
+    if key == 'q' then love.event.quit(0) end
+    
+    for k, v in pairs(conf.player_keymap) do
+      if key == k and (v.control == conf.ControlType.Movement) then
+        -- Calculate target tile coordinates (current tile + direction)
+        local current_tile_x = math.floor(self.vec.x / active_map.tilewidth)
+        local current_tile_y = math.floor(self.vec.y / active_map.tileheight)
+        
+        -- Direction vectors for each heading
+        local dx = math.floor(math.cos(v.heading) + 0.5)
+        local dy = math.floor(math.sin(v.heading) + 0.5)
+        
+        local target_tile_x = current_tile_x + dx
+        local target_tile_y = current_tile_y + dy
+        
+        if not collision.is_tile_collidable(active_map, target_tile_x + 1, target_tile_y + 1) then
+          -- Move to target tile (convert back to world coordinates)
+          self.vec.x = target_tile_x * active_map.tilewidth
+          self.vec.y = target_tile_y * active_map.tileheight
+        end
+      end
+    end
+  end
+end
+
+function player_module.draw(player_obj)
+  if player_obj and player_obj.image then
+    love.graphics.draw(player_obj.image, math.floor(player_obj.vec.x), math.floor(player_obj.vec.y))
+  end
+end
+
+return player_module
diff --git a/main/plugin/windfield/init.lua b/main/plugin/windfield/init.lua
deleted file mode 100644 (file)
index 8554822..0000000
+++ /dev/null
@@ -1,929 +0,0 @@
---[[\r
-The MIT License (MIT)\r
-\r
-Copyright (c) 2018 SSYGEN\r
-\r
-Permission is hereby granted, free of charge, to any person obtaining a copy\r
-of this software and associated documentation files (the "Software"), to deal\r
-in the Software without restriction, including without limitation the rights\r
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
-copies of the Software, and to permit persons to whom the Software is\r
-furnished to do so, subject to the following conditions:\r
-\r
-The above copyright notice and this permission notice shall be included in all\r
-copies or substantial portions of the Software.\r
-\r
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
-SOFTWARE.\r
-]]--\r
-\r
-local path = ... .. '.' \r
-local wf = {} \r
-wf.Math = require(path .. 'mlib.mlib') \r
-\r
-World = {}\r
-World.__index = World \r
-\r
-function wf.newWorld(xg, yg, sleep)\r
-    local world = wf.World.new(wf, xg, yg, sleep)\r
-\r
-    world.box2d_world:setCallbacks(world.collisionOnEnter, world.collisionOnExit, world.collisionPre, world.collisionPost)\r
-    world:collisionClear()\r
-    world:addCollisionClass('Default')\r
-\r
-    -- Points all box2d_world functions to this wf.World object\r
-    -- This means that the user can call world:setGravity for instance without having to say world.box2d_world:setGravity\r
-    for k, v in pairs(world.box2d_world.__index) do \r
-        if k ~= '__gc' and k ~= '__eq' and k ~= '__index' and k ~= '__tostring' and k ~= 'update' and k ~= 'destroy' and k ~= 'type' and k ~= 'typeOf' then\r
-            world[k] = function(self, ...)\r
-                return v(self.box2d_world, ...)\r
-            end\r
-        end\r
-    end\r
-\r
-    return world\r
-end\r
-\r
-function World.new(wf, xg, yg, sleep)\r
-    local self = {}\r
-    local settings = settings or {}\r
-    self.wf = wf\r
-\r
-    self.draw_query_for_n_frames = 10\r
-    self.query_debug_drawing_enabled = false\r
-    self.explicit_collision_events = false\r
-    self.collision_classes = {}\r
-    self.masks = {}\r
-    self.is_sensor_memo = {}\r
-    self.query_debug_draw = {}\r
-\r
-    love.physics.setMeter(32)\r
-    self.box2d_world = love.physics.newWorld(xg, yg, sleep) \r
-\r
-    return setmetatable(self, World)\r
-end\r
-\r
-function World:update(dt)\r
-    self:collisionEventsClear()\r
-    self.box2d_world:update(dt)\r
-end\r
-\r
-function World:draw(alpha)\r
-    -- get the current color values to reapply\r
-    local r, g, b, a = love.graphics.getColor()\r
-    -- alpha value is optional\r
-    alpha = alpha or 255\r
-    -- Colliders debug\r
-    love.graphics.setColor(222, 222, 222, alpha)\r
-    local bodies = self.box2d_world:getBodies()\r
-    for _, body in ipairs(bodies) do\r
-        local fixtures = body:getFixtures()\r
-        for _, fixture in ipairs(fixtures) do\r
-            if fixture:getShape():type() == 'PolygonShape' then\r
-                love.graphics.polygon('line', body:getWorldPoints(fixture:getShape():getPoints()))\r
-            elseif fixture:getShape():type() == 'EdgeShape' or fixture:getShape():type() == 'ChainShape' then\r
-                local points = {body:getWorldPoints(fixture:getShape():getPoints())}\r
-                for i = 1, #points, 2 do\r
-                    if i < #points-2 then love.graphics.line(points[i], points[i+1], points[i+2], points[i+3]) end\r
-                end\r
-            elseif fixture:getShape():type() == 'CircleShape' then\r
-                local body_x, body_y = body:getPosition()\r
-                local shape_x, shape_y = fixture:getShape():getPoint()\r
-                local r = fixture:getShape():getRadius()\r
-                love.graphics.circle('line', body_x + shape_x, body_y + shape_y, r, 360)\r
-            end\r
-        end\r
-    end\r
-    love.graphics.setColor(255, 255, 255, alpha)\r
-\r
-    -- Joint debug\r
-    love.graphics.setColor(222, 128, 64, alpha)\r
-    local joints = self.box2d_world:getJoints()\r
-    for _, joint in ipairs(joints) do\r
-        local x1, y1, x2, y2 = joint:getAnchors()\r
-        if x1 and y1 then love.graphics.circle('line', x1, y1, 4) end\r
-        if x2 and y2 then love.graphics.circle('line', x2, y2, 4) end\r
-    end\r
-    love.graphics.setColor(255, 255, 255, alpha)\r
-\r
-    -- Query debug\r
-    love.graphics.setColor(64, 64, 222, alpha)\r
-    for _, query_draw in ipairs(self.query_debug_draw) do\r
-        query_draw.frames = query_draw.frames - 1\r
-        if query_draw.type == 'circle' then\r
-            love.graphics.circle('line', query_draw.x, query_draw.y, query_draw.r)\r
-        elseif query_draw.type == 'rectangle' then\r
-            love.graphics.rectangle('line', query_draw.x, query_draw.y, query_draw.w, query_draw.h)\r
-        elseif query_draw.type == 'line' then\r
-            love.graphics.line(query_draw.x1, query_draw.y1, query_draw.x2, query_draw.y2)\r
-        elseif query_draw.type == 'polygon' then\r
-            local triangles = love.math.triangulate(query_draw.vertices)\r
-            for _, triangle in ipairs(triangles) do love.graphics.polygon('line', triangle) end\r
-        end\r
-    end\r
-    for i = #self.query_debug_draw, 1, -1 do\r
-        if self.query_debug_draw[i].frames <= 0 then\r
-            table.remove(self.query_debug_draw, i)\r
-        end\r
-    end\r
-    love.graphics.setColor(r, g, b, a)\r
-end\r
-\r
-function World:setQueryDebugDrawing(value)\r
-    self.query_debug_drawing_enabled = value\r
-end\r
-\r
-function World:setExplicitCollisionEvents(value)\r
-    self.explicit_collision_events = value\r
-end\r
-\r
-function World:addCollisionClass(collision_class_name, collision_class)\r
-    if self.collision_classes[collision_class_name] then error('Collision class ' .. collision_class_name .. ' already exists.') end\r
-\r
-    if self.explicit_collision_events then\r
-        self.collision_classes[collision_class_name] = collision_class or {}\r
-    else\r
-        self.collision_classes[collision_class_name] = collision_class or {}\r
-        self.collision_classes[collision_class_name].enter = {}\r
-        self.collision_classes[collision_class_name].exit = {}\r
-        self.collision_classes[collision_class_name].pre = {}\r
-        self.collision_classes[collision_class_name].post = {}\r
-        for c_class_name, _ in pairs(self.collision_classes) do\r
-            table.insert(self.collision_classes[collision_class_name].enter, c_class_name)\r
-            table.insert(self.collision_classes[collision_class_name].exit, c_class_name)\r
-            table.insert(self.collision_classes[collision_class_name].pre, c_class_name)\r
-            table.insert(self.collision_classes[collision_class_name].post, c_class_name)\r
-        end\r
-        for c_class_name, _ in pairs(self.collision_classes) do\r
-            table.insert(self.collision_classes[c_class_name].enter, collision_class_name)\r
-            table.insert(self.collision_classes[c_class_name].exit, collision_class_name)\r
-            table.insert(self.collision_classes[c_class_name].pre, collision_class_name)\r
-            table.insert(self.collision_classes[c_class_name].post, collision_class_name)\r
-        end\r
-    end\r
-\r
-    self:collisionClassesSet()\r
-end\r
-\r
-function World:collisionClassesSet()\r
-    self:generateCategoriesMasks()\r
-\r
-    self:collisionClear()\r
-    local collision_table = self:getCollisionCallbacksTable()\r
-    for collision_class_name, collision_list in pairs(collision_table) do\r
-        for _, collision_info in ipairs(collision_list) do\r
-            if collision_info.type == 'enter' then self:addCollisionEnter(collision_class_name, collision_info.other) end\r
-            if collision_info.type == 'exit' then self:addCollisionExit(collision_class_name, collision_info.other) end\r
-            if collision_info.type == 'pre' then self:addCollisionPre(collision_class_name, collision_info.other) end\r
-            if collision_info.type == 'post' then self:addCollisionPost(collision_class_name, collision_info.other) end\r
-        end\r
-    end\r
-\r
-    self:collisionEventsClear()\r
-end\r
-\r
-function World:collisionClear()\r
-    self.collisions = {}\r
-    self.collisions.on_enter = {}\r
-    self.collisions.on_enter.sensor = {}\r
-    self.collisions.on_enter.non_sensor = {}\r
-    self.collisions.on_exit = {}\r
-    self.collisions.on_exit.sensor = {}\r
-    self.collisions.on_exit.non_sensor = {}\r
-    self.collisions.pre = {}\r
-    self.collisions.pre.sensor = {}\r
-    self.collisions.pre.non_sensor = {}\r
-    self.collisions.post = {}\r
-    self.collisions.post.sensor = {}\r
-    self.collisions.post.non_sensor = {}\r
-end\r
-\r
-function World:collisionEventsClear()\r
-    local bodies = self.box2d_world:getBodies()\r
-    for _, body in ipairs(bodies) do\r
-        local collider = body:getFixtures()[1]:getUserData()\r
-        collider:collisionEventsClear()\r
-    end\r
-end\r
-\r
-function World:addCollisionEnter(type1, type2)\r
-    if not self:isCollisionBetweenSensors(type1, type2) then\r
-        table.insert(self.collisions.on_enter.non_sensor, {type1 = type1, type2 = type2})\r
-    else table.insert(self.collisions.on_enter.sensor, {type1 = type1, type2 = type2}) end\r
-end\r
-\r
-function World:addCollisionExit(type1, type2)\r
-    if not self:isCollisionBetweenSensors(type1, type2) then\r
-        table.insert(self.collisions.on_exit.non_sensor, {type1 = type1, type2 = type2})\r
-    else table.insert(self.collisions.on_exit.sensor, {type1 = type1, type2 = type2}) end\r
-end\r
-\r
-function World:addCollisionPre(type1, type2)\r
-    if not self:isCollisionBetweenSensors(type1, type2) then\r
-        table.insert(self.collisions.pre.non_sensor, {type1 = type1, type2 = type2})\r
-    else table.insert(self.collisions.pre.sensor, {type1 = type1, type2 = type2}) end\r
-end\r
-\r
-function World:addCollisionPost(type1, type2)\r
-    if not self:isCollisionBetweenSensors(type1, type2) then\r
-        table.insert(self.collisions.post.non_sensor, {type1 = type1, type2 = type2})\r
-    else table.insert(self.collisions.post.sensor, {type1 = type1, type2 = type2}) end\r
-end\r
-\r
-function World:doesType1IgnoreType2(type1, type2)\r
-    local collision_ignores = {}\r
-    for collision_class_name, collision_class in pairs(self.collision_classes) do\r
-        collision_ignores[collision_class_name] = collision_class.ignores or {}\r
-    end\r
-    local all = {}\r
-    for collision_class_name, _ in pairs(collision_ignores) do\r
-        table.insert(all, collision_class_name)\r
-    end\r
-    local ignored_types = {}\r
-    for _, collision_class_type in ipairs(collision_ignores[type1]) do\r
-        if collision_class_type == 'All' then\r
-            for _, collision_class_name in ipairs(all) do\r
-                table.insert(ignored_types, collision_class_name)\r
-            end\r
-        else table.insert(ignored_types, collision_class_type) end\r
-    end\r
-    for key, _ in pairs(collision_ignores[type1]) do\r
-        if key == 'except' then\r
-            for _, except_type in ipairs(collision_ignores[type1].except) do\r
-                for i = #ignored_types, 1, -1 do\r
-                    if ignored_types[i] == except_type then table.remove(ignored_types, i) end\r
-                end\r
-            end\r
-        end\r
-    end\r
-    for _, ignored_type in ipairs(ignored_types) do\r
-        if ignored_type == type2 then return true end\r
-    end\r
-end\r
-\r
-function World:isCollisionBetweenSensors(type1, type2)\r
-    if not self.is_sensor_memo[type1] then self.is_sensor_memo[type1] = {} end\r
-    if not self.is_sensor_memo[type1][type2] then self.is_sensor_memo[type1][type2] = (self:doesType1IgnoreType2(type1, type2) or self:doesType1IgnoreType2(type2, type1)) end\r
-    if self.is_sensor_memo[type1][type2] then return true\r
-    else return false end\r
-end\r
-\r
--- https://love2d.org/forums/viewtopic.php?f=4&t=75441\r
-function World:generateCategoriesMasks()\r
-    local collision_ignores = {}\r
-    for collision_class_name, collision_class in pairs(self.collision_classes) do\r
-        collision_ignores[collision_class_name] = collision_class.ignores or {}\r
-    end\r
-    local incoming = {}\r
-    local expanded = {}\r
-    local all = {}\r
-    for object_type, _ in pairs(collision_ignores) do\r
-        incoming[object_type] = {}\r
-        expanded[object_type] = {}\r
-        table.insert(all, object_type)\r
-    end\r
-    for object_type, ignore_list in pairs(collision_ignores) do\r
-        for key, ignored_type in pairs(ignore_list) do\r
-            if ignored_type == 'All' then\r
-                for _, all_object_type in ipairs(all) do\r
-                    table.insert(incoming[all_object_type], object_type)\r
-                    table.insert(expanded[object_type], all_object_type)\r
-                end\r
-            elseif type(ignored_type) == 'string' then\r
-                if ignored_type ~= 'All' then\r
-                    table.insert(incoming[ignored_type], object_type)\r
-                    table.insert(expanded[object_type], ignored_type)\r
-                end\r
-            end\r
-            if key == 'except' then\r
-                for _, except_ignored_type in ipairs(ignored_type) do\r
-                    for i, v in ipairs(incoming[except_ignored_type]) do\r
-                        if v == object_type then\r
-                            table.remove(incoming[except_ignored_type], i)\r
-                            break\r
-                        end\r
-                    end\r
-                end\r
-                for _, except_ignored_type in ipairs(ignored_type) do\r
-                    for i, v in ipairs(expanded[object_type]) do\r
-                        if v == except_ignored_type then\r
-                            table.remove(expanded[object_type], i)\r
-                            break\r
-                        end\r
-                    end\r
-                end\r
-            end\r
-        end\r
-    end\r
-    local edge_groups = {}\r
-    for k, v in pairs(incoming) do\r
-        table.sort(v, function(a, b) return string.lower(a) < string.lower(b) end)\r
-    end\r
-    local i = 0\r
-    for k, v in pairs(incoming) do\r
-        local str = ""\r
-        for _, c in ipairs(v) do\r
-            str = str .. c\r
-        end\r
-        if not edge_groups[str] then i = i + 1; edge_groups[str] = {n = i} end\r
-        table.insert(edge_groups[str], k)\r
-    end\r
-    local categories = {}\r
-    for k, _ in pairs(collision_ignores) do\r
-        categories[k] = {}\r
-    end\r
-    for k, v in pairs(edge_groups) do\r
-        for i, c in ipairs(v) do\r
-            categories[c] = v.n\r
-        end\r
-    end\r
-    for k, v in pairs(expanded) do\r
-        local category = {categories[k]}\r
-        local current_masks = {}\r
-        for _, c in ipairs(v) do\r
-            table.insert(current_masks, categories[c])\r
-        end\r
-        self.masks[k] = {categories = category, masks = current_masks}\r
-    end\r
-end\r
-\r
-function World:getCollisionCallbacksTable()\r
-    local collision_table = {}\r
-    for collision_class_name, collision_class in pairs(self.collision_classes) do\r
-        collision_table[collision_class_name] = {}\r
-        for _, v in ipairs(collision_class.enter or {}) do table.insert(collision_table[collision_class_name], {type = 'enter', other = v}) end\r
-        for _, v in ipairs(collision_class.exit or {}) do table.insert(collision_table[collision_class_name], {type = 'exit', other = v}) end\r
-        for _, v in ipairs(collision_class.pre or {}) do table.insert(collision_table[collision_class_name], {type = 'pre', other = v}) end\r
-        for _, v in ipairs(collision_class.post or {}) do table.insert(collision_table[collision_class_name], {type = 'post', other = v}) end\r
-    end\r
-    return collision_table\r
-end\r
-\r
-local function collEnsure(collision_class_name1, a, collision_class_name2, b)\r
-    if a.collision_class == collision_class_name2 and b.collision_class == collision_class_name1 then return b, a\r
-    else return a, b end\r
-end\r
-\r
-local function collIf(collision_class_name1, collision_class_name2, a, b)\r
-    if (a.collision_class == collision_class_name1 and b.collision_class == collision_class_name2) or\r
-       (a.collision_class == collision_class_name2 and b.collision_class == collision_class_name1) then\r
-       return true\r
-    else return false end\r
-end\r
-\r
-function World.collisionOnEnter(fixture_a, fixture_b, contact)\r
-    local a, b = fixture_a:getUserData(), fixture_b:getUserData()\r
-\r
-    if fixture_a:isSensor() and fixture_b:isSensor() then\r
-        if a and b then\r
-            for _, collision in ipairs(a.world.collisions.on_enter.sensor) do\r
-                if collIf(collision.type1, collision.type2, a, b) then\r
-                    a, b = collEnsure(collision.type1, a, collision.type2, b)\r
-                    table.insert(a.collision_events[collision.type2], {collision_type = 'enter', collider_1 = a, collider_2 = b, contact = contact})\r
-                    if collision.type1 == collision.type2 then \r
-                        table.insert(b.collision_events[collision.type1], {collision_type = 'enter', collider_1 = b, collider_2 = a, contact = contact})\r
-                    end\r
-                end\r
-            end\r
-        end\r
-\r
-    elseif not (fixture_a:isSensor() or fixture_b:isSensor()) then\r
-        if a and b then\r
-            for _, collision in ipairs(a.world.collisions.on_enter.non_sensor) do\r
-                if collIf(collision.type1, collision.type2, a, b) then\r
-                    a, b = collEnsure(collision.type1, a, collision.type2, b)\r
-                    table.insert(a.collision_events[collision.type2], {collision_type = 'enter', collider_1 = a, collider_2 = b, contact = contact})\r
-                    if collision.type1 == collision.type2 then \r
-                        table.insert(b.collision_events[collision.type1], {collision_type = 'enter', collider_1 = b, collider_2 = a, contact = contact})\r
-                    end\r
-                end\r
-            end\r
-        end\r
-    end\r
-end\r
-\r
-function World.collisionOnExit(fixture_a, fixture_b, contact)\r
-    local a, b = fixture_a:getUserData(), fixture_b:getUserData()\r
-\r
-    if fixture_a:isSensor() and fixture_b:isSensor() then\r
-        if a and b then\r
-            for _, collision in ipairs(a.world.collisions.on_exit.sensor) do\r
-                if collIf(collision.type1, collision.type2, a, b) then\r
-                    a, b = collEnsure(collision.type1, a, collision.type2, b)\r
-                    table.insert(a.collision_events[collision.type2], {collision_type = 'exit', collider_1 = a, collider_2 = b, contact = contact})\r
-                    if collision.type1 == collision.type2 then \r
-                        table.insert(b.collision_events[collision.type1], {collision_type = 'exit', collider_1 = b, collider_2 = a, contact = contact})\r
-                    end\r
-                end\r
-            end\r
-        end\r
-\r
-    elseif not (fixture_a:isSensor() or fixture_b:isSensor()) then\r
-        if a and b then\r
-            for _, collision in ipairs(a.world.collisions.on_exit.non_sensor) do\r
-                if collIf(collision.type1, collision.type2, a, b) then\r
-                    a, b = collEnsure(collision.type1, a, collision.type2, b)\r
-                    table.insert(a.collision_events[collision.type2], {collision_type = 'exit', collider_1 = a, collider_2 = b, contact = contact})\r
-                    if collision.type1 == collision.type2 then \r
-                        table.insert(b.collision_events[collision.type1], {collision_type = 'exit', collider_1 = b, collider_2 = a, contact = contact})\r
-                    end\r
-                end\r
-            end\r
-        end\r
-    end\r
-end\r
-\r
-function World.collisionPre(fixture_a, fixture_b, contact)\r
-    local a, b = fixture_a:getUserData(), fixture_b:getUserData()\r
-\r
-    if fixture_a:isSensor() and fixture_b:isSensor() then\r
-        if a and b then\r
-            for _, collision in ipairs(a.world.collisions.pre.sensor) do\r
-                if collIf(collision.type1, collision.type2, a, b) then\r
-                    a, b = collEnsure(collision.type1, a, collision.type2, b)\r
-                    a:preSolve(b, contact)\r
-                    if collision.type1 == collision.type2 then \r
-                        b:preSolve(a, contact)\r
-                    end\r
-                end\r
-            end\r
-        end\r
-\r
-    elseif not (fixture_a:isSensor() or fixture_b:isSensor()) then\r
-        if a and b then\r
-            for _, collision in ipairs(a.world.collisions.pre.non_sensor) do\r
-                if collIf(collision.type1, collision.type2, a, b) then\r
-                    a, b = collEnsure(collision.type1, a, collision.type2, b)\r
-                    a:preSolve(b, contact)\r
-                    if collision.type1 == collision.type2 then \r
-                        b:preSolve(a, contact)\r
-                    end\r
-                end\r
-            end\r
-        end\r
-    end\r
-end\r
-\r
-function World.collisionPost(fixture_a, fixture_b, contact, ni1, ti1, ni2, ti2)\r
-    local a, b = fixture_a:getUserData(), fixture_b:getUserData()\r
-\r
-    if fixture_a:isSensor() and fixture_b:isSensor() then\r
-        if a and b then\r
-            for _, collision in ipairs(a.world.collisions.post.sensor) do\r
-                if collIf(collision.type1, collision.type2, a, b) then\r
-                    a, b = collEnsure(collision.type1, a, collision.type2, b)\r
-                    a:postSolve(b, contact, ni1, ti1, ni2, ti2)\r
-                    if collision.type1 == collision.type2 then \r
-                        b:postSolve(a, contact, ni1, ti1, ni2, ti2)\r
-                    end\r
-                end\r
-            end\r
-        end\r
-\r
-    elseif not (fixture_a:isSensor() or fixture_b:isSensor()) then\r
-        if a and b then\r
-            for _, collision in ipairs(a.world.collisions.post.non_sensor) do\r
-                if collIf(collision.type1, collision.type2, a, b) then\r
-                    a, b = collEnsure(collision.type1, a, collision.type2, b)\r
-                    a:postSolve(b, contact, ni1, ti1, ni2, ti2)\r
-                    if collision.type1 == collision.type2 then \r
-                        b:postSolve(a, contact, ni1, ti1, ni2, ti2)\r
-                    end\r
-                end\r
-            end\r
-        end\r
-    end\r
-end\r
-\r
-function World:newCircleCollider(x, y, r, settings)\r
-    return self.wf.Collider.new(self, 'Circle', x, y, r, settings)\r
-end\r
-\r
-function World:newRectangleCollider(x, y, w, h, settings)\r
-    return self.wf.Collider.new(self, 'Rectangle', x, y, w, h, settings)\r
-end\r
-\r
-function World:newBSGRectangleCollider(x, y, w, h, corner_cut_size, settings)\r
-    return self.wf.Collider.new(self, 'BSGRectangle', x, y, w, h, corner_cut_size, settings)\r
-end\r
-\r
-function World:newPolygonCollider(vertices, settings)\r
-    return self.wf.Collider.new(self, 'Polygon', vertices, settings)\r
-end\r
-\r
-function World:newLineCollider(x1, y1, x2, y2, settings)\r
-    return self.wf.Collider.new(self, 'Line', x1, y1, x2, y2, settings)\r
-end\r
-\r
-function World:newChainCollider(vertices, loop, settings)\r
-    return self.wf.Collider.new(self, 'Chain', vertices, loop, settings)\r
-end\r
-\r
--- Internal AABB box2d query used before going for more specific and precise computations.\r
-function World:_queryBoundingBox(x1, y1, x2, y2)\r
-    local colliders = {}\r
-    local callback = function(fixture)\r
-        if not fixture:isSensor() then table.insert(colliders, fixture:getUserData()) end\r
-        return true\r
-    end\r
-    self.box2d_world:queryBoundingBox(x1, y1, x2, y2, callback)\r
-    return colliders\r
-end\r
-\r
-function World:collisionClassInCollisionClassesList(collision_class, collision_classes)\r
-    if collision_classes[1] == 'All' then\r
-        local all_collision_classes = {}\r
-        for class, _ in pairs(self.collision_classes) do\r
-            table.insert(all_collision_classes, class)\r
-        end\r
-        if collision_classes.except then\r
-            for _, except in ipairs(collision_classes.except) do\r
-                for i, class in ipairs(all_collision_classes) do\r
-                    if class == except then \r
-                        table.remove(all_collision_classes, i)\r
-                        break\r
-                    end\r
-                end\r
-            end\r
-        end\r
-        for _, class in ipairs(all_collision_classes) do\r
-            if class == collision_class then return true end\r
-        end\r
-    else\r
-        for _, class in ipairs(collision_classes) do\r
-            if class == collision_class then return true end\r
-        end\r
-    end\r
-end\r
-\r
-function World:queryCircleArea(x, y, radius, collision_class_names)\r
-    if not collision_class_names then collision_class_names = {'All'} end\r
-    if self.query_debug_drawing_enabled then table.insert(self.query_debug_draw, {type = 'circle', x = x, y = y, r = radius, frames = self.draw_query_for_n_frames}) end\r
-    \r
-    local colliders = self:_queryBoundingBox(x-radius, y-radius, x+radius, y+radius) \r
-    local outs = {}\r
-    for _, collider in ipairs(colliders) do\r
-        if self:collisionClassInCollisionClassesList(collider.collision_class, collision_class_names) then\r
-            for _, fixture in ipairs(collider.body:getFixtures()) do\r
-                if self.wf.Math.polygon.getCircleIntersection(x, y, radius, {collider.body:getWorldPoints(fixture:getShape():getPoints())}) then\r
-                    table.insert(outs, collider)\r
-                    break\r
-                end\r
-            end\r
-        end\r
-    end\r
-    return outs\r
-end\r
-\r
-function World:queryRectangleArea(x, y, w, h, collision_class_names)\r
-    if not collision_class_names then collision_class_names = {'All'} end\r
-    if self.query_debug_drawing_enabled then table.insert(self.query_debug_draw, {type = 'rectangle', x = x, y = y, w = w, h = h, frames = self.draw_query_for_n_frames}) end\r
-\r
-    local colliders = self:_queryBoundingBox(x, y, x+w, y+h) \r
-    local outs = {}\r
-    for _, collider in ipairs(colliders) do\r
-        if self:collisionClassInCollisionClassesList(collider.collision_class, collision_class_names) then\r
-            for _, fixture in ipairs(collider.body:getFixtures()) do\r
-                if self.wf.Math.polygon.isPolygonInside({x, y, x+w, y, x+w, y+h, x, y+h}, {collider.body:getWorldPoints(fixture:getShape():getPoints())}) then\r
-                    table.insert(outs, collider)\r
-                    break\r
-                end\r
-            end\r
-        end\r
-    end\r
-    return outs\r
-end\r
-\r
-function World:queryPolygonArea(vertices, collision_class_names)\r
-    if not collision_class_names then collision_class_names = {'All'} end\r
-    if self.query_debug_drawing_enabled then table.insert(self.query_debug_draw, {type = 'polygon', vertices = vertices, frames = self.draw_query_for_n_frames}) end\r
-\r
-    local cx, cy = self.wf.Math.polygon.getCentroid(vertices)\r
-    local d_max = 0\r
-    for i = 1, #vertices, 2 do\r
-        local d = self.wf.Math.line.getLength(cx, cy, vertices[i], vertices[i+1])\r
-        if d > d_max then d_max = d end\r
-    end\r
-    local colliders = self:_queryBoundingBox(cx-d_max, cy-d_max, cx+d_max, cy+d_max)\r
-    local outs = {}\r
-    for _, collider in ipairs(colliders) do\r
-        if self:collisionClassInCollisionClassesList(collider.collision_class, collision_class_names) then\r
-            for _, fixture in ipairs(collider.body:getFixtures()) do\r
-                if self.wf.Math.polygon.isPolygonInside(vertices, {collider.body:getWorldPoints(fixture:getShape():getPoints())}) then\r
-                    table.insert(outs, collider)\r
-                    break\r
-                end\r
-            end\r
-        end\r
-    end\r
-    return outs\r
-end\r
-\r
-function World:queryLine(x1, y1, x2, y2, collision_class_names)\r
-    if not collision_class_names then collision_class_names = {'All'} end\r
-    if self.query_debug_drawing_enabled then \r
-        table.insert(self.query_debug_draw, {type = 'line', x1 = x1, y1 = y1, x2 = x2, y2 = y2, frames = self.draw_query_for_n_frames}) \r
-    end\r
-\r
-    local colliders = {}\r
-    local callback = function(fixture, ...)\r
-        if not fixture:isSensor() then table.insert(colliders, fixture:getUserData()) end\r
-        return 1\r
-    end\r
-    self.box2d_world:rayCast(x1, y1, x2, y2, callback)\r
-\r
-    local outs = {}\r
-    for _, collider in ipairs(colliders) do\r
-        if self:collisionClassInCollisionClassesList(collider.collision_class, collision_class_names) then\r
-            table.insert(outs, collider)\r
-        end\r
-    end\r
-    return outs\r
-end\r
-\r
-function World:addJoint(joint_type, ...)\r
-    local args = {...}\r
-    if args[1].body then args[1] = args[1].body end\r
-    if type(args[2]) == "table" and args[2].body then args[2] = args[2].body end\r
-    local joint = love.physics['new' .. joint_type](unpack(args))\r
-    return joint\r
-end\r
-\r
-function World:removeJoint(joint)\r
-    joint:destroy()\r
-end\r
-\r
-function World:destroy()\r
-    local bodies = self.box2d_world:getBodies()\r
-    for _, body in ipairs(bodies) do\r
-        local collider = body:getFixtures()[1]:getUserData()\r
-        collider:destroy()\r
-    end\r
-    local joints = self.box2d_world:getJoints()\r
-    for _, joint in ipairs(joints) do joint:destroy() end\r
-    self.box2d_world:destroy()\r
-    self.box2d_world = nil\r
-end\r
-\r
-\r
-\r
-local Collider = {}\r
-Collider.__index = Collider\r
-\r
-local generator = love.math.newRandomGenerator(os.time())\r
-local function UUID()\r
-    local fn = function(x)\r
-        local r = generator:random(16) - 1\r
-        r = (x == "x") and (r + 1) or (r % 4) + 9\r
-        return ("0123456789abcdef"):sub(r, r)\r
-    end\r
-    return (("xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx"):gsub("[xy]", fn))\r
-end\r
-\r
-function Collider.new(world, collider_type, ...)\r
-    local self = {}\r
-    self.id = UUID()\r
-    self.world = world\r
-    self.type = collider_type\r
-    self.object = nil\r
-\r
-    self.shapes = {}\r
-    self.fixtures = {}\r
-    self.sensors = {}\r
-\r
-    self.collision_events = {}\r
-    self.collision_stay = {}\r
-    self.enter_collision_data = {}\r
-    self.exit_collision_data = {}\r
-    self.stay_collision_data = {}\r
-\r
-    local args = {...}\r
-    local shape, fixture\r
-    if self.type == 'Circle' then\r
-        self.collision_class = (args[4] and args[4].collision_class) or 'Default'\r
-        self.body = love.physics.newBody(self.world.box2d_world, args[1], args[2], (args[4] and args[4].body_type) or 'dynamic')\r
-        shape = love.physics.newCircleShape(args[3])\r
-\r
-    elseif self.type == 'Rectangle' then\r
-        self.collision_class = (args[5] and args[5].collision_class) or 'Default'\r
-        self.body = love.physics.newBody(self.world.box2d_world, args[1] + args[3]/2, args[2] + args[4]/2, (args[5] and args[5].body_type) or 'dynamic')\r
-        shape = love.physics.newRectangleShape(args[3], args[4])\r
-\r
-    elseif self.type == 'BSGRectangle' then\r
-        self.collision_class = (args[6] and args[6].collision_class) or 'Default'\r
-        self.body = love.physics.newBody(self.world.box2d_world, args[1] + args[3]/2, args[2] + args[4]/2, (args[6] and args[6].body_type) or 'dynamic')\r
-        local w, h, s = args[3], args[4], args[5]\r
-        shape = love.physics.newPolygonShape({\r
-            -w/2, -h/2 + s, -w/2 + s, -h/2,\r
-             w/2 - s, -h/2, w/2, -h/2 + s,\r
-             w/2, h/2 - s, w/2 - s, h/2,\r
-            -w/2 + s, h/2, -w/2, h/2 - s\r
-        })\r
-\r
-    elseif self.type == 'Polygon' then\r
-        self.collision_class = (args[2] and args[2].collision_class) or 'Default'\r
-        self.body = love.physics.newBody(self.world.box2d_world, 0, 0, (args[2] and args[2].body_type) or 'dynamic')\r
-        shape = love.physics.newPolygonShape(unpack(args[1]))\r
-\r
-    elseif self.type == 'Line' then\r
-        self.collision_class = (args[5] and args[5].collision_class) or 'Default'\r
-        self.body = love.physics.newBody(self.world.box2d_world, 0, 0, (args[5] and args[5].body_type) or 'dynamic')\r
-        shape = love.physics.newEdgeShape(args[1], args[2], args[3], args[4])\r
-\r
-    elseif self.type == 'Chain' then\r
-        self.collision_class = (args[3] and args[3].collision_class) or 'Default'\r
-        self.body = love.physics.newBody(self.world.box2d_world, 0, 0, (args[3] and args[3].body_type) or 'dynamic')\r
-        shape = love.physics.newChainShape(args[1], unpack(args[2]))\r
-    end\r
-\r
-    -- Define collision classes and attach them to fixture and sensor\r
-    fixture = love.physics.newFixture(self.body, shape)\r
-    if self.world.masks[self.collision_class] then\r
-        fixture:setCategory(unpack(self.world.masks[self.collision_class].categories))\r
-        fixture:setMask(unpack(self.world.masks[self.collision_class].masks))\r
-    end\r
-    fixture:setUserData(self)\r
-    local sensor = love.physics.newFixture(self.body, shape)\r
-    sensor:setSensor(true)\r
-    sensor:setUserData(self)\r
-\r
-    self.shapes['main'] = shape\r
-    self.fixtures['main'] = fixture\r
-    self.sensors['main'] = sensor\r
-    self.shape = shape\r
-    self.fixture = fixture\r
-    \r
-    self.preSolve = function() end\r
-    self.postSolve = function() end\r
-\r
-    -- Points all body, fixture and shape functions to this wf.Collider object\r
-    -- This means that the user can call collider:setLinearVelocity for instance without having to say collider.body:setLinearVelocity\r
-    for k, v in pairs(self.body.__index) do \r
-        if k ~= '__gc' and k ~= '__eq' and k ~= '__index' and k ~= '__tostring' and k ~= 'destroy' and k ~= 'type' and k ~= 'typeOf' then\r
-            self[k] = function(self, ...)\r
-                return v(self.body, ...)\r
-            end\r
-        end\r
-    end\r
-    for k, v in pairs(self.fixture.__index) do \r
-        if k ~= '__gc' and k ~= '__eq' and k ~= '__index' and k ~= '__tostring' and k ~= 'destroy' and k ~= 'type' and k ~= 'typeOf' then\r
-            self[k] = function(self, ...)\r
-                return v(self.fixture, ...)\r
-            end\r
-        end\r
-    end\r
-    for k, v in pairs(self.shape.__index) do \r
-        if k ~= '__gc' and k ~= '__eq' and k ~= '__index' and k ~= '__tostring' and k ~= 'destroy' and k ~= 'type' and k ~= 'typeOf' then\r
-            self[k] = function(self, ...)\r
-                return v(self.shape, ...)\r
-            end\r
-        end\r
-    end\r
-\r
-    return setmetatable(self, Collider)\r
-end\r
-\r
-function Collider:collisionEventsClear()\r
-    self.collision_events = {}\r
-    for other, _ in pairs(self.world.collision_classes) do\r
-        self.collision_events[other] = {}\r
-    end\r
-end\r
-\r
-function Collider:setCollisionClass(collision_class_name)\r
-    if not self.world.collision_classes[collision_class_name] then error("Collision class " .. collision_class_name .. " doesn't exist.") end\r
-    self.collision_class = collision_class_name\r
-    for _, fixture in pairs(self.fixtures) do\r
-        if self.world.masks[collision_class_name] then\r
-            fixture:setCategory(unpack(self.world.masks[collision_class_name].categories))\r
-            fixture:setMask(unpack(self.world.masks[collision_class_name].masks))\r
-        end\r
-    end\r
-end\r
-\r
-function Collider:enter(other_collision_class_name)\r
-    local events = self.collision_events[other_collision_class_name]\r
-    if events and #events >= 1  then\r
-        for _, e in ipairs(events) do\r
-            if e.collision_type == 'enter' then\r
-                if not self.collision_stay[other_collision_class_name] then self.collision_stay[other_collision_class_name] = {} end\r
-                table.insert(self.collision_stay[other_collision_class_name], {collider = e.collider_2, contact = e.contact})\r
-                self.enter_collision_data[other_collision_class_name] = {collider = e.collider_2, contact = e.contact}\r
-                return true\r
-            end\r
-        end\r
-    end\r
-end\r
-\r
-function Collider:getEnterCollisionData(other_collision_class_name)\r
-    return self.enter_collision_data[other_collision_class_name]\r
-end\r
-\r
-function Collider:exit(other_collision_class_name)\r
-    local events = self.collision_events[other_collision_class_name]\r
-    if events and #events >= 1  then\r
-        for _, e in ipairs(events) do\r
-            if e.collision_type == 'exit' then\r
-                if self.collision_stay[other_collision_class_name] then\r
-                    for i = #self.collision_stay[other_collision_class_name], 1, -1 do\r
-                        local collision_stay = self.collision_stay[other_collision_class_name][i]\r
-                        if collision_stay.collider.id == e.collider_2.id then table.remove(self.collision_stay[other_collision_class_name], i) end\r
-                    end\r
-                end\r
-                self.exit_collision_data[other_collision_class_name] = {collider = e.collider_2, contact = e.contact}\r
-                return true \r
-            end\r
-        end\r
-    end\r
-end\r
-\r
-function Collider:getExitCollisionData(other_collision_class_name)\r
-    return self.exit_collision_data[other_collision_class_name]\r
-end\r
-\r
-function Collider:stay(other_collision_class_name)\r
-    if self.collision_stay[other_collision_class_name] then\r
-        if #self.collision_stay[other_collision_class_name] >= 1 then\r
-            return true\r
-        end\r
-    end\r
-end\r
-\r
-function Collider:getStayCollisionData(other_collision_class_name)\r
-    return self.collision_stay[other_collision_class_name]\r
-end\r
-\r
-function Collider:setPreSolve(callback)\r
-    self.preSolve = callback\r
-end\r
-\r
-function Collider:setPostSolve(callback)\r
-    self.postSolve = callback\r
-end\r
-\r
-function Collider:setObject(object)\r
-    self.object = object \r
-end\r
-\r
-function Collider:getObject()\r
-    return self.object\r
-end\r
-\r
-function Collider:addShape(shape_name, shape_type, ...)\r
-    if self.shapes[shape_name] or self.fixtures[shape_name] then error("Shape/fixture " .. shape_name .. " already exists.") end\r
-    local args = {...}\r
-    local shape = love.physics['new' .. shape_type](unpack(args))\r
-    local fixture = love.physics.newFixture(self.body, shape)\r
-    if self.world.masks[self.collision_class] then\r
-        fixture:setCategory(unpack(self.world.masks[self.collision_class].categories))\r
-        fixture:setMask(unpack(self.world.masks[self.collision_class].masks))\r
-    end\r
-    fixture:setUserData(self)\r
-    local sensor = love.physics.newFixture(self.body, shape)\r
-    sensor:setSensor(true)\r
-    sensor:setUserData(self)\r
-\r
-    self.shapes[shape_name] = shape\r
-    self.fixtures[shape_name] = fixture\r
-    self.sensors[shape_name] = sensor\r
-end\r
-\r
-function Collider:removeShape(shape_name)\r
-    if not self.shapes[shape_name] then return end\r
-    self.shapes[shape_name] = nil\r
-    self.fixtures[shape_name]:setUserData(nil)\r
-    self.fixtures[shape_name]:destroy()\r
-    self.fixtures[shape_name] = nil\r
-    self.sensors[shape_name]:setUserData(nil)\r
-    self.sensors[shape_name]:destroy()\r
-    self.sensors[shape_name] = nil\r
-end\r
-\r
-function Collider:destroy()\r
-    self.collision_stay = nil\r
-    self.enter_collision_data = nil\r
-    self.exit_collision_data = nil\r
-    self:collisionEventsClear()\r
-\r
-    self:setObject(nil)\r
-    for name, _ in pairs(self.fixtures) do\r
-        self.shapes[name] = nil\r
-        self.fixtures[name]:setUserData(nil)\r
-        self.fixtures[name] = nil\r
-        self.sensors[name]:setUserData(nil)\r
-        self.sensors[name] = nil\r
-    end\r
-    self.body:destroy()\r
-    self.body = nil\r
-end\r
-\r
-wf.World = World\r
-wf.Collider = Collider\r
-\r
-return wf\r
-\r
diff --git a/main/plugin/windfield/mlib/Changes.txt b/main/plugin/windfield/mlib/Changes.txt
deleted file mode 100644 (file)
index 1b41d50..0000000
+++ /dev/null
@@ -1,568 +0,0 @@
-0.11.0\r
-====\r
-Added:\r
-----\r
-- mlib.vec2 component\r
-\r
-To-Do: \r
-----\r
-- Update README.md\r
-- Update spec.lua\r
-- Fix tabbing\r
-\r
-0.10.1\r
-====\r
-Added:\r
-----\r
-- Point category\r
-       - point.rotate\r
-       - point.scale\r
-       - point.polarToCartesian\r
-       - point.cartesianToPolar\r
-\r
-Changed:\r
-----\r
-- math.getPercent now returns decimals (instead of percentages) since those are more common to use.\r
-\r
-To-Do:\r
-----\r
-- Determine if isCompletelyInsideFunctions should return true with tangents.\r
-- Check argument order for logicality and consistency.\r
-- Add error checking.\r
-- Make sure to see if any aliases were missed. (e.g. isSegmentInside)\r
-- Clean up and correct README (add "Home" link, etc.)\r
-\r
-0.10.0\r
-====\r
-Added:\r
-----\r
-\r
-Changed:\r
-----\r
-- mlib.line.segment is now mlib.segment.\r
-- mlib.line.getIntercept has been renamed to mlib.line.getYIntercept\r
-- mlib.line.getYIntercept now returns the x-coordinate for vertical lines instead of false.\r
-- mlib.line.getYIntercept now returns the value `isVertical` as the second return value.\r
-- mlib.line.getPerpendicularBisector is now mlib.segment.getPerpendicularBisector.\r
-\r
-Fixed:\r
-----\r
-- mlib.line.getIntersection now should handle vertical slopes better.\r
-- mlib.line.getClosestPoint now uses local function checkFuzzy for checking horizontal lines.\r
-- Fixed possible bug in mlib.line.getSegmentIntersection and vertical lines.\r
-- mlib.segment.getIntersection now uses fuzzy checking for parallel lines.\r
-- mlib.math.round is now much more efficient.\r
-- Removed some useless code from mlib.polygon.isSegmentInside.\r
-\r
-To-Do:\r
-----\r
-- Determine if isCompletelyInsideFunctions should return true with tangents.\r
-- Check argument order for logicality and consistency.\r
-- Improve speed.\r
-- Add error checking.\r
-- Make sure to see if any aliases were missed. (e.g. isSegmentInside)\r
-- Implement mlib.shapes again(?)\r
-- Clean up and correct README (add "Home" link, etc.)\r
-\r
-0.9.4\r
-====\r
-Added:\r
-----\r
-\r
-Changed:\r
-----\r
-- mlib.line.getDistance is now slightly faster.\r
-- Made code much easier to debug by using new utility `cycle`.\r
-- Added new utility.\r
-- Various other minor changes.\r
-\r
-Removed:\r
-----\r
-- Unused local utility function copy\r
-\r
-To-Do\r
-----\r
-- Determine if isCompletelyInsideFunctions should return true with tangents.\r
-- Make argument order more logical.\r
-- Improve speed and error checking.\r
-- Make sure to see if any aliases were missed. (e.g. isSegmentInside)\r
-- Implement mlib.shapes again(?)\r
-- Clean up README (add "Home" link, etc.)\r
-\r
-0.9.3\r
-====\r
-Added:\r
-----\r
-- milb.circle.isCircleCompletelyInside\r
-- mlib.circle.isPolygonCompletelyInside\r
-- milb.circle.isSegmentCompletelyInside\r
-- mlib.polygon.isCircleCompletelyInside\r
-- mlib.polygon.isPolygonCompletelyInside\r
-- mlib.polygon.isSegmentCompletelyInside\r
-\r
-               - ALIASES -\r
-- mlib.circle.getPolygonIntersection\r
-- mlib.circle.isCircleInsidePolygon\r
-- mlib.circle.isCircleCompletelyInsidePolygon\r
-- milb.line.getCircleIntersection\r
-- milb.line.getPolygonIntersection\r
-- milb.line.getLineIntersection\r
-- mlib.line.segment.getCircleIntersection\r
-- mlib.line.segment.getPolygonIntersection\r
-- mlib.line.segment.getLineIntersection\r
-- mlib.line.segment.getSegmentIntersection\r
-- mlib.line.segment.isSegmentCompletelyInsideCircle\r
-- mlib.line.segment.isSegmentCompletelyInsidePolygon\r
-- mlib.polygon.isCircleCompletelyOver\r
-\r
-Changed:\r
-----\r
-- mlib.circle.getCircleIntersection now returns 'inside' instead of 'intersection' if the point has not intersections but is within the circle.\r
-- Fixed problem involving mlib.circle.getSegmentIntersection\r
-\r
-- README.md now has more information on how to run specs and other minor improvements.\r
-- Fixed some commenting on explanation of derivation of mlib.line.getIntersection.\r
-- Updated the example to use the current version of mlib.\r
-- Made/Changed some comments in the example main.lua.\r
-\r
-Removed:\r
-----\r
-\r
-To-Do\r
-----\r
-- Make examples file on github (examples/shapes/main.lua, etc.) not just one line.\r
-- Determine if isCompletelyInsideFunctions should return true with tangents.\r
-- Make argument order more logical.\r
-- Make sure to see if any aliases were missed. (e.g. isSegmentInside)\r
-- Update spec links in README\r
-\r
-0.9.2\r
-====\r
-Added:\r
-----\r
-\r
-Changed:\r
-----\r
-- mlib.polygon.getPolygonIntersection now does not create duplicate local table.\r
-- mlib.line.getPerpendicularSlope now does not create a global variable.\r
-- mlib.math.getSummation now allows the error to go through instead of returning false if the stop value is not a number.\r
-\r
-- Changed any instance of the term "userdata" with "input"\r
-\r
-Removed:\r
-----\r
-\r
-0.9.1\r
-====\r
-Added:\r
-----\r
-- Added mlib.statistics.getCentralTendency\r
-- Added mlib.statistics.getDispersion\r
-- Added mlib.statistics.getStandardDeviation\r
-- Added mlib.statistics.getVariation\r
-- Added mlib.statistics.getVariationRatio\r
-\r
-Removed:\r
-----\r
-\r
-Changed:\r
-----\r
-- FIX:         mlib.polygon.checkPoint now handles vertices better.\r
-\r
-\r
-To-Do\r
-----\r
-- Add more functions.\r
-\r
-0.9.0\r
-====\r
-Added:\r
-----\r
-- mlib.line.getDistance as an alias for mlib.line.getLength.\r
-- mlib.line.checkPoint\r
-- Internal documentation.\r
-\r
-Removed:\r
-----\r
-- mlib.circle.isPointInCircle is replaced with mlib.circle.checkPoint\r
-- mlib.circle.checkPoint is replaced with mlib.circle.isPointOnCircle\r
-- Variation of mlib.circle.getLineIntersection( cx, cy, radius, slope, intercept ) is no longer supported, as it can cause errors with vertical lines.\r
-\r
-Changed:\r
-----\r
-- CHANGE:      mlib.line.getIntersection now returns true for colinear lines.\r
-- CHANGE:      mlib.line.getIntersection now returns true if the line are collinear.\r
-- CHANGE:      mlib.line.getIntersection now returns true if vertical lines are collinear.\r
-- CHANGE:      mlib.line.getSegmentIntersection now returns true if the line and segment are collinear.\r
-- CHANGE:      Changed the order of mlib.line.segment.checkPoint arguments.\r
-- NAME:        mlib.polygon.lineIntersects is now mlib.polygon.getLineIntersection\r
-- NAME:        mlib.polygon.lineSegmentIntersects is now mlib.polygon.getSegmentIntersection\r
-- NAME:        mlib.polygon.isLineSegmentInside is now mlib.polygon.isSegmentInside\r
-- NAME:        mlib.polygon.polygonIntersects is now mlib.polygon.getPolygonIntersection\r
-- CHANGED:     mlib.circle.checkPoint now takes arguments ( px, py, cx, cy, radius ).\r
-- CHANGED:     mlib.circle.isPointOnCircle now takes arguments ( px, py, cx, cy, radius ).\r
-- NAME:        mlib.polygon.circleIntersects is now mlib.polygon.getCircleIntersection\r
-- NAME:        mlib.circle.isLineSecant is now mlib.circle.getLineIntersection\r
-- NAME:        mlib.circle.isSegmentSecant is now mlib.circle.getSegmentIntersection\r
-- NAME:        mlib.circle.circlesIntersects is now mlib.circle.getCircleIntersection\r
-- CHANGE:      Added types 'tangent' and 'intersection' to mlib.circle.getCircleIntersection.\r
-- NAME:                mlib.math.getRootsOfQuadratic is now mlib.math.getQuadraticRoots\r
-- CHANGE:      mlib.math.getRoot now only returns the positive, since it there is not always negatives.\r
-- NAME:        mlib.math.getPercent is now mlib.math.getPercentage\r
-\r
-- Cleaned up code (added comments, spaced lines, etc.)\r
-- Made syntax that uses camelCase instead of CamelCase.\r
-       - Match style of more programmers.\r
-       - Easier to type.\r
-- Moved to semantic numbering.\r
-- Made any returns strings lower-case.\r
-- Updated specs for missing functions.\r
-\r
-To-Do\r
-----\r
-- Update readme.\r
-- Add mlib.statistics.getStandardDeviation\r
-- Add mlib.statistics.getMeasuresOfCentralTendency\r
-- Add mlib.statistics.getMeasuresOfDispersion\r
-\r
-1.1.0.2\r
-====\r
-Added:\r
-----\r
-- MLib.Polygon.IsPolygonInside\r
-\r
-Removed:\r
-----\r
-- Removed all MLib.Shape:\r
-       - Was very slow.\r
-       - Could not define custom callbacks.\r
-       - Allow for flexibility.\r
-\r
-Changed:\r
-----\r
-- Switched MLib.Line.GetIntersection back to the old way\r
-- MLib.Line.GetSegmentIntersection now returns 4 values if the lines are parallel.\r
-\r
-TODO:\r
-- Make it so that MLib.Shape objects can use ':' syntax for other functions (i.e. MLib.Line.GetLength for Line objects, etc.)\r
-- Intuitive error messages.\r
-\r
-\r
-1.1.0.1\r
-====\r
-Added:\r
-----\r
-\r
-Removed:\r
-----\r
-\r
-Changed:\r
-- MLib.Line.GetIntersection now returns true, instead of two points.\r
-\r
-----\r
-\r
-Fixed:\r
-----\r
-- MLib.Line.GetIntersection now handles vertical lines: returns true if they collide, false otherwise.\r
-- MLib.Polygon.LineIntersects now also handles verticals.\r
-\r
-TODO:\r
-- Fix\r
-       - MLib.Shape Table can't have metatables.\r
-\r
-1.1.0.0\r
-====\r
-Added:\r
-----\r
-- MLib.Polygon.IsCircleInside\r
-- MLib.Polygon.LineSegmentIntersects\r
-- MLib.Polygon.IsLineSegmentInside\r
-- MLib.Statistics.GetFrequency\r
-- MLib.Math.Factorial\r
-- MLib.Math.SystemOfEquations\r
-\r
-Removed:\r
-----\r
-\r
-Changed:\r
-----\r
-- MLib.Polygon.LineIntersects is now MLib.Polygon.LineSegmentIntersects.\r
-- Put Word-wrap on Changes.txt\r
-\r
-Fixed:\r
-----\r
-- Problems with numberous MLib.Polygon and MLib.Circle problems.\r
-\r
-TODO:\r
-- Fix\r
-       - MLib.Shape Table can't have metatables.\r
-\r
-1.0.0.3\r
-====\r
-Added:\r
-----\r
-\r
-Removed:\r
-----\r
-\r
-Changed:\r
-----\r
-\r
-Fixed:\r
-----\r
-- README.md\r
-\r
-TODO:\r
-- Add:\r
-  - Frequency\r
-  - Binomial Probability\r
-  - Standard Deviation\r
-  - Conditional Probability\r
-\r
-1.0.0.2\r
-====\r
-Added:\r
-----\r
-\r
-Removed:\r
-----\r
-- Ability to use a direction for Math.GetAngle's 5th argument instead of having a third point. See Fixed for more.\r
-\r
-Changed:\r
-----\r
-- Changed README.md for clarity and consistency.\r
-- Updated spec.lua\r
-- See Fixed for more.\r
-\r
-Fixed:\r
-----\r
-- Circle.IsSegmentSecant now properly accounts for chords actually being chords, and not secants.\r
-- Circle.CircleIntersects now can return 'Colinear' or 'Equal' if the circles have same x and y but different radii (Colinear) or are exactly the same (Equal).\r
-- Statistics.GetMode now returns a table with the modes, and the second argument as the number of times they appear.\r
-- Math.GetRoot now returns the negative number as a second argument.\r
-- Math.GetPercentOfChange now works for 0 to 0 (previously false).\r
-- Math.GetAngle now takes only three points and no direction option.\r
-- Typos in Shape.CheckCollisions and Shape.Remove.\r
-- Fixed nil problems in Shape.CheckCollisions.\r
-- Improved readablility and DRYness of Shape.CheckCollisions.\r
-- Bugs in Shape.Remove and Shape.CheckCollisions regarding passing tables as arguments.\r
-\r
-TODO:\r
-- Add:\r
-  - Frequency\r
-  - Binomial Probability\r
-  - Standard Deviation\r
-  - Conditional Probability\r
-\r
-1.0.0.1\r
-====\r
-Added:\r
-----\r
-\r
-Removed:\r
-----\r
-\r
-Changed:\r
-----\r
-- Changes.txt now expanded to include short excertps from all previous commits.\r
-- Changed release number from 3.0.0 to 1.0.0.1\r
-- Math.Round now can round to decimal places as the second argument.\r
-- Commented unnecessary call of Segment.CheckPoint in Polygon.LineIntersects.\r
-- Polygon.LineIntersects now returns where the lines intersect.\r
-       - false if not intersection.\r
-       - A table with all of the intersections { { px, py } }\r
-- Same with Polygon.PolygonIntersects, Polygon.CircleIntersects,\r
-\r
-Fixed:\r
-----\r
-- Error with GetSlope being called incorrectly.\r
-- README.md Line.GetPerpendicularSlope misdirection.\r
-- Same with Line.GetPerpendicularBisector, Line.Segment.GetIntersection, Circle.IsLineSecant, Circle.IsSegmentSecant, Statistics.GetMean, Median, Mode, and Range, and Shape:Remove, and fixed the naming for Shape:CheckCollisions and Shape:Remove.\r
-- Clarified README.md\r
-- Made util SortWithReferences local.\r
-- Errors caused by local functions.\r
-\r
-TODO:\r
-- Add:\r
-  - Frequency\r
-  - Binomial Probability\r
-  - Standard Deviation\r
-  - Conditional Probability\r
-\r
-3.0.0\r
------\r
-ADDED:\r
-- Added function GetSignedArea.\r
-REMOVED:\r
-- Removed drawing functions.\r
-- Removed MLib.Line.Functions entirely.\r
-CHANGED:\r
-- Changed all the names to CamelCase.\r
-- Changed module name to MLib.\r
-- Changed return order of GetPerpendicualrBisector from Slope, Midpoint to Midpoint, Slope.\r
-- Changed returned string of MLib.circle.isLineSecant to be upper-case.\r
-- Changed IsPrime to accept only one number at a time.\r
-- Changed NewShape's type to Capitals.\r
-\r
-Related to code:\r
-- Added more accuarate comments.\r
-- Made code more DRY.\r
-- Made code monkey-patchable and saved space (by declaring all functions as local values then inserted them into a large table.\r
-\r
-TODO:\r
-- Make LineIntersectsPolygon return where intersection occurs.\r
-- Ditto with PolygonIntersectsPolygon.\r
-- Add:\r
-  - Frequency\r
-  - Binomial Probability\r
-  - Standard Deviation\r
-  - Conditional Probability\r
-\r
-\r
-Not as accurately maintained before 2.0.2\r
------------------------------------------\r
-\r
-2.0.2\r
------\r
-- Cleaned up code, mostly.\r
-\r
-2.0.1\r
------\r
-- Bug fixes, mlib.shape:remove & demos added.\r
-\r
-2.0.0\r
------\r
-- Added mlib.shape and various bug fixes.\r
-\r
-2.0.0\r
------\r
-- Made mlib.shape and made numberous bug fixes.\r
-\r
-1.9.4\r
------\r
-- Made mlib.math.prime faster and removed ability to test multiple numbers at once. Thanks Robin!\r
-\r
-1.9.3\r
------\r
-- Fixed polygon.area and polygon.centroid\r
-\r
-1.9.2\r
------\r
-- Updated to LOVE 0.9.0.\r
-\r
-1.9.1\r
------\r
-- Made mlib.line.closestPoint able to take either two points on the slope or the slope and intercept.\r
-\r
-1.9.0\r
------\r
-- Added mlib.lineSegmentIntersects (no affiliation with previous one (changed to mlib.line.segment.intersect)) and mlib.line.closestPoint\r
-\r
-1.8.3\r
------\r
-- Changed naming mechanism to be more organized.\r
-\r
-1.8.2\r
------\r
-- "Fixed" mlib.lineSegmentsIntersect AGAIN!!!!  :x\r
-\r
-1.8.1\r
------\r
-- Removed a print statement.\r
-\r
-1.8.0\r
------\r
-- mlib.pointInPolygon added\r
-\r
-1.7.5\r
------\r
-- mlib.lineSegmentsIntersect vertical lines fixed again. This time for real. I promise... or hope, at least...  :P\r
-\r
-1.7.4\r
------\r
-- mlib.lineSegmentsIntersect vertical parallels fixed\r
-\r
-1.7.3\r
------\r
-- mlib.lineSegmentsIntersect parallels fixed\r
-\r
-1.7.2\r
------\r
-- mlib.lineSegmentsIntersect now handles vertical lines\r
-\r
-1.7.1\r
------\r
-- mlib.lineSegmentsIntersect now returns the two places in between where the line segments begin to intersect.\r
-\r
-1.7.0\r
------\r
-- Added mlib.circlesIntersect, mlib.pointOnLineSegment, mlib.linesIntersect, and mlib.lineSegmentsIntersect\r
-\r
-1.6.1\r
------\r
-- Employed usage of summations for mlib.getPolygonArea and mlib.getPolygonCentroid and removed area as an argument for mlib.getPolygonCentroid.\r
-\r
-1.6.0\r
------\r
-- Added several functions.\r
-\r
-1.5.0\r
------\r
-- Made lots of changes to syntax to make it easier to use (hopefully). I also put out specs.\r
-\r
-1.4.1\r
------\r
-- Localized mlib. Thanks, Yonaba!\r
-\r
-1.4.0\r
------\r
-- Added mlib.getPolygonCentroid (gets the midpoint of a non-self-intersecting polygons)\r
-\r
-1.3.2\r
------\r
-- Made mlib.getPrime take tables as arguments, so you can check all the values of a table.\r
-\r
-1.3.1\r
------\r
-- Changed name method to mlib.getPolygonArea\r
-\r
-1.3.0\r
------\r
-- Added mlib.get_polygon_area and removed mlib.get_convex_area and mlib.get_triangle_area since they are repetitive.\r
-\r
-1.2.2\r
------\r
-- Made functions return faster, functions that previously returned tables now return multiple arguments.\r
-\r
-1.2.1\r
------\r
-- Localized functions, made tables acceptable as arguments, refined function speed, mlib.get_mode now returns number most repeated as well as how many times.\r
-\r
-1.2.0\r
------\r
-- Added mlib.get_angle\r
-\r
-1.1.0\r
------\r
-- Added mlib.get_convex_area\r
-\r
-1.0.4\r
------\r
-- Fixed get_mode to handle bimodials.\r
-\r
-1.0.3\r
------\r
-- Prime Checker optimized (hopefully final update on this.)\r
-\r
-1.0.2\r
------\r
-- Prime checker now works! (At least to 1000. I haven't tested any\r
-further)\r
-\r
-1.0.1\r
------\r
-- 'Fixed' the prime checker\r
-\r
-1.0.0\r
------\r
-- Initial release\r
diff --git a/main/plugin/windfield/mlib/LICENSE.md b/main/plugin/windfield/mlib/LICENSE.md
deleted file mode 100644 (file)
index 0e7071e..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-Copyright (c) 2015 Davis Claiborne\r
-\r
-This software is provided 'as-is', without any express or implied\r
-warranty. In no event will the authors be held liable for any damages\r
-arising from the use of this software.\r
-\r
-Permission is granted to anyone to use this software for any purpose,\r
-including commercial applications, and to alter it and redistribute it\r
-freely, subject to the following restrictions:\r
-\r
-1. The origin of this software must not be misrepresented; you must not\r
-   claim that you wrote the original software. If you use this software\r
-   in a product, an acknowledgement in the product documentation would be\r
-   appreciated but is not required.\r
-2. Altered source versions must be plainly marked as such, and must not be\r
-   misrepresented as being the original software.\r
-3. This notice may not be removed or altered from any source distribution.\r
diff --git a/main/plugin/windfield/mlib/README.md b/main/plugin/windfield/mlib/README.md
deleted file mode 100644 (file)
index a5efed3..0000000
+++ /dev/null
@@ -1,890 +0,0 @@
-MLib\r
-====\r
-\r
-__MLib__ is a math and shape-intersection detection library written in Lua. It's aim is to be __robust__ and __easy to use__.\r
-\r
-__NOTE:__ \r
-- I am (slowly) working on completely rewriting this in order to be easier to use and less bug-prone. You can check out the progress [here](../../tree/dev).\r
-- I am currently slowing development of MLib while moving over to helping with [CPML](https://github.com/excessive/cpml). To discuss this, please comment [here](../../issues/12).\r
-\r
-If you are looking for a library that handles updating/collision responses for you, take a look at [hxdx](https://github.com/adonaac/hxdx). It uses MLib functions as well as Box2d to handle physics calculations. \r
-\r
-## Downloading\r
-You can download the latest __stable__ version of MLib by downloading the latest [release](../../releases/).\r
-You can download the latest __working__ version of MLib by downloading the latest [commit](../../commits/master/). Documentation will __only__ be updated upon releases, not upon commits.\r
-\r
-## Implementing\r
-To use MLib, simply place [mlib.lua](mlib.lua) inside the desired folder in your project. Then use the `require 'path.to.mlib'` to use any of the functions.\r
-\r
-## Examples\r
-If you don't have [LÖVE](https://love2d.org/) installed, you can download the .zip of the demo from the [Executables](Examples/Executables) folder and extract and run the .exe that way.\r
-You can see some examples of the code in action [here](Examples).\r
-All examples are done using the *awesome* engine of [LÖVE](https://love2d.org/).\r
-To run them properly, download the [.love file](Examples/LOVE) and install LÖVE to your computer.\r
-After that, make sure you set .love files to open with "love.exe".\r
-For more, see [here](https://love2d.org/).\r
-\r
-## When should I use MLib?\r
-- If you need to know exactly where two objects intersect.\r
-- If you need general mathematical equations to be done.\r
-- If you need very precise details about point intersections.\r
-\r
-## When should I __not__ use MLib?\r
-- All of the objects in a platformer, or other game, for instance, should not be registered with MLib. Only ones that need very specific information.\r
-- When you don't need precise information/odd shapes.\r
-\r
-## Specs\r
-#### For Windows\r
-If you run Windows and have Telescope in `%USERPROFILE%\Documents\GitHub` (you can also manually change the path in [test.bat](test.bat)) you can simply run [test.bat](test.bat) and it will display the results, and then clean up after it's finished.\r
-\r
-#### Default\r
-Alternatively, you can find the tests [here](spec.lua). Keep in mind that you may need to change certain semantics to suit your OS.\r
-You can run them via [Telescope](https://github.com/norman/telescope/) and type the following command in the command-line of the root folder:\r
-```\r
-tsc -f specs.lua\r
-```\r
-If that does not work, you made need to put a link to Lua inside of the folder for `telescope` and run the following command:\r
-```\r
-lua tsc -f specs.lua\r
-```\r
-If you encounter further errors, try to run the command line as an administrator (usually located in `C:\Windows\System32\`), then right-click on `cmd.exe` and select `Run as administrator`, then do\r
-```\r
-cd C:\Path\to\telescope\\r
-```\r
-And __then__ run one of the above commands. If none of those work, just take my word for it that all the tests pass and look at this picture.\r
-![Success](Reference Pictures/Success.png)\r
-\r
-## Functions\r
-- [mlib.line](#mlibline)\r
-  - [mlib.line.checkPoint](#mliblinecheckpoint)\r
-  - [mlib.line.getClosestPoint](#mliblinegetclosestpoint)\r
-  - [mlib.line.getYIntercept](#mliblinegetintercept)\r
-  - [mlib.line.getIntersection](#mliblinegetintersection)\r
-  - [mlib.line.getLength](#mliblinegetlength)\r
-  - [mlib.line.getMidpoint](#mliblinegetmidpoint)\r
-  - [mlib.line.getPerpendicularSlope](#mliblinegetperpendicularslope)\r
-  - [mlib.line.getSegmentIntersection](#mliblinegetsegmentintersection)\r
-  - [mlib.line.getSlope](#mliblinegetslope)\r
-- [mlib.segment](#mlibsegment)\r
-  - [mlib.segment.checkPoint](#mlibsegmentcheckpoint)\r
-  - [mlib.segment.getPerpendicularBisector](#mlibsegmentgetperpendicularbisector)\r
-  - [mlib.segment.getIntersection](#mlibsegmentgetintersection)\r
-- [mlib.polygon](#mlibpolygon)\r
-  - [mlib.polygon.checkPoint](#mlibpolygoncheckpoint)\r
-  - [mlib.polygon.getCentroid](#mlibpolygongetcentroid)\r
-  - [mlib.polygon.getCircleIntersection](#mlibpolygongetcircleintersection)\r
-  - [mlib.polygon.getLineIntersection](#mlibpolygongetlineintersection)\r
-  - [mlib.polygon.getPolygonArea](#mlibpolygongetpolygonarea)\r
-  - [mlib.polygon.getPolygonIntersection](#mlibpolygongetpolygonintersection)\r
-  - [mlib.polygon.getSegmentIntersection](#mlibpolygongetsegmentintersection)\r
-  - [mlib.polygon.getSignedPolygonArea](#mlibpolygongetsignedpolygonarea)\r
-  - [mlib.polygon.getTriangleHeight](#mlibpolygongettriangleheight)\r
-  - [mlib.polygon.isCircleInside](#mlibpolygoniscircleinside)\r
-  - [mlib.polygon.isCircleCompletelyInside](#mlibpolygoniscirclecompletelyinside)\r
-  - [mlib.polygon.isPolygonInside](#mlibpolygonispolygoninside)\r
-  - [mlib.polygon.isPolygonCompletelyInside](#mlibpolygonispolygoncompletelyinside)\r
-  - [mlib.polygon.isSegmentInside](#mlibpolygonissegmentinside)\r
-  - [mlib.polygon.isSegmentCompletelyInside](#mlibpolygonissegmentcompletelyinside)\r
-- [mlib.circle](#mlibcircle)\r
-  - [mlib.circle.checkPoint](#mlibcirclecheckpoint)\r
-  - [mlib.circle.getArea](#mlibcirclegetarea)\r
-  - [mlib.circle.getCircleIntersection](#mlibcirclegetcircleintersection)\r
-  - [mlib.circle.getCircumference](#mlibcirclegetcircumference)\r
-  - [mlib.circle.getLineIntersection](#mlibcirclegetlineintersection)\r
-  - [mlib.circle.getSegmentIntersection](#mlibcirclegetsegmentintersection)\r
-  - [mlib.circle.isCircleCompletelyInside](#mlibcircleiscirclecompletelyinside)\r
-  - [mlib.circle.isCircleCompletelyInsidePolygon](#mlibcircleiscirclecompletelyinsidepolygon)\r
-  - [mlib.circle.isPointOnCircle](#mlibcircleispointoncircle)\r
-  - [mlib.circle.isPolygonCompletelyInside](#mlibcircleispolygoncompletelyinside)\r
-- [mlib.statistics](#mlibstatistics)\r
-  - [mlib.statistics.getCentralTendency](#mlibstatisticsgetcentraltendency)\r
-  - [mlib.statistics.getDispersion](#mlibstatisticsgetdispersion)\r
-  - [mlib.statistics.getMean](#mlibstatisticsgetmean)\r
-  - [mlib.statistics.getMedian](#mlibstatisticsgetmedian)\r
-  - [mlib.statistics.getMode](#mlibstatisticsgetmode)\r
-  - [mlib.statistics.getRange](#mlibstatisticsgetrange)\r
-  - [mlib.statistics.getStandardDeviation](#mlibstatisticsgetstandarddeviation)\r
-  - [mlib.statistics.getVariance](#mlibstatisticsgetvariance)\r
-  - [mlib.statistics.getVariationRatio](#mlibstatisticsgetvariationratio)\r
-- [mlib.math](#mlibmath)\r
-  - [mlib.math.getAngle](#mlibmathgetangle)\r
-  - [mlib.math.getPercentage](#mlibmathgetpercentage)\r
-  - [mlib.math.getPercentOfChange](#mlibmathgetpercentofchange)\r
-  - [mlib.math.getQuadraticRoots](#mlibmathgetquadraticroots)\r
-  - [mlib.math.getRoot](#mlibmathgetroot)\r
-  - [mlib.math.getSummation](#mlibmathgetsummation)\r
-  - [mlib.math.isPrime](#mlibmathisprime)\r
-  - [mlib.math.round](#mlibmathround)\r
-- [Aliases](#aliases)\r
-\r
-#### mlib.line\r
-- Deals with linear aspects, such as slope and length.\r
-\r
-##### mlib.line.checkPoint\r
-- Checks if a point lies on a line.\r
-- Synopsis:\r
-  - `onPoint = mlib.line.checkPoint( px, px, x1, y1, x2, y2 )`\r
-- Arguments:\r
-  - `px`, `py`: Numbers. The x and y coordinates of the point being tested.\r
-  - `x1`, `y1`, `x2`, `y2`: Numbers. Two x and y coordinates of the line being tested.\r
-- Returns:\r
-  - `onPoint`: Boolean.\r
-    - `true` if the point is on the line.\r
-       - `false` if it does not.\r
-- Notes:\r
-  - You cannot use the format `mlib.line.checkPoint( px, px, slope, intercept )` because this would lead to errors on vertical lines.\r
-\r
-##### mlib.line.getClosestPoint\r
-- Gives the closest point to a line.\r
-- Synopses:\r
-  - `cx, cy = mlib.line.getClosestPoint( px, py, x1, y1, x2, y2 )`\r
-  - `cx, cy = mlib.line.getClosestPoint( px, py, slope, intercept )`\r
-- Arguments:\r
-  - `x`, `y`: Numbers. The x and y coordinates of the point.\r
-  - `x1`, `y1`, `x2`, `y2`: Numbers. Two x and y coordinates on the line.\r
-  - `slope`, `intercept`:\r
-    - Numbers. The slope and y-intercept of the line.\r
-       - Booleans (`false`). The slope and y-intercept of a vertical line.\r
-- Returns:\r
-  - `cx`, `cy`: Numbers. The closest points that lie on the line to the point.\r
-\r
-##### mlib.line.getYIntercept\r
-- Gives y-intercept of the line.\r
-- Synopses:\r
-  - `intercept, isVertical = mlib.line.getYIntercept( x1, y1, x2, y2 )`\r
-  - `intercept, isVertical = mlib.line.getYIntercept( x1, y1, slope )`\r
-- Arguments:\r
-  - `x1`, `y1`, `x2`, `y2`: Numbers. Two x and y coordinates that lie on the line.\r
-  - `slope`:\r
-    - Number. The slope of the line.\r
-- Returns:\r
-  - `intercept`:\r
-    - Number. The y-intercept of the line.\r
-    - Number. The `x1` coordinate of the line if the line is vertical.\r
-  - `isVertical`:\r
-    - Boolean. `true` if the line is vertical, `false` if the line is not vertical.\r
-\r
-##### mlib.line.getIntersection\r
-- Gives the intersection of two lines.\r
-- Synopses:\r
-  - `x, y = mlib.line.getIntersection( x1, y1, x2, y2, x3, y3, x4, y4 )`\r
-  - `x, y = mlib.line.getIntersection( slope1, intercept1, x3, y3, x4, y4 )`\r
-  - `x, y = mlib.line.getIntersection( slope1, intercept1, slope2, intercept2 )`\r
-- Arguments:\r
-  - `x1`, `y1`, `x2`, `y2`: Numbers. Two x and y coordinates that lie on the first line.\r
-  - `x3`, `y3`, `x4`, `y4`: Numbers. Two x and y coordinates that lie on the second line.\r
-  - `slope1`, `intercept1`:\r
-    - Numbers. The slope and y-intercept of the first line.\r
-       - Booleans (`false`). The slope and y-intercept of the first line (if the first line is vertical).\r
-  - `slope2`, `intercept2`:\r
-    - Numbers. The slope and y-intercept of the second line.\r
-       - Booleans (`false`). The slope and y-intercept of the second line (if the second line is vertical).\r
-- Returns:\r
-  - `x`, `y`:\r
-    - Numbers. The x and y coordinate where the lines intersect.\r
-       - Boolean:\r
-         - `true`, `nil`: The lines are collinear.\r
-         - `false`, `nil`: The lines are parallel and __not__ collinear.\r
-\r
-##### mlib.line.getLength\r
-- Gives the distance between two points.\r
-- Synopsis:\r
-  - `length = mlib.line.getLength( x1, y1, x2, y2 )\r
-- Arguments:\r
-  - `x1`, `y1`, `x2`, `y2`: Numbers. Two x and y coordinates.\r
-- Returns:\r
-  - `length`: Number. The distance between the two points.\r
-\r
-##### mlib.line.getMidpoint\r
-- Gives the midpoint of two points.\r
-- Synopsis:\r
-  - `x, y = mlib.line.getMidpoint( x1, y1, x2, y2 )`\r
-- Arguments:\r
-  - `x1`, `y1`, `x2`, `y2`: Numbers. Two x and y coordinates.\r
-- Returns:\r
-  - `x`, `y`: Numbers. The midpoint x and y coordinates.\r
-\r
-##### mlib.line.getPerpendicularSlope\r
-- Gives the perpendicular slope of a line.\r
-- Synopses:\r
-  - `perpSlope = mlib.line.getPerpendicularSlope( x1, y1, x2, y2 )`\r
-  - `perpSlope = mlib.line.getPerpendicularSlope( slope )`\r
-- Arguments:\r
-  - `x1`, `y1`, `x2`, `y2`: Numbers. Two x and y coordinates.\r
-  - `slope`: Number. The slope of the line.\r
-- Returns:\r
-  - `perpSlope`:\r
-    - Number. The perpendicular slope of the line.\r
-       - Boolean (`false`). The perpendicular slope of the line (if the original line was horizontal).\r
-\r
-##### mlib.line.getSegmentIntersection\r
-- Gives the intersection of a line segment and a line.\r
-- Synopses:\r
-  - `x1, y1, x2, y2 = mlib.line.getSegmentIntersection( x1, y1, x2, y2, x3, y3, x4, y4 )`\r
-  - `x1, y1, x2, y2 = mlib.line.getSegmentIntersection( x1, y1, x2, y2, slope, intercept )`\r
-- Arguments:\r
-  - `x1`, `y1`, `x2`, `y2`: Numbers. Two x and y coordinates that lie on the line segment.\r
-  - `x3`, `y3`, `x4`, `y4`: Numbers. Two x and y coordinates that lie on the line.\r
-  - `slope`, `intercept`:\r
-    - Numbers. The slope and y-intercept of the the line.\r
-       - Booleans (`false`). The slope and y-intercept of the line (if the line is vertical).\r
-- Returns:\r
-  - `x1`, `y1`, `x2`, `y2`:\r
-    - Number, Number, Number, Number.\r
-         - The points of the line segment if the line and segment are collinear.\r
-       - Number, Number, Boolean (`nil`), Boolean (`nil`).\r
-         - The coordinate of intersection if the line and segment intersect and are not collinear.\r
-       - Boolean (`false`), Boolean (`nil`), Boolean (`nil`),\r
-         - Boolean (`nil`). If the line and segment don't intersect.\r
-\r
-##### mlib.line.getSlope\r
-- Gives the slope of a line.\r
-- Synopsis:\r
-  - `slope = mlib.line.getSlope( x1, y1, x2, y2 )\r
-- Arguments:\r
-  - `x1`, `y1`, `x2`, `y2`: Numbers. Two x and y coordinates.\r
-- Returns:\r
-  - `slope`:\r
-    - Number. The slope of the line.\r
-       - Boolean (`false`). The slope of the line (if the line is vertical).\r
-\r
-#### mlib.segment\r
-- Deals with line segments.\r
-\r
-##### mlib.segment.checkPoint\r
-- Checks if a point lies on a line segment.\r
-- Synopsis:\r
-  - `onSegment = mlib.segment.checkPoint( px, py, x1 y1, x2, y2 )`\r
-- Arguments:\r
-  - `px`, `py`: Numbers. The x and y coordinates of the point being checked.\r
-  - `x1`, `y1`, `x2`, `y2`: Numbers. Two x and y coordinates.\r
-- Returns:\r
-  - `onSegment`: Boolean.\r
-    - `true` if the point lies on the line segment.\r
-       - `false` if the point does not lie on the line segment.\r
-\r
-##### mlib.segment.getPerpendicularBisector\r
-- Gives the perpendicular bisector of a line.\r
-- Synopsis:\r
-  - `x, y, slope = mlib.segment.getPerpendicularBisector( x1, y1, x2, y2 )`\r
-- Arguments:\r
-  - `x1`, `y1`, `x2`, `y2`: Numbers. Two x and y coordinates.\r
-- Returns:\r
-  - `x`, `y`: Numbers. The midpoint of the line.\r
-  - `slope`:\r
-    - Number. The perpendicular slope of the line.\r
-       - Boolean (`false`). The perpendicular slope of the line (if the original line was horizontal).\r
-\r
-##### mlib.segment.getIntersection\r
-- Checks if two line segments intersect.\r
-- Synopsis:\r
-  - `cx1, cy1, cx2, cy2 = mlib.segment.getIntersection( x1, y1, x2, y2, x3, y3 x4, y4 )`\r
-- Arguments:\r
-  - `x1`, `y1`, `x2`, `y2`: Numbers. Two x and y coordinates of the first line segment.\r
-  - `x3`, `y3`, `x4`, `y4`: Numbers. Two x and y coordinates of the second line segment.\r
-- Returns:\r
-  - `cx1`, `cy1`, `cx2`, `cy2`:\r
-    - Number, Number, Number, Number.\r
-         - The points of the resulting intersection if the line segments are collinear.\r
-       - Number, Number, Boolean (`nil`), Boolean (`nil`).\r
-         - The point of the resulting intersection if the line segments are not collinear.\r
-       - Boolean (`false`), Boolean (`nil`), Boolean (`nil`) , Boolean (`nil`).\r
-         - If the line segments don't intersect.\r
-\r
-#### mlib.polygon\r
-- Handles aspects involving polygons.\r
-\r
-##### mlib.polygon.checkPoint\r
-- Checks if a point is inside of a polygon.\r
-- Synopses:\r
-  - `inPolygon = mlib.polygon.checkPoint( px, py, vertices )`\r
-  - `inPolygon = mlib.polygon.checkPoint( px, py, ... )`\r
-- Arguments:\r
-  - `px`, `py`: Numbers. The x and y coordinate of the point being checked.\r
-  - `vertices`: Table. The vertices of the polygon in the format `{ x1, y1, x2, y2, x3, y3, ... }`\r
-  - `...`: Numbers. The x and y coordinates of the polygon. (Same as using `unpack( vertices )`)\r
-- Returns:\r
-  - `inPolygon`: Boolean.\r
-    - `true` if the point is inside the polygon.\r
-       - `false` if the point is not inside the polygon.\r
-\r
-##### mlib.polygon.getCentroid\r
-- Returns the centroid of the polygon.\r
-- Synopses:\r
-  - `cx, cy = mlib.polygon.getCentroid( vertices )`\r
-  - `cx, cy = mlib.polygon.getCentroid( ... )`\r
-- Arguments:\r
-  - `vertices`: Table. The vertices of the polygon in the format `{ x1, y1, x2, y2, x3, y3, ... }`\r
-  - `...`: Numbers. The x and y coordinates of the polygon. (Same as using `unpack( vertices )`)\r
-- Returns:\r
-  - `cx`, `cy`: Numbers. The x and y coordinates of the centroid.\r
-\r
-##### mlib.polygon.getCircleIntersection\r
-- Returns the coordinates of where a circle intersects a polygon.\r
-- Synopses:\r
-  - `intersections = mlib.polygon.getCircleIntersection( cx, cy, radius, vertices )`\r
-  - `intersections = mlib.polygon.getCircleIntersection( cx, cy, radius, ... )\r
-- Arguments:\r
-  - `cx`, `cy`: Number. The coordinates of the center of the circle.\r
-  - `radius`: Number. The radius of the circle.\r
-  - `vertices`: Table. The vertices of the polygon in the format `{ x1, y1, x2, y2, x3, y3, ... }`\r
-  - `...`: Numbers. The x and y coordinates of the polygon. (Same as using `unpack( vertices )`)\r
-- Returns:\r
-  - `intersections`: Table. Contains the intersections and type.\r
-- Example:\r
-```lua\r
-local tab = _.polygon.getCircleIntersection( 5, 5, 1, 4, 4, 6, 4, 6, 6, 4, 6 )\r
-for i = 1, # tab do\r
-       print( i .. ':', unpack( tab[i] ) )\r
-end\r
--- 1:  tangent         5               4\r
--- 2:  tangent         6               5\r
--- 3:  tangent         5               6\r
--- 4:  tagnent         4               5\r
-```\r
-- For more see [mlib.circle.getSegmentIntersection](#mlibcirclegetsegmentintersection) or the [specs](spec.lua# L676)\r
-\r
-##### mlib.polygon.getLineIntersection\r
-- Returns the coordinates of where a line intersects a polygon.\r
-- Synopses:\r
-  - `intersections = mlib.polygon.getLineIntersection( x1, y1, x2, y2, vertices )`\r
-  - `intersections = mlib.polygon.getLineIntersection( x1, y1, x2, y2, ... )\r
-- Arguments:\r
-  - `x1`, `y1`, `x2`, `y2`: Numbers. Two x and y coordinates.\r
-  - `vertices`: Table. The vertices of the polygon in the format `{ x1, y1, x2, y2, x3, y3, ... }`\r
-  - `...`: Numbers. The x and y coordinates of the polygon. (Same as using `unpack( vertices )`)\r
-- Returns:\r
-  - `intersections`: Table. Contains the intersections.\r
-- Notes:\r
-  - With collinear lines, they are actually broken up. i.e. `{ 0, 4, 0, 0 }` would become `{ 0, 4 }, { 0, 0 }`.\r
-\r
-##### mlib.polygon.getPolygonArea\r
-- Gives the area of a polygon.\r
-- Synopses:\r
-  - `area = mlib.polygon.getArea( vertices )`\r
-  - `area = mlib.polygon.getArea( ... )\r
-- Arguments:\r
-  - `vertices`: Table. The vertices of the polygon in the format `{ x1, y1, x2, y2, x3, y3, ... }`\r
-  - `...`: Numbers. The x and y coordinates of the polygon. (Same as using `unpack( vertices )`)\r
-- Returns:\r
-  - `area`: Number. The area of the polygon.\r
-\r
-##### mlib.polygon.getPolygonIntersection\r
-- Gives the intersection of two polygons.\r
-- Synopsis:\r
-  - `intersections = mlib.polygon.getPolygonIntersections( polygon1, polygon2 )`\r
-- Arguments:\r
-  - `polygon1`: Table. The vertices of the first polygon in the format `{ x1, y1, x2, y2, x3, y3, ... }`\r
-  - `polygon2`: Table. The vertices of the second polygon in the format `{ x1, y1, x2, y2, x3, y3, ... }`\r
-- Returns:\r
-  - `intersections`: Table. A table of the points of intersection.\r
-\r
-##### mlib.polygon.getSegmentIntersection\r
-- Returns the coordinates of where a line segmeing intersects a polygon.\r
-- Synopses:\r
-  - `intersections = mlib.polygon.getSegmentIntersection( x1, y1, x2, y2, vertices )`\r
-  - `intersections = mlib.polygon.getSegmentIntersection( x1, y1, x2, y2, ... )\r
-- Arguments:\r
-  - `x1`, `y1`, `x2`, `y2`: Numbers. Two x and y coordinates.\r
-  - `vertices`: Table. The vertices of the polygon in the format `{ x1, y1, x2, y2, x3, y3, ... }`\r
-  - `...`: Numbers. The x and y coordinates of the polygon. (Same as using `unpack( vertices )`)\r
-- Returns:\r
-  - `intersections`: Table. Contains the intersections.\r
-- Notes:\r
-  - With collinear line segments, they are __not__ broken up. See the [specs](spec.lua# L508) for more.\r
-\r
-##### mlib.polygon.getSignedPolygonArea\r
-- Gets the signed area of the polygon. If the points are ordered counter-clockwise the area is positive. If the points are ordered clockwise the number is negative.\r
-- Synopses:\r
-  - `area = mlib.polygon.getLineIntersection( vertices )`\r
-  - `area = mlib.polygon.getLineIntersection( ... )\r
-- Arguments:\r
-  - `vertices`: Table. The vertices of the polygon in the format `{ x1, y1, x2, y2, x3, y3, ... }`\r
-  - `...`: Numbers. The x and y coordinates of the polygon. (Same as using `unpack( vertices )`)\r
-- Returns:\r
-  - `area`: Number. The __signed__ area of the polygon. If the points are ordered counter-clockwise the area is positive. If the points are ordered clockwise the number is negative.\r
-\r
-##### mlib.polygon.getTriangleHeight\r
-- Gives the height of a triangle.\r
-- Synopses:\r
-  - `height = mlib.polygon.getTriangleHeigh( base, x1, y1, x2, y2, x3, y3 )`\r
-  - `height = mlib.polygon.getTriangleHeight( base, area )`\r
-- Arguments:\r
-  - `base`: Number. The length of the base of the triangle.\r
-  - `x1`, `y1`, `x2`, `y2`, `x3`, `y3`: Numbers. The x and y coordinates of the triangle.\r
-  - `area`: Number. The regular area of the triangle. __Not__ the signed area.\r
-- Returns:\r
-  - `height`: Number. The height of the triangle.\r
-\r
-##### mlib.polygon.isCircleInside\r
-- Checks if a circle is inside the polygon.\r
-- Synopses:\r
-  - `inPolygon = mlib.polygon.isCircleInside( cx, cy, radius, vertices )`\r
-  - `inPolygon = mlib.polygon.isCircleInside( cx, cy, radius, ... )`\r
-- Arguments:\r
-  - `cx`, `cy`: Numbers. The x and y coordinates for the center of the circle.\r
-  - `radius`: Number. The radius of the circle.\r
-  - `vertices`: Table. The vertices of the polygon in the format `{ x1, y1, x2, y2, x3, y3, ... }`\r
-  - `...`: Numbers. The x and y coordinates of the polygon. (Same as using `unpack( vertices )`)\r
-- Returns:\r
-  - `inPolygon`: Boolean.\r
-    - `true` if the circle is inside the polygon.\r
-       - `false` if the circle is not inside the polygon.\r
-- Notes:\r
-  - Only returns true if the center of the circle is inside the circle.\r
-\r
-##### mlib.polygon.isCircleCompletelyInside\r
-- Checks if a circle is completely inside the polygon.\r
-- Synopses:\r
-  - `inPolygon = mlib.polygon.isCircleCompletelyInside( cx, cy, radius, vertices )`\r
-  - `inPolygon = mlib.polygon.isCircleCompletelyInside( cx, cy, radius, ... )`\r
-- Arguments:\r
-  - `cx`, `cy`: Numbers. The x and y coordinates for the center of the circle.\r
-  - `radius`: Number. The radius of the circle.\r
-  - `vertices`: Table. The vertices of the polygon in the format `{ x1, y1, x2, y2, x3, y3, ... }`\r
-  - `...`: Numbers. The x and y coordinates of the polygon. (Same as using `unpack( vertices )`)\r
-- Returns:\r
-  - `inPolygon`: Boolean.\r
-    - `true` if the circle is __completely__ inside the polygon.\r
-       - `false` if the circle is not inside the polygon.\r
-\r
-##### mlib.polygon.isPolygonInside\r
-- Checks if a polygon is inside a polygon.\r
-- Synopsis:\r
-  - `inPolygon = mlib.polygon.isPolygonInside( polygon1, polygon2 )`\r
-- Arguments:\r
-  - `polygon1`: Table. The vertices of the first polygon in the format `{ x1, y1, x2, y2, x3, y3, ... }`\r
-  - `polygon2`: Table. The vertices of the second polygon in the format `{ x1, y1, x2, y2, x3, y3, ... }`\r
-- Returns:\r
-  - `inPolygon`: Boolean.\r
-    - `true` if the `polygon2` is inside of `polygon1`.\r
-       - `false` if `polygon2` is not inside of `polygon2`.\r
-- Notes:\r
-  - Returns true as long as any of the line segments of `polygon2` are inside of the `polygon1`.\r
-\r
-##### mlib.polygon.isPolygonCompletelyInside\r
-- Checks if a polygon is completely inside a polygon.\r
-- Synopsis:\r
-  - `inPolygon = mlib.polygon.isPolygonCompletelyInside( polygon1, polygon2 )`\r
-- Arguments:\r
-  - `polygon1`: Table. The vertices of the first polygon in the format `{ x1, y1, x2, y2, x3, y3, ... }`\r
-  - `polygon2`: Table. The vertices of the second polygon in the format `{ x1, y1, x2, y2, x3, y3, ... }`\r
-- Returns:\r
-  - `inPolygon`: Boolean.\r
-    - `true` if the `polygon2` is __completely__ inside of `polygon1`.\r
-       - `false` if `polygon2` is not inside of `polygon2`.\r
-\r
-##### mlib.polygon.isSegmentInside\r
-- Checks if a line segment is inside a polygon.\r
-- Synopses:\r
-  - `inPolygon = mlib.polygon.isSegmentInside( x1, y1, x2, y2, vertices )`\r
-  - `inPolygon = mlib.polygon.isSegmentInside( x1, y1, x2, y2, ... )`\r
-- Arguments:\r
-  - `x1`, `y1`, `x2`, `y2`: Numbers. The x and y coordinates of the line segment.\r
-  - `vertices`: Table. The vertices of the polygon in the format `{ x1, y1, x2, y2, x3, y3, ... }`\r
-  - `...`: Numbers. The x and y coordinates of the polygon. (Same as using `unpack( vertices )`)\r
-- Returns:\r
-  - `inPolygon`: Boolean.\r
-    - `true` if the line segment is inside the polygon.\r
-       - `false` if the line segment is not inside the polygon.\r
-- Note:\r
-  - Only one of the points has to be in the polygon to be considered 'inside' of the polygon.\r
-  - This is really just a faster version of [mlib.polygon.getPolygonIntersection](#mlibpolygongetpolygonintersection) that does not give the points of intersection.\r
-\r
-##### mlib.polygon.isSegmentCompletelyInside\r
-- Checks if a line segment is completely inside a polygon.\r
-- Synopses:\r
-  - `inPolygon = mlib.polygon.isSegmentCompletelyInside( x1, y1, x2, y2, vertices )`\r
-  - `inPolygon = mlib.polygon.isSegmentCompletelyInside( x1, y1, x2, y2, ... )`\r
-- Arguments:\r
-  - `x1`, `y1`, `x2`, `y2`: Numbers. The x and y coordinates of the line segment.\r
-  - `vertices`: Table. The vertices of the polygon in the format `{ x1, y1, x2, y2, x3, y3, ... }`\r
-  - `...`: Numbers. The x and y coordinates of the polygon. (Same as using `unpack( vertices )`)\r
-- Returns:\r
-  - `inPolygon`: Boolean.\r
-    - `true` if the line segment is __completely__ inside the polygon.\r
-       - `false` if the line segment is not inside the polygon.\r
-\r
-#### mlib.circle\r
-- Handles aspects involving circles.\r
-\r
-##### mlib.circle.checkPoint\r
-- Checks if a point is on the inside or on the edge the circle.\r
-- Synopsis:\r
-  - `inCircle = mlib.circle.checkPoint( px, px, cx, cy, radius )`\r
-- Arguments:\r
-  - `px`, `py`: Numbers. The x and y coordinates of the point being tested.\r
-  - `cx`, `cy`: Numbers. The x and y coordinates of the center of the circle.\r
-  - `radius`: Number. The radius of the circle.\r
-- Returns:\r
-  - `inCircle`: Boolean.\r
-    - `true` if the point is inside or on the circle.\r
-       - `false` if the point is outside of the circle.\r
-\r
-##### mlib.circle.getArea\r
-- Gives the area of a circle.\r
-- Synopsis:\r
-  - `area = mlib.circle.getArea( radius )`\r
-- Arguments:\r
-  - `radius`: Number. The radius of the circle.\r
-- Returns:\r
-  - `area`: Number. The area of the circle.\r
-\r
-##### mlib.circle.getCircleIntersection\r
-- Gives the intersections of two circles.\r
-- Synopsis:\r
-  - `intersections = mlib.circle.getCircleIntersection( c1x, c1y, radius1, c2x, c2y, radius2 )\r
-- Arguments:\r
-  - `c1x`, `c1y`: Numbers. The x and y coordinate of the first circle.\r
-  - `radius1`: Number. The radius of the first circle.\r
-  - `c2x`, `c2y`: Numbers. The x and y coordinate of the second circle.\r
-  - `radius2`: Number. The radius of the second circle.\r
-- Returns:\r
-  - `intersections`: Table. A table that contains the type and where the circle collides. See the [specs](spec.lua# L698) for more.\r
-\r
-##### mlib.circle.getCircumference\r
-- Returns the circumference of a circle.\r
-- Synopsis:\r
-  - `circumference = mlib.circle.getCircumference( radius )`\r
-- Arguments:\r
-  - `radius`: Number. The radius of the circle.\r
-- Returns:\r
-  - `circumference`: Number. The circumference of a circle.\r
-\r
-##### mlib.circle.getLineIntersection\r
-- Returns the intersections of a circle and a line.\r
-- Synopsis:\r
-  - `intersections = mlib.circle.getLineIntersections( cx, cy, radius, x1, y1, x2, y2 )`\r
-- Arguments:\r
-  - `cx`, `cy`: Numbers. The x and y coordinates for the center of the circle.\r
-  - `radius`: Number. The radius of the circle.\r
-  - `x1`, `y1`, `x2`, `y2`: Numbers. Two x and y coordinates the lie on the line.\r
-- Returns:\r
-  - `intersections`: Table. A table with the type and where the intersections happened. Table is formatted:\r
-    - `type`, `x1`, `y1`, `x2`, `y2`\r
-         - String (`'secant'`), Number, Number, Number, Number\r
-           - The numbers are the x and y coordinates where the line intersects the circle.\r
-         - String (`'tangent'`), Number, Number, Boolean (`nil`), Boolean (`nil`)\r
-           - `x1` and `x2` represent where the line intersects the circle.\r
-         - Boolean (`false`), Boolean (`nil`), Boolean (`nil`), Boolean (`nil`), Boolean (`nil`)\r
-           - No intersection.\r
-    - For more see the [specs](spec.lua# L660).\r
-\r
-##### mlib.circle.getSegmentIntersection\r
-- Returns the intersections of a circle and a line segment.\r
-- Synopsis:\r
-  - `intersections = mlib.circle.getSegmentIntersections( cx, cy, radius, x1, y1, x2, y2 )`\r
-- Arguments:\r
-  - `cx`, `cy`: Numbers. The x and y coordinates for the center of the circle.\r
-  - `radius`: Number. The radius of the circle.\r
-  - `x1`, `y1`, `x2`, `y2`: Numbers. The two x and y coordinates of the line segment.\r
-- Returns:\r
-  - `intersections`: Table. A table with the type and where the intersections happened. Table is formatted:\r
-    - `type`, `x1`, `y1`, `x2`, `y2`\r
-         - String (`'chord'`), Number, Number, Number, Number\r
-           - The numbers are the x and y coordinates where the line segment is on both edges of the circle.\r
-         - String (`'enclosed'`), Number, Number, Number, Number\r
-           - The numbers are the x and y coordinates of the line segment if it is fully inside of the circle.\r
-         - String (`'secant'`), Number, Number, Number, Number\r
-           - The numbers are the x and y coordinates where the line segment intersects the circle.\r
-         - String (`'tangent'`), Number, Number, Boolean (`nil`), Boolean (`nil`)\r
-           - `x1` and `x2` represent where the line segment intersects the circle.\r
-         - Boolean (`false`), Boolean (`nil`), Boolean (`nil`), Boolean (`nil`), Boolean (`nil`)\r
-           - No intersection.\r
-    - For more see the [specs](spec.lua# L676).\r
-\r
-##### mlib.circle.isCircleCompletelyInside\r
-- Checks if one circle is completely inside of another circle.\r
-- Synopsis:\r
-  - `completelyInside = mlib.circle.isCircleCompletelyInside( c1x, c1y, c1radius, c2x, c2y, c2radius )`\r
-- Arguments:\r
-  - `c1x`, `c1y`: Numbers. The x and y coordinates of the first circle.\r
-  - `c1radius`: Number. The radius of the first circle.\r
-  - `c2x`, `c2y`: Numbers. The x and y coordinates of the second circle.\r
-  - `c2radius`: Number. The radius of the second circle.\r
-- Returns:\r
-  - `completelyInside`: Boolean.\r
-    - `true` if circle1 is inside of circle2.\r
-       - `false` if circle1 is not __completely__ inside of circle2.\r
-\r
-##### mlib.circle.isCircleCompletelyInsidePolygon\r
-- Checks if a circle is completely inside the polygon.\r
-- Synopses:\r
-  - `inPolygon = mlib.polygon.isCircleCompletelyInside( cx, cy, radius, vertices )`\r
-  - `inPolygon = mlib.polygon.isCircleCompletelyInside( cx, cy, radius, ... )`\r
-- Arguments:\r
-  - `cx`, `cy`: Numbers. The x and y coordinates for the center of the circle.\r
-  - `radius`: Number. The radius of the circle.\r
-  - `vertices`: Table. The vertices of the polygon in the format `{ x1, y1, x2, y2, x3, y3, ... }`\r
-  - `...`: Numbers. The x and y coordinates of the polygon. (Same as using `unpack( vertices )`)\r
-- Returns:\r
-  - `inPolygon`: Boolean.\r
-    - `true` if the circle is __completely__ inside the polygon.\r
-       - `false` if the circle is not inside the polygon.\r
-\r
-##### mlib.circle.isPointOnCircle\r
-- Checks if a point is __exactly__ on the edge of the circle.\r
-- Synopsis:\r
-  - `onCircle = mlib.circle.checkPoint( px, px, cx, cy, radius )`\r
-- Arguments:\r
-  - `px`, `py`: Numbers. The x and y coordinates of the point being tested.\r
-  - `cx`, `cy`: Numbers. The x and y coordinates of the center of the circle.\r
-  - `radius`: Number. The radius of the circle.\r
-- Returns:\r
-  - `onCircle`: Boolean.\r
-    - `true` if the point is on the circle.\r
-       - `false` if the point is on the inside or outside of the circle.\r
-- Notes:\r
-  - Will return false if the point is inside __or__ outside of the circle.\r
-\r
-##### mlib.circle.isPolygonCompletelyInside\r
-- Checks if a polygon is completely inside of a circle.\r
-- Synopsis:\r
-  - `completelyInside = mlib.circle.isPolygonCompletelyInside( circleX, circleY, circleRadius, vertices )`\r
-  - `completelyInside = mlib.circle.isPolygonCompletelyInside( circleX, circleY, circleRadius, ... )`\r
-- Arguments:\r
-  - `circleX`, `circleY`: Numbers. The x and y coordinates of the circle.\r
-  - `circleRadius`: Number. The radius of the circle.\r
-  - `vertices`: Table. A table containing all of the vertices of the polygon.\r
-  - `...`: Numbers. All of the points of the polygon.\r
-- Returns:\r
-  - `completelyInside`: Boolean.\r
-    - `true` if the polygon is inside of the circle.\r
-       - `false` if the polygon is not __completely__ inside of the circle.\r
-\r
-#### mlib.statistics\r
-- Handles statistical aspects of math.\r
-\r
-##### mlib.statistics.getCentralTendency\r
-- Gets the central tendency of the data.\r
-- Synopses:\r
-  - `modes, occurrences, median, mean = mlib.statistics.getCentralTendency( data )`\r
-  - `modes, occurrences, median, mean = mlib.statistics.getCentralTendency( ... )`\r
-- Arguments:\r
-  - `data`: Table. A table containing the values of data.\r
-  - `...`: Numbers. All of the numbers in the data set.\r
-- Returns:\r
-  - `modes, occurrences`: Table, Number. The modes of the data and the number of times it occurs. See [mlib.statistics.getMode](#mlibstatisticsgetmode).\r
-  - `median`: Number. The median of the data set.\r
-  - `mean`: Number. The mean of the data set.\r
-\r
-##### mlib.statistics.getDispersion\r
-- Gets the dispersion of the data.\r
-- Synopses:\r
-  - `variationRatio, range, standardDeviation = mlib.statistics.getDispersion( data )`\r
-  - `variationRatio, range, standardDeviation = mlib.statistics.getDispersion( ... )`\r
-- Arguments:\r
-  - `data`: Table. A table containing the values of data.\r
-  - `...`: Numbers. All of the numbers in the data set.\r
-- Returns:\r
-  - `variationRatio`: Number. The variation ratio of the data set.\r
-  - `range`: Number. The range of the data set.\r
-  - `standardDeviation`: Number. The standard deviation of the data set.\r
-\r
-##### mlib.statistics.getMean\r
-- Gets the arithmetic mean of the data.\r
-- Synopses:\r
-  - `mean = mlib.statistics.getMean( data )`\r
-  - `mean = mlib.statistics.getMean( ... )`\r
-- Arguments:\r
-  - `data`: Table. A table containing the values of data.\r
-  - `...`: Numbers. All of the numbers in the data set.\r
-- Returns:\r
-  - `mean`: Number. The arithmetic mean of the data set.\r
-\r
-##### mlib.statistics.getMedian\r
-- Gets the median of the data set.\r
-- Synopses:\r
-  - `median = mlib.statistics.getMedian( data )`\r
-  - `median = mlib.statistics.getMedian( ... )`\r
-- Arguments:\r
-  - `data`: Table. A table containing the values of data.\r
-  - `...`: Numbers. All of the numbers in the data set.\r
-- Returns:\r
-  - `median`: Number. The median of the data.\r
-\r
-##### mlib.statistics.getMode\r
-- Gets the mode of the data set.\r
-- Synopses:\r
-  - `mode, occurrences = mlib.statistics.getMode( data )`\r
-  - `mode, occurrences = mlib.statistics.getMode( ... )`\r
-- Arguments:\r
-  - `data`: Table. A table containing the values of data.\r
-  - `...`: Numbers. All of the numbers in the data set.\r
-- Returns:\r
-  - `mode`: Table. The mode(s) of the data.\r
-  - `occurrences`: Number. The number of time the mode(s) occur.\r
-\r
-##### mlib.statistics.getRange\r
-- Gets the range of the data set.\r
-- Synopses:\r
-  - `range = mlib.statistics.getRange( data )`\r
-  - `range = mlib.statistics.getRange( ... )`\r
-- Arguments:\r
-  - `data`: Table. A table containing the values of data.\r
-  - `...`: Numbers. All of the numbers in the data set.\r
-- Returns:\r
-  - `range`: Number. The range of the data.\r
-\r
-##### mlib.statistics.getStandardDeviation\r
-- Gets the standard deviation of the data.\r
-- Synopses:\r
-  - `standardDeviation = mlib.statistics.getStandardDeviation( data )`\r
-  - `standardDeviation = mlib.statistics.getStandardDeviation( ... )`\r
-- Arguments:\r
-  - `data`: Table. A table containing the values of data.\r
-  - `...`: Numbers. All of the numbers in the data set.\r
-- Returns:\r
-  - `standardDeviation`: Number. The standard deviation of the data set.\r
-\r
-##### mlib.statistics.getVariance\r
-- Gets the variation of the data.\r
-- Synopses:\r
-  - `variance = mlib.statistics.getVariance( data )`\r
-  - `variance = mlib.statistics.getVariance( ... )`\r
-- Arguments:\r
-  - `data`: Table. A table containing the values of data.\r
-  - `...`: Numbers. All of the numbers in the data set.\r
-- Returns:\r
-  - `variance`: Number. The variation of the data set.\r
-\r
-##### mlib.statistics.getVariationRatio\r
-- Gets the variation ratio of the data.\r
-- Synopses:\r
-  - `variationRatio = mlib.statistics.getVariationRatio( data )`\r
-  - `variationRatio = mlib.statistics.getVariationRatio( ... )`\r
-- Arguments:\r
-  - `data`: Table. A table containing the values of data.\r
-  - `...`: Numbers. All of the numbers in the data set.\r
-- Returns:\r
-  - `variationRatio`: Number. The variation ratio of the data set.\r
-\r
-#### mlib.math\r
-- Miscellaneous functions that have no home.\r
-\r
-##### mlib.math.getAngle\r
-- Gets the angle between three points.\r
-- Synopsis:\r
-  - `angle = mlib.math.getAngle( x1, y1, x2, y2, x3, y3 )`\r
-- Arguments:\r
-  - `x1`, `y1`: Numbers. The x and y coordinates of the first point.\r
-  - `x2`, `y2`: Numbers. The x and y coordinates of the vertex of the two points.\r
-  - `x3`, `y3`: Numbers. The x and y coordinates of the second point.\r
-\r
-##### mlib.math.getPercentage\r
-- Gets the percentage of a number.\r
-- Synopsis:\r
-  - `percentage = mlib.math.getPercentage( percent, number )`\r
-- Arguments:\r
-  - `percent`: Number. The decimal value of the percent (i.e. 100% is 1, 50% is .5).\r
-  - `number`: Number. The number to get the percentage of.\r
-- Returns:\r
-  - `percentage`: Number. The `percent`age or `number`.\r
-\r
-##### mlib.math.getPercentOfChange\r
-- Gets the percent of change from one to another.\r
-- Synopsis:\r
-  - `change = mlib.math.getPercentOfChange( old, new )`\r
-- Arguments:\r
-  - `old`: Number. The original number.\r
-  - `new`: Number. The new number.\r
-- Returns:\r
-  - `change`: Number. The percent of change from `old` to `new`.\r
-\r
-##### mlib.math.getQuadraticRoots\r
-- Gets the quadratic roots of the the equation.\r
-- Synopsis:\r
-  - `root1, root2 = mlib.math.getQuadraticRoots( a, b, c )`\r
-- Arguments:\r
-  - `a`, `b`, `c`: Numbers. The a, b, and c values of the equation `a * x ^ 2 + b * x ^ 2 + c`.\r
-- Returns:\r
-  - `root1`, `root2`: Numbers. The roots of the equation (where `a * x ^ 2 + b * x ^ 2 + c = 0`).\r
-\r
-##### mlib.math.getRoot\r
-- Gets the `n`th root of a number.\r
-- Synopsis:\r
-  - `x = mlib.math.getRoot( number, root )`\r
-- Arguments:\r
-  - `number`: Number. The number to get the root of.\r
-  - `root`: Number. The root.\r
-- Returns:\r
-  - `x`: The `root`th root of `number`.\r
-- Example:\r
-```lua\r
-local a = mlib.math.getRoot( 4, 2 ) -- Same as saying 'math.pow( 4, .5 )' or 'math.sqrt( 4 )' in this case.\r
-local b = mlib.math.getRoot( 27, 3 )\r
-\r
-print( a, b ) --> 2, 3\r
-```\r
-  - For more, see the [specs](spec.lua# L860).\r
-\r
-##### mlib.math.getSummation\r
-- Gets the summation of numbers.\r
-- Synopsis:\r
-  - `summation = mlib.math.getSummation( start, stop, func )`\r
-- Arguments:\r
-  - `start`: Number. The number at which to start the summation.\r
-  - `stop`: Number. The number at which to stop the summation.\r
-  - `func`: Function. The method to add the numbers.\r
-    - Arguments:\r
-         - `i`: Number. Index.\r
-         - `previous`: Table. The previous values used.\r
-- Returns:\r
-  - `Summation`: Number. The summation of the numbers.\r
-  - For more, see the [specs](spec.lua# L897).\r
-\r
-##### mlib.math.isPrime\r
-- Checks if a number is prime.\r
-- Synopsis:\r
-  - `isPrime = mlib.math.isPrime( x )`\r
-- Arguments:\r
-  - `x`: Number. The number to check if it's prime.\r
-- Returns:\r
-  - `isPrime`: Boolean.\r
-    - `true` if the number is prime.\r
-       - `false` if the number is not prime.\r
-\r
-##### mlib.math.round\r
-- Rounds a number to the given decimal place.\r
-- Synopsis:\r
-  - `rounded = mlib.math.round( number, [place] )\r
-- Arguments:\r
-  - `number`: Number. The number to round.\r
-  - `place (1)`: Number. The decimal place to round to. Defaults to 1.\r
-- Returns:\r
-  - The rounded number.\r
-  - For more, see the [specs](spec.lua# L881).\r
-\r
-#### Aliases\r
-| Alias                                         | Corresponding Function                                                            |\r
-| ----------------------------------------------|:---------------------------------------------------------------------------------:|\r
-| milb.line.getDistance                         | [mlib.line.getLength](#mliblinegetlength)                                         |\r
-| mlib.line.getCircleIntersection               | [mlib.circle.getLineIntersection](#mlibcirclegetlineintersection)                 |\r
-| milb.line.getPolygonIntersection              | [mlib.polygon.getLineIntersection](#mlibpolygongetlineintersection)               |\r
-| mlib.line.getLineIntersection                 | [mlib.line.getIntersection](#mliblinegetintersection)                             |\r
-| mlib.segment.getCircleIntersection            | [mlib.circle.getSegmentIntersection](#mlibcirclegetsegmentintersection)           |\r
-| milb.segment.getPolygonIntersection           | [mlib.pollygon.getSegmentIntersection](#mlibpollygongetsegmentintersection)       |\r
-| mlib.segment.getLineIntersection              | [mlib.line.getSegmentIntersection](#mliblinegetsegmentintersection)               |\r
-| mlib.segment.getSegmentIntersection           | [mlib.segment.getIntersection](#mlibsegmentgetintersection)                       |\r
-| milb.segment.isSegmentCompletelyInsideCircle  | [mlib.circle.isSegmentCompletelyInside](#mlibcircleissegmentcompletelyinside)     |\r
-| mlib.segment.isSegmentCompletelyInsidePolygon | [mlib.polygon.isSegmentCompletelyInside](#mlibpolygonissegmentcompletelyinside)   |\r
-| mlib.circle.getPolygonIntersection            | [mlib.polygon.getCircleIntersection](#mlibpolygongetcircleintersection)           |\r
-| mlib.circle.isCircleInsidePolygon             | [mlib.polygon.isCircleInside](#mlibpolygoniscircleinside)                         |\r
-| mlib.circle.isCircleCompletelyInsidePolygon   | [mlib.polygon.isCircleCompletelyInside](#mlibpolygoniscirclecompletelyinside)     |\r
-| mlib.polygon.isCircleCompletelyOver           | [mlib.circleisPolygonCompletelyInside](#mlibcircleispolygoncompletelyinside)      |\r
-\r
-## License\r
-A math library made in Lua\r
-copyright (C) 2014 Davis Claiborne\r
-This program is free software; you can redistribute it and/or modify\r
-it under the terms of the GNU General Public License as published by\r
-the Free Software Foundation; either version 2 of the License, or\r
-(at your option) any later version.\r
-This program is distributed in the hope that it will be useful,\r
-but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-GNU General Public License for more details.\r
-You should have received a copy of the GNU General Public License along\r
-with this program; if not, write to the Free Software Foundation, Inc.,\r
-51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
-Contact me at davisclaib at gmail.com\r
diff --git a/main/plugin/windfield/mlib/mlib.lua b/main/plugin/windfield/mlib/mlib.lua
deleted file mode 100644 (file)
index 76067c6..0000000
+++ /dev/null
@@ -1,1152 +0,0 @@
---[[ License\r
-       A math library made in Lua\r
-       copyright (C) 2014 Davis Claiborne\r
-       This program is free software; you can redistribute it and/or modify\r
-       it under the terms of the GNU General Public License as published by\r
-       the Free Software Foundation; either version 2 of the License, or\r
-       (at your option) any later version.\r
-       This program is distributed in the hope that it will be useful,\r
-       but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-       GNU General Public License for more details.\r
-       You should have received a copy of the GNU General Public License along\r
-       with this program; if not, write to the Free Software Foundation, Inc.,\r
-       51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
-       Contact me at davisclaib@gmail.com\r
-]]\r
-\r
--- Local Utility Functions ---------------------- {{{\r
-local unpack = table.unpack or unpack\r
-\r
--- Used to handle variable-argument functions and whether they are passed as func{ table } or func( unpack( table ) )\r
-local function checkInput( ... )\r
-       local input = {}\r
-       if type( ... ) ~= 'table' then input = { ... } else input = ... end\r
-       return input\r
-end\r
-\r
--- Deals with floats / verify false false values. This can happen because of significant figures.\r
-local function checkFuzzy( number1, number2 )\r
-       return ( number1 - .00001 <= number2 and number2 <= number1 + .00001 )\r
-end\r
-\r
--- Remove multiple occurrences from a table.\r
-local function removeDuplicatePairs( tab )\r
-       for index1 = #tab, 1, -1 do\r
-               local first = tab[index1]\r
-               for index2 = #tab, 1, -1 do\r
-                       local second = tab[index2]\r
-                       if index1 ~= index2 then\r
-                               if type( first[1] ) == 'number' and type( second[1] ) == 'number' and type( first[2] ) == 'number' and type( second[2] ) == 'number' then\r
-                                       if checkFuzzy( first[1], second[1] ) and checkFuzzy( first[2], second[2] ) then\r
-                                               table.remove( tab, index1 )\r
-                                       end\r
-                               elseif first[1] == second[1] and first[2] == second[2] then\r
-                                       table.remove( tab, index1 )\r
-                               end\r
-                       end\r
-               end\r
-       end\r
-       return tab\r
-end\r
-\r
-\r
-local function removeDuplicates4Points( tab )\r
-    for index1 = #tab, 1, -1 do\r
-        local first = tab[index1]\r
-        for index2 = #tab, 1, -1 do\r
-            local second = tab[index2]\r
-            if index1 ~= index2 then\r
-                if type( first[1] ) ~= type( second[1] ) then return false end\r
-                if type( first[2] ) == 'number' and type( second[2] ) == 'number' and type( first[3] ) == 'number' and type( second[3] ) == 'number' then\r
-                    if checkFuzzy( first[2], second[2] ) and checkFuzzy( first[3], second[3] ) then\r
-                        table.remove( tab, index1 )\r
-                    end\r
-                elseif checkFuzzy( first[1], second[1] ) and checkFuzzy( first[2], second[2] ) and checkFuzzy( first[3], second[3] ) then\r
-                    table.remove( tab, index1 )\r
-                end\r
-            end\r
-        end\r
-    end\r
-    return tab\r
-end\r
-\r
-\r
--- Add points to the table.\r
-local function addPoints( tab, x, y )\r
-    tab[#tab + 1] = x\r
-    tab[#tab + 1] = y\r
-end\r
-\r
--- Like removeDuplicatePairs but specifically for numbers in a flat table\r
-local function removeDuplicatePointsFlat( tab )\r
-    for i = #tab, 1 -2 do\r
-        for ii = #tab - 2, 3, -2 do\r
-            if i ~= ii then\r
-                local x1, y1 = tab[i], tab[i + 1]\r
-                local x2, y2 = tab[ii], tab[ii + 1]\r
-                if checkFuzzy( x1, x2 ) and checkFuzzy( y1, y2 ) then\r
-                    table.remove( tab, ii ); table.remove( tab, ii + 1 )\r
-                end\r
-            end\r
-        end\r
-    end\r
-    return tab\r
-end\r
-\r
-\r
--- Check if input is actually a number\r
-local function validateNumber( n )\r
-       if type( n ) ~= 'number' then return false\r
-       elseif n ~= n then return false -- nan\r
-       elseif math.abs( n ) == math.huge then return false\r
-       else return true end\r
-end\r
-\r
-local function cycle( tab, index ) return tab[( index - 1 ) % #tab + 1] end\r
-\r
-local function getGreatestPoint( points, offset )\r
-    offset = offset or 1\r
-    local start = 2 - offset\r
-    local greatest = points[start]\r
-    local least = points[start]\r
-    for i = 2, #points / 2 do\r
-        i = i * 2 - offset\r
-        if points[i] > greatest then\r
-            greatest = points[i]\r
-        end\r
-        if points[i] < least then\r
-            least = points[i]\r
-        end\r
-    end\r
-    return greatest, least\r
-end\r
-\r
-local function isWithinBounds( min, num, max )\r
-    return num >= min and num <= max\r
-end\r
-\r
-local function distance2( x1, y1, x2, y2 ) -- Faster since it does not use math.sqrt\r
-       local dx, dy = x1 - x2, y1 - y2\r
-       return dx * dx + dy * dy\r
-end -- }}}\r
-\r
--- Points -------------------------------------- {{{\r
-local function rotatePoint( x, y, rotation, ox, oy )\r
-    ox, oy = ox or 0, oy or 0\r
-    return ( x - ox ) * math.cos( rotation ) + ox - ( y - oy ) * math.sin( rotation ), ( x - ox ) * math.sin( rotation ) + ( y - oy ) * math.cos( rotation ) + oy\r
-end\r
-\r
-local function scalePoint( x, y, scale, ox, oy )\r
-    ox, oy = ox or 0, oy or 0\r
-    return ( x - ox ) * scale + ox, ( y - oy ) * scale + oy\r
-end\r
--- }}}\r
-\r
--- Lines --------------------------------------- {{{\r
--- Returns the length of a line.\r
-local function getLength( x1, y1, x2, y2 )\r
-       local dx, dy = x1 - x2, y1 - y2\r
-       return math.sqrt( dx * dx + dy * dy )\r
-end\r
-\r
--- Gives the midpoint of a line.\r
-local function getMidpoint( x1, y1, x2, y2 )\r
-       return ( x1 + x2 ) / 2, ( y1 + y2 ) / 2\r
-end\r
-\r
--- Gives the slope of a line.\r
-local function getSlope( x1, y1, x2, y2 )\r
-       if checkFuzzy( x1, x2 ) then return false end -- Technically it's undefined, but this is easier to program.\r
-       return ( y1 - y2 ) / ( x1 - x2 )\r
-end\r
-\r
--- Gives the perpendicular slope of a line.\r
--- x1, y1, x2, y2\r
--- slope\r
-local function getPerpendicularSlope( ... )\r
-       local input = checkInput( ... )\r
-       local slope\r
-\r
-       if #input ~= 1 then\r
-               slope = getSlope( unpack( input ) )\r
-       else\r
-               slope = unpack( input )\r
-       end\r
-\r
-       if not slope then return 0 -- Vertical lines become horizontal.\r
-       elseif checkFuzzy( slope, 0 ) then return false -- Horizontal lines become vertical.\r
-    else return -1 / slope end\r
-end\r
-\r
--- Gives the y-intercept of a line.\r
--- x1, y1, x2, y2\r
--- x1, y1, slope\r
-local function getYIntercept( x, y, ... )\r
-       local input = checkInput( ... )\r
-       local slope\r
-\r
-       if #input == 1 then\r
-               slope = input[1]\r
-       else\r
-               slope = getSlope( x, y, unpack( input ) )\r
-       end\r
-\r
-       if not slope then return x, true end -- This way we have some information on the line.\r
-       return y - slope * x, false\r
-end\r
-\r
--- Gives the intersection of two lines.\r
--- slope1, slope2, x1, y1, x2, y2\r
--- slope1, intercept1, slope2, intercept2\r
--- x1, y1, x2, y2, x3, y3, x4, y4\r
-local function getLineLineIntersection( ... )\r
-       local input = checkInput( ... )\r
-       local x1, y1, x2, y2, x3, y3, x4, y4\r
-       local slope1, intercept1\r
-       local slope2, intercept2\r
-       local x, y\r
-\r
-       if #input == 4 then -- Given slope1, intercept1, slope2, intercept2.\r
-               slope1, intercept1, slope2, intercept2 = unpack( input )\r
-\r
-               -- Since these are lines, not segments, we can use arbitrary points, such as ( 1, y ), ( 2, y )\r
-               y1 = slope1 and slope1 * 1 + intercept1 or 1\r
-               y2 = slope1 and slope1 * 2 + intercept1 or 2\r
-               y3 = slope2 and slope2 * 1 + intercept2 or 1\r
-               y4 = slope2 and slope2 * 2 + intercept2 or 2\r
-               x1 = slope1 and ( y1 - intercept1 ) / slope1 or intercept1\r
-               x2 = slope1 and ( y2 - intercept1 ) / slope1 or intercept1\r
-               x3 = slope2 and ( y3 - intercept2 ) / slope2 or intercept2\r
-               x4 = slope2 and ( y4 - intercept2 ) / slope2 or intercept2\r
-       elseif #input == 6 then -- Given slope1, intercept1, and 2 points on the other line.\r
-               slope1, intercept1 = input[1], input[2]\r
-               slope2 = getSlope( input[3], input[4], input[5], input[6] )\r
-               intercept2 = getYIntercept( input[3], input[4], input[5], input[6] )\r
-\r
-               y1 = slope1 and slope1 * 1 + intercept1 or 1\r
-               y2 = slope1 and slope1 * 2 + intercept1 or 2\r
-               y3 = input[4]\r
-               y4 = input[6]\r
-               x1 = slope1 and ( y1 - intercept1 ) / slope1 or intercept1\r
-               x2 = slope1 and ( y2 - intercept1 ) / slope1 or intercept1\r
-               x3 = input[3]\r
-               x4 = input[5]\r
-       elseif #input == 8 then -- Given 2 points on line 1 and 2 points on line 2.\r
-               slope1 = getSlope( input[1], input[2], input[3], input[4] )\r
-               intercept1 = getYIntercept( input[1], input[2], input[3], input[4] )\r
-               slope2 = getSlope( input[5], input[6], input[7], input[8] )\r
-               intercept2 = getYIntercept( input[5], input[6], input[7], input[8] )\r
-\r
-               x1, y1, x2, y2, x3, y3, x4, y4 = unpack( input )\r
-       end\r
-\r
-       if not slope1 and not slope2 then -- Both are vertical lines\r
-               if x1 == x3 then -- Have to have the same x positions to intersect\r
-                       return true\r
-               else\r
-                       return false\r
-               end\r
-       elseif not slope1 then -- First is vertical\r
-               x = x1 -- They have to meet at this x, since it is this line's only x\r
-               y = slope2 and slope2 * x + intercept2 or 1\r
-       elseif not slope2 then -- Second is vertical\r
-               x = x3 -- Vice-Versa\r
-               y = slope1 * x + intercept1\r
-       elseif checkFuzzy( slope1, slope2 ) then -- Parallel (not vertical)\r
-               if checkFuzzy( intercept1, intercept2 ) then -- Same intercept\r
-                       return true\r
-               else\r
-                       return false\r
-               end\r
-       else -- Regular lines\r
-               x = ( -intercept1 + intercept2 ) / ( slope1 - slope2 )\r
-               y = slope1 * x + intercept1\r
-       end\r
-\r
-       return x, y\r
-end\r
-\r
--- Gives the closest point on a line to a point.\r
--- perpendicularX, perpendicularY, x1, y1, x2, y2\r
--- perpendicularX, perpendicularY, slope, intercept\r
-local function getClosestPoint( perpendicularX, perpendicularY, ... )\r
-       local input = checkInput( ... )\r
-       local x, y, x1, y1, x2, y2, slope, intercept\r
-\r
-       if #input == 4 then -- Given perpendicularX, perpendicularY, x1, y1, x2, y2\r
-               x1, y1, x2, y2 = unpack( input )\r
-               slope = getSlope( x1, y1, x2, y2 )\r
-               intercept = getYIntercept( x1, y1, x2, y2 )\r
-       elseif #input == 2 then -- Given perpendicularX, perpendicularY, slope, intercept\r
-               slope, intercept = unpack( input )\r
-        x1, y1 = 1, slope and slope * 1 + intercept or 1 -- Need x1 and y1 in case of vertical/horizontal lines.\r
-       end\r
-\r
-       if not slope then -- Vertical line\r
-               x, y = x1, perpendicularY -- Closest point is always perpendicular.\r
-       elseif checkFuzzy( slope, 0 ) then -- Horizontal line\r
-               x, y = perpendicularX, y1\r
-       else\r
-               local perpendicularSlope = getPerpendicularSlope( slope )\r
-               local perpendicularIntercept = getYIntercept( perpendicularX, perpendicularY, perpendicularSlope )\r
-               x, y = getLineLineIntersection( slope, intercept, perpendicularSlope, perpendicularIntercept )\r
-       end\r
-\r
-       return x, y\r
-end\r
-\r
--- Gives the intersection of a line and a line segment.\r
--- x1, y1, x2, y2, x3, y3, x4, y4\r
--- x1, y1, x2, y2, slope, intercept\r
-local function getLineSegmentIntersection( x1, y1, x2, y2, ... )\r
-       local input = checkInput( ... )\r
-\r
-       local slope1, intercept1, x, y, lineX1, lineY1, lineX2, lineY2\r
-       local slope2, intercept2 = getSlope( x1, y1, x2, y2 ), getYIntercept( x1, y1, x2, y2 )\r
-\r
-       if #input == 2 then -- Given slope, intercept\r
-               slope1, intercept1 = input[1], input[2]\r
-        lineX1, lineY1 = 1, slope1 and slope1 + intercept1\r
-        lineX2, lineY2 = 2, slope1 and slope1 * 2 + intercept1\r
-       else -- Given x3, y3, x4, y4\r
-        lineX1, lineY1, lineX2, lineY2 = unpack( input )\r
-               slope1 = getSlope( unpack( input ) )\r
-               intercept1 = getYIntercept( unpack( input ) )\r
-       end\r
-\r
-       if not slope1 and not slope2 then -- Vertical lines\r
-               if checkFuzzy( x1, lineX1 ) then\r
-                       return x1, y1, x2, y2\r
-               else\r
-                       return false\r
-               end\r
-       elseif not slope1 then -- slope1 is vertical\r
-               x, y = input[1], slope2 * input[1] + intercept2\r
-       elseif not slope2 then -- slope2 is vertical\r
-               x, y = x1, slope1 * x1 + intercept1\r
-       else\r
-               x, y = getLineLineIntersection( slope1, intercept1, slope2, intercept2 )\r
-       end\r
-\r
-       local length1, length2, distance\r
-       if x == true then -- Lines are collinear.\r
-               return x1, y1, x2, y2\r
-       elseif x then -- There is an intersection\r
-               length1, length2 = getLength( x1, y1, x, y ), getLength( x2, y2, x, y )\r
-               distance = getLength( x1, y1, x2, y2 )\r
-       else -- Lines are parallel but not collinear.\r
-               if checkFuzzy( intercept1, intercept2 ) then\r
-                       return x1, y1, x2, y2\r
-               else\r
-                       return false\r
-               end\r
-       end\r
-\r
-       if length1 <= distance and length2 <= distance then return x, y else return false end\r
-end\r
-\r
--- Checks if a point is on a line.\r
--- Does not support the format using slope because vertical lines would be impossible to check.\r
-local function checkLinePoint( x, y, x1, y1, x2, y2 )\r
-       local m = getSlope( x1, y1, x2, y2 )\r
-       local b = getYIntercept( x1, y1, m )\r
-\r
-       if not m then -- Vertical\r
-               return checkFuzzy( x, x1 )\r
-       end\r
-       return checkFuzzy( y, m * x + b )\r
-end -- }}}\r
-\r
--- Segment -------------------------------------- {{{\r
--- Gives the perpendicular bisector of a line.\r
-local function getPerpendicularBisector( x1, y1, x2, y2 )\r
-       local slope = getSlope( x1, y1, x2, y2 )\r
-       local midpointX, midpointY = getMidpoint( x1, y1, x2, y2 )\r
-       return midpointX, midpointY, getPerpendicularSlope( slope )\r
-end\r
-\r
--- Gives whether or not a point lies on a line segment.\r
-local function checkSegmentPoint( px, py, x1, y1, x2, y2 )\r
-       -- Explanation around 5:20: https://www.youtube.com/watch?v=A86COO8KC58\r
-       local x = checkLinePoint( px, py, x1, y1, x2, y2 )\r
-       if not x then return false end\r
-\r
-       local lengthX = x2 - x1\r
-       local lengthY = y2 - y1\r
-\r
-       if checkFuzzy( lengthX, 0 ) then -- Vertical line\r
-               if checkFuzzy( px, x1 ) then\r
-                       local low, high\r
-                       if y1 > y2 then low = y2; high = y1\r
-                       else low = y1; high = y2 end\r
-\r
-                       if py >= low and py <= high then return true\r
-                       else return false end\r
-               else\r
-                       return false\r
-               end\r
-       elseif checkFuzzy( lengthY, 0 ) then -- Horizontal line\r
-               if checkFuzzy( py, y1 ) then\r
-                       local low, high\r
-                       if x1 > x2 then low = x2; high = x1\r
-                       else low = x1; high = x2 end\r
-\r
-                       if px >= low and px <= high then return true\r
-                       else return false end\r
-               else\r
-                       return false\r
-               end\r
-       end\r
-\r
-       local distanceToPointX = ( px - x1 )\r
-       local distanceToPointY = ( py - y1 )\r
-       local scaleX = distanceToPointX / lengthX\r
-       local scaleY = distanceToPointY / lengthY\r
-\r
-       if ( scaleX >= 0 and scaleX <= 1 ) and ( scaleY >= 0 and scaleY <= 1 ) then -- Intersection\r
-               return true\r
-       end\r
-       return false\r
-end\r
-\r
--- Gives the point of intersection between two line segments.\r
-local function getSegmentSegmentIntersection( x1, y1, x2, y2, x3, y3, x4, y4 )\r
-       local slope1, intercept1 = getSlope( x1, y1, x2, y2 ), getYIntercept( x1, y1, x2, y2 )\r
-       local slope2, intercept2 = getSlope( x3, y3, x4, y4 ), getYIntercept( x3, y3, x4, y4 )\r
-\r
-       if ( ( slope1 and slope2 ) and checkFuzzy( slope1, slope2 ) ) or ( not slope1 and not slope2 ) then -- Parallel lines\r
-               if checkFuzzy( intercept1, intercept2 ) then -- The same lines, possibly in different points.\r
-                       local points = {}\r
-                       if checkSegmentPoint( x1, y1, x3, y3, x4, y4 ) then addPoints( points, x1, y1 ) end\r
-                       if checkSegmentPoint( x2, y2, x3, y3, x4, y4 ) then addPoints( points, x2, y2 ) end\r
-                       if checkSegmentPoint( x3, y3, x1, y1, x2, y2 ) then addPoints( points, x3, y3 ) end\r
-                       if checkSegmentPoint( x4, y4, x1, y1, x2, y2 ) then addPoints( points, x4, y4 ) end\r
-\r
-                       points = removeDuplicatePointsFlat( points )\r
-                       if #points == 0 then return false end\r
-                       return unpack( points )\r
-               else\r
-                       return false\r
-               end\r
-       end\r
-\r
-       local x, y = getLineLineIntersection( x1, y1, x2, y2, x3, y3, x4, y4 )\r
-       if x and checkSegmentPoint( x, y, x1, y1, x2, y2 ) and checkSegmentPoint( x, y, x3, y3, x4, y4 ) then\r
-               return x, y\r
-       end\r
-       return false\r
-end -- }}}\r
-\r
--- Math ----------------------------------------- {{{\r
--- Get the root of a number (i.e. the 2nd (square) root of 4 is 2)\r
-local function getRoot( number, root )\r
-       return number ^ ( 1 / root )\r
-end\r
-\r
--- Checks if a number is prime.\r
-local function isPrime( number )\r
-       if number < 2 then return false end\r
-\r
-       for i = 2, math.sqrt( number ) do\r
-               if number % i == 0 then\r
-                       return false\r
-               end\r
-       end\r
-       return true\r
-end\r
-\r
--- Rounds a number to the xth decimal place (round( 3.14159265359, 4 ) --> 3.1416)\r
-local function round( number, place )\r
-       local pow = 10 ^ ( place or 0 )\r
-    return math.floor( number * pow + .5 ) / pow\r
-end\r
-\r
--- Gives the summation given a local function\r
-local function getSummation( start, stop, func )\r
-       local returnValues = {}\r
-       local sum = 0\r
-       for i = start, stop do\r
-               local value = func( i, returnValues )\r
-               returnValues[i] = value\r
-               sum = sum + value\r
-       end\r
-       return sum\r
-end\r
-\r
--- Gives the percent of change.\r
-local function getPercentOfChange( old, new )\r
-       if old == 0 and new == 0 then\r
-        return 0\r
-       else\r
-               return ( new - old ) / math.abs( old )\r
-       end\r
-end\r
-\r
--- Gives the percentage of a number.\r
-local function getPercentage( percent, number )\r
-       return percent * number\r
-end\r
-\r
--- Returns the quadratic roots of an equation.\r
-local function getQuadraticRoots( a, b, c )\r
-       local discriminant = b ^ 2 - ( 4 * a * c )\r
-       if discriminant < 0 then return false end\r
-       discriminant = math.sqrt( discriminant )\r
-       local denominator = ( 2 * a )\r
-       return ( -b - discriminant ) / denominator, ( -b + discriminant ) / denominator\r
-end\r
-\r
--- Gives the angle between three points.\r
-local function getAngle( x1, y1, x2, y2, x3, y3 )\r
-    local a = getLength( x3, y3, x2, y2 )\r
-    local b = getLength( x1, y1, x2, y2 )\r
-    local c = getLength( x1, y1, x3, y3 )\r
-\r
-   return math.acos( ( a * a + b * b - c * c ) / ( 2 * a * b ) )\r
-end -- }}}\r
-\r
--- Circle --------------------------------------- {{{\r
--- Gives the area of the circle.\r
-local function getCircleArea( radius )\r
-       return math.pi * ( radius * radius )\r
-end\r
-\r
--- Checks if a point is within the radius of a circle.\r
-local function checkCirclePoint( x, y, circleX, circleY, radius )\r
-       return getLength( circleX, circleY, x, y ) <= radius\r
-end\r
-\r
--- Checks if a point is on a circle.\r
-local function isPointOnCircle( x, y, circleX, circleY, radius )\r
-       return checkFuzzy( getLength( circleX, circleY, x, y ), radius )\r
-end\r
-\r
--- Gives the circumference of a circle.\r
-local function getCircumference( radius )\r
-       return 2 * math.pi * radius\r
-end\r
-\r
--- Gives the intersection of a line and a circle.\r
-local function getCircleLineIntersection( circleX, circleY, radius, x1, y1, x2, y2 )\r
-       slope = getSlope( x1, y1, x2, y2 )\r
-       intercept = getYIntercept( x1, y1, slope )\r
-\r
-       if slope then\r
-               local a = ( 1 + slope ^ 2 )\r
-               local b = ( -2 * ( circleX ) + ( 2 * slope * intercept ) - ( 2 * circleY * slope ) )\r
-               local c = ( circleX ^ 2 + intercept ^ 2 - 2 * ( circleY ) * ( intercept ) + circleY ^ 2 - radius ^ 2 )\r
-\r
-               x1, x2 = getQuadraticRoots( a, b, c )\r
-\r
-               if not x1 then return false end\r
-\r
-               y1 = slope * x1 + intercept\r
-               y2 = slope * x2 + intercept\r
-\r
-               if checkFuzzy( x1, x2 ) and checkFuzzy( y1, y2 ) then\r
-                       return 'tangent', x1, y1\r
-               else\r
-                       return 'secant', x1, y1, x2, y2\r
-               end\r
-       else -- Vertical Lines\r
-               local lengthToPoint1 = circleX - x1\r
-               local remainingDistance = lengthToPoint1 - radius\r
-               local intercept = math.sqrt( -( lengthToPoint1 ^ 2 - radius ^ 2 ) )\r
-\r
-               if -( lengthToPoint1 ^ 2 - radius ^ 2 ) < 0 then return false end\r
-\r
-               local bottomX, bottomY = x1, circleY - intercept\r
-               local topX, topY = x1, circleY + intercept\r
-\r
-               if topY ~= bottomY then\r
-                       return 'secant', topX, topY, bottomX, bottomY\r
-               else\r
-                       return 'tangent', topX, topY\r
-               end\r
-       end\r
-end\r
-\r
--- Gives the type of intersection of a line segment.\r
-local function getCircleSegmentIntersection( circleX, circleY, radius, x1, y1, x2, y2 )\r
-       local Type, x3, y3, x4, y4 = getCircleLineIntersection( circleX, circleY, radius, x1, y1, x2, y2 )\r
-       if not Type then return false end\r
-\r
-       local slope, intercept = getSlope( x1, y1, x2, y2 ), getYIntercept( x1, y1, x2, y2 )\r
-\r
-       if isPointOnCircle( x1, y1, circleX, circleY, radius ) and isPointOnCircle( x2, y2, circleX, circleY, radius ) then -- Both points are on line-segment.\r
-               return 'chord', x1, y1, x2, y2\r
-       end\r
-\r
-       if slope then\r
-               if checkCirclePoint( x1, y1, circleX, circleY, radius ) and checkCirclePoint( x2, y2, circleX, circleY, radius ) then -- Line-segment is fully in circle.\r
-                       return 'enclosed', x1, y1, x2, y2\r
-               elseif x3 and x4 then\r
-                       if checkSegmentPoint( x3, y3, x1, y1, x2, y2 ) and not checkSegmentPoint( x4, y4, x1, y1, x2, y2 ) then -- Only the first of the points is on the line-segment.\r
-                               return 'tangent', x3, y3\r
-                       elseif checkSegmentPoint( x4, y4, x1, y1, x2, y2 ) and not checkSegmentPoint( x3, y3, x1, y1, x2, y2 ) then -- Only the second of the points is on the line-segment.\r
-                               return 'tangent', x4, y4\r
-                       else -- Neither of the points are on the circle (means that the segment is not on the circle, but "encasing" the circle)\r
-                               if checkSegmentPoint( x3, y3, x1, y1, x2, y2 ) and checkSegmentPoint( x4, y4, x1, y1, x2, y2 ) then\r
-                                       return 'secant', x3, y3, x4, y4\r
-                               else\r
-                                       return false\r
-                               end\r
-                       end\r
-               elseif not x4 then -- Is a tangent.\r
-                       if checkSegmentPoint( x3, y3, x1, y1, x2, y2 ) then\r
-                               return 'tangent', x3, y3\r
-                       else -- Neither of the points are on the line-segment (means that the segment is not on the circle or "encasing" the circle).\r
-                               local length = getLength( x1, y1, x2, y2 )\r
-                               local distance1 = getLength( x1, y1, x3, y3 )\r
-                               local distance2 = getLength( x2, y2, x3, y3 )\r
-\r
-                               if length > distance1 or length > distance2 then\r
-                                       return false\r
-                               elseif length < distance1 and length < distance2 then\r
-                                       return false\r
-                               else\r
-                                       return 'tangent', x3, y3\r
-                               end\r
-                       end\r
-               end\r
-       else\r
-               local lengthToPoint1 = circleX - x1\r
-               local remainingDistance = lengthToPoint1 - radius\r
-               local intercept = math.sqrt( -( lengthToPoint1 ^ 2 - radius ^ 2 ) )\r
-\r
-               if -( lengthToPoint1 ^ 2 - radius ^ 2 ) < 0 then return false end\r
-\r
-               local topX, topY = x1, circleY - intercept\r
-               local bottomX, bottomY = x1, circleY + intercept\r
-\r
-               local length = getLength( x1, y1, x2, y2 )\r
-               local distance1 = getLength( x1, y1, topX, topY )\r
-               local distance2 = getLength( x2, y2, topX, topY )\r
-\r
-               if bottomY ~= topY then -- Not a tangent\r
-                       if checkSegmentPoint( topX, topY, x1, y1, x2, y2 ) and checkSegmentPoint( bottomX, bottomY, x1, y1, x2, y2 ) then\r
-                               return 'chord', topX, topY, bottomX, bottomY\r
-                       elseif checkSegmentPoint( topX, topY, x1, y1, x2, y2 ) then\r
-                               return 'tangent', topX, topY\r
-                       elseif checkSegmentPoint( bottomX, bottomY, x1, y1, x2, y2 ) then\r
-                               return 'tangent', bottomX, bottomY\r
-                       else\r
-                               return false\r
-                       end\r
-               else -- Tangent\r
-                       if checkSegmentPoint( topX, topY, x1, y1, x2, y2 ) then\r
-                               return 'tangent', topX, topY\r
-                       else\r
-                               return false\r
-                       end\r
-               end\r
-       end\r
-end\r
-\r
--- Checks if one circle intersects another circle.\r
-local function getCircleCircleIntersection( circle1x, circle1y, radius1, circle2x, circle2y, radius2 )\r
-       local length = getLength( circle1x, circle1y, circle2x, circle2y )\r
-       if length > radius1 + radius2 then return false end -- If the distance is greater than the two radii, they can't intersect.\r
-       if checkFuzzy( length, 0 ) and checkFuzzy( radius1, radius2 ) then return 'equal' end\r
-       if checkFuzzy( circle1x, circle2x ) and checkFuzzy( circle1y, circle2y ) then return 'collinear' end\r
-\r
-       local a = ( radius1 * radius1 - radius2 * radius2 + length * length ) / ( 2 * length )\r
-       local h = math.sqrt( radius1 * radius1 - a * a )\r
-\r
-       local p2x = circle1x + a * ( circle2x - circle1x ) / length\r
-       local p2y = circle1y + a * ( circle2y - circle1y ) / length\r
-       local p3x = p2x + h * ( circle2y - circle1y ) / length\r
-       local p3y = p2y - h * ( circle2x - circle1x ) / length\r
-       local p4x = p2x - h * ( circle2y - circle1y ) / length\r
-       local p4y = p2y + h * ( circle2x - circle1x ) / length\r
-\r
-       if not validateNumber( p3x ) or not validateNumber( p3y ) or not validateNumber( p4x ) or not validateNumber( p4y ) then\r
-               return 'inside'\r
-       end\r
-\r
-       if checkFuzzy( length, radius1 + radius2 ) or checkFuzzy( length, math.abs( radius1 - radius2 ) ) then return 'tangent', p3x, p3y end\r
-       return 'intersection', p3x, p3y, p4x, p4y\r
-end\r
-\r
--- Checks if circle1 is entirely inside of circle2.\r
-local function isCircleCompletelyInsideCircle( circle1x, circle1y, circle1radius, circle2x, circle2y, circle2radius )\r
-       if not checkCirclePoint( circle1x, circle1y, circle2x, circle2y, circle2radius ) then return false end\r
-       local Type = getCircleCircleIntersection( circle2x, circle2y, circle2radius, circle1x, circle1y, circle1radius )\r
-       if ( Type ~= 'tangent' and Type ~= 'collinear' and Type ~= 'inside' ) then return false end\r
-       return true\r
-end\r
-\r
--- Checks if a line-segment is entirely within a circle.\r
-local function isSegmentCompletelyInsideCircle( circleX, circleY, circleRadius, x1, y1, x2, y2 )\r
-       local Type = getCircleSegmentIntersection( circleX, circleY, circleRadius, x1, y1, x2, y2 )\r
-       return Type == 'enclosed'\r
-end -- }}}\r
-\r
--- Polygon -------------------------------------- {{{\r
--- Gives the signed area.\r
--- If the points are clockwise the number is negative, otherwise, it's positive.\r
-local function getSignedPolygonArea( ... )\r
-       local points = checkInput( ... )\r
-\r
-       -- Shoelace formula (https://en.wikipedia.org/wiki/Shoelace_formula).\r
-       points[#points + 1] = points[1]\r
-       points[#points + 1] = points[2]\r
-\r
-       return ( .5 * getSummation( 1, #points / 2,\r
-               function( index )\r
-                       index = index * 2 - 1 -- Convert it to work properly.\r
-                       return ( ( points[index] * cycle( points, index + 3 ) ) - ( cycle( points, index + 2 ) * points[index + 1] ) )\r
-               end\r
-       ) )\r
-end\r
-\r
--- Simply returns the area of the polygon.\r
-local function getPolygonArea( ... )\r
-       return math.abs( getSignedPolygonArea( ... ) )\r
-end\r
-\r
--- Gives the height of a triangle, given the base.\r
--- base, x1, y1, x2, y2, x3, y3, x4, y4\r
--- base, area\r
-local function getTriangleHeight( base, ... )\r
-       local input = checkInput( ... )\r
-       local area\r
-\r
-       if #input == 1 then area = input[1] -- Given area.\r
-       else area = getPolygonArea( input ) end -- Given coordinates.\r
-\r
-       return ( 2 * area ) / base, area\r
-end\r
-\r
--- Gives the centroid of the polygon.\r
-local function getCentroid( ... )\r
-       local points = checkInput( ... )\r
-\r
-       points[#points + 1] = points[1]\r
-       points[#points + 1] = points[2]\r
-\r
-       local area = getSignedPolygonArea( points ) -- Needs to be signed here in case points are counter-clockwise.\r
-\r
-       -- This formula: https://en.wikipedia.org/wiki/Centroid#Centroid_of_polygon\r
-       local centroidX = ( 1 / ( 6 * area ) ) * ( getSummation( 1, #points / 2,\r
-               function( index )\r
-                       index = index * 2 - 1 -- Convert it to work properly.\r
-                       return ( ( points[index] + cycle( points, index + 2 ) ) * ( ( points[index] * cycle( points, index + 3 ) ) - ( cycle( points, index + 2 ) * points[index + 1] ) ) )\r
-               end\r
-       ) )\r
-\r
-       local centroidY = ( 1 / ( 6 * area ) ) * ( getSummation( 1, #points / 2,\r
-               function( index )\r
-                       index = index * 2 - 1 -- Convert it to work properly.\r
-                       return ( ( points[index + 1] + cycle( points, index + 3 ) ) * ( ( points[index] * cycle( points, index + 3 ) ) - ( cycle( points, index + 2 ) * points[index + 1] ) ) )\r
-               end\r
-       ) )\r
-\r
-       return centroidX, centroidY\r
-end\r
-\r
--- Returns whether or not a line intersects a polygon.\r
--- x1, y1, x2, y2, polygonPoints\r
-local function getPolygonLineIntersection( x1, y1, x2, y2, ... )\r
-       local input = checkInput( ... )\r
-       local choices = {}\r
-\r
-       local slope = getSlope( x1, y1, x2, y2 )\r
-       local intercept = getYIntercept( x1, y1, slope )\r
-\r
-       local x3, y3, x4, y4\r
-       if slope then\r
-               x3, x4 = 1, 2\r
-               y3, y4 = slope * x3 + intercept, slope * x4 + intercept\r
-       else\r
-               x3, x4 = x1, x1\r
-               y3, y4 = y1, y2\r
-       end\r
-\r
-       for i = 1, #input, 2 do\r
-               local x1, y1, x2, y2 = getLineSegmentIntersection( input[i], input[i + 1], cycle( input, i + 2 ), cycle( input, i + 3 ), x3, y3, x4, y4 )\r
-               if x1 and not x2 then choices[#choices + 1] = { x1, y1 }\r
-               elseif x1 and x2 then choices[#choices + 1] = { x1, y1, x2, y2 } end\r
-        -- No need to check 2-point sets since they only intersect each poly line once.\r
-       end\r
-\r
-       local final = removeDuplicatePairs( choices )\r
-       return #final > 0 and final or false\r
-end\r
-\r
--- Returns if the line segment intersects the polygon.\r
--- x1, y1, x2, y2, polygonPoints\r
-local function getPolygonSegmentIntersection( x1, y1, x2, y2, ... )\r
-       local input = checkInput( ... )\r
-       local choices = {}\r
-\r
-       for i = 1, #input, 2 do\r
-               local x1, y1, x2, y2 = getSegmentSegmentIntersection( input[i], input[i + 1], cycle( input, i + 2 ), cycle( input, i + 3 ), x1, y1, x2, y2 )\r
-               if x1 and not x2 then choices[#choices + 1] = { x1, y1 }\r
-               elseif x2 then choices[#choices + 1] = { x1, y1, x2, y2 } end\r
-       end\r
-\r
-       local final = removeDuplicatePairs( choices )\r
-       return #final > 0 and final or false\r
-end\r
-\r
--- Checks if the point lies INSIDE the polygon not on the polygon.\r
-local function checkPolygonPoint( px, py, ... )\r
-       local points = { unpack( checkInput( ... ) ) } -- Make a new table, as to not edit values of previous.\r
-\r
-       local greatest, least = getGreatestPoint( points, 0 )\r
-       if not isWithinBounds( least, py, greatest ) then return false end\r
-       greatest, least = getGreatestPoint( points )\r
-       if not isWithinBounds( least, px, greatest ) then return false end\r
-\r
-       local count = 0\r
-       for i = 1, #points, 2 do\r
-               if checkFuzzy( points[i + 1], py ) then\r
-                       points[i + 1] = py + .001 -- Handles vertices that lie on the point.\r
-            -- Not exactly mathematically correct, but a lot easier.\r
-               end\r
-               if points[i + 3] and checkFuzzy( points[i + 3], py ) then\r
-                       points[i + 3] = py + .001 -- Do not need to worry about alternate case, since points[2] has already been done.\r
-               end\r
-               local x1, y1 = points[i], points[i + 1]\r
-               local x2, y2 = points[i + 2] or points[1], points[i + 3] or points[2]\r
-\r
-               if getSegmentSegmentIntersection( px, py, greatest, py, x1, y1, x2, y2 ) then\r
-                       count = count + 1\r
-               end\r
-       end\r
-\r
-       return count and count % 2 ~= 0\r
-end\r
-\r
--- Returns if the line segment is fully or partially inside.\r
--- x1, y1, x2, y2, polygonPoints\r
-local function isSegmentInsidePolygon( x1, y1, x2, y2, ... )\r
-       local input = checkInput( ... )\r
-\r
-       local choices = getPolygonSegmentIntersection( x1, y1, x2, y2, input ) -- If it's partially enclosed that's all we need.\r
-       if choices then return true end\r
-\r
-       if checkPolygonPoint( x1, y1, input ) or checkPolygonPoint( x2, y2, input ) then return true end\r
-       return false\r
-end\r
-\r
--- Returns whether two polygons intersect.\r
-local function getPolygonPolygonIntersection( polygon1, polygon2 )\r
-       local choices = {}\r
-\r
-       for index1 = 1, #polygon1, 2 do\r
-               local intersections = getPolygonSegmentIntersection( polygon1[index1], polygon1[index1 + 1], cycle( polygon1, index1 + 2 ), cycle( polygon1, index1 + 3 ), polygon2 )\r
-               if intersections then\r
-                       for index2 = 1, #intersections do\r
-                               choices[#choices + 1] = intersections[index2]\r
-                       end\r
-               end\r
-       end\r
-\r
-       for index1 = 1, #polygon2, 2 do\r
-               local intersections = getPolygonSegmentIntersection( polygon2[index1], polygon2[index1 + 1], cycle( polygon2, index1 + 2 ), cycle( polygon2, index1 + 3 ), polygon1 )\r
-               if intersections then\r
-                       for index2 = 1, #intersections do\r
-                               choices[#choices + 1] = intersections[index2]\r
-                       end\r
-               end\r
-       end\r
-\r
-       choices = removeDuplicatePairs( choices )\r
-       for i = #choices, 1, -1 do\r
-               if type( choices[i][1] ) == 'table' then -- Remove co-linear pairs.\r
-                       table.remove( choices, i )\r
-               end\r
-       end\r
-\r
-       return #choices > 0 and choices\r
-end\r
-\r
--- Returns whether the circle intersects the polygon.\r
--- x, y, radius, polygonPoints\r
-local function getPolygonCircleIntersection( x, y, radius, ... )\r
-       local input = checkInput( ... )\r
-       local choices = {}\r
-\r
-       for i = 1, #input, 2 do\r
-               local Type, x1, y1, x2, y2 = getCircleSegmentIntersection( x, y, radius, input[i], input[i + 1], cycle( input, i + 2 ), cycle( input, i + 3 ) )\r
-               if x2 then\r
-                       choices[#choices + 1] = { Type, x1, y1, x2, y2 }\r
-               elseif x1 then choices[#choices + 1] = { Type, x1, y1 } end\r
-       end\r
-\r
-       local final = removeDuplicates4Points( choices )\r
-\r
-       return #final > 0 and final\r
-end\r
-\r
--- Returns whether the circle is inside the polygon.\r
--- x, y, radius, polygonPoints\r
-local function isCircleInsidePolygon( x, y, radius, ... )\r
-       local input = checkInput( ... )\r
-       return checkPolygonPoint( x, y, input )\r
-end\r
-\r
--- Returns whether the polygon is inside the polygon.\r
-local function isPolygonInsidePolygon( polygon1, polygon2 )\r
-       local bool = false\r
-       for i = 1, #polygon2, 2 do\r
-               local result = false\r
-               result = isSegmentInsidePolygon( polygon2[i], polygon2[i + 1], cycle( polygon2, i + 2 ), cycle( polygon2, i + 3 ), polygon1 )\r
-               if result then bool = true; break end\r
-       end\r
-       return bool\r
-end\r
-\r
--- Checks if a segment is completely inside a polygon\r
-local function isSegmentCompletelyInsidePolygon( x1, y1, x2, y2, ... )\r
-       local polygon = checkInput( ... )\r
-       if not checkPolygonPoint( x1, y1, polygon )\r
-       or not checkPolygonPoint( x2, y2, polygon )\r
-       or getPolygonSegmentIntersection( x1, y1, x2, y2, polygon ) then\r
-               return false\r
-       end\r
-       return true\r
-end\r
-\r
--- Checks if a polygon is completely inside another polygon\r
-local function isPolygonCompletelyInsidePolygon( polygon1, polygon2 )\r
-       for i = 1, #polygon1, 2 do\r
-               local x1, y1 = polygon1[i], polygon1[i + 1]\r
-               local x2, y2 = polygon1[i + 2] or polygon1[1], polygon1[i + 3] or polygon1[2]\r
-               if not isSegmentCompletelyInsidePolygon( x1, y1, x2, y2, polygon2 ) then\r
-                       return false\r
-               end\r
-       end\r
-       return true\r
-end\r
-\r
--------------- Circle w/ Polygons --------------\r
--- Gets if a polygon is completely within a circle\r
--- circleX, circleY, circleRadius, polygonPoints\r
-local function isPolygonCompletelyInsideCircle( circleX, circleY, circleRadius, ... )\r
-       local input = checkInput( ... )\r
-       local function isDistanceLess( px, py, x, y, circleRadius ) -- Faster, does not use math.sqrt\r
-               local distanceX, distanceY = px - x, py - y\r
-               return distanceX * distanceX + distanceY * distanceY < circleRadius * circleRadius -- Faster. For comparing distances only.\r
-       end\r
-\r
-       for i = 1, #input, 2 do\r
-               if not checkCirclePoint( input[i], input[i + 1], circleX, circleY, circleRadius ) then return false end\r
-       end\r
-       return true\r
-end\r
-\r
--- Checks if a circle is completely within a polygon\r
--- circleX, circleY, circleRadius, polygonPoints\r
-local function isCircleCompletelyInsidePolygon( circleX, circleY, circleRadius, ... )\r
-       local input = checkInput( ... )\r
-       if not checkPolygonPoint( circleX, circleY, ... ) then return false end\r
-\r
-       local rad2 = circleRadius * circleRadius\r
-\r
-       for i = 1, #input, 2 do\r
-               local x1, y1 = input[i], input[i + 1]\r
-               local x2, y2 = input[i + 2] or input[1], input[i + 3] or input[2]\r
-               if distance2( x1, y1, circleX, circleY ) <= rad2 then return false end\r
-               if getCircleSegmentIntersection( circleX, circleY, circleRadius, x1, y1, x2, y2 ) then return false end\r
-       end\r
-       return true\r
-end -- }}}\r
-\r
--- Statistics ----------------------------------- {{{\r
--- Gets the average of a list of points\r
--- points\r
-local function getMean( ... )\r
-       local input = checkInput( ... )\r
-\r
-       mean = getSummation( 1, #input,\r
-               function( i, t )\r
-                       return input[i]\r
-               end\r
-       ) / #input\r
-\r
-       return mean\r
-end\r
-\r
-local function getMedian( ... )\r
-       local input = checkInput( ... )\r
-\r
-       table.sort( input )\r
-\r
-       local median\r
-       if #input % 2 == 0 then -- If you have an even number of terms, you need to get the average of the middle 2.\r
-               median = getMean( input[#input / 2], input[#input / 2 + 1] )\r
-       else\r
-               median = input[#input / 2 + .5]\r
-       end\r
-\r
-       return median\r
-end\r
-\r
--- Gets the mode of a number.\r
-local function getMode( ... )\r
-       local input = checkInput( ... )\r
-\r
-       table.sort( input )\r
-       local sorted = {}\r
-       for i = 1, #input do\r
-               local value = input[i]\r
-               sorted[value] = sorted[value] and sorted[value] + 1 or 1\r
-       end\r
-\r
-       local occurrences, least = 0, {}\r
-       for i, value in pairs( sorted ) do\r
-               if value > occurrences then\r
-                       least = { i }\r
-                       occurrences = value\r
-               elseif value == occurrences then\r
-                       least[#least + 1] = i\r
-               end\r
-       end\r
-\r
-       if #least >= 1 then return least, occurrences\r
-       else return false end\r
-end\r
-\r
--- Gets the range of the numbers.\r
-local function getRange( ... )\r
-       local input = checkInput( ... )\r
-       local high, low = math.max( unpack( input ) ), math.min( unpack( input ) )\r
-       return high - low\r
-end\r
-\r
--- Gets the variance of a set of numbers.\r
-local function getVariance( ... )\r
-       local input = checkInput( ... )\r
-       local mean = getMean( ... )\r
-       local sum = 0\r
-       for i = 1, #input do\r
-               sum = sum + ( mean - input[i] ) * ( mean - input[i] )\r
-       end\r
-       return sum / #input\r
-end\r
-\r
--- Gets the standard deviation of a set of numbers.\r
-local function getStandardDeviation( ... )\r
-       return math.sqrt( getVariance( ... ) )\r
-end\r
-\r
--- Gets the central tendency of a set of numbers.\r
-local function getCentralTendency( ... )\r
-       local mode, occurrences = getMode( ... )\r
-       return mode, occurrences, getMedian( ... ), getMean( ... )\r
-end\r
-\r
--- Gets the variation ratio of a data set.\r
-local function getVariationRatio( ... )\r
-       local input = checkInput( ... )\r
-       local numbers, times = getMode( ... )\r
-       times = times * #numbers -- Account for bimodal data\r
-       return 1 - ( times / #input )\r
-end\r
-\r
--- Gets the measures of dispersion of a data set.\r
-local function getDispersion( ... )\r
-       return getVariationRatio( ... ), getRange( ... ), getStandardDeviation( ... )\r
-end -- }}}\r
-\r
-return {\r
-       _VERSION = 'MLib 0.10.0',\r
-       _DESCRIPTION = 'A math and shape-intersection detection library for Lua',\r
-       _URL = 'https://github.com/davisdude/mlib',\r
-    point = {\r
-        rotate = rotatePoint,\r
-        scale = scalePoint,\r
-    },\r
-       line = {\r
-               getLength = getLength,\r
-               getMidpoint = getMidpoint,\r
-               getSlope = getSlope,\r
-               getPerpendicularSlope = getPerpendicularSlope,\r
-               getYIntercept = getYIntercept,\r
-               getIntersection = getLineLineIntersection,\r
-               getClosestPoint = getClosestPoint,\r
-               getSegmentIntersection = getLineSegmentIntersection,\r
-               checkPoint = checkLinePoint,\r
-\r
-               -- Aliases\r
-               getDistance = getLength,\r
-               getCircleIntersection = getCircleLineIntersection,\r
-               getPolygonIntersection = getPolygonLineIntersection,\r
-               getLineIntersection = getLineLineIntersection,\r
-    },\r
-    segment = {\r
-        checkPoint = checkSegmentPoint,\r
-               getPerpendicularBisector = getPerpendicularBisector,\r
-        getIntersection = getSegmentSegmentIntersection,\r
-\r
-        -- Aliases\r
-        getCircleIntersection = getCircleSegmentIntersection,\r
-        getPolygonIntersection = getPolygonSegmentIntersection,\r
-        getLineIntersection = getLineSegmentIntersection,\r
-        getSegmentIntersection = getSegmentSegmentIntersection,\r
-        isSegmentCompletelyInsideCircle = isSegmentCompletelyInsideCircle,\r
-        isSegmentCompletelyInsidePolygon = isSegmentCompletelyInsidePolygon,\r
-       },\r
-       math = {\r
-               getRoot = getRoot,\r
-               isPrime = isPrime,\r
-               round = round,\r
-               getSummation =  getSummation,\r
-               getPercentOfChange = getPercentOfChange,\r
-               getPercentage = getPercentage,\r
-               getQuadraticRoots = getQuadraticRoots,\r
-               getAngle = getAngle,\r
-       },\r
-       circle = {\r
-               getArea = getCircleArea,\r
-               checkPoint = checkCirclePoint,\r
-               isPointOnCircle = isPointOnCircle,\r
-               getCircumference = getCircumference,\r
-               getLineIntersection = getCircleLineIntersection,\r
-               getSegmentIntersection = getCircleSegmentIntersection,\r
-               getCircleIntersection = getCircleCircleIntersection,\r
-               isCircleCompletelyInside = isCircleCompletelyInsideCircle,\r
-               isPolygonCompletelyInside = isPolygonCompletelyInsideCircle,\r
-               isSegmentCompletelyInside = isSegmentCompletelyInsideCircle,\r
-\r
-               -- Aliases\r
-               getPolygonIntersection = getPolygonCircleIntersection,\r
-               isCircleInsidePolygon = isCircleInsidePolygon,\r
-               isCircleCompletelyInsidePolygon = isCircleCompletelyInsidePolygon,\r
-       },\r
-       polygon = {\r
-               getSignedArea = getSignedPolygonArea,\r
-               getArea = getPolygonArea,\r
-               getTriangleHeight = getTriangleHeight,\r
-               getCentroid = getCentroid,\r
-               getLineIntersection = getPolygonLineIntersection,\r
-               getSegmentIntersection = getPolygonSegmentIntersection,\r
-               checkPoint = checkPolygonPoint,\r
-               isSegmentInside = isSegmentInsidePolygon,\r
-               getPolygonIntersection = getPolygonPolygonIntersection,\r
-               getCircleIntersection = getPolygonCircleIntersection,\r
-               isCircleInside = isCircleInsidePolygon,\r
-               isPolygonInside = isPolygonInsidePolygon,\r
-               isCircleCompletelyInside = isCircleCompletelyInsidePolygon,\r
-               isSegmentCompletelyInside = isSegmentCompletelyInsidePolygon,\r
-               isPolygonCompletelyInside = isPolygonCompletelyInsidePolygon,\r
-\r
-               -- Aliases\r
-               isCircleCompletelyOver = isPolygonCompletelyInsideCircle,\r
-       },\r
-       statistics = {\r
-               getMean = getMean,\r
-               getMedian = getMedian,\r
-               getMode = getMode,\r
-               getRange = getRange,\r
-               getVariance = getVariance,\r
-               getStandardDeviation = getStandardDeviation,\r
-               getCentralTendency = getCentralTendency,\r
-               getVariationRatio = getVariationRatio,\r
-               getDispersion = getDispersion,\r
-       },\r
-}\r
index 2d984319adb235c4fd84498b0801c3f62b370c33..d28d0027a39c4b9550d53afa441ac923c9ffb12d 100644 (file)
@@ -1,4 +1,14 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <tileset version="1.10" tiledversion="1.11.2" name="colored_packed" tilewidth="16" tileheight="16" tilecount="1078" columns="49">
  <image source="../assets/tilesets/kenney_1_bit/Tilesheet/colored_packed.png" width="784" height="352"/>
+ <tile id="49">
+  <properties>
+   <property name="wall" type="bool" value="true"/>
+  </properties>
+ </tile>
+ <tile id="50">
+  <properties>
+   <property name="wall" type="bool" value="true"/>
+  </properties>
+ </tile>
 </tileset>
index efeee1ee708eac77d17cac42d063b1db2d898023..211680375b9ee8ff14f430dcff55a6ef90c8fae4 100644 (file)
@@ -10,7 +10,7 @@ return {
   tilewidth = 16,
   tileheight = 16,
   nextlayerid = 5,
-  nextobjectid = 9,
+  nextobjectid = 10,
   properties = {},
   tilesets = {
     {
@@ -41,6 +41,48 @@ return {
       wangsets = {},
       tilecount = 1078,
       tiles = {}
+    },
+    {
+      name = "colored_packed",
+      firstgid = 1079,
+      class = "",
+      tilewidth = 16,
+      tileheight = 16,
+      spacing = 0,
+      margin = 0,
+      columns = 49,
+      image = "../assets/tilesets/kenney_1_bit/Tilesheet/colored_packed.png",
+      imagewidth = 784,
+      imageheight = 352,
+      objectalignment = "unspecified",
+      tilerendersize = "tile",
+      fillmode = "stretch",
+      tileoffset = {
+        x = 0,
+        y = 0
+      },
+      grid = {
+        orientation = "orthogonal",
+        width = 16,
+        height = 16
+      },
+      properties = {},
+      wangsets = {},
+      tilecount = 1078,
+      tiles = {
+        {
+          id = 49,
+          properties = {
+            ["wall"] = true
+          }
+        },
+        {
+          id = 50,
+          properties = {
+            ["wall"] = true
+          }
+        }
+      }
     }
   },
   layers = {
@@ -59,29 +101,31 @@ return {
       offsety = 0,
       parallaxx = 1,
       parallaxy = 1,
-      properties = {},
+      properties = {
+        ["wall"] = true
+      },
       encoding = "lua",
       data = {
-        51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
-        51, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 51,
-        51, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 51,
-        51, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 51,
-        51, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 51,
-        51, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 746, 747, 748, 1, 1, 1, 1, 1, 1, 1, 1, 51,
-        51, 1, 1, 1, 1, 1, 1, 206, 2684354765, 2684354765, 2684354765, 2684354765, 2684354765, 2684354766, 1, 1, 1, 1, 795, 796, 797, 1, 1, 1, 1, 1, 1, 1, 1, 51,
-        51, 1, 1, 1, 1, 1, 1, 205, 1, 1, 1, 1, 1, 205, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 51,
-        51, 1, 1, 1, 1, 1, 1, 205, 206, 2684354765, 2684354765, 2684354765, 2684354766, 205, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 51,
-        51, 1, 1, 1, 1, 1, 1, 205, 205, 1, 209, 1, 205, 205, 1, 1, 1, 1, 1, 1, 19, 21, 19, 21, 1, 1, 1, 1, 1, 51,
-        51, 1, 1, 1, 1, 1, 1, 205, 1610612942, 2684354765, 208, 2684354765, 3221225678, 205, 1, 1, 1, 1, 1, 1, 117, 119, 117, 119, 1, 1, 1, 1, 1, 51,
-        51, 1, 1, 1, 1, 1, 1, 205, 1, 1, 3221225677, 1, 1, 205, 1, 1, 1, 1, 1, 1, 19, 21, 19, 21, 1, 1, 1, 1, 1, 51,
-        51, 1, 1, 1, 1, 1, 1, 1610612942, 2684354765, 2684354765, 1610612943, 2684354765, 2684354765, 3221225678, 1, 1, 1, 1, 1, 1, 117, 119, 117, 119, 1, 1, 1, 1, 1, 51,
-        51, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 51,
-        51, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 51,
-        51, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 51,
-        51, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 51,
-        51, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 51,
-        51, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 51,
-        51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51
+        1129, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+        918, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 51,
+        919, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 51,
+        920, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 51,
+        921, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 51,
+        922, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 746, 747, 748, 1, 1, 1, 1, 1, 1, 1, 1, 51,
+        923, 1, 1, 1, 1, 1, 1, 206, 2684354765, 2684354765, 2684354765, 2684354765, 2684354765, 2684354766, 1, 1, 1, 1, 795, 796, 797, 1, 1, 1, 1, 1, 1, 1, 1, 51,
+        924, 1, 1, 1, 1, 1, 1, 205, 1, 1, 1, 1, 1, 205, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 51,
+        925, 1, 1, 1, 1, 1, 1, 205, 206, 2684354765, 2684354765, 2684354765, 2684354766, 205, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 51,
+        926, 1, 1, 1, 1, 1, 1, 205, 205, 1, 209, 1, 205, 205, 1, 1, 1, 1, 1, 1, 19, 21, 19, 21, 1, 1, 1, 1, 1, 51,
+        927, 1, 1, 1, 1, 1, 1, 205, 1610612942, 2684354765, 208, 2684354765, 3221225678, 205, 1, 1, 1, 1, 1, 1, 117, 119, 117, 119, 1, 1, 1, 1, 1, 51,
+        928, 1, 1, 1, 1, 1, 1, 205, 1, 1, 3221225677, 1, 1, 205, 1, 1, 1, 1, 1, 1, 19, 21, 19, 21, 1, 1, 1, 1, 1, 51,
+        1129, 1, 1, 1, 1, 1, 1, 1610612942, 2684354765, 2684354765, 1610612943, 2684354765, 2684354765, 3221225678, 1, 1, 1, 1, 1, 1, 117, 119, 117, 119, 1, 1, 1, 1, 1, 51,
+        1129, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 51,
+        1129, 1, 1129, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 51,
+        1129, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 51,
+        1129, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 51,
+        1129, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 51,
+        1129, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 51,
+        1129, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51
       }
     },
     {
@@ -111,20 +155,6 @@ return {
           gid = 515,
           visible = true,
           properties = {}
-        },
-        {
-          id = 8,
-          name = "",
-          type = "",
-          shape = "rectangle",
-          x = 128,
-          y = 64,
-          width = 16,
-          height = 16,
-          rotation = 0,
-          gid = 515,
-          visible = true,
-          properties = {}
         }
       }
     }
index d8d9090b7b5260c718709e64899c72c2bddf2028..8ca1effb69f2bd85bde32cc2e93405fc109d43ad 100644 (file)
@@ -6,9 +6,25 @@
  <tileset firstgid="1" name="colored_packed" tilewidth="16" tileheight="16" tilecount="1078" columns="49">
   <image source="../assets/tilesets/kenney_1_bit/Tilesheet/colored_packed.png" width="784" height="352"/>
  </tileset>
+ <tileset firstgid="1079" name="colored_packed" tilewidth="16" tileheight="16" tilecount="1078" columns="49">
+  <image source="../assets/tilesets/kenney_1_bit/Tilesheet/colored_packed.png" width="784" height="352"/>
+  <tile id="49">
+   <properties>
+    <property name="wall" type="bool" value="true"/>
+   </properties>
+  </tile>
+  <tile id="50">
+   <properties>
+    <property name="wall" type="bool" value="true"/>
+   </properties>
+  </tile>
+ </tileset>
  <layer id="1" name="Tile Layer 1" width="30" height="20">
+  <properties>
+   <property name="wall" type="bool" value="true"/>
+  </properties>
   <data encoding="csv">
-51,869,870,871,872,873,874,875,876,877,878,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,
+1129,869,870,871,872,873,874,875,876,877,878,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,
 918,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,51,
 919,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,51,
 920,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,51,
 926,1,1,1,1,1,1,205,205,1,209,1,205,205,1,1,1,1,1,1,19,21,19,21,1,1,1,1,1,51,
 927,1,1,1,1,1,1,205,1610612942,2684354765,208,2684354765,3221225678,205,1,1,1,1,1,1,117,119,117,119,1,1,1,1,1,51,
 928,1,1,1,1,1,1,205,1,1,3221225677,1,1,205,1,1,1,1,1,1,19,21,19,21,1,1,1,1,1,51,
-51,1,1,1,1,1,1,1610612942,2684354765,2684354765,1610612943,2684354765,2684354765,3221225678,1,1,1,1,1,1,117,119,117,119,1,1,1,1,1,51,
-51,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,51,
-51,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,51,
-51,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,51,
-51,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,51,
-51,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,51,
-51,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,51,
-51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51
+1129,1,1,1,1,1,1,1610612942,2684354765,2684354765,1610612943,2684354765,2684354765,3221225678,1,1,1,1,1,1,117,119,117,119,1,1,1,1,1,51,
+1129,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,51,
+1129,1,1129,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,51,
+1129,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,51,
+1129,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,51,
+1129,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,51,
+1129,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,51,
+1129,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51
 </data>
  </layer>
  <objectgroup id="2" name="Object Layer 1">