This took me way longer than I expected to. An hour? Maybe two. I’m not very happy with it. But I haven’t seen any other examples of this.
function setup()
local str = [[Hello! This is a test to animate the appearance of text. It is a work in progress.]]
t = {}
t[0]=""
for i = 1, #str do
t[i] = str:sub(i, i)
print(t[i])
end
end
-- function to slowly draw text at x,y every speedth frame
-- feed it an empty table holding a text key and a target array of text (see setup above)
-- use a table for subject because pointers
function slowText(x,y, subject, target, iter, speed)
local i = iter.i
local j = i+1
if target[j] and time % speed == 0 then
subject.text = subject.text .. table.concat(target, "", i, j)
iter.i=iter.i+2
end
-- This stuff below is graphical, Codea only
local w = textSize(subject.text)
pushStyle()
textWrapWidth(740)
fontSize(20)
fill(252)
font("ArialMT")
text(subject.text, x + (w/2), y)
popStyle()
end
-- The draw function gets called once every frame
time = 0
iter = {i=0}
local str={text=""}
function draw()
time = time + 1
background(40, 40, 50)
strokeWidth(5)
slowText(28,280,str,t,iter,2)
if time == 59 then time = 0 end
end
@xThomas Here an example. It should be made into a class to be able to display different text at different speeds at the same time.
function setup()
textMode(CORNER)
str ="Hello! This is a test to animate the appearance of text. It is a work in progress."
end
function draw()
background(0)
fill(255)
slowText(10,300,str,20) -- change 20. Higher value mean slower display.
end
function slowText(x,y, subject,limit)
if len==nil or cnt==nil then
cnt=0
len=1
end
if len<#str then
if cnt<limit then
cnt=cnt+1
else
len=len+1
cnt=0
end
end
text(string.sub(subject,1,len),x,y)
end
Here is a class version of the above code. More things can be added to the class.
displayMode(FULLSCREEN)
supportedOrientations(LANDSCAPE_ANY)
function setup()
s1=slowText(50,200,20,color(255,0,0),20,"Hello! This is a test to animate the appearance of text. It is a work in progress.")
s2=slowText(10,400,50,color(0,255,0),50,"Hello! This is a test to animate text, the end.")
end
function draw()
background(0)
s1:draw()
s2:draw()
end
slowText = class()
function slowText:init(x,y,limit,col,size,str)
self.x=x
self.y=y
self.col=col
self.size=size
self.str=str
self.limit=limit
self.len=1
self.cnt=0
end
function slowText:draw()
pushMatrix()
fill(self.col)
fontSize(self.size)
textMode(CORNER)
if self.len<#self.str then
if self.cnt<self.limit then
self.cnt=self.cnt+1
else
self.len=self.len+1
self.cnt=0
end
end
text(string.sub(self.str,1,self.len),self.x,self.y)
popMatrix()
end
Here’s another version where I added more to the class.
displayMode(FULLSCREEN)
supportedOrientations(LANDSCAPE_ANY)
function setup()
s1=slowText(WIDTH/2,200,20,color(255,0,0),20,0,0,"Hello! This is a test to animate the appearance of text. It is a work in progress.")
s2=slowText(400,HEIGHT/2,50,color(0,255,0),40,45,0,"Hello! This is a test to animate text, work in progress.")
s3=slowText(WIDTH/2+100,HEIGHT/2,50,color(255,255,0),40,0,.1,"Hello!")
end
function draw()
background(0)
s1:draw()
s2:draw()
s3:draw()
end
slowText = class()
function slowText:init(x,y,limit,col,size,ang,inc,str)
self.x=x
self.y=y
self.col=col
self.size=size
self.ang=ang
self.str=str
self.inc=inc
self.limit=limit
self.len=1
self.cnt=0
end
function slowText:draw()
pushMatrix()
fill(self.col)
fontSize(self.size)
if self.len<#self.str then
if self.cnt<self.limit then
self.cnt=self.cnt+1
else
self.len=self.len+1
self.cnt=0
end
end
translate(self.x,self.y)
self.ang=self.ang+self.inc
rotate(self.ang)
text(string.sub(self.str,1,self.len),0,0)
popMatrix()
end
this typewriter function makes it so you write text, standard alignment is left. as you make new lines it makes the old text go towards the top of the screen. note that codea will not draw text if textsize is greater than the sceeen. and this is a very minimal implementation, i made it this way by accident trying to do something else. What I actually wanted to do was different but whatever.
I think textAlign(LEFT) is bugged a bit, as when you try to draw text on only one line, it doesn’t actually do the aligning. You need at least two lines.
-- typewriter
-- Use this function to perform your initial setup
function setup()
print("Hello World!")
end
local long = [["gagshgjhdghsjgjhfgsgfhjshjfjhgdjhfgjhdgfhjgsjhfgjhhgfhgjdhgfhjdjfhgdjhfgjhdgfjhgdjhfgjhdgfjhgdfjhgejhfgjhdgfjhgdfhjgdjhfghjdgfhjgdjhfgjhgdfjhgejhfgjhgjhrgfjhgrfhjgjhdfgjhgdfjhgjrhfghjrgfjhr\
\
ijsgkjgdjkgfhkdgjfjghdkfghkghjgjhgjhghjg^>#^%\\#^{%#^%]#{^%#{]%}^*^#[]^*^]{"]]
-- This function gets called once every frame
function draw()
-- This sets a dark background color
background(40, 40, 50)
-- This sets the line thickness
strokeWidth(5)
fill(177)
fontSize(15)
font("Inconsolata")
textWrapWidth(312)
typewriter('Apple Banana Crayon Dog Eagle Falcon Greens Ohayo')
typewriter(long, 6, 200,399)
-- Do your drawing here
end
local textObject = {
text = "\
",
}
--[[
Auxilary function for animating text one character at a time. Made for RPG games.
Tries to align text to the left so that character n is always at the same x,y position
no matter the string. For this reason please use monospaced fonts.
The first parameter is the string to animate. The optional second parameter is the
speed to draw at in frames per second. (default is 6). Third and fourth determine where
to draw the text. Always aligns LEFT.
todo: add align mode
Returns String of textObject.text if called without first parameter
]]
local count = 0
local time = 0
function typewriter(characters, fps, x, y)
if not characters then
return textObject.text
else
characters = '\
'..characters --keeps first line display correctly
time = time + 1
fps = fps or 6
if time % fps == 0 then count = count + 1 end
x = x or 0
y = y or 0
if textObject.text ~= characters then
textObject.text = string.sub(characters, 1, count)
textAlign(LEFT)
local w,h = textSize(typewriter())
local wrap = textWrapWidth()
local x = x + w/2
local y = y + h/2
text(textObject.text, x, y)
else
textAlign(LEFT)
local w,h = textSize(typewriter())
local wrap = textWrapWidth()
local x = x + w/2
local y = y + h/2
text(textObject.text, x, y)
end
end
end
function touched(touch)
if touch then showKeyboard() end
end
function keyboard( key )
long = keyboardBuffer()
end