Fonts Performance, How to know your FPS and some custom files aren't included in the build?

So I’ve been playing around with porting my game to WP8, tested on Lumia 720 which has dual core 1Ghz (a nice device which still on the low end but without sinking to 520) and here are some issues that I can’t figure out (yet) :

  1. When making a build, some custom files that aren’t .lua, .xml or other well known files aren’t included in the build eventhough they’re added to the solution. Thus my app keep saying it can’t find the file. I looked at the property and the “Build Action” for these files is : “None” instead of “Content” and there isn’t a way to change this from the property panel.

How can I add custom files to my build as I do have some of them (with my own format)?

  1. Fonts performance is really bad and by bad I mean updating a text every frame will cause the app to a grinding halt. I know that you suggest using bitmap font but my game use plenty of text and it seems the porting tasks are daunting. It seems though the performance hit only happened significantly when you keep on updating the text so I might want to experiment on this. Any help/tricks to get the best performance is very much welcomed.

I can’t really tell how bad the fps dip is cause comes the 3rd problem below

  1. How do I tell my real fps or set my fps (config.lua still working?)? I tried to calculate my own by using the delta time for each enterframe like I always used to. Using either : system.getTimer() or event.time but I get a wild result which doesn’t really say much and very different from the FPS counter from the debugger.
    This might be a warning to cause I use system.getTimer to track/perform some tasks in my game and if it isn’t dependable then I need a new method to track time.

Thanks guys,
 

You can set the “Build Action” property of a file to “Content” by following steps 5 and 6 in the link below.  Note that you cannot change this property if your in the middle of compiling or debugging your app project.

   http://docs.coronalabs.com/daily/coronacards/wp8/portapp.html#copying-project-files

If you want good 60 FPS performance, then I’m afraid that you don’t have much choice but to switch to bitmap fonts.  But the good news is that by doing this, you’ll be increase the performance on Android and iOS too.  It would be especially noticeable on Android.  The only other method that I can think of is to pre-load text objects (still an initial performance hit) and re-use them when needed, but remember that text objects are really bitmap/textures so this is an extensive thing to do from a memory/RAM perspective.  Especially since low-memory WP8 devices are very popular.

You can use the following code to print the average FPS to the Visual Studio “Output” panel…

local lastEnterFrameTime = nil local durationCollectionSize = display.fps local durationCollectionIndex = 1 local durationCollection = {} for index = 1, durationCollectionSize do durationCollection[index] = 0 end local function onEnterFrame(event) local currentTime = system.getTimer() -- If this is the first frame, then fetch the current time and exit out. if (lastEnterFrameTime == nil) then lastEnterFrameTime = currentTime return end -- Store the duration since the last frame. durationCollection[durationCollectionIndex] = currentTime - lastEnterFrameTime lastEnterFrameTime = currentTime -- Do not continue if we have more durations to collection before averaging below. if (durationCollectionIndex \< durationCollectionSize) then durationCollectionIndex = durationCollectionIndex + 1 return end -- Average the collected durations and print it to the log. local averageDuration = 0 for index = 1, durationCollectionSize do averageDuration = averageDuration + durationCollection[index] end averageDuration = averageDuration / durationCollectionSize local averageFps = 1000 / averageDuration print("Average FPS = " .. tostring(averageFps) .. ", Average Duration = " .. tostring(averageDuration)) -- Reset data collection. durationCollectionIndex = 1 end Runtime:addEventListener("enterFrame", onEnterFrame)

That’s the thing,

I can’t change my files from “None” to “Content” since on the properties panel it seems the only option available. I’ve googled and found some solutions but most of them involving hacking the registry?

Please don’t change the registry.  It won’t resolve this.  Changing the “Build Action” will make a change to your *.csproj file.

I’m kind of perplexed as to why you only a see “None” in the drop down menu.  No one else is having this problem.  Are you sure you are left clicking the file in the “Solution Explorer” panel to highlight it before clicking on the “Build Action” property?  A file must be selected before you can see its properties.  And in the “Properties” panel, you need to click on the field to the right of the “Build Action” label to make the drop-down box appear.  (If you already know all this then I apologize, but I’m kind of scratching me head as to why you’re not seeing these options.)

Hi Joshua,

Thanks for being very patience. Apparently scrapping the solution and just created  a new one solved the problem and now I got my game running.

After stripping all the text rendering in the game, it runs wonderfully smooth at almost 60 fps all the time :). I noticed that it seems the font problem only happens when there’s an update on the text. I guess it has to redraw everything and that’s an expensive operation.

For now, I think we’re gonna leave the GUI where the static text doesn’t change much to use the old fonts since it seems once it  renders on the screen then the fps is back to normal again.

For dynamic text we have to change to bitmap font i guess but at least it won’t take too much time to port

 

Oh good.  I’m glad you got it working now.

Yeah, we worked really hard to achieve 60 FPS support, which is not an easy thing to do in a Silverlight/XAML based app.  I know many game developers struggle with this on WP8 and this is something that we wanted to “just work” on this platform.

Regarding text rendering, you’re right.  The performance hit happens when you create the text via display.newText() and when you update the text.  It’s really only an issue when you update the text often, such as during gameplay, or when you’re creating several text objects at once.  I think display.newText() is fine to use if you have just a few text objects which never update, such as on a menu screen, or if it comes from a source whose text that you cannot control, such as Facebook or Twitter.

Anyways, I hope you have a good experience porting your app to WP8!

We tried to make our native integration as easy as possible in Visual Studio.  Much easier than it is with Android and iOS right now.

Hi Joshua,

Yes, I think I got it all figured out but one thing though… I’m not sure who to ask about this but the problem is about fontsize.
What I want to know is how does Corona render font according to its fontsize?

I’m trying to see if I can match my bitmap font exactly like display.newText but there’s a size difference in the fontsize that I don’t understand.
I’m using bmGlyph to bake a 48pt font bitmaps and try to compare it with what Corona produce and there’s a big difference in size.

CbofE4n.png
Both are supposed to be 48pt font but what corona renders is larger than the bitmap font.

Any help in figuring this out? My goal is to be able to do this which already working good enough other than the font size problem :

local normalText = display.newText("Corona Font : Doctor Jekyll NF", 10, 200, "Doctor Jekyll NF", 48 ) normalText:setTextColor(0,1,0) local bitmapText = bmf2.newText("Bitmap Font : Doctor Jekyll NF", 10, 100, "Doctor Jekyll NF", 48 ) bitmapText:setTextColor(0,1,0)

Corona’s display.newText() function will multiply the point size you give it with the content scale.

For example, if you use a content width and height of 320x480 (standard iPhone resolution), then on an iPhone 4 retina display, the content scale would be x2.  So, that means the font size you give this function will be multiplied by 2, which makes sense in this particular case because you pixel widthxheight of an iPhone retina is twice as big (but same physical size) so you need a twice as large font size.

I was confused about why I couldn’t change my Build Action for a while until I realized I had to stop the game running first… It’s not obvious from the UI.

You can set the “Build Action” property of a file to “Content” by following steps 5 and 6 in the link below.  Note that you cannot change this property if your in the middle of compiling or debugging your app project.

   http://docs.coronalabs.com/daily/coronacards/wp8/portapp.html#copying-project-files

If you want good 60 FPS performance, then I’m afraid that you don’t have much choice but to switch to bitmap fonts.  But the good news is that by doing this, you’ll be increase the performance on Android and iOS too.  It would be especially noticeable on Android.  The only other method that I can think of is to pre-load text objects (still an initial performance hit) and re-use them when needed, but remember that text objects are really bitmap/textures so this is an extensive thing to do from a memory/RAM perspective.  Especially since low-memory WP8 devices are very popular.

You can use the following code to print the average FPS to the Visual Studio “Output” panel…

local lastEnterFrameTime = nil local durationCollectionSize = display.fps local durationCollectionIndex = 1 local durationCollection = {} for index = 1, durationCollectionSize do durationCollection[index] = 0 end local function onEnterFrame(event) local currentTime = system.getTimer() -- If this is the first frame, then fetch the current time and exit out. if (lastEnterFrameTime == nil) then lastEnterFrameTime = currentTime return end -- Store the duration since the last frame. durationCollection[durationCollectionIndex] = currentTime - lastEnterFrameTime lastEnterFrameTime = currentTime -- Do not continue if we have more durations to collection before averaging below. if (durationCollectionIndex \< durationCollectionSize) then durationCollectionIndex = durationCollectionIndex + 1 return end -- Average the collected durations and print it to the log. local averageDuration = 0 for index = 1, durationCollectionSize do averageDuration = averageDuration + durationCollection[index] end averageDuration = averageDuration / durationCollectionSize local averageFps = 1000 / averageDuration print("Average FPS = " .. tostring(averageFps) .. ", Average Duration = " .. tostring(averageDuration)) -- Reset data collection. durationCollectionIndex = 1 end Runtime:addEventListener("enterFrame", onEnterFrame)

That’s the thing,

I can’t change my files from “None” to “Content” since on the properties panel it seems the only option available. I’ve googled and found some solutions but most of them involving hacking the registry?

Please don’t change the registry.  It won’t resolve this.  Changing the “Build Action” will make a change to your *.csproj file.

I’m kind of perplexed as to why you only a see “None” in the drop down menu.  No one else is having this problem.  Are you sure you are left clicking the file in the “Solution Explorer” panel to highlight it before clicking on the “Build Action” property?  A file must be selected before you can see its properties.  And in the “Properties” panel, you need to click on the field to the right of the “Build Action” label to make the drop-down box appear.  (If you already know all this then I apologize, but I’m kind of scratching me head as to why you’re not seeing these options.)

Hi Joshua,

Thanks for being very patience. Apparently scrapping the solution and just created  a new one solved the problem and now I got my game running.

After stripping all the text rendering in the game, it runs wonderfully smooth at almost 60 fps all the time :). I noticed that it seems the font problem only happens when there’s an update on the text. I guess it has to redraw everything and that’s an expensive operation.

For now, I think we’re gonna leave the GUI where the static text doesn’t change much to use the old fonts since it seems once it  renders on the screen then the fps is back to normal again.

For dynamic text we have to change to bitmap font i guess but at least it won’t take too much time to port

 

Oh good.  I’m glad you got it working now.

Yeah, we worked really hard to achieve 60 FPS support, which is not an easy thing to do in a Silverlight/XAML based app.  I know many game developers struggle with this on WP8 and this is something that we wanted to “just work” on this platform.

Regarding text rendering, you’re right.  The performance hit happens when you create the text via display.newText() and when you update the text.  It’s really only an issue when you update the text often, such as during gameplay, or when you’re creating several text objects at once.  I think display.newText() is fine to use if you have just a few text objects which never update, such as on a menu screen, or if it comes from a source whose text that you cannot control, such as Facebook or Twitter.

Anyways, I hope you have a good experience porting your app to WP8!

We tried to make our native integration as easy as possible in Visual Studio.  Much easier than it is with Android and iOS right now.

Hi Joshua,

Yes, I think I got it all figured out but one thing though… I’m not sure who to ask about this but the problem is about fontsize.
What I want to know is how does Corona render font according to its fontsize?

I’m trying to see if I can match my bitmap font exactly like display.newText but there’s a size difference in the fontsize that I don’t understand.
I’m using bmGlyph to bake a 48pt font bitmaps and try to compare it with what Corona produce and there’s a big difference in size.

CbofE4n.png
Both are supposed to be 48pt font but what corona renders is larger than the bitmap font.

Any help in figuring this out? My goal is to be able to do this which already working good enough other than the font size problem :

local normalText = display.newText("Corona Font : Doctor Jekyll NF", 10, 200, "Doctor Jekyll NF", 48 ) normalText:setTextColor(0,1,0) local bitmapText = bmf2.newText("Bitmap Font : Doctor Jekyll NF", 10, 100, "Doctor Jekyll NF", 48 ) bitmapText:setTextColor(0,1,0)

Corona’s display.newText() function will multiply the point size you give it with the content scale.

For example, if you use a content width and height of 320x480 (standard iPhone resolution), then on an iPhone 4 retina display, the content scale would be x2.  So, that means the font size you give this function will be multiplied by 2, which makes sense in this particular case because you pixel widthxheight of an iPhone retina is twice as big (but same physical size) so you need a twice as large font size.

I was confused about why I couldn’t change my Build Action for a while until I realized I had to stop the game running first… It’s not obvious from the UI.