Test of putting overlays of text on top of a SpriteKit app.
In particular, mimic typical meme layout with an overlay that stands out against a background picture.
Tapping the screen will switch to a different rendering technique at the end of the touch. If you tap and drag you will see the trail of rectangles which is standard for an SK game.
Using an SKLabelNode built with an NSAttributedString is dramatically faster than the other approaches.
There is a gotcha with the values specified for borders - see this long woeful bug tale.
The initial template for an SK game displays a Hello World using an SKLabelNode that is constructed in the initial GameScene.sks
- you can edit it in the Scene visual editor.
This node type supports a single style specifying font name, size, style and color, or using an NSAttributedString which allows for inline changes of font attributes. It is still a single line of text with control over how it wraps but no easy way to use multiple lines (inserting line breaks programmatically may work)
The sample builds for iOS 9 and when it runs there, the first rendering mode will be mono. On iOS 11 and later, the SKLabelNode
is capable of displaying an attributed string - see makeLabelNode.
The second rendering mode uses UIView objects overlaid on the SKView as sub views. Using a UILabel allows you to use attributed strings regardless of the version. See makeUILabelOverlay
The third test rendering mode uses a web view and HTML to provide the formatting. See makeWebOverlay
. Because the HTML is over the top, you cannot see your interaction with SpriteKit.
The fourth test (pink background) is the same as the third but puts the HTML behind the SpriteKit view, turning it transparent. That allows for interaction with SpriteKit still. Warning this may flicker violently on the simulator. if it appears there at all. See makeWebUnderlay
.
The failing fifth test rendering mode redraws the same web view but saves an image of it and adds that as a SpriteKit node. (with the yellow background). It uses the helper class WebviewImageCapturer
because capturing an image is an async activity only possible after the original finishes rendering. See makeWebImage.
I give up but thought the extra exploration was worth pushing for people to see.
Although the visual scene editor apparently allows you to specify the colour, this doesn't seem to persist and translate into runtime.
Attributed Strings for SKLabelNode were added in iOS 11.
The visual editor supports attributed strings but not wrapping them with inserted linebreaks. If you set the modes correctly, as mentioned below, they will wrap.
There was a useful gist on building multiple label nodes SKMultilineLabel
by Craig Grummitt but only taking a single style and breaking the word wrapping (note this is a complex issue!).
You can use a combination of:
label.lineBreakMode = .byWordWrapping
label.numberOfLines = 0
To get wrapped text - the key is specifying the numberOfLines
as the default is to a single line.
The fifth sample was supposed to be the dream, combining the flexibility of HTML rendered in a web view with getting it into a SpriteNode for all kinds of manipulations.
The only trouble is, WKWebView.takeSnapshot seems to be very buggy on devices.
See this StackOverflow question and this one with the bleak conclusion you can only grab snapshots after you get the web view visible.
Created using XCode 9.4.1 "ios Game" template