feat(actor3D): add zSorting support
This commit is contained in:
parent
5bdb275b8a
commit
c043bb8ecf
1 changed files with 88 additions and 11 deletions
|
@ -29,6 +29,7 @@ local World3D = BaseWorld:extend()
|
|||
local Sti = require(cwd .. "libs.sti")
|
||||
local Bump = require(cwd .. "libs.bump")
|
||||
local Bump3D = require(cwd .. "libs.bump-3dpd")
|
||||
local Tsort = require(cwd .. "libs.tsort")
|
||||
local CameraSystem = require(cwd .. "camera")
|
||||
|
||||
local PADDING_VALUE = 10/100
|
||||
|
@ -79,17 +80,7 @@ function BaseWorld:getVisibleActors(id)
|
|||
actors = self:getActors()
|
||||
end
|
||||
|
||||
table.sort(actors, function(a,b)
|
||||
if (a.y == b.y) then
|
||||
if (a.depth == b.depth) then
|
||||
return a.creationID < b.creationID
|
||||
else
|
||||
return a.depth > b.depth
|
||||
end
|
||||
else
|
||||
return a.y < b.y
|
||||
end
|
||||
end)
|
||||
actors = self:zSortItems(actors)
|
||||
|
||||
return actors
|
||||
end
|
||||
|
@ -199,4 +190,90 @@ function World3D:getShapeInRect(x, y, w, h)
|
|||
return self.shapes:queryRect(x, y, w, h)
|
||||
end
|
||||
|
||||
-- DRAW FUNCTIONS
|
||||
-- Functions to draw the world
|
||||
|
||||
function World3D:zSortItems(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.
|
||||
-- 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
|
||||
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)
|
||||
aDepth = itemA.depth
|
||||
aID = itemA.id
|
||||
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)
|
||||
bDepth = itemB.depth
|
||||
bID = itemB.id
|
||||
bType = itemB.type
|
||||
bZ = math.ceil(bZ)
|
||||
bY = math.ceil(bY)
|
||||
|
||||
if aZ >= bZ + bD then
|
||||
-- item A is completely above item B
|
||||
graph:add(itemB, itemA)
|
||||
elseif bZ >= aZ + aD then
|
||||
-- item B is completely above item A
|
||||
graph:add(itemA, itemB)
|
||||
elseif aY + aH <= bY then
|
||||
-- item A is completely behind item B
|
||||
graph:add(itemA, itemB)
|
||||
elseif bY + bH <= aY then
|
||||
-- item B is completely behind item A
|
||||
graph:add(itemB, itemA)
|
||||
elseif (aY - aZ) + aH > (bY - bZ) + bH then
|
||||
-- item A's forward-most point is in front of item B's forward-most point
|
||||
graph:add(itemB, itemA)
|
||||
elseif (aY - aZ) + aH < (bY - bZ) + bH then
|
||||
-- item B's forward-most point is in front of item A's forward-most point
|
||||
graph:add(itemA, itemB)
|
||||
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
|
||||
err("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
|
||||
|
||||
return World3D
|
||||
|
|
Loading…
Reference in a new issue