feat(world): add zSorting

Fixes #73
This commit is contained in:
Kazhnuz 2024-11-05 21:03:13 +01:00
parent 02f765dda0
commit ced3ae0993
4 changed files with 82 additions and 3 deletions

View file

@ -39,6 +39,7 @@ function Actor:new(world, position)
self:_initVisual(self.def.visuals or {})
self.isDestroyed = false
self.depth = self.def.depth or 0
self.timers = TweenManager(self)

View file

@ -37,6 +37,8 @@ local Vector3D = require "framework.libs.brinevector3D"
local GFX = require "framework.scenes.world.actors.gfx"
local comparisons = require "framework.scenes.world.zsort"
local function _tryFunction(toUpdate, dt, func)
if (toUpdate ~= nil) then
func(dt)
@ -63,11 +65,21 @@ function World:new(datas)
self.type = self.def.type or "2D"
self.drawShadow = (self.def.drawShadow == true)
self.currentCreationID = 0
World.super.new(self)
self:_setSorting()
self:_load()
end
function World:_setSorting()
self.sort = comparisons.depthSort
if self.type == "3D" then
self.sort = comparisons.zSort
end
end
function World:onLoad()
end
@ -229,16 +241,23 @@ function World:newActor(name, x, y, z, properties, mapname)
end
function World:showGFX(effect, position, useMiddle)
table.insert(self.actors, GFX(self, position, effect, false, (useMiddle == true)))
local gfx = GFX(self, position, effect, false, (useMiddle == true))
gfx.creationID = self.currentCreationID
self.currentCreationID = self.currentCreationID + 1
table.insert(self.actors, gfx)
end
function World:addActor(name, position)
local Actor = self:_getActorObject(name)
if (name == "player") then
self.player = Actor(self, position)
self.player.creationID = self.currentCreationID
else
table.insert(self.actors, Actor(self, position))
local actor = Actor(self, position)
table.insert(self.actors, actor)
actor.creationID = self.currentCreationID
end
self.currentCreationID = self.currentCreationID + 1
end
function World:removeActor(actor)
@ -309,7 +328,10 @@ function World:getBodiesInCube(x, y, z, w, h, d)
-- Handle shapes, which make know what object is visible or not
function World:addTerrain(body)
self:registerShape(Terrain(self, body.position, body.dimensions))
local terrain = Terrain(self, body.position, body.dimensions)
terrain.creationID = self.currentCreationID
self.currentCreationID = self.currentCreationID + 1
self:registerShape(terrain)
end
function World:registerShape(actor)
@ -337,6 +359,7 @@ end
function World:drawShapes()
local position, dimensions = self.camera:getViewCoordinate()
local shapes = self:getShapeInRect(position, dimensions)
table.sort(shapes, self.sort)
for _, shape in ipairs(shapes) do
shape:draw()
end

View file

@ -27,6 +27,7 @@ local Vector3D = require "framework.libs.brinevector3D"
function MappedBox:new(world, position, dimensions)
self.world = world
self.position = Vector3D(position.x, position.y, position.z or 0)
self.depth = -1
MappedBox.super.new(self, dimensions)
self.haveLine = false

View file

@ -0,0 +1,54 @@
local comparisons = {}
function comparisons.depthSort(itemA, itemB)
local aDepth, aID = itemA.depth, itemA.creationID
local bDepth, bID = itemB.depth, itemB.creationID
local comparison = 0
if aDepth > bDepth then
comparison = 1
elseif aDepth < bDepth then
comparison = -1
else
if aID > bID then
comparison = 1
elseif aID < bID then
comparison = -1
end
end
return comparison == -1
end
function comparisons.zSort(itemA, itemB)
local aY, aZ, aH, aD = itemA.position.y, itemA.position.z, itemA.dimensions.h, itemA.dimensions.d
local bY, bZ,bH, bD = itemB.position.y, itemB.position.z, itemB.dimensions.h, itemB.dimensions.d
local comparison = 0
if aY + aH <= bY then
-- item A is completely behind item B
comparison = -1
elseif bY + bH <= aY then
-- item B is completely behind item A
comparison = 1
elseif aZ >= bZ + bD then
-- item A is completely above item B
comparison = 1
elseif bZ >= aZ + aD then
-- item B is completely above item A
comparison = -1
elseif aY + aH > bY + bH then --(aY - aZ) + aH > (bY - bZ) + bH then
-- item A's forward-most point is in front of item B's forward-most point
comparison = 1
elseif aY + aH < bY + bH then --aY < (bY - bZ) + bH then
-- item B's forward-most point is in front of item A's forward-most point
comparison = -1
else
-- item A's forward-most point is the same than item B's forward-most point
return comparisons.depthSort(itemA, itemB)
end
return comparison == -1
end
return comparisons