Animation¶
Display supports playing Animations.
Define an animation¶
Animations can either be frame-based, or use a custom function. Here’s a frame-based animation:
local on = { index = "!", color = prism.Color4.YELLOW }
local off = { index = " ", color = prism.Color4.BLACK }
spectrum.Animation({ on, off, on }, 0.2, "pauseAtEnd")
0.2 is the amount of seconds to play each frame for. It could also be a table of times, { 0.2,
0.2, 0.2, 0.2 }, or by ranges, { ["1-2"] = 0.5, ["3-4"] = 0.25 }. The final parameter tells
the animation what to do when it loops. This can either be a function (which accepts the animation
instance and the number of loops), or the string name of a function on Animation.
Animations can be registered to the spectrum.animations registry:
local on = { index = "!", color = prism.Color4.YELLOW }
local off = { index = " ", color = prism.Color4.BLACK }
spectrum.registerAnimation("Exclamation", function()
return spectrum.Animation({ on, off, on }, 0.2, "pauseAtEnd")
end)
Individual frames can also be functions that accept a Display, x, and y:
local on = { index = "!", color = prism.Color4.YELLOW }
local off = { index = " ", color = prism.Color4.BLACK }
local function putAround(display, x, y)
display:putSprite(x + 1, y, "!", on)
display:putSprite(x - 1, y, "!", on)
display:putSprite(x, y + 1, "!", on)
display:putSprite(x, y - 1, "!", on)
end
spectrum.registerAnimation("Exclamation", function()
return spectrum.Animation(
{ putAround, off, putAround },
0.2,
"pauseAtEnd"
)
end)
For more complex animations, a function that accepts the elapsed time and the display can be used. Other parameters passed to the constructor are ignored.
spectrum.registerAnimation("Projectile", function(owner, targetPosition)
--- @cast owner Actor
--- @cast targetPosition Vector2
local x, y = owner:expectPosition():decompose()
local line = prism.Bresenham(x, y, targetPosition.x, targetPosition.y)
return spectrum.Animation(function(t, display)
local index = math.floor(t / 0.05) + 1
display:put(line[index][1], line[index][2], "*", prism.Color4.ORANGE)
if index == #line then return true end
return false
end)
end)
Tip
Make sure to return true when the animation is over.
Play an animation¶
To play an animation, Level:yield() an AnimationMessage. There are a few
options here. You can play an animation at an actor’s position:
level:yield(prism.messages.AnimationMessage {
animation = spectrum.animations.Exclamation(),
actor = kobold
})
Note
If an actor is passed to a custom animation, Display:overrideActor() will be called
when the animation starts, and Display:unoverrideActor() will be called when it ends.
Or at a position:
level:yield(prism.messages.AnimationMessage {
animation = spectrum.animations.Exclamation(),
x = position.x,
y = position.y
})
If an actor is passed, the x and y are relative to the actor’s position:
level:yield(prism.messages.AnimationMessage {
animation = spectrum.animations.Exclamation(),
actor = target,
y = -1
})
Animations can force the LevelState to wait for them to finish playing:
level:yield(prism.messages.AnimationMessage {
animation = spectrum.animations.Exclamation(),
actor = target,
y = -1,
blocking = true
})
Or they can be skippable by passing skippable = true, though you will have to decide when you
want animations to be skipped by calling Display:skipAnimations(), e.g. on a key press or
mouse click.
Drawing animations¶
The Display will draw animations automatically, so long as you are using a
LevelState and using Display:putSenses(). Otherwise, you will have to call
Display:update() and Display:putAnimations() yourself.