So I reverently updated to Xcode 7 Beta and I'm somewhat unsure as to whether that is pertinent information but I figured I'd mention it anyway. My issue is that when I use the convertPointToView() function, it calls for an argument of type SKScene whereas (obviously) I want to it to take a point. I have another class which doesn't inherit SKScene where I want to use this function and it errors with "use of unresolved identifier convertPointToView" (I am importing SKScene). I find this to be very strange since I've written other programs that use this function and work fine even with the Xcode 7 beta, however, it doesn't seem to be working here. If anyone knows why I am having all this trouble, I'd really appreciate some help.
import Foundation
import SpriteKit
import SceneKit
class StandardLabel: UILabel {
init(x: Double, y: Double, width: Double, height: Double, doCenter: Bool, text: String, textColor: UIColor, backgroundColor: UIColor, font: String, fontSize: CGFloat, border: Bool, sceneWidth: Int) {
var frame = CGRect()
if doCenter {
frame = CGRect(x: convertPointToView(CGPoint(x: sceneWidth / 2, y: 0)).x, y: height, width: width, height: height)
} else {
frame = CGRect(x: x, y: y, width: width, height: height)
}
super.init(frame: frame)
self.text = text
self.textColor = textColor
self.backgroundColor = backgroundColor
self.textAlignment = NSTextAlignment.Center
self.font = UIFont(name: font, size: fontSize)
if border {
super.layer.borderColor = UIColor.blackColor().CGColor
super.layer.borderWidth = 5
}
}
I'd suggest that if you want to add text within your scene, that you use SKLabelNode, because it uses the same coordinate system as the other items that you'll be aligning, and you won't have to worry about converting your coordinates between different systems.
Use a UILabel if you want to display text outside of your scene (although for a SpriteKit (2D) game this wouldn't make sense because they're full screen, and I think would make sense mostly if you're making a SceneKit (3D) game).
Also, you don't need to make a subclass just to set default color and text size, it probably makes more sense to have this as a private helper method on your scene.
SKLabelNode doesn't have any 'border' property (like UILabel.layer does) so instead you'll need to draw an outline using SKShapeNode. This example uses the exact frame of the label so the text and the border are touching. You probably want to add a gap so there's space between the text and border but I'll leave that to you.
Here's a commented code snippet that adds two labels to a scene: "Baore" at size 80 with red text and border, and the label "Hello" at size 30 with blue text and border. Both are centered horizontally, "Baore" is also centered vertically, "Hello" is offset from the center by 150.
You could have also moved the position logic into the helper function, but to me that just feels weird... but up to you to decide how you want to do that!
import SpriteKit
class GameScene: SKScene {
override func didMoveToView(view: SKView) {
// `makeLabelWithOutline` is a helper function that takes 3 parameters
// - labelText
// - textSize
// - tint color to use for text and outline
// because textSize and tint have default values, you can
// omit them, and the default values will be used instead
// so this will be a label with text "Baore" at size 80 and red text and outline
let baoreLabel = self.makeLabelWithOutline("Baore")
baoreLabel.position = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame))
self.addChild(baoreLabel)
// so this will be a label with text "Hello" at size 30 and blue text and outline
let helloLabel = self.makeLabelWithOutline("hello", textSize: 30, tint: UIColor.blueColor())
helloLabel.position = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame)+150)
self.addChild(helloLabel)
}
private func makeLabelWithOutline(labelText:String, textSize:CGFloat = 80, tint:UIColor = UIColor.redColor()) -> SKNode {
let myLabel = SKLabelNode(fontNamed:"Futura-CondensedExtraBold")
myLabel.text = labelText
myLabel.fontColor = tint
myLabel.fontSize = textSize
// create the outline for the label
let labelOutline = SKShapeNode(rect: myLabel.frame)
labelOutline.strokeColor = tint
labelOutline.lineWidth = 5
labelOutline.addChild(myLabel)
return labelOutline
// we're returning an SKNode with this hierachy:
// SKShapeNode (the outline)
// ↳ SKLabelNode (the "Baore" label)
}
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
}
}
convertPointToView
is an instance method of an SKScene object so you'll need to call it on some instance of an SKScene (maybe pass in a reference to the entire scene instead of just the sceneWidth
?)
I'm not sure if it helps, but there's also convertPoint:toView:
which might make more sense if you're dealing with a UILabel (??)