How do I do manual text wrapping via a formula instead of a for each-loop?

0 favourites
  • 5 posts
From the Asset Store
OpenAI TTS
$10 USD
Text-to-Speech plugin.Allows your Construct 3 project to convert written text into spoken words
  • Does anyone know of a good formula for word-wrapping based on an variable length limit?

    I.e. if I have String and the length limit is Foo, is there a good formula for splitting String in the right places so that it inserts line breaks where the lines would otherwise have exceeded the length limit?

    Thanks in advance.

  • There's no formula, you'll have to use a loop one way or another. Usually you'd use tokenat to get a word at a time, then you'd measure the width of the text somehow and finally add newlines if you exceed a maxwidth. Rough pseudo code of how that may look is here. There are ways it can be improved.

    var x=0
    var maxwidth=100
    var textInput="some kind of text"
    var textOutput=""
    var word=""
    
    start of layout
    repeat tokencount(textInput, " ") times
    -- set word to tokenat(textInput, loopindex, " ")
    -- add measure(word&" ") to x
    -- compare x > maxwidth
    -- -- add newline to textOutput
    -- -- set x to 0
    -- add word&" " to textOutput
    

    The measure function isn't actually in construct. To measure the text it will depend on how you are displaying text.

    If using the text object the best you have is the Text.textwidth expression but that is only updated when the object is drawn. But Javascript can be used to measure the text. Basically in javascript create a html canvas with a 2d context, set the font, and then use context.measureText(text).width. The main thing you'll have to deal with is the font sizes will be different so the font size will have to be scaled somehow. I can't find an example where I figured that one out.

    With spritefonts it can be easier. It has the spritefont.CharacterWidth(char) expression, but since it only measures a character at a time you'll have to use a loop to add the widths up for the whole word. You can also take advantage of mono spaced spritefonts by calculating the width=len(word)*charwidth.

    An alternate way is to use texture atlas of a font and a json of the widths and where to find the letters.

    Anyways here is a c3p that does the text wrapping manually with the last idea. The logic would basically be the same for the others. I don't have any examples for the other object types.

    dropbox.com/s/67ukw6bak4gvq41/no_dom_text_scroll.c3p

    For simple I often I just use the automatic text wrapping used in the text and spritefont objects. Worst case you can just add the newlines yourself to the text you're using if the automatic stuff isn't satisfactory. Those are the only simple solutions I know

  • That's a nice solution, though wouldn't it be more straight-forward to do something along the lines of:

     var OriginalMessage = "foo foo foo foo foo foo foo foo" 
     var MaxWidth = 10 
     var Index = 0 
     
     // For each word 
     foreach tokencount( OriginalMessage, " " ) 
     	Index = Index + 1 
     	CurrentWord = tokenat( OriginalMessage, Index, " ") 
     	var Line = "" 
     	var Message "" 
     
     	// The Line can fit more words
     	if ( len( Phrase ) + len( CurrentWord ) ) < MaxWidth 
     		Line = Line + CurrentWord 
     
     		// Add the last line in loop 
     		if Index == tokencount( OriginalMessage, " " ) 
     			Phrase = Phrase + newline + Line 
     
     	// Line is full, clear it 
     	else 
     		Phrase = Phrase + newline + Line 
     		Line = CurrentWord 
    

    I still think that this could somehow be expressed through a formula though. I wonder if anyone here has figured it out without looping.

  • That would perhaps work with a monospaced font. In general most fonts are variable width.

    I like formulas, but something like this doesn’t reduce to one. You can put it all in a function to reuse it though

  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • What's wrong with looping?

    Without looping you would be able to insert breaks but they would not be taking word length or spaces into account.

    I'd approach this with len() too, but using len() isn't perfect though. Just counting characters does not guarantee that any given string will fit into a certain pixel width, since different characters take up different amounts of horizontal space. That's why rojo discusses measuring the text.

Jump to:
Active Users
There are 1 visitors browsing this topic (0 users and 1 guests)