- add boar

- implement manifests for sprites
- fix sprite and shadowcaster draw algorithm
This commit is contained in:
PeaAshMeter 2026-04-13 03:20:50 +03:00
parent 36271b447c
commit 4761446e73
12 changed files with 51 additions and 17 deletions

View File

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

View File

@ -0,0 +1,9 @@
return {
width = 32,
height = 32,
base = {
x = 14,
y = 26
},
size = 0.6 -- условная доля тайла, которую занимает спрайт
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -0,0 +1,9 @@
return {
width = 96,
height = 64,
base = {
x = 38,
y = 47
},
size = 0.4 -- условная доля тайла, которую занимает спрайт
}

View File

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -10,6 +10,10 @@ function behavior:draw()
local sprite = self.owner:has(Tree.behaviors.sprite)
local positioned = self.owner:has(Tree.behaviors.positioned)
if not positioned then return end
if not sprite then
love.graphics.setCanvas()
return
end
local ppm = Tree.level.camera.pixelsPerMeter
local position = positioned.position + Vec3 { 0.5, 0.5 }
@ -21,18 +25,16 @@ function behavior:draw()
table.insert(lights, Tree.level.characters[id])
end
Tree.level.camera:attach()
love.graphics.setCanvas(Tree.level.render.textures.shadowLayer)
love.graphics.push()
love.graphics.setColor(0, 0, 0, 1)
love.graphics.translate(position.x, position.y)
love.graphics.ellipse("fill", 0, 0, 0.2, 0.2 * math.cos(math.pi / 4))
love.graphics.ellipse("fill", 0, 0, sprite.manifest.size / 2, sprite.manifest.size / 2 * math.cos(math.pi / 4))
love.graphics.pop()
if not sprite then
love.graphics.setCanvas()
return
end
love.graphics.setCanvas(Tree.level.render.textures.spriteLightLayer)
love.graphics.setBlendMode("add")
@ -49,9 +51,9 @@ function behavior:draw()
(1 - easing.easeInSine((position.y - lightPos.y))) - 0.3 * lightVec:length())
end
sprite.animationTable[sprite.state]:draw(Tree.assets.files.sprites.character[sprite.state],
sprite.animationTable[sprite.state]:draw(sprite.sheets[sprite.state],
position.x,
position.y, nil, 1 / ppm * sprite.side, 1 / ppm, 38, 47)
position.y, nil, 1 / ppm * sprite.side, 1 / ppm, sprite.manifest.base.x, sprite.manifest.base.y)
end
love.graphics.setBlendMode("alpha")

View File

@ -3,6 +3,8 @@ local anim8 = require "lib.utils.anim8"
--- @class SpriteBehavior : Behavior
--- @field animationTable table<string, table>
--- @field animationGrid table
--- @field manifest table
--- @field sheets table
--- @field state "idle"|"run"|"hurt"|"attack"
--- @field side 1|-1
local sprite = {}
@ -17,11 +19,12 @@ function sprite.new(spriteDir)
local anim = setmetatable({}, sprite)
anim.animationTable = {}
anim.animationGrid = {}
anim.manifest = spriteDir.manifest
anim.sheets = spriteDir.sheets
-- n: name; i: image
for n, i in pairs(spriteDir) do
local aGrid = anim8.newGrid(96, 64, i:getWidth(), i:getHeight())
local tiles = '1-' .. math.ceil(i:getWidth() / 96)
for n, i in pairs(spriteDir.sheets) do
local aGrid = anim8.newGrid(anim.manifest.width, anim.manifest.height, i:getWidth(), i:getHeight())
local tiles = '1-' .. math.ceil(i:getWidth() / anim.manifest.width)
anim.animationGrid[n] = aGrid(tiles, 1)
end
@ -39,7 +42,7 @@ function sprite:update(dt)
end
function sprite:draw()
if not self.animationTable[self.state] or not Tree.assets.files.sprites.character[self.state] then return end
if not self.animationTable[self.state] or not self.sheets[self.state] then return end
self.owner:try(Tree.behaviors.positioned,
function(pos)
@ -51,16 +54,16 @@ function sprite:draw()
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(),
Tree.assets.files.sprites.character[self.state]:getHeight()
local texW, texH = self.sheets[self.state]:getWidth(),
self.sheets[self.state]:getHeight()
local shader = Tree.assets.files.shaders.outline
shader:send("texSize", { texW, texH })
shader:send("time", love.timer:getTime())
love.graphics.setShader(shader)
end
self.animationTable[self.state]:draw(Tree.assets.files.sprites.character[self.state],
self.animationTable[self.state]:draw(self.sheets[self.state],
position.x,
position.y, nil, 1 / ppm * self.side, 1 / ppm, 38, 47)
position.y, nil, 1 / ppm * self.side, 1 / ppm, self.manifest.base.x, self.manifest.base.y)
love.graphics.setShader()
Tree.level.camera:detach()
@ -74,7 +77,7 @@ function sprite:animate(state)
return function(callback)
if not self.animationGrid[state] then
print("[SpriteBehavior]: no animation for '" .. state .. "'")
callback()
return callback()
end
self.animationTable[state] = anim8.newAnimation(self.animationGrid[state], self.ANIMATION_SPEED,
function()

View File

@ -56,6 +56,17 @@ function love.load()
Tree.behaviors.spellcaster.new(),
Tree.behaviors.ai.new()
},
character.spawn("BOAR")
:addBehavior {
Tree.behaviors.residentsleeper.new(),
Tree.behaviors.stats.new(nil, nil, 2),
Tree.behaviors.positioned.new(Vec3 { 7, 7 }),
Tree.behaviors.tiled.new(),
Tree.behaviors.sprite.new(Tree.assets.files.sprites.boar),
Tree.behaviors.shadowcaster.new(),
Tree.behaviors.spellcaster.new(),
Tree.behaviors.ai.new()
},
}
for id, _ in pairs(chars) do