Using extensions can make the life of a programmer much easier.
Here are some extensions that I use regularly.
When I need to create containers, and establish margins, or calculate how much bigger a container should be, to fit something inside of it, I use this function. I noticed I was using SKNode calculateAccumulatedFrame() and then adding margins a lot, so I made this useful function.
Usually I know exactly the width in which I want to fit some text. Even if it is long, I wanted to create a type of label where I just pass a few arguments, and it generates the labels for me. That is what this function does.
The last two functions were created to avoid too many lines of coding, and also when a SKNode has many children, it is a quick method to remove them all by the end of an animation.
extension SKNode{
/** Calculates Accumulated frame of Node + margins defined */
func calculateFrameWithMargins(height:CGFloat, width:CGFloat) -> CGRect{
let oldFrame = self.calculateAccumulatedFrame()
let originX = oldFrame.origin.x - width
let originY = oldFrame.origin.y - height
let newWidth = oldFrame.size.width + (2 * width)
let newHeight = oldFrame.size.height + (2 * height)
return CGRect(x: originX, y: originY, width: newWidth, height: newHeight)
}
func createMultilineLabel(message:String, maxWidth:CGFloat, fontSize:CGFloat, aligned:SKLabelHorizontalAlignmentMode){
let mainLabel = SKLabelNode(fontNamed: GameFontNames.inconsolata)
mainLabel.fontSize = fontSize
mainLabel.horizontalAlignmentMode = aligned
mainLabel.verticalAlignmentMode = .top
mainLabel.color = SKColor.lightGray
let tArray = message.components(separatedBy: " ")
var lastFittingLabel:SKLabelNode = mainLabel.copy() as! SKLabelNode
lastFittingLabel.text = ""
var builtLabels:[SKLabelNode] = []
var lblPosY:CGFloat = 0.0
print("word array")
for windex in 0...tArray.count - 1{
let word = tArray[windex]
let trialLabel:SKLabelNode = lastFittingLabel.copy() as! SKLabelNode
if let previousText = trialLabel.text{
if previousText == "" {
trialLabel.text = word
}else{
trialLabel.text!.append(" \(word)")
}
}else{
trialLabel.text = word
}
let labelWidth = trialLabel.calculateAccumulatedFrame().width
if labelWidth > maxWidth{
// does not fit. Add the last one to the array
lastFittingLabel.position = CGPoint(x: 0.0, y: lblPosY)
builtLabels.append(lastFittingLabel.copy() as! SKLabelNode)
// Update height of next Label
let heightChange = lastFittingLabel.calculateAccumulatedFrame().height + 2.0
lblPosY -= heightChange
// as this word doesn't fit, we need to add it to the next label
lastFittingLabel.text = word
}else{
// does fit. update
lastFittingLabel = (trialLabel.copy() as! SKLabelNode)
}
// Add the last one
if windex == tArray.count - 1{
lastFittingLabel.position = CGPoint(x: 0.0, y: lblPosY)
builtLabels.append(lastFittingLabel)
}
}
for label in builtLabels{
self.addChild(label)
}
}
/** Removes all children */
func clearAllChildren(){
// Clear the children
if self.children.count > 0{
for child in children{
child.removeFromParent()
}
}
}
/** Removes self from parent */
func clearFromParent(){
if let _ = self.parent{
self.removeFromParent()
}
}
}