Is there a way to draw a long text on the screen using SpriteBatch.DrawString? I mean inserts new lines when comes to the end of the screen.
I'd suggest looking at XNAwiki - TextRendering.
Inserting new lines is something you'd have to calculate yourself it's not something you an do automatically with the XNA framework, but yes it's possible to write code to do that.
One way to do it would be to take the string want to write and to move through it a word at a time an measure it until you get enough words to fill the width of whatever area it is you want to fill. Once you've found that width, you'd either change the Y Position of the string you want to draw and move onto the next line or insert a new line character into the string at that point and start calculating the amount of words that should be on the next line.
A thing to pay attention to is that string manipulation is expensive and generates a lot of garbage so you should try and minimize the amount of times you do something like that. If the text is static and never changes it would be ideal to do this one and never again while the game is running.
Related
I am following this guide which contains a brush and eraser functionality. The guide's code sets the "globalCompositeOperation" to "destination-out" and basically ends up creating another line that will cover whatever you have drawn before with the brush.
This would work pretty well in some cases, but if I made my "destination-out" lines not-draggable and the "source-over" lines draggable, then if I drag the "source-over" lines around the canvas these lines would still be intact and it would not look like as if they were erased.
In a better attempt to explain my problem, I provide you this example: If I were to create two parallel lines, line1(x1,y1) and line2(x2,y2), and then I decide to draw a "destination-out" line in the middle of both, is there a way I can keep that "erased" part in the middle of line1 and line2 if I were to move one of the lines away from the "destination-out" line?
I'm sure it is not like this, but is it possible to change certain points inside the line as "destination-out" while the rest of the points are "source-over" If not, how can we simulate this action without having to create a long static extra "destination-out" line?
A multiline auto typing text box class (which uses an SKNode as the parent) is created using basically 2 elements:
an SKSpriteNode that acts as text box frame & background image/texture holder.
an NSMutableArray containing a set limited amount (rows) of NSStrings that each have a set character length.
After modifying this text box class so that it can be initialized with any frame width & height, I realized I didn't program the NSMutableArray to automatically change its content in a such way that it nicely fits within the background node (with a bit of padding involved as well). So here I am wondering how to do that since NSString's can only return the character count and not the width & height of each string in points (points could have maybe helped me create character constraints in some way).
Right now, the NSMutableArray uses a hardcoded maximum character count per NSString & a maximum row count for the entire array (it's 5 rows right now and when that limit is reached, a new "page"/array is created). This forces me to manually re-adjust these parameters every time I change the background node frame size which defeats the purpose of the class allowing the background frame to change.
Thing is, I'm trying to solve this in such a way that when I post this class on github, I want the solution to take into consideration any fontName & fontSize.
What are my options for solving this problem?
I've done something similar to this. It doesn't work 100% as to what you want, but should be similar enough. It uses a root node and from there, it will build multi-line text using an array of NSString which will in turn be used to build the SKLabelNode.
I'll outline what I did. I should also say I only run this when new text is set. In other words, I do not incur the penalty of deriving the information every frame. Only once.
The generalized steps are:
You will iterate over each character in the text string. Note I do this because my code supports word wrapping as well as other alignment capabilities. So for me, I want that level of control. As this is being done only upon creation, I'm fine with the overhead. If you don't want to word wrap you could always just create an array of words and work from there.
As you iterate over each character, you'll be generating an array of lines. Where each line in the array is a line that will fit in your frame. For now let's not worry about vertical constraints. So here we are primarily worried about width. For the current line, each character you are iterating over will get added to the current line. For this potential line string, you will use NSString's sizeWithAttributes, which is configured for your font. For example in my code it is an NSDictionary which contains: NSFontAttributeName : [UIFont fontWithName:self.fontName size:self.size]. This will be used to check the width, if that width exceeds the frame width, you are overrunning the line.
So the code may look something like:
size = [line sizeWithAttributes:attributes];
if (size.width > maxTextWidth) {
needNewline = YES;
}
If you have overrun a line, you need to determine if you are word wrapping. If you are, you can just add the current line (minus one character) to the lines array. If not you have prune off the last word in the current line and then add that to the array of lines.
The tricky parts are dealing with whitespace and handling non-word wrapped overflow. I have not addressed whitespace but you need to consider this very much in your code. Additionally, you also do want to factor in leading pixels, etc.
Once you have your array of lines, you can then create your children SKLabelNodes. I add them to the root, which allows me to move the group anywhere it needs to be.
The real key here is the lines array generation.
I would like to implement karaoke-like progress highlight for iOS.
I know I could use NSAttributedString and highlight the text character by character. However, I would like the highlight to progress pixel by pixel, not character by character.
Any ideas?
P.S. No need for sample code, just point me to the right direction.
Here is an example:
I can't think of any automatic way to do that. There would be several problems to solve. It would be pretty hard, I think.
The hardest would probably be figuring out the pixel position of each word so you can pace the coloring to match the timing within the music. With text and attributed layout, you could probably get the text engine to give you the boundaries of each word and then apply the color attribute to each word as it's spoken/sung. You'd have to have data about the time offset for the beginning and end of each word's being sung.
You might have to use Core Text to get layout information about the bounding rectangles of each word.
Once you get that you could build a path (UIBezierPath or CGPath; they're pretty interchangeable) that follows the flow of the text, and then install that path in to a shape layer. You could then make the text transparent, make the shape layer a colored background that shows through, and animate the shape layer's strokeStart and/or strokeEnd properties to make it fill the text. You might need to do it word by word with a short animation that interpolates between one word and the next to get the timing right.
You probably want to have a look at Core Text, which is the lower level framework used for laying out text, using this you can obtain necessary paths that you need to render said effect (I suggest starting from answers similar to this)
There are plenty of answers for alternative, perhaps simpler answers, for example character by character or word-by-word, which may be easier to implement.
Good day everyone.
I'm trying to draw the text "Pass Complete!" to screen with this code:
spriteBatch.DrawString(font, "PASS COMPLETE!", new Vector2(30, 130), Color.White);
Which does fire off the proper IF statement. However, how do I go about then removing that text from the screen? I'm really not sure at all where to go on from here and my instructor wants me to google the answer or find it in textbook. I have been all over my XNA textbook and I have found no outlet to removing that text.
Thanks for any and all help.
Update:
protected override void Draw(GameTime gameTime)
I have the IF statement included in here. Basically it checks collision with p_Receiver and if it the bool checks out, it draws the DrawString. Should I maybe be looking at this from a different angle?
Final:
I went ahead with the following as the answer and it's working better then before. :)
if (PassInfo == 3) {
(timer code)
(IF timer not "used up" then run the draw)
Working good for now.
I appreciate it.
I'm doing this by function that add text with some parameters into generic list. and then i update and draw items from that list. in pseudo code:
function addText(text,position,duration)
texts.add(new t(text,position,duration))
end function
function updateText()
for each t as text in texts.findall(where t.active)
t.duration -= 1
if t.duration < 0 then t.active = false
next
end function
function drawText()
for each t as text in texts.findall(where t.active)
//draw it
next
end function
so by this you can add unlimited number of texts on different position and duration on screen.
A lot of games redraw the entire window / screen each time through the draw cycle so there's a distinct chance that the solution to removing it is simply to stop drawing it.
i.e. have your if condition not draw the text when it is no longer required.
If, on the other hand, you've some more complex drawing logic that only draws portions of the window / screen that need updating then you'll need to include logic to redraw that part of the screen that contained the text once it is no longer needed.
I am writing a vba macro that checks that word documents are formatted correctly to meet certain specifications. One of the things I have to check for are the left margins of each line - different paragraphs are supposed to have different first indents and hanging indents depending on the context. This should be as simple as checking the style, but unfortunately it is not - some of the documents use styles to change the indents, but others use manual spaces and tabs to position the text correctly. So I need some way to check the actual physical position of the first physical character in each Document.Paragraphs. I have no problem getting a range with the first visible character in the paragraph, but I'm not sure about getting the distance from the margin (or from the left side of the page - doesn't make a difference because the margins are consistent).
I found the Window.GetPoint method, but I'm nervous to use it, because that is based on the actual physical location on the screen. This macro is going to be used on different computers, with different versions of word, and I'm not sure about how it is affected by other view settings (like print layout, zoom, etc.) Is there a consistent way to use this method to determine the distance from the margin?
The other method would be (because all of the documents are in Courier New 12) to look at the firstindent property of the style, and the count manually all of the spaces and tabs (but that would need to take into account tabstops). This I'm also not sure how to do.
I would think that there should be a much simpler way of doing this, but I can't find it, so if anyone has any suggestions I would really appreciate any help.
It was there after all! Range.Information(wdHorizontalPositionRelativeToPage)