I’m having issues with tweens on objects set up by a class for animating text. For some reasons all the tutorials I find assume that the tweens are defined by a function, rather than a class.
function Write:init(str)
self.x=WIDTH/2
self.y=HEIGHT/2
self.str=str
self.col=color(0, 244, 255, 255)
--etc
end
function Write:draw()
--draws the text
end
function Write:erase()
print "callback" --ie this is just for debugging.
end
A few questions:
Is it possible to put the tween command into the Write:init function, something like this:
tween(2, self, {y=50})
every time I try this, or variations on it, I get an error. I can’t define the tween inside the class, is that correct?
I can’t seem to tween the colour (I want the alpha to go down to 0, so that the text fades). This:
produces an error, as does adding any kind of colour variable
the callback function seems to get called at the very bginning of the tween, rather than at the end of the tween.
Also I don’t know how or whether a table.remove would work if the erase() function is inside the Write class
It would be great if someone could tell me where I’m going wrong. Perhaps there’s a reason why none of the tweening tutorials I’ve seen are animating objects defined by a class, and I need to convert the Write class into a set of functions in the Main tab. I’m new to Codea/Lua (my last programming experience was Blitz Basic on the Amiga a long tme ago), and don’t have a sense yet of when class or a function is the best way of defining the objects in the game.
@JakAttak you’re right. I went back to have another look at my original code. Apart from not using the callback function correctly, the destination was a variable I’d defined locally somewhere else (it was from my first Codea project, and the code was a mess basically). I thought I’d tried every combo (obviously not). I fixed all of that, and it now works. i.e. I have a class for animating text on the screen, the tween in the init of the class with self as object, and a callback that tells the draw loop to kill the text once the animation is done. Thank you everyone, I learnt a lot.
Slightly off-topic follow-on question, my FPS drops from 60 to 30 or lower when there’s lots of action on screen (ie explosions plus this text routine displaying points, multipliers, and so on). Is it faster to create an image of the text, and then draw it as a mesh, than using text() for the frame-by-frame drawing? Or is it the tweens that are the processor drag? I also have the same question for my explosion sparks, which are currently drawn with ellipse(). Would an image mesh be faster? Generally, I’m very impressed with the speed of codea. I have 50 physical bodies bouncing around, all drawn with meshes, and FPS is a consistent 60 on the iPad Air.
@yojimbo2000 - I suspect your problem is because you can’t use self as the item to be tweened, because self is not a normal table. If you define a table inside your class and tween that, you should be OK.
I’m not sure about the colour variable but that’s easy to get around by just tweening an ordinary number and then setting the colour value to that.
I don’t understand the last question about the table remove, can you provide more detail?
OK, I’ll investigate putting a table inside the class.
I tried your suggestion of tweening a separate alpha variable, it worked, thanks for that.
the callback is meant to erase the writing object after the tween has finished.
Before I thought about using callback, I had a self.timer variable set in Write:init(), which would manually count down inside the draw loop. When it reached 0 I’d erase that entry. THis is the code from the main draw loop:
for i,v in ipairs(writing) do
v:draw()
if v.timer==0 then table.remove(writing, i) else v.timer = v.timer -1 end
end
Rather than this manual method, I thought it would be more elegant to use the callback to kill the writing when the tween finished. However, I don’t know how I would get the correct position in table.remove for this, and also the erase() function seems to get called at the very start of the tween, not the end of the motion
function setup()
writing={}
table.insert(writing, Write ("game over",200,200,300,500))
table.insert(writing, Write ("game start",400,200,300,520))
end
function draw()
background(0)
for a,b in pairs(writing) do
b:draw()
end
end
function touched(t)
if t.state==BEGAN then
for a,b in pairs(writing) do
b:touched(t)
end
end
end
function erase()
print("tween done")
end
Write=class()
function Write:init(str,xs,ys,xe,ye)
self.str=str
self.col=color(0, 244, 255, 255)
self.starts={x=xs,y=ys}
self.ends={x=xe,y=ye}
end
function Write:tw()
tween(2,self.starts,self.ends,tween.easing.sineOutIn,erase)
end
function Write:draw()
fill(self.col)
text(self.str,self.starts.x,self.starts.y)
end
function Write:touched(t)
self:tw()
end
There’s no real need for a class for this. When I did it, I put messages into a table, and as each one expired, I removed it and tweened the next. That’s simpler to manage.
@dave1707 thanks for that example, the tween motion works great. However, I see the “callback” debug text being printed straightaway, not at the end of the motion. Are you seeing that behaviour too?
UPDATED: Great, it works now! So the callback cannot be inside the class? That’s interesting. I think @Ignatz is right, maybe it is better in a table/ function
@yojimbo2000 Here’s a version with the callback in the class. I have it clear the string when the tween is done.
function setup()
writing={}
table.insert(writing, Write ("game over",8,200,200,300,500))
table.insert(writing, Write ("game start",3,400,200,300,520))
end
function draw()
background(0)
for a,b in pairs(writing) do
b:draw()
end
end
function touched(t)
if t.state==BEGAN then
for a,b in pairs(writing) do
b:touched(t)
end
end
end
Write=class()
function Write:init(str,t,xs,ys,xe,ye)
self.str=str
self.col=color(0, 244, 255, 255)
self.starts={x=xs,y=ys}
self.ends={x=xe,y=ye}
self.time=t
end
function Write:tw()
tween(self.time,self.starts,self.ends,tween.easing.sineOutIn,
function() self.str="" print("tween done") end)
end
function Write:draw()
fill(self.col)
text(self.str,self.starts.x,self.starts.y)
end
function Write:touched(t)
self:tw()
end
Ok, combining @dave1707 and @Ignatz’s suggestions. I’ve also placed the tween in the unit function and commented out the touch function. The tween animates, the callback happens when it should, but, setting the value to nil does not kill the object. I’ve found this previously with objects stored in tables, I had to use remove.table to kill the object. Any ideas how to fix this?
function setup()
writing={}
kill={}
table.insert(writing, Write ("game over",200,200,300,500))
table.insert(writing, Write ("game start",400,200,300,520))
end
function draw()
background(0)
for a,b in pairs(writing) do
b:draw()
end
for _,b in ipairs(kill) do
b=nil -- why doesnt this work?
end
end
--[[function touched(t)
if t.state==BEGAN then
for a,b in pairs(writing) do
b:touched(t)
end
end
end]]--
Write=class()
function Write:init(str,xs,ys,xe,ye)
self.str=str
self.col=color(0, 244, 255, 255)
self.starts={x=xs,y=ys}
self.ends={x=xe,y=ye}
tween(2,self.starts,self.ends,tween.easing.sineOutIn,erase)
end
function Write:tw()
tween(2,self.starts,self.ends,tween.easing.sineOutIn,self:erase())
end
function Write:draw()
fill(self.col)
text(self.str,self.starts.x,self.starts.y)
end
function Write:touched(t)
self:tw()
end
function erase()
table.insert(kill,self)
print "callback" --debug
end
You’re right, sorry I didn’t see the second version that you posted.
And it works!
I had no idea that you could define a null function in a single line like that with just spaces inbetween each command. That is fantastically useful. Is there a tutorial anywhere explaining this syntax?
Thank you
I guess though that I should have the object stored in a table inside the class though, because the self.str=“” isn’t killing the object as such, just making it invisible, right? ie, as the game went on, the pairs(writing) loop would continue to get longer (I’ll be using this every time the player scores points). Although maybe the processor overhead will be minimal if things aren’t actually being drawn.
@yojimbo2000 I was just clearing the str variable because I didn’t know what you really want to do. You can add as much code as you want in that function to do whatever.