Manually placing text characters

Hi, I would like to create different parts of words separately so as to give them different colours, and then place them together so that they look natural. Unfortunately, when I try this, things are a little off.

Code:

local fontSize = 16
local abcd = display.newText{text = "abcd", fontSize = fontSize}
abcd.x, abcd.y = display.screenOriginX + abcd.width, display.screenOriginY + abcd.height
local a = display.newText{text = "a", fontSize = fontSize}
a.x, a.y = abcd.x - abcd.width*0.5 + a.width*0.5, abcd.y + abcd.height*0.7
local bcd = display.newText{text = "bcd", fontSize = fontSize}
bcd:setFillColor(1,0,0)
bcd.x, bcd.y = a.x + a.width*0.5 + bcd.width*0.5, a.y

Output:
abcdabcd

As you can see, there is a couple of extra pixels between the bottom a and the red bcd.
Could anyone please explain what’s going on, or suggest a solution?

Your code is hard to read. As I can see you are trying to find the X position based on the width of “a”, “bcd” or “abcd”. But the width is always different, see width prints in my example.

So it’s better to use one standard number, like the height, because it’s the same. See height prints in my example.

Also try to make your code clean and easy to read otherwise you will be making mistakes that are hard to find.

I’m not sure if my example is the best, but this worked for me. Just play with the numbers and use prints to see output of the values.

local left 		 = display.screenOriginX + 100
local top 		 = display.screenOriginY + 100
local font 		 = "Arial"
local fontSize   = 60

local abcd = display.newText("abcd", left, top, font, fontSize )

local a = display.newText("a", 0, 0, font, fontSize)
	  a.x = abcd.x - (abcd.height * 0.7)
	  a.y = abcd.y + (abcd.height * 0.7)

local bcd = display.newText("bcd", 0, 0, font, fontSize)
	  bcd.x = abcd.x + (abcd.height * 0.25)
	  bcd.y = abcd.y + (abcd.height * 0.7)
	  bcd:setFillColor(1,0,0)

print("abcd.width", abcd.width)
print("a.width", a.width)
print("bcd.width", bcd.width)

print("abcd.height", abcd.height)
print("a.height", a.height)
print("bcd.height", bcd.height)

Using a fixed width font will also make it easier. That is what I use for my word search app. There are plenty to choose from:

1 Like

Thanks for the replies. Sorry about the sloppy code, my brain was running out of steam when I posted and I wasn’t thinking at my best (which isn’t great at the best of times…).
I’m not sure I understand the problem with positioning things by width. If I place one object on top of another, and then move it left or right by half of each of their widths, they should be flush. I’ve done this lots of times with other display objects without problem.

I’ve tried it with a fixed-width font and it’s the same problem.

Some investigation seems to suggest the issue only occurs when the first part of “conjoined” text objects is made from a single character:

local left 		 = display.screenOriginX
local top 		 = display.screenOriginY
local fontSize   = 16


local function make(firstString, secondString, y)
	local whole = display.newText{text = firstString..secondString, y = y, fontSize = fontSize}; whole:setFillColor(1,0,0)
	local firstPart = display.newText{text = firstString, fontSize = fontSize}
	local secondPart = display.newText{text = secondString, fontSize = fontSize}
	
	whole.x = left + whole.width/2
	firstPart.x = left + firstPart.width/2
	secondPart.x = firstPart.x + firstPart.width/2 + secondPart.width/2

	firstPart.y = whole.y + whole.height*0.7
	secondPart.y = firstPart.y
	
	local combinedWidth = firstPart.width + secondPart.width
	print(whole.width, combinedWidth)
end


make("a", "b", top + fontSize/2)
make("a", "bb", top + 50)
make("aa", "b", top + 100)
make("aa", "bb", top + 150)

A quick test suggests I can resolve this by checking that the first part of a conjoined pair is a single character, and if it is, place the second part as normal, but move it back by an amount equal to half the difference between the width of the whole and the sum of the widths of the two parts. Sorry if that’s confusing. Hopefully you can figure out what I mean.

I’ll let you know how it goes.

I jumped the gun when I concluded that the problem only arises when the first part is a single character. Moreover, the particular letters involved make a difference. For example:

make("ab", "b", top + fontSize/2) -- fine
make("fb", "b", top + 50)		  -- not fine

I’ll keep at it and see if I can make any sense of it, but most likely it’s down to really nitty-gritty source code stuff that is way beyond me.

I don’t think that you can accomplish what you are trying to accomplish via display.newText API. You’ll need to use bitmap fonts.

Yeah, I was just looking into ponyFont as you said that. :slight_smile: