diff --git a/lib/annotations.lua b/lib/annotations.lua index 9753b5d..944093b 100644 --- a/lib/annotations.lua +++ b/lib/annotations.lua @@ -4,3 +4,4 @@ Tree.behaviors.spellcaster = require "lib.character.behaviors.spellcaster" Tree.behaviors.sprite = require "lib.character.behaviors.sprite" Tree.behaviors.stats = require "lib.character.behaviors.stats" Tree.behaviors.residentsleeper = require "lib.character.behaviors.residentsleeper" +Tree.behaviors.shadowcaster = require "lib.character.behaviors.shadowcaster" diff --git a/lib/character/behaviors/shadowcaster.lua b/lib/character/behaviors/shadowcaster.lua index e69de29..687078e 100644 --- a/lib/character/behaviors/shadowcaster.lua +++ b/lib/character/behaviors/shadowcaster.lua @@ -0,0 +1,98 @@ +--- @class ShadowcasterBehavior : Behavior +local behavior = {} +behavior.id = "shadowcaster" +behavior.__index = behavior + +function behavior.new() return setmetatable({}, behavior) end + +local function makeGradientMesh(w, h, topColor, bottomColor) + local vertices = { + { 0, 0, 0, 0, topColor[1], topColor[2], topColor[3], topColor[4] }, -- левый верх + { w, 0, 1, 0, topColor[1], topColor[2], topColor[3], topColor[4] }, -- правый верх + { w + w * 0.1, h, 1, 1, bottomColor[1], bottomColor[2], bottomColor[3], bottomColor[4] }, -- правый низ + { 0 - w * 0.1, h, 0, 1, bottomColor[1], bottomColor[2], bottomColor[3], bottomColor[4] }, -- левый низ + } + local mesh = love.graphics.newMesh(vertices, "fan", "static") + return mesh +end + +local function getFakeShadow(r) + local pi = math.pi + + if r <= pi / 4 then + -- 1 + return false, 1 + end + if r <= pi / 2 then + -- 2 + return true, 1 - (r - pi / 4) / (pi / 4) + end + if r <= 3 * pi / 4 then + -- 3 + return true, (r - pi / 2) / (pi / 4) + end + if r <= 5 * pi / 4 then + -- 4 + return false, 1 + end + if r <= 3 * pi / 2 then + -- 5 + return true, 1 - (r - 5 * pi / 4) / (pi / 4) + end + if r <= 7 * pi / 4 then + -- 6 + return true, (r - 3 * pi / 2) / (pi / 4) + end + -- 1 + return false, 1 +end + +function behavior:draw() + local sprite = self.owner:has(Tree.behaviors.sprite) + local map = self.owner:has(Tree.behaviors.map) + if not map then return end + + local ppm = Tree.level.camera.pixelsPerMeter + local position = map.displayedPosition + Vec3 { 0.5, 0.5 } + + love.graphics.setCanvas(Tree.level.render.shadowLayer) + love.graphics.push() + love.graphics.scale(ppm) + love.graphics.setColor(0, 0, 0, 0.5) + love.graphics.translate(position.x, position.y) + love.graphics.ellipse("fill", 0, 0, 0.2, 0.2 * math.cos(math.pi / 4)) + + if not sprite then + love.graphics.pop() + return + end + + local r = love.timer.getTime() % (2 * math.pi) + + local drawFakeShadow, opacity = getFakeShadow(r) + local nangle = (math.pi + r) % (2 * math.pi) + love.graphics.rotate(nangle) + + love.graphics.setColor(0, 0, 0, math.min(opacity * opacity, 0.5)) + sprite.animationTable[sprite.state]:draw(Tree.assets.files.sprites.character[sprite.state], + 0, + 0, nil, ((nangle >= math.pi / 2 and nangle < (3 * math.pi / 2)) and -1 or 1) / ppm * sprite.side, + 1.2 / ppm, + 38, 47) + + if drawFakeShadow then + love.graphics.setColor(0, 0, 0, 1) + local mesh = makeGradientMesh(0.4, 1, { 0, 0, 0, 0.15 }, + { 0, 0, 0, 0.0 }) + love.graphics.push() + love.graphics.rotate(math.pi) + love.graphics.translate(-0.2, 0) + love.graphics.draw(mesh) + love.graphics.pop() + end + love.graphics.pop() + love.graphics.setColor(1, 1, 1) + love.graphics.setCanvas() +end + +return behavior diff --git a/lib/character/behaviors/sprite.lua b/lib/character/behaviors/sprite.lua index 2a9ac84..32ac8e0 100644 --- a/lib/character/behaviors/sprite.lua +++ b/lib/character/behaviors/sprite.lua @@ -38,17 +38,6 @@ function sprite:update(dt) anim:update(dt) end -local function makeGradientMesh(w, h, topColor, bottomColor) - local vertices = { - { 0, 0, 0, 0, topColor[1], topColor[2], topColor[3], topColor[4] }, -- левый верх - { w, 0, 1, 0, topColor[1], topColor[2], topColor[3], topColor[4] }, -- правый верх - { w + w * 0.1, h, 1, 1, bottomColor[1], bottomColor[2], bottomColor[3], bottomColor[4] }, -- правый низ - { 0 - w * 0.1, h, 0, 1, bottomColor[1], bottomColor[2], bottomColor[3], bottomColor[4] }, -- левый низ - } - local mesh = love.graphics.newMesh(vertices, "fan", "static") - return mesh -end - function sprite:draw() if not self.animationTable[self.state] or not Tree.assets.files.sprites.character[self.state] then return end @@ -57,71 +46,9 @@ function sprite:draw() local ppm = Tree.level.camera.pixelsPerMeter local position = map.displayedPosition + Vec3 { 0.5, 0.5 } - Tree.level.camera:detach() - love.graphics.push() - love.graphics.scale(ppm) - love.graphics.setCanvas(Tree.level.render.shadowLayer) - love.graphics.setColor(0, 0, 0, 0.5) - love.graphics.translate(position.x, position.y) - love.graphics.ellipse("fill", 0, 0, 0.2, 0.2 * math.cos(math.pi / 4)) - - local r = love.timer.getTime() % (2 * math.pi) - local doWeUseFakeShadow = function(r) - local pi = math.pi - - if r <= pi / 4 then - -- 1 - return false, 1 - end - if r <= pi / 2 then - -- 2 - return true, 1 - (r - pi / 4) / (pi / 4) - end - if r <= 3 * pi / 4 then - -- 3 - return true, (r - pi / 2) / (pi / 4) - end - if r <= 5 * pi / 4 then - -- 4 - return false, 1 - end - if r <= 3 * pi / 2 then - -- 5 - return true, 1 - (r - 5 * pi / 4) / (pi / 4) - end - if r <= 7 * pi / 4 then - -- 6 - return true, (r - 3 * pi / 2) / (pi / 4) - end - -- 1 - return false, 1 - end - - local drawFakeShadow, opacity = doWeUseFakeShadow(r) - local nangle = (math.pi + r) % (2 * math.pi) - love.graphics.rotate(nangle) - - love.graphics.setColor(0, 0, 0, math.min(opacity * opacity, 0.5)) - self.animationTable[self.state]:draw(Tree.assets.files.sprites.character[self.state], - 0, - 0, nil, ((nangle >= math.pi / 2 and nangle < (3 * math.pi / 2)) and -1 or 1) / ppm * self.side, - 1.2 / ppm, - 38, 47) - - if drawFakeShadow then - love.graphics.setColor(0, 0, 0, 1) - local mesh = makeGradientMesh(0.4, 1, { 0, 0, 0, 0.15 }, - { 0, 0, 0, 0.0 }) - love.graphics.push() - love.graphics.rotate(math.pi) - love.graphics.translate(-0.2, 0) - love.graphics.draw(mesh) - love.graphics.pop() - end - love.graphics.pop() - - Tree.level.camera:attach() love.graphics.setCanvas(Tree.level.render.spriteLayer) + Tree.level.camera:attach() + love.graphics.setColor(1, 1, 1) if Tree.level.selector.id == self.owner.id then local texW, texH = Tree.assets.files.sprites.character[self.state]:getWidth(), @@ -134,7 +61,9 @@ function sprite:draw() self.animationTable[self.state]:draw(Tree.assets.files.sprites.character[self.state], position.x, position.y, nil, 1 / ppm * self.side, 1 / ppm, 38, 47) + love.graphics.setShader() + Tree.level.camera:detach() love.graphics.setCanvas() end ) diff --git a/lib/character/character.lua b/lib/character/character.lua index bde0c2c..b5344ba 100644 --- a/lib/character/character.lua +++ b/lib/character/character.lua @@ -31,6 +31,7 @@ local function spawn(name, spriteDir, position, size, initiative) Tree.behaviors.stats.new(nil, nil, initiative), Tree.behaviors.map.new(position, size), Tree.behaviors.sprite.new(spriteDir), + Tree.behaviors.shadowcaster.new(), Tree.behaviors.spellcaster.new() } diff --git a/lib/level/grid/tile_grid.lua b/lib/level/grid/tile_grid.lua index 2625b5b..2294e33 100644 --- a/lib/level/grid/tile_grid.lua +++ b/lib/level/grid/tile_grid.lua @@ -14,9 +14,11 @@ end function map:draw() love.graphics.setCanvas(Tree.level.render.floorLayer) + Tree.level.camera:attach() utils.each(self.__grid, function(el) el:draw() end) + Tree.level.camera:detach() love.graphics.setCanvas() end diff --git a/lib/level/level.lua b/lib/level/level.lua index 2f92129..1d8cf96 100644 --- a/lib/level/level.lua +++ b/lib/level/level.lua @@ -41,15 +41,11 @@ function level:update(dt) end function level:draw() - self.camera:attach() self.render:clear() self.tileGrid:draw() while not self.characterGrid.yOrderQueue:is_empty() do -- по сути это сортировка кучей за n log n self.characterGrid.yOrderQueue:pop():draw() end - self.camera:detach() - --self.render.shadowLayer:newImageData():encode("png", "shadowLayer.png") - -- os.exit(0) self.render:draw() end diff --git a/lib/spellbook.lua b/lib/spellbook.lua index 7130f25..11160f1 100644 --- a/lib/spellbook.lua +++ b/lib/spellbook.lua @@ -68,12 +68,14 @@ end function walk:draw() if not self.path then return end --- Это отрисовка пути персонажа к мышке + Tree.level.camera:attach() love.graphics.setCanvas(Tree.level.render.overlayLayer) love.graphics.setColor(0.6, 0.75, 0.5) for p in self.path:values() do love.graphics.circle("fill", p.x + 0.45, p.y + 0.45, 0.1) end love.graphics.setCanvas() + Tree.level.camera:detach() love.graphics.setColor(1, 1, 1) end