I\'m not finding any support for dropshadow or outline of a font in Sprite Kit. For the dropshadow, I\'m guessing I could create a second SKLabelNode and offset it behind t
I've been able to achieve a somewhat acceptable "outline" by not only using the "2 SKLabelNode" dropshadow techniques described here, but also by adding three more "drop shadows".
In other words, once you have the bottom dropshadow in place, add three more. One offset toward the top, one offset toward the right, and one offset toward the left — so I have four "drop shadows" underneath, with the main label on top for a total of five SKLabelNodes just to create this outline effect.
In my app, I have to animate this text, so I took it one step further and created a bitmap texture from these five labels and created a single SKSpriteNode from this texture, which allowed me to then delete the five original label nodes, and animate the bitmap version.
It might also be worth noting that by creating a texture from the label nodes, it resulted in a blurry texture, which I fixed by doubling the size of the label nodes before creating the texture, then reducing the size of the generated texture by 50%.
I am attaching an image to show you the result. It may not be the most elegant approach, but it seems to work for my particular situation. Hope this helps!
With respect to outlining :
Short answer: You've got your work cut out for you.
Long answer: You've really got your work cut out for you.
We have been doing this on a project and the basic approach has been to create a UILabel and render it to a texture that goes into a sprite.
To get the outline onto the UILabel, you can use this:
How do I make UILabel display outlined text?
and to render that into a UIImage (that you can make a texture with [SKTexture textureWithImage:img]), use this :
How to create an image from UILabel?
This comes with a fist-full of problems, chief among them being slow, greedy rendering which was largely solved by pre-rendering to file whenever possible for static text.
I don't think you'll be able to pull this off with an effect node because of the precision that fonts tend to require. In retrospect, I would think twice before going down this road.
I created a class inheriting from SKSpriteNode where it creates necessary SKLabelNode and 4 shadow labels according to the parameters passed to constructor.
You need to call the update() method when you changed any public property. (BorderSize more than 6-7 looks funny.)
import Foundation
import SpriteKit
class LFOutlinedLabel : SKSpriteNode {
private let skewX : [CGFloat] = [-1, 1, 1,-1]
private let skewY : [CGFloat] = [-1,-1, 1, 1]
private var label : SKLabelNode = SKLabelNode()
private var shadows : [SKLabelNode] = []
public var borderOpacity : CGFloat = 1
public var borderSize: CGFloat = 1
public var borderColor: UIColor = UIColor.black
public var text : String = "?"
public var fontName : String = Fonts.OptimaExtraBlack.rawValue
public var fontColor: UIColor = UIColor.white
public var fontSize : CGFloat = 40
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
//self.setup()
}
override init(texture: SKTexture!, color: UIColor, size: CGSize) {
super.init(texture: texture, color: color, size: size)
//self.setup()
}
convenience init(size: CGSize, font: String, fSize: CGFloat, fColor: UIColor, bSize: CGFloat, bColor: UIColor, bOpacity: CGFloat)
{
self.init(texture: nil, color: UIColor.clear, size: size)
self.fontName = font
self.fontSize = fSize
self.fontColor = fColor
self.borderSize = bSize
self.borderColor = bColor
self.borderOpacity = bOpacity
self.setup()
}
// create shadow labels
private func setup() {
if shadows.count == 0 {
let width = self.size.width / 2
let height = self.size.height / 2
for j in 0...3 {
let shadow = SKLabelNode(text: self.text)
addChild(shadow)
shadow.verticalAlignmentMode = .center
shadow.horizontalAlignmentMode = .center
shadow.zPosition = 999
shadow.position = CGPoint(x: width + (skewX[j] * borderSize) , y: height + (skewY[j] * borderSize))
shadow.text = self.text
shadow.fontSize = self.fontSize
shadow.fontName = self.fontName
shadow.fontColor = borderColor
shadows.append(shadow)
}
let label = SKLabelNode(text: self.text)
addChild(label)
label.verticalAlignmentMode = .center
label.horizontalAlignmentMode = .center
label.zPosition = 1000
label.position = CGPoint(x: width , y: height )
label.text = self.text
label.fontSize = self.fontSize
label.fontName = self.fontName
label.fontColor = fontColor
self.label = label
}
}
public func update(){
let width = self.size.width / 2
let height = self.size.height / 2
self.label.fontSize = fontSize
self.label.fontName = fontName
self.label.fontColor = fontColor
self.label.verticalAlignmentMode = .center
self.label.horizontalAlignmentMode = .center
self.label.text = text
self.label.position = CGPoint(x: width , y: height )
for i in 0...3 {
shadows[i].verticalAlignmentMode = .center
shadows[i].horizontalAlignmentMode = .center
shadows[i].fontColor = borderColor
shadows[i].fontSize = fontSize
shadows[i].alpha = borderOpacity
shadows[i].fontName = fontName
shadows[i].text = text
shadows[i].position = CGPoint(x: width + (skewX[i] * borderSize) , y: height + (skewY[i] * borderSize) )
}
}
}
the recent code can be found at https://gist.github.com/detaybey/214b23731a3b4d0344ce58643795f4b7
I suggest MKOutlinedLabelNode.
Example:
let textNode = MKOutlinedLabelNode(fontNamed: "Helvetica", fontSize: 32)
textNode.borderColor = UIColor.blackColor()
textNode.horizontalAlignmentMode = SKLabelHorizontalAlignmentMode.Center
textNode.fontColor = UIColor.blueColor()
textNode.outlinedText = "Test"
You can also check out ASAttributedLabelNode.