I looked up tween and my tween example and it seems like just the thing. Let’s find out.

Long story short, the tween function varies named members of a table, over a time interval. Our Splat, as a class instance, is a table. Therefore we should be able to use tween quite nicely to scale our splat.

Here it is as it stands:

-- Splat
-- RJ 20200521

local Splats = {}

local Vecs = {
vec2(-2,0), vec2(-2,-2), vec2(2,-2), vec2(3,1), vec2(2,-1), vec2(0,2), vec2(1,3), vec2(-1,3), vec2(-4,-1), vec2(-3,1)
}

function drawSplats()
    for k, splat in pairs(Splats) do
        splat:draw()
    end
end

Splat = class()

function Splat:init(pos)
    self.pos = pos
    Splats[self] = self
    self.size = 1
end

function Splat:draw()
    pushStyle()
    pushMatrix()
    translate(self.pos.x, self.pos.y)
    fill(255)
    scale(2)
    local s = self.size
    for i,v in ipairs(Vecs) do
        ellipse(s*v.x, s*v.y, 2)
    end
    popMatrix()
    popStyle()
    self.size = self.size * (1 + DeltaTime)
    if self.size > 5 then Splats[self] = nil end
end

Our current scaling runs for four seconds (from 1 to 5) and scales the splat from 2 to 10, because it’s at scale 2 already. I’ll remove the scale call, start size at 2, and run it up to 10, in 4 seconds, with a tween.

If this works. Here goes. Oh, before I start, the tween can have a “callback” function when it’s done. I think I know how I’ll use that but let’s do it in two steps. First time, I expect the splat will expand and then stay on the screen, because I’m removing the if that kills it.

function Splat:init(pos)
    self.pos = pos
    Splats[self] = self
    self.size = 2
    tween(4, self, {size=10}, tween.easing.linear)
end

function Splat:draw()
    pushStyle()
    pushMatrix()
    translate(self.pos.x, self.pos.y)
    fill(255)
    local s = self.size
    for i,v in ipairs(Vecs) do
        ellipse(s*v.x, s*v.y, 2)
    end
    popMatrix()
    popStyle()
end

Notice that in the draw function, I don’t adjust s, I just use it. And in the init, I call tween. Here’s what the parameters mean:

  • 4, time: the time in seconds for the tween to run
  • self, table: the table to be modified
  • {size=10} target: a table of target values
  • tween.easing.linear, easing: an arcane incantation saying that the variables should change linearly. There are other options.

And just as I expected, the explosions grow and just stay there when done:

stopped

Now I mentioned that you can have a “callback” when a tween ends, so we’ll add a function that causes a Splat to die when that happens:

function Splat:init(pos)
    local die = function()
        Splats[self] = nil
    end
    self.pos = pos
    Splats[self] = self
    self.size = 2
    tween(4, self, {size=10}, tween.easing.linear, die)
end

The function die is local to the init, and as such, its reference to self refers to the specific instance being created. Each Splat gets its own private die function. When that function is called at the end of the tween, it nils the entry in the Splats table, so that Splat is never drawn again.

And it works as advertised:

splats die

Summing Up

Well, I called this number 13.5 because that’s all I intended to do this evening. It’s a pretty simple thing, this tween, but it gave us a simpler way to animate our explosion and erase it when it’s over.

A good argument for reading the documents and checking out the example projects!

See you next time!