Text alignment bug?

First off, I know Corona well, make tutorials lots of folks watch and follow, and can generally figure out a problem with time and patience

This said, the following is driving me bat-sh*t crazy. I’ve got text that is right aligned and when it changes, according to the methodology outlined here:

http://developer.anscamobile.com/reference/index/objectsetreferencepoint

it doesn’t stick to x for the right alignment.

\_W = display.contentWidth;  
\_H = display.contentHeight;  
  
local t = {"One", "2Two", "FreeFreeThree", "FourScore", "5"};  
  
local ttl = display.newText("Let's Begin", 0, 0, font, 68\*2);  
ttl.xScale = 0.5; ttl.yScale = 0.5;  
ttl:setTextColor(255,255,255);  
ttl:setReferencePoint(display.TopRightReferencePoint);  
  
function ttl:write(params)  
 --Store the current X and Y position for use 5 lines down  
 local \_X = self.x;  
 local \_Y = self.y;  
 self.text = params.title;  
 self:setReferencePoint(display.TopRightReferencePoint);  
 ttl.x = \_X; ttl.y = \_Y;  
end  
  
ttl.x,ttl.y = \_W\*0.5,\_H\*0.5;  
  
local tmr  
tmr = timer.performWithDelay(1000, function(e)  
 ttl:write({title=t[e.count]});  
 if(e.count == #t) then  
 timer.cancel(tmr);  
 tmr = nil;  
 end  
end,#t);  
  

What on earth is wrong here? [import]uid: 7947 topic_id: 14366 reply_id: 314366[/import]

Got it! The text’s xScale and yScale were interfering with proper positioning. If you use the Retina text trick (which I don’t even know if it’s necessary anymore), use this:

\_W = display.contentWidth;  
\_H = display.contentHeight;  
  
local t = {"One", "2Two", "FreeFreeThree", "FourScore", "5"};  
  
local ttl = display.newText("Let's Begin", 0, 0, font, 68\*2);  
ttl.xScale = 1; ttl.yScale = 1;  
ttl:setTextColor(255,255,255);  
ttl:setReferencePoint(display.TopRightReferencePoint);  
  
function ttl:write(params)  
 --Store the current X and Y position for use 5 lines down  
 local \_X = self.x;  
 local \_Y = self.y;  
 self.text = params.title;  
 --Temporarily change the xScale and yScale back to 1 to set the reference point correclty  
 self.xScale,self.yScale = 1,1;  
 self:setReferencePoint(display.TopRightReferencePoint);  
 --Change the xScale and yScale back to 0.5 for retina text  
 self.xScale,self.yScale = 0.5,0.5;  
 ttl.x = \_X; ttl.y = \_Y;  
end  
  
ttl.x,ttl.y = \_W\*0.5,\_H\*0.5;  
  
local tmr  
tmr = timer.performWithDelay(1000, function(e)  
 ttl:write({title=t[e.count]});  
 if(e.count == #t) then  
 timer.cancel(tmr);  
 tmr = nil;  
 end  
end,#t);  

Hope this helps someone else. [import]uid: 7947 topic_id: 14366 reply_id: 53071[/import]

My text display object jumps (i.e., changes the alignment) when the text changes, and I can’t see why. Maybe you’d be able to help, since you’ve spent a lot of time thinking about the text alignment problem and solving it.

I show score on upper left corner of the screen. I’ve set reference point to display.TopLeftReferencePoint. I use director class, and when the scene is loaded, the score appears left aligned and all is good.

However, when the player’s score changes from 0 to new number the first time, the text jumps to the left. It jumps back to where it should be when the player earns more points. After that, the alignment seems to be fixed properly. I just don’t understand why the text jumps to the left the first time around. It feels like the reference point changes from top left to top center, and then changes back to top left permanently.

As a safety precaution, in the score-update function, I reset both the reference point and the x,y coordinate, but the jumping-to-the-left issue remain the same. (In other words, resetting or not resetting the reference point & x,y coordinate in the score-update function make no difference.)

Here’s the stripped down version of how my text display object is created and how the score update function works. It’s a simple process – and I simply can’t see why on earth the score text jumps the first time the player’s score changes from 0 to positive number. FYI, the display object currentScoreTxt isn’t called anywhere else in the code.

-- forward reference  
local currentScoreTxt;  
  
local function what\_happens\_upon\_an\_event()  
 -- update the score display  
 local function updateScore()  
 currentScoreTxt:setReferencePoint(display.TopLeftReferencePoint);  
 currentScoreTxt.x = 15;  
 currentScoreTxt.y = 5;  
 currentScoreTxt.text = "Score: " .. comma\_value(currentScore);  
 end  
  
 -- series of if-statement, and one of which results in earning points like this:  
 currentScore = currentScore + 300;  
 updateScore();  
end  
  
-- create display object  
currentScoreTxt = display.newText("Score: 0", 0, 0, fontName1, fontSize + 10);  
currentScoreTxt:setTextColor(255, 255, 255);  
currentScoreTxt:setReferencePoint(display.TopLeftReferencePoint);  
currentScoreTxt.x = 15;  
currentScoreTxt.y = 5;  
game1Group:insert(currentScoreTxt);  

Do you see where it might be going wrong? I’d be grateful to hear your thoughts.

[import]uid: 67217 topic_id: 14366 reply_id: 53160[/import]

Order of manipulations matters:

1.) Set the text
2.) Change the reference point
3.) position the text

Try this instead:

-- update the score display local function updateScore() currentScoreTxt.text = "Score: " .. comma\_value(currentScore); currentScoreTxt:setReferencePoint(display.TopLeftReferencePoint); currentScoreTxt.x = 15; currentScoreTxt.y = 5; end [import]uid: 7947 topic_id: 14366 reply_id: 53161[/import]

I find that method is actually ineffective in some cases; with my current work, this method gets the same problem the OP has:

[code]–Problem example
local sometext = display.newText()
– left empty, assume there’s some code here
– later on, in a function:

sometext.text = "The number is "…thisvar
sometext:setReferencePoint(display.BottomRightReferencePoint)
sometext.size = 20
sometext.x = 1
sometext.y = 1[/code]

In this example even though you set the reference point, the first text displayed will ignore your reference point and just use the default. The opposite (initially setting the point, but not later) is even worse as your new text can’t take into account the change in text. (Setting some temporary initial text has no effect, either.)

The only way I’ve found to get around this is to set everything twice. Set everything in that order (Point, Size, X, Y) after declaring display.newText(), and then set it again later when the program actually is driven to say something with it. (I really hope there’s a better solution out there, but this is all I can find.)

[code]-- Awkward but working solution
local sometext = display.newText()
sometext:setReferencePoint(display.BottomRightReferencePoint)
sometext.size = 20
sometext.x = 1
sometext.y = 1

– left empty, assume there’s some code here
– later on, in a function:

sometext.text = "The number is "…thisvar
sometext:setReferencePoint(display.BottomRightReferencePoint)
sometext.size = 20
sometext.x = 1
sometext.y = 1[/code]

I tried experimenting a bit to slim down the amount of dupe code, but ReferencePoint doesn’t actually do anything unless you set X/Y later. So you need to set the point and position every time - even if there’s no text - to avoid the first time misalignment problem. [import]uid: 41884 topic_id: 14366 reply_id: 53208[/import]

It’s worth noting that this isn’t an exact fix either. I’ve noticed that at certain text sizes, the position of your anchor point will shift by a few pixels regardless. (No idea why, really…) [import]uid: 41884 topic_id: 14366 reply_id: 53211[/import]

No, it is effective in all cases. In order for setRef to work properly, the object width has to be set BEFORE setRef is called. The problem with the code you’ve provided is that you are:

1.) Not init’ing newText properly
2.) You are changing the size AFTER the setRef line (it has to be done before).

I’ve rewritten your code:

[code]
_W = display.contentWidth;
_H = display.contentHeight;

local t = {“One”, “2Two”, “FreeFreeThree”, “FourScore”, “5”, “Super duper long string”};

– This works all the time
local sometext = display.newText("", 0, 0, native.systemFont, 12) – you have to init it properly, even with a blank string
sometext.size = 20 – If you want to change the size later
sometext:setReferencePoint(display.BottomRightReferencePoint)
sometext.x, sometext.y = _W-1,_H-1 --Place the text at the lower right corner of the screen (see constants above)
sometext:setTextColor(255,255,255);–White text (background is black)

–Create a method to write the text
function sometext:write(txt)
–Generate a random text size to show that the refPoint will stick
–because setRef is is placed AFTER the size change (thereby having its width already set)
self.size = math.random(40,80)–place this line after the setRef line and see what happens
self.text = txt;
self:setReferencePoint(display.BottomRightReferencePoint)
self.x, self.y = _W-1,_H-1 --Place the text at the lower right corner of the screen
end

local tmr
tmr = timer.performWithDelay(1000, function(e)
sometext:write("The number is "… t[e.count]);
if(e.count == #t) then
timer.cancel(tmr);
tmr = nil;
end
end,#t);
[/code] [import]uid: 7947 topic_id: 14366 reply_id: 53213[/import]

I suspect it has to do with the default font being variable-width. With a fixed-width font (like Courier below), it’ll stick tighter (change the random var below to a fixed number and you’ll see it stick regardless of size):

[code]
_W = display.contentWidth;
_H = display.contentHeight;

local t = {“One”, “2Two”, “FreeFreeThree”, “FourScore”, “5”, “Super duper long string”};

local vline = display.newLine( _W-5,0, _W-5,_H);
vline:setColor(255,255,255,255);
vline.width = 1;

local hline = display.newLine( _W-5,_H-1, 0,_H-1);
hline:setColor(255,255,255,255);
hline.width = 1;

– This works all the time
local sometext = display.newText("", 0, 0, “Courier”, 12) – you have to init it properly!
sometext.size = 20 – If you want to change the size later
sometext:setReferencePoint(display.BottomRightReferencePoint)
sometext.x, sometext.y = _W-1,_H-1 --Place the text at the lower right corner of the screen
sometext:setTextColor(255,255,255);–White text

–Create a method to write your text
function sometext:write(txt)
–Generate a random text size to show that the refPoint will stick
–because it is placed AFTER the size change (thereby having its width already set)
self.size = 40;
self.text = txt;
print(self.width);
self:setReferencePoint(display.BottomRightReferencePoint)

self.x, self.y = _W-1,_H-1 --Place the text at the lower right corner of the screen
end

local tmr
tmr = timer.performWithDelay(1000, function(e)
sometext:write("The number is "… t[e.count]);
if(e.count == #t) then
timer.cancel(tmr);
tmr = nil;
end
end,#t);
[/code] [import]uid: 7947 topic_id: 14366 reply_id: 53218[/import]

Thanks for the reply, hdez, but I need to break down what you’re saying into easier terms for my newbie brain. A lot of your code is nice but I’m trying to get to the “what is the bare minimum we need for this to work” :slight_smile:

(Incidentally, sorry, when I said the OP, I meant the guy asking about his scoring problem. My bad.)

  1. Actually, none of that is required to init newText properly. It’s built to not pass an error even if empty, and I actually wrote my reply at first with an empty string, but dropped it simply because it did not affect the result.

  2. Your example seems to contradict you; Line 9 does not need (and cannot use) setReferencePoint as - like you said - the width isn’t set yet (there’s no text). I understand what you mean about empty strings, but I just tried it out:

[code]
local sometext = display.newText(" ") – added string for the heck of it! :wink:
sometext.size = 16
sometext:setReferencePoint(display.BottomRightReferencePoint)

– … later on, in a function

sometext.text = “Hi!”
–sometext:setReferencePoint(display.BottomRightReferencePoint)
sometext.x = 20
sometext.y = 30[/code]

In this example, “Hi!” will ignore setReferencePoint because it was set ahead of time. If you remove the first setRef and uncomment the second one, it works fine. At least on my build, the SDK really doesn’t care about using setRef if the string is empty or nil…

(Unless I’m wrong somewhere else, of course. I’m guessing the pixel variation problem is due to the scale of the font, maybe?) [import]uid: 41884 topic_id: 14366 reply_id: 53223[/import]

@richard9 and @hdez, THANK YOU!

When I moved currentScoreTxt.text = "Score: " … comma_value(currentScore); to the top of the update score function, the jumping-to-the-left issue went away.

@hdez, what you noted above, i.e., “in order for setRef to work properly, the object width has to be set BEFORE setRef is called”, helped to clarify the nature of the setRef for me – how the physical size of the text matters.

Thanks again!
[import]uid: 67217 topic_id: 14366 reply_id: 53227[/import]

hi richard9,

so, with regards #1, I’m not really sure how the following (with or without the empty string) doesn’t throw a catastrophic error for you. Maybe it’s a Mac-Corona / PC-Corona thing (I’m running Mac Version 2011.606)?

local sometext = display.newText() -- Throws a big error, rendering comes to a complete halt  

regarding #2,
If I take out the setRef from the function (and it doesn’t matter if the function is implemented as a method of the text object or as a standalone function), the text hops around (as it should - it’s using the initial setRef). And about the contradiction, I’m not sure what you mean there for as soon as you change the content or manipulate the size of the text (change the string, scale the text, change the font, change the font size, or some combination of some or all of the above) you have immediately changed the size of the object itself, thereby allowing the new setRef call to utilize that size with regards to the positioning that happens a line or so later. X & Y positioning is based around the setRef point. So, Line 9 (I think you mean in your most recent post) can use it. But then, there is so much code on this page, it could be a different Line 9.

I don’t doubt that your code is working the way you report. Without seeing the rest of your code, I’ve not the slightest idea if somewhere else your setRef is being addressed (since your previous solution was to double the call anyways).

Also, about doing the bare minimum to get it to work, I empathize and simply present a method that makes a little more semantic sense to me (“hey, sometext - write!”) and also avoids references to objects within functions (you can use the ‘self’ keyword since it is a method on the object - this is helpful for more complete garbage collection). It certainly isn’t the only way it can be done and certainly we each have our own methodologies that we work by.

Finally, I should revise the order of manipulations that I put above in post #3:

Order of text manipulations:

1.) Set the text
2.) Change the appearance of the text (size, font, scaling)
3.) Change or reset the reference point
4.) Position the text [import]uid: 7947 topic_id: 14366 reply_id: 53239[/import]

Yeah, I’m on the latest PC free build, so it could definitely be a platform specific thing. (Although if so, Corona has a really big bug to fix. I’m pretty sure there about 30 places in my lua file that would fail without the blank declare!) :wink:

Glad your problem is solved, ask! It fixed a few issues on my own app too so good news for all. :slight_smile:

My contradiction was merely referring to how you used an initial setRef statement, which at best does nothing (blank string) and at worst is the original confusing problem (since as we’ve learned, the reference point needs to be set after setting the text and size.) Since the text won’t use the refPoint without setting the X/Y after, there’s really no reason to use it the first time unless you have a real string there to help you visualize its position.

And hey, I actually appreciate the code because usually when I read these threads I can stare at it for awhile and learn new functions. It’s just that I had to break it down in my own post because I really wanted to know the absolute bare minimum answer. :wink:

The font thing, well…I need to find a way to get fonts working correctly. The Ansca stuff all uses a font not included in the Windows build, and the default font pointing process doesn’t seem to fly for me. Not a big deal yet.

PS: Actually…since you are using a Mac, I should probably bug you to check that other bug I had. If my widget problems were really PC only…well, that would probably march me on down to the Apple store to buy a macbook… [import]uid: 41884 topic_id: 14366 reply_id: 53244[/import]

Ahh, ok. I see the line 9 thing. I’m not used to instantiating text-less text objects so I simply reverted to habit with the setRef code. Though, it bears mentioning that truly text-less text would be “” and not " " (the space would generate a width).

If you are new to Corona, I’ve got a set of tutorials here: http://www.youtube.com/playlist?list=PLB8268CBEDDE78ED9

I’ll have gander at your other problem. [import]uid: 7947 topic_id: 14366 reply_id: 53253[/import]