diff --git a/lib/character/behaviors/sprite.lua b/lib/character/behaviors/sprite.lua index 3b99843..c0db6b6 100644 --- a/lib/character/behaviors/sprite.lua +++ b/lib/character/behaviors/sprite.lua @@ -27,7 +27,7 @@ function sprite.new(spriteDir) anim.state = "idle" anim.side = sprite.RIGHT - anim:play("idle") + anim:loop("idle") return anim end @@ -54,20 +54,6 @@ function sprite:draw() ) end ---- @param state string ---- @param loop nil | boolean | fun(): nil -function sprite:play(state, loop) - if not self.animationGrid[state] then - return print("[SpriteBehavior]: no animation for '" .. state .. "'") - end - self.animationTable[state] = anim8.newAnimation(self.animationGrid[state], self.ANIMATION_SPEED, - type(loop) == "function" and loop or - function() - if not loop then self:play("idle", true) end - end) - self.state = state -end - --- @param node AnimationNode function sprite:animate(state, node) if not self.animationGrid[state] then diff --git a/lib/spellbook.lua b/lib/spellbook.lua index 334c712..6d33b39 100644 --- a/lib/spellbook.lua +++ b/lib/spellbook.lua @@ -7,7 +7,7 @@ --- --TODO: каждый каст должен возвращать объект, который позволит отследить момент завершения анимации спелла --- Да, это Future/Promise/await/async -local Animation = require "lib.animation_node" +local AnimationNode = require "lib.animation_node" --- @class Spell Здесь будет много бойлерплейта, поэтому тоже понадобится спеллмейкерский фреймворк, который просто вернет готовый Spell --- @field update fun(self: Spell, caster: Character, dt: number): nil Изменяет состояние спелла @@ -40,44 +40,18 @@ function walk:cast(caster, target) for p in path:values() do print(p) end - Animation { - function(node) caster:has(Tree.behaviors.sprite):animate("hurt", node) end, - onEnd = function() caster:has(Tree.behaviors.spellcaster):endCast() end, - children = { - Animation { - function(node) - caster:has(Tree.behaviors.sprite):loop('idle') - caster:has(Tree.behaviors.residentsleeper):sleep(1000, node) - end, - children = { - Animation { - function(node) - caster:has(Tree.behaviors.map):followPath(path, node) - end, - } - } - }, - Animation { - function(node) - Tree.level.characters[2]:has(Tree.behaviors.sprite):animate("hurt", node) - end, - children = { - Animation { - function(node) - local from = Tree.level.characters[2]:has(Tree.behaviors.map).position - local p = (require "lib.pathfinder")(from, Vec3 { 10, 10 }) - Tree.level.characters[2]:has(Tree.behaviors.map):followPath(p, node) - end - } - } - } - } - }:run() - caster:try(Tree.behaviors.stats, function(stats) stats.mana = stats.mana - 2 print(stats.mana) end) + + local sprite = caster:has(Tree.behaviors.sprite) + if not sprite then return true end + AnimationNode { + function(node) caster:has(Tree.behaviors.map):followPath(path, node) end, + onEnd = function() caster:has(Tree.behaviors.spellcaster):endCast() end, + }:run() + return true end @@ -105,14 +79,15 @@ function regenerateMana:cast(caster, target) stats.mana = 10 end) print(caster.id, "has regenerated mana") - caster:try(Tree.behaviors.sprite, function(sprite) -- бойлерплейт (временный) - -- В данный момент заклинание не позволяет отслеживать состояние последствий своего применения, так что надо повесить хоть какую-то анимашку просто для того, чтобы отложить завершение каста куда-то в будущее - -- См. также https://learn.javascript.ru/settimeout-setinterval - sprite:play("hurt", function() - sprite:play("idle") - caster:has(Tree.behaviors.spellcaster):endCast() - end) - end) + local sprite = caster:has(Tree.behaviors.sprite) + if not sprite then return true end + AnimationNode { + function(node) + sprite:animate("hurt", node) + end, + onEnd = function() caster:has(Tree.behaviors.spellcaster):endCast() end + }:run() + return true end @@ -135,18 +110,35 @@ function attack:cast(caster, target) stats.hp = stats.hp - 4 end) - caster:try(Tree.behaviors.sprite, function(sprite) - sprite:play("attack", function() - sprite:play("idle") - targetCharacter:try(Tree.behaviors.sprite, function(targetSprite) - targetSprite:play("hurt", function() - targetSprite:play("idle") - caster:has(Tree.behaviors.spellcaster):endCast() - end) - end) - end) - end) + local sprite = caster:has(Tree.behaviors.sprite) + local targetSprite = targetCharacter:has(Tree.behaviors.sprite) + if not sprite or not targetSprite then return true end + AnimationNode { + function(node) + caster:has(Tree.behaviors.residentsleeper):sleep(0, node) + end, + onEnd = function() caster:has(Tree.behaviors.spellcaster):endCast() end, + children = { + AnimationNode { + function(node) + sprite:animate("attack", node) + end + }, + AnimationNode { + function(node) + targetCharacter:has(Tree.behaviors.residentsleeper):sleep(200, node) + end, + children = { + AnimationNode { + function(node) + targetSprite:animate("hurt", node) + end + } + } + } + } + }:run() return true end