2016-02-01 6 views
8

Ich muss in der Lage sein, ein Multi-Line-Label in Swift 2 Sprite-Kit für ein Spiel zu machen. Der Text muss sich um den Bildschirm herum bewegen, anstatt ihn zu verlassen. Bellow ist, was ich habe, aber ich weiß nicht, wasMehrzeiliges Etikett im Swift 2 Sprite-Kit?

import Foundation 
import UIKit 
import SpriteKit 

class JDQuotes: SKLabelNode { 

    var number = 0 

    init(num: Int) { 
     super.init() 

     if num == 1 { 

      text = "\"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. laborum.\"" 

     } 
    } 

    required init?(coder aDecoder: NSCoder) { 
     fatalError("init(coder:) has not been implemented") 
    } 
} 
+0

ich würde uns einfach ein UIlabel und als Unteransicht hinzufügen, über dem SKView. – jarryd

+0

Hier ist eine Lösung von Drittanbietern. SKLabels unterstützt im Allgemeinen keine Mehrfachzeilen. 'https: // craiggrummitt.wordpress.com/2015/04/10/multi-line-sklabels-in-swift /' – Akaino

Antwort

3

zu tun Es gibt eine Github Lösung über here als SKLabelNodes unterstützen nicht mehrere Linien.

-Code zitiert:

import SpriteKit 

class SKMultilineLabel: SKNode { 
//props 
var labelWidth:Int {didSet {update()}} 
var labelHeight:Int = 0 
var text:String {didSet {update()}} 
var fontName:String {didSet {update()}} 
var fontSize:CGFloat {didSet {update()}} 
var pos:CGPoint {didSet {update()}} 
var fontColor:UIColor {didSet {update()}} 
var leading:Int {didSet {update()}} 
var alignment:SKLabelHorizontalAlignmentMode {didSet {update()}} 
var dontUpdate = false 
var shouldShowBorder:Bool = false {didSet {update()}} 
//display objects 
var rect:SKShapeNode? 
var labels:[SKLabelNode] = [] 

init(text:String, labelWidth:Int, pos:CGPoint, fontName:String="ChalkboardSE-Regular",fontSize:CGFloat=10,fontColor:UIColor=UIColor.blackColor(),leading:Int=10, alignment:SKLabelHorizontalAlignmentMode = .Center, shouldShowBorder:Bool = false) 
{ 
    self.text = text 
    self.labelWidth = labelWidth 
    self.pos = pos 
    self.fontName = fontName 
    self.fontSize = fontSize 
    self.fontColor = fontColor 
    self.leading = leading 
    self.shouldShowBorder = shouldShowBorder 
    self.alignment = alignment 

    super.init() 

    self.update() 
} 

//if you want to change properties without updating the text field, 
// set dontUpdate to false and call the update method manually. 
func update() { 
    if (dontUpdate) {return} 
    if (labels.count>0) { 
     for label in labels { 
      label.removeFromParent() 
     } 
     labels = [] 
    } 
    let separators = NSCharacterSet.whitespaceAndNewlineCharacterSet() 
    let words = text.componentsSeparatedByCharactersInSet(separators) 

    let len = countElements(text) 

    var finalLine = false 
    var wordCount = -1 
    var lineCount = 0 
    while (!finalLine) { 
     lineCount++ 
     var lineLength = CGFloat(0) 
     var lineString = "" 
     var lineStringBeforeAddingWord = "" 

     // creation of the SKLabelNode itself 
     var label = SKLabelNode(fontNamed: fontName) 
     // name each label node so you can animate it if u wish 
     label.name = "line\(lineCount)" 
     label.horizontalAlignmentMode = alignment 
     label.fontSize = fontSize 
     label.fontColor = UIColor.whiteColor() 

     while lineLength < CGFloat(labelWidth) 
     { 
      wordCount++ 
      if wordCount > words.count-1 
      { 
       //label.text = "\(lineString) \(words[wordCount])" 
       finalLine = true 
       break 
      } 
      else 
      { 
       lineStringBeforeAddingWord = lineString 
       lineString = "\(lineString) \(words[wordCount])" 
       label.text = lineString 
       lineLength = label.width 
      } 
     } 
     if lineLength > 0 { 
      wordCount-- 
      if (!finalLine) { 
       lineString = lineStringBeforeAddingWord 
      } 
      label.text = lineString 
      var linePos = pos 
      if (alignment == .Left) { 
       linePos.x -= CGFloat(labelWidth/2) 
      } else if (alignment == .Right) { 
       linePos.x += CGFloat(labelWidth/2) 
      } 
      linePos.y += CGFloat(-leading * lineCount) 
      label.position = CGPointMake(linePos.x , linePos.y) 
      self.addChild(label) 
      labels.append(label) 
      //println("was \(lineLength), now \(label.width)") 
     } 

    } 
    labelHeight = lineCount * leading 
    showBorder() 
} 
func showBorder() { 
    if (!shouldShowBorder) {return} 
    if let rect = self.rect { 
     self.removeChildrenInArray([rect]) 
    } 
    self.rect = SKShapeNode(rectOfSize: CGSize(width: labelWidth, height: labelHeight)) 
    if let rect = self.rect { 
     rect.strokeColor = UIColor.whiteColor() 
     rect.lineWidth = 1 
     rect.position = CGPoint(x: pos.x, y: pos.y - (CGFloat(labelHeight)/2.0)) 
     self.addChild(rect) 
    } 

} 
} 

EDIT: Genauso gut könnte man this version überprüfen, wie es 11 für Swift2

+0

Ein Problem dabei ist, dass SKLabelNode nicht in Chargen wie SKSpriteNode gerendert wird. Wenn Sie also 20 Zeilen haben, werden 20 Zeichen benötigt, was sich auf die Leistung auswirken kann. Sie könnten versuchen, einem SKEffectNode eine Multi-Label-Instanz hinzuzufügen und sie dann zu rastern. Dadurch werden die für mehrzeilige Etikettenrendering benötigten Zeichenschritte auf 1 reduziert. – Whirlwind

+0

Ich habe bis jetzt keine extremen Leistungsprobleme bemerkt. Ich bin nicht übermäßig mit mehrzeiligen Etiketten, also könnten Sie Recht haben. – Akaino

+1

Ich schätze deine Bemühungen, versteh mich nicht falsch, aber du verstehst bestimmte Situationen nicht. Das Übergeben einer Zeichenfolge, die länger als "labelWidth" ist, endet in der Endlosschleife (im Moment des Sprechens). – Whirlwind

4

Ab iOS aktualisiert wird, wird dies schließlich möglich mit SKLabelNode:

let lb = SKLabelNode(fontNamed: "Copperplate") 
    lb.text = "Put your long text here..." 
    lb.numberOfLines = 0 
    lb.preferredMaxLayoutWidth = 1000