From 05a8b71180aeabf703a0c1fba1916787d1e3e5ac Mon Sep 17 00:00:00 2001 From: Kazhnuz Date: Fri, 7 May 2021 19:14:13 +0200 Subject: [PATCH] chore: extract shapes from actor3D --- .../birb/modules/world/actors/actor3D.lua | 71 +------------- .../modules/world/actors/mixins/shapes.lua | 97 +++++++++++++++++++ 2 files changed, 102 insertions(+), 66 deletions(-) create mode 100644 sonic-radiance.love/birb/modules/world/actors/mixins/shapes.lua diff --git a/sonic-radiance.love/birb/modules/world/actors/actor3D.lua b/sonic-radiance.love/birb/modules/world/actors/actor3D.lua index d1e93d2..af89ada 100644 --- a/sonic-radiance.love/birb/modules/world/actors/actor3D.lua +++ b/sonic-radiance.love/birb/modules/world/actors/actor3D.lua @@ -30,6 +30,7 @@ local SpritedActor = require("birb.modules.world.actors.mixins.sprites") local TimedActor = require("birb.modules.world.actors.mixins.timers") local InputActor = require("birb.modules.world.actors.mixins.inputs") local PhysicalActor = require("birb.modules.world.actors.mixins.physics") +local Shape3DActor = require("birb.modules.world.actors.mixins.shapes") local Actor3D = Object:extend() Actor3D:implement(BaseActor) @@ -37,6 +38,7 @@ Actor3D:implement(SpritedActor) Actor3D:implement(TimedActor) Actor3D:implement(InputActor) Actor3D:implement(PhysicalActor) +Actor3D:implement(Shape3DActor) -- INIT FUNCTIONS -- Initialise the actor and its base functions @@ -47,20 +49,13 @@ function Actor3D:new(world, type, x, y, z, w, h, d, isSolid) self:initTimers() self:initSprite() self:initKeys() - - self.world:registerShape(self) - self.boxes = Boxes - self.doCastShadows = true + self:initShape(Boxes, true) end function Actor3D:destroy() - self:removeOldShadowTargets() - if self.box ~= nil then - self.world:removeTerrain(self) - end - self.world:removeActor(self) + self:destroyShape() self.mainHitbox:destroy() - self.world:removeShape(self) + self.world:removeActor(self) self.isDestroyed = true end @@ -157,62 +152,6 @@ function Actor3D:packForHitbox() return {0, 0, 0, self.w, self.h, self.d} end --- SHADOW FUNCTIONS --- Handle everything related to shadow - -function Actor3D:castShadow() - local shadowTargets = self.world:getTerrainInRect(self.x, self.y, self.w, self.d) - -- initialize the shadowTargetsPrevious variable if it doesn't exist - if (self.shadowTargetsPrevious == nil) then - self.shadowTargetsPrevious = {} - end - - for i, target in ipairs(shadowTargets) do - -- We test if the actor is below the current actor - if (target ~= self) and (target.box ~= nil) then - - if (target.z + target.d <= self.z + self.d) then - -- Remove the target of the list of item targeted last update, - -- in order to only have object no longer shadowed after the - -- end of the loop - for j, oldtarget in ipairs(self.shadowTargetsPrevious) do - if (target == oldtarget) then - table.remove(self.shadowTargetsPrevious, j) - end - end - - -- We update the shadow source - local x, y = math.floor(self.x - target.x), math.floor(self.y - target.y) - target.box:setShadowSource(self, x, y) - end - - end - - end - - -- At this point, if a target is still in the shadowTargetsPrevious list, - -- it mean that it's not shadowed. So we can simply remove the shadow. - self:removeOldShadowTargets() - - self.shadowTargetsPrevious = shadowTargets -end - -function Actor3D:removeOldShadowTargets() - if (self.shadowTargetsPrevious ~= nil) then - for i, target in ipairs(self.shadowTargetsPrevious) do - if (target.box ~= nil) then - target.box:removeShadowSource(self) - end - end - end -end - -function Actor3D:redrawShadowCanvas() - if (self.box ~= nil) then - self.box:redrawShadowCanvas() - end -end - -- DRAW FUNCTIONS -- Draw the actors. diff --git a/sonic-radiance.love/birb/modules/world/actors/mixins/shapes.lua b/sonic-radiance.love/birb/modules/world/actors/mixins/shapes.lua new file mode 100644 index 0000000..05a1d21 --- /dev/null +++ b/sonic-radiance.love/birb/modules/world/actors/mixins/shapes.lua @@ -0,0 +1,97 @@ +-- ShapedActor.lua :: Handle the shape of a 2.5D actor. +-- It handle terrain box, and shadows + +--[[ + Copyright © 2019 Kazhnuz + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal in + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + the Software, and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +]] + +local ShapedActor = Object:extend() + +function ShapedActor:initShape(boxObj, doCastShadows) + self.world:registerShape(self) + self.boxes = boxObj + self.doCastShadows = doCastShadows +end + +function ShapedActor:destroyShape() + self:removeOldShadowTargets() + if self.box ~= nil then + self.world:removeTerrain(self) + end + self.world:removeShape(self) +end + +-- SHADOW FUNCTIONS +-- Handle everything related to shadow + +function ShapedActor:castShadow() + local shadowTargets = self.world:getTerrainInRect(self.x, self.y, self.w, self.d) + -- initialize the shadowTargetsPrevious variable if it doesn't exist + if (self.shadowTargetsPrevious == nil) then + self.shadowTargetsPrevious = {} + end + + for i, target in ipairs(shadowTargets) do + -- We test if the actor is below the current actor + if (target ~= self) and (target.box ~= nil) then + + if (target.z + target.d <= self.z + self.d) then + -- Remove the target of the list of item targeted last update, + -- in order to only have object no longer shadowed after the + -- end of the loop + for j, oldtarget in ipairs(self.shadowTargetsPrevious) do + if (target == oldtarget) then + table.remove(self.shadowTargetsPrevious, j) + end + end + + -- We update the shadow source + local x, y = math.floor(self.x - target.x), math.floor(self.y - target.y) + target.box:setShadowSource(self, x, y) + end + + end + + end + + -- At this point, if a target is still in the shadowTargetsPrevious list, + -- it mean that it's not shadowed. So we can simply remove the shadow. + self:removeOldShadowTargets() + + self.shadowTargetsPrevious = shadowTargets +end + +function ShapedActor:removeOldShadowTargets() + if (self.shadowTargetsPrevious ~= nil) then + for i, target in ipairs(self.shadowTargetsPrevious) do + if (target.box ~= nil) then + target.box:removeShadowSource(self) + end + end + end +end + +function ShapedActor:redrawShadowCanvas() + if (self.box ~= nil) then + self.box:redrawShadowCanvas() + end +end + +return ShapedActor