Page 1 of 1

Font rotation & anchor point

Posted: Sun Jan 05, 2025 9:17 am
by Altostratus
Hello,

I'm new to Love2D but have prior experience in other languages and frameworks. I'm trying to draw the individual characters of a string around a circle, with the baseline of each character pointing to the circle's center, at a specified radius (imagine a clock face with roman numerals).

After reading about Canvas transformations and pulling my hair out a bit, I've come up with this, which works fine:

Code: Select all

function DrawString(letters, x, y, r)
    love.graphics.push()
    love.graphics.translate(x, y)
    for i = 1, (#letters) do
        local l = string.sub(letters, i, i)
        local w = Font:getWidth(l) / 2 -- Font is defined globally
        love.graphics.print(l, -w, -r * Screen.s) -- Screen.s adjusts for resolution scaling
        love.graphics.rotate(math.pi * 2 / #letters)
    end
    love.graphics.pop()
end
I'm wondering if it's the best way to do it. Most of the time it'll be a background object, and calculating and redrawing it on every frame seems expensive. I don't have any issues yet since I'm just starting, but I'm curious about best practices.

Thanks for your help.

Re: Font rotation & anchor point

Posted: Sun Jan 05, 2025 5:47 pm
by kov_serg

Code: Select all

if not love then os.execute "love ." os.exit() end
local gr=love.graphics
local app={t=0}

function ctext(text,xo,yo,r,a0,shift)
	shift=shift or 0
	gr.setColor{0,0.3,0} gr.circle('line',xo,yo,r)
	if shift~=0 then gr.setColor{0.4,0,0} gr.circle('line',xo,yo,r+shift) end
	local font=gr.getFont()
	local n,a=#text, a0 or 0
	for i=1,n do
		local ch=text:sub(i,i)
		local w,h=font:getWidth(ch), font:getHeight(ch)
		a=a+0.5*w/(r+shift)
		gr.push()
		gr.translate(xo+r*math.sin(a), yo+r*math.cos(a))
		gr.rotate(-a) gr.translate(-w*0.5,shift)
		gr.setColor{0.2,0.2,0.2} gr.rectangle('line',0,0,w,h) gr.setColor{1,1,1}
		gr.print(ch)
		gr.pop()
		a=a+0.5*w/(r+shift)
	end
end

function love.load() gr.setNewFont(24) end
function love.update(dt) app.t=app.t+dt end
function love.keypressed(key)
	if key=='escape' then love.event.quit() end
end
function love.draw()
	ctext("The quick brown fox jumps over the lazy dog 0123456789.",200,200,125,app.t*0.3-1.7,-10)
end
Image

Re: Font rotation & anchor point

Posted: Mon Jan 06, 2025 6:42 pm
by dad
I think what you're asking for is something like this:

Code: Select all

local canvas = love.graphics.newCanvas(r* 2, r * 2)
function love.load()
	love.graphics.setCanvas(canvas)
	DrawString("Hello, World!", r, r, r)
	love.graphics.setCanvas()
end

function love.draw()
	love.graphics.draw(canvas, 0, 0)
end
So that you only call DrawString once (in this example), or just whenever this circle needs to be updated, rather than each draw call. No canvas transformations should be needed.

Re: Font rotation & anchor point

Posted: Mon Jan 06, 2025 7:09 pm
by BurrickSlayer
Another option would be to use a Text object: https://love2d.org/wiki/Text

The name "Text" might be a bit misleading here, because actually this is a text batch object (that's why it will be renamed to TextBatch in LÖVE 12). In other words, you can add several strings to this object, each with a different transformation. And then you can draw them all together with one draw call.