diff --git a/birb/modules/world/actors/actor3D.lua b/birb/modules/world/actors/actor3D.lua index c9941dd..a101ee9 100644 --- a/birb/modules/world/actors/actor3D.lua +++ b/birb/modules/world/actors/actor3D.lua @@ -28,6 +28,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) @@ -35,6 +36,7 @@ Actor3D:implement(SpritedActor) Actor3D:implement(TimedActor) Actor3D:implement(InputActor) Actor3D:implement(PhysicalActor) +Actor3D:implement(Shape3DActor) local Hitbox = require(cwd .. "utils.hitbox3D") local Boxes = require(cwd .. "utils.boxes") @@ -47,19 +49,13 @@ function Actor3D:new(world, type, x, y, z, w, h, d, isSolid) self:initPhysics(Hitbox, x, y, z, w, h, d, isSolid) self:initTimers() self:initSprite() - 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 @@ -154,62 +150,6 @@ function Actor3D:getViewCenter() return x, y - (self.d/2) 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/birb/modules/world/actors/mixins/shapes.lua b/birb/modules/world/actors/mixins/shapes.lua new file mode 100644 index 0000000..9bd7f5a --- /dev/null +++ b/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 \ No newline at end of file