When life gives you lemons, write a class that gives you lemonade.
While I like @yojimbo2000’s textbox class, I figured there was a solution for my numbers involving a numerical texture atlas and a single mesh for all the various on-screen counters I have and a way to avoid constantly writing text, even if that text gets written to a mesh. So I wrote this. Only uses text on setup. Thereafter it’s pure mesh magic! It works really fast on the iPad 3 and has practically eliminated my memory leak issues.
It’s not the most elegant coding (none of my stuff is) but it does what I need it to.
--# Main
displayMode(FULLSCREEN)
function setup()
NumberMesh = mesh()
NumberMesh.texture = createNumberSheet()
points = NumberRects("52", 2, WIDTH/2, HEIGHT/2, 200)
end
function draw()
background(120, 61, 61, 255)
NumberMesh:draw()
if math.random(99) > 95 then
points:update(math.random(20))
end
end
function createNumberSheet()
pushStyle()
local source = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ".", ""}
local nsinfo = {}
font("Futura-CondensedExtraBold")
fontSize(150)
local _, textheight = textSize("0")
local textwidth = 0
for i = 1,#source do
local letter = source[i]
nsinfo[i] = {}
nsinfo[i].word = letter
nsinfo[i].width = textSize(letter) + 4
textwidth = textwidth + nsinfo[i].width
end
local img = image(textwidth, textheight)
local startwidth = 0
for i = 1, #nsinfo do
nsinfo[i].startfrac = startwidth / textwidth
nsinfo[i].sizefrac = nsinfo[i].width / textwidth
startwidth = startwidth + nsinfo[i].width
end
setContext(img)
background(255,0,0)
textMode(CORNER)
fill(255)
local margin = 2
for i = 1, #nsinfo do
text(nsinfo[i].word, margin, 0)
margin = margin + nsinfo[i].width
end
setContext()
popStyle()
NumberLookup = {}
for i = 1, #nsinfo do
NumberLookup[nsinfo[i].word] = {sizefrac = nsinfo[i].sizefrac, startfrac = nsinfo[i].startfrac}
end
return img
end
--# NumberRects
local ssub = string.sub
local tostring = tostring
NumberRects = class()
function NumberRects:init(str, len, x, y, size)
-- you can accept and set parameters here
self.len = len
self.x = x
self.y = y
self.size = size
self.rects = {}
for i = 1,len do
self.rects[i] = NumberMesh:addRect(self.x, self.y, self.size, self.size)
end
self:update(str)
end
function NumberRects:update( x )
self.str = tostring(x)
local mult = self.size
local ratio = 1004/192
local lookup = NumberLookup
local sizefractot = 0
for i = 1, #self.str do
local letter = ssub(self.str, i, i)
sizefractot = sizefractot + lookup[letter].sizefrac
end
local margin = self.x - (sizefractot * mult * ratio)/2
local textheight = self.y
local letterheight = mult
for i = 1, #self.str do
local letter = ssub(self.str, i, i)
local sizefrac = lookup[letter].sizefrac
local startfrac = lookup[letter].startfrac
local letterwidth = mult * ratio * sizefrac
NumberMesh:setRect(self.rects[i], margin - letterwidth/2, textheight, letterwidth, mult )
NumberMesh:setRectTex(self.rects[i], startfrac, 0, sizefrac, 1)
margin = margin + letterwidth
end
if #self.str < self.len then
for i = (#self.str + 1), self.len do
NumberMesh:setRect(self.rects[i], 0,0,0,0 )
end
end
end