diff --git a/sonic-bluestreak.love/birb/modules/world/world3D.lua b/sonic-bluestreak.love/birb/modules/world/world3D.lua index 42ee40b..01fda9b 100644 --- a/sonic-bluestreak.love/birb/modules/world/world3D.lua +++ b/sonic-bluestreak.love/birb/modules/world/world3D.lua @@ -80,7 +80,7 @@ function World3D:getVisibleActors(id) actors = self:getActors() end - actors = self:zSortItems(actors) + actors = self:ySortItems(actors) return actors end @@ -182,6 +182,79 @@ end -- DRAW FUNCTIONS -- Functions to draw the world +function World3D:ySortItems(items) + -- zSorting algorithm taken from bump3D example, adapted to gamecore. + local graph = Tsort.new() + local noOverlap = {} + + -- Iterate through all visible items, and calculate ordering of all pairs + -- of overlapping items. + for _, itemA in ipairs(items) do repeat + local x, y, w, h = self.shapes:getRect(itemA) + local otherItemsFilter = function(other) return other ~= itemA end + local overlapping, len = self.shapes:queryRect(x, y, w, h, otherItemsFilter) + + if len == 0 then + table.insert(noOverlap, itemA) + + break + end + + local _, aY, aZ, _, aH, aD = self.bodies:getCube(itemA.mainHitbox) + local aDepth, aID, aType + aDepth = itemA.depth + aID = itemA.creationID + aType = itemA.type + aZ = math.ceil(aZ) + aY = math.ceil(aY) + + for _, itemB in ipairs(overlapping) do + local _, bY, bZ, _, bH, bD = self.bodies:getCube(itemB.mainHitbox) + local bDepth, bID, bType + bDepth = itemB.depth + bID = itemB.creationID + bType = itemB.type + bZ = math.ceil(bZ) + bY = math.ceil(bY) + + if aY < bY then + -- item A is completely behind item B + graph:add(itemA, itemB) + elseif bY < aY then + -- item B is completely behind item A + graph:add(itemB, itemA) + else + -- item A's forward-most point is the same than item B's forward-most point + if aDepth > bDepth then + graph:add(itemB, itemA) + elseif aDepth < bDepth then + graph:add(itemA, itemB) + else + if aID > bID then + graph:add(itemA, itemB) + elseif aID < bID then + graph:add(itemB, itemA) + else + error("two object can't have the same ID") + end + end + end + end + until true end + + local sorted, err = graph:sort() + if err then + error(err) + end + for _, item in ipairs(noOverlap) do + table.insert(sorted, item) + end + + return sorted + +end + + function World3D:zSortItems(items) -- zSorting algorithm taken from bump3D example, adapted to gamecore. local graph = Tsort.new() @@ -189,7 +262,6 @@ function World3D:zSortItems(items) -- Iterate through all visible items, and calculate ordering of all pairs -- of overlapping items. - -- TODO: Each pair is calculated twice currently. Maybe this is slow? for _, itemA in ipairs(items) do repeat local x, y, w, h = self.shapes:getRect(itemA) local otherItemsFilter = function(other) return other ~= itemA end