在SpriteKit中使用SKLabelNode插入换行符

Arj*_*ani 31 objective-c ios7 sprite-kit

关于如何使用SpriteKit中的SKLabelNode类插入换行符的简单问题.我有以下代码但它不起作用 -

 SKLabelNode *nerdText = [SKLabelNode labelNodeWithFontNamed:@"Times"];
    NSString *st1 = @"Test break";
    NSString *st2 = @"I want it to break";
    NSString *test = [NSString stringWithFormat:@"%@,\r%@",st1,st2]; //Even tried \n
    nerdText.text = test;
    nerdText.fontSize = 11;
    nerdText.fontColor = [SKColor colorWithRed:0.15 green:0.15 blue:0.3 alpha:1.0];
    nerdText.position = CGPointMake(150.0, 250.0);
    [self addChild:nerdText];
Run Code Online (Sandbox Code Playgroud)

请帮帮我!

Dog*_*fee 16

我不认为你可以,这是一种"黑客"方式来做到这一点

SKNode *nerdText = [SKNode node]; 
SKLabelNode *a = [SKLabelNode labelNodeWithFontNamed:@"Arial"];
a.fontSize = 16;
a.fontColor = [SKColor yellowColor];
SKLabelNode *b = [SKLabelNode labelNodeWithFontNamed:@"Arial"];
b.fontSize = 16;
b.fontColor = [SKColor yellowColor];
NSString *st1 = @"Line 1";
NSString *st2 = @"Line 2";
b.position = CGPointMake(b.position.x, b.position.y - 20);
a.text = st1;
b.text = st2;
[nerdText addChild:a];
[nerdText addChild:b];
nerdText.position = CGPointMake(150.0, 250.0);
[self addChild:nerdText];
Run Code Online (Sandbox Code Playgroud)

  • 我今天遇到了这个问题,尽管这很有效......我希望有一个更好的解决方案,因为这非常hacky. (3认同)

Chr*_*ein 14

我有同样的问题.我为SKLabelNode创建了一个名为DSMultilineLabelNode的替代品,它支持自动换行,换行等.底层实现将字符串绘制到图形上下文中,然后将其应用于SKSpriteNode上的纹理.

它可以在GitHub上找到:

https://github.com/downrightsimple/DSMultilineLabelNode


Jer*_*hao 9

 static func multipleLineText(labelInPut: SKLabelNode) -> SKLabelNode {
        let subStrings:[String] = labelInPut.text!.componentsSeparatedByString("\n")
        var labelOutPut = SKLabelNode()
        var subStringNumber:Int = 0
        for subString in subStrings {
            let labelTemp = SKLabelNode(fontNamed: labelInPut.fontName)
            labelTemp.text = subString
            labelTemp.fontColor = labelInPut.fontColor
            labelTemp.fontSize = labelInPut.fontSize
            labelTemp.position = labelInPut.position
            labelTemp.horizontalAlignmentMode = labelInPut.horizontalAlignmentMode
            labelTemp.verticalAlignmentMode = labelInPut.verticalAlignmentMode
            let y:CGFloat = CGFloat(subStringNumber) * labelInPut.fontSize
            print("y is \(y)")
            if subStringNumber == 0 {
                labelOutPut = labelTemp
                subStringNumber++
            } else {
                labelTemp.position = CGPoint(x: 0, y: -y)
                labelOutPut.addChild(labelTemp)
                subStringNumber++
            }
        }
        return labelOutPut
    }
Run Code Online (Sandbox Code Playgroud)


Oli*_*erD 8

从 iOS 11/macOS 10.13 开始,SKLabelNode有一个numberOfLines属性的行为方式与具有的属性相似UILabel。默认情况下,它设置为 1。如果将其设置为零,则可以拥有无​​限数量的行。另见lineBreakModepreferredMaxLayoutWidth。我认为值得在这里指出这一点,以防有人在看到 Apple 文档之前到达此页面。如果您的最低构建目标是 iOS 11/macOS 10.13,则不需要上面发布的辅助方法。


Jon*_*nny 7

这是你真正的另外五分钟黑客攻击.这不是太糟糕.

+(SKSpriteNode*)spritenodecontaininglabelsFromStringcontainingnewlines:(NSString*)text fontname:(NSString*)fontname fontcolor:(NSColor*)colorFont fontsize:(const CGFloat)SIZEFONT verticalMargin:(const CGFloat)VERTICALMARGIN emptylineheight:(const CGFloat)EMPTYLINEHEIGHT {
    NSArray* strings = [text componentsSeparatedByString:@"\n"];
    //DLog(@"string count: %lu", (unsigned long)strings.count);

    NSColor* color = NSColor.clearColor;
#ifdef DEBUG
    color = [NSColor colorWithCalibratedRed:1 green:0 blue:0 alpha:0.5];
#endif
    SKSpriteNode* spritenode = [SKSpriteNode spriteNodeWithColor:color size:CGSizeMake(0, 0)];

    CGFloat totalheight = 0;
    CGFloat maxwidth = 0;

    NSMutableArray* labels = [NSMutableArray array];
    for (NSUInteger i = 0; i < strings.count; i++) {
        NSString* str = [strings objectAtIndex:i];
        const BOOL ISEMPTYLINE = [str isEqualToString:@""];

        if (!ISEMPTYLINE) {
            SKLabelNode* label = [SKLabelNode labelNodeWithFontNamed:fontname];
            label.text = str;
            label.fontColor = colorFont;
            label.fontSize = SIZEFONT;

            const CGSize SIZEOFLABEL = [label calculateAccumulatedFrame].size;
            if (SIZEOFLABEL.width > maxwidth)
                maxwidth = SIZEOFLABEL.width;
            totalheight += SIZEOFLABEL.height;
            [labels addObject:label];
        }
        else {
            totalheight += EMPTYLINEHEIGHT;
            [labels addObject:[NSNull null]];
        }
        if (i + 1 < strings.count)
            totalheight += VERTICALMARGIN;
    }
    spritenode.size = CGSizeMake(maxwidth, totalheight);

    //DLog(@"spritenode total size: %@", NSStringFromSize(spritenode.size));
    CGFloat y = spritenode.size.height * 0.5;
    const CGFloat X = 0;
    for (NSUInteger i = 0; i < strings.count; i++) {
        id obj = [labels objectAtIndex:i];
        if ([obj isKindOfClass:SKLabelNode.class]) {
            SKLabelNode* label = obj;
            label.verticalAlignmentMode = SKLabelVerticalAlignmentModeTop;
            label.position = ccp(X, y);
            [spritenode addChild:label];
            const CGSize SIZEOFLABEL = [label calculateAccumulatedFrame].size;
            y -= SIZEOFLABEL.height;
        }
        else {
            y -= EMPTYLINEHEIGHT;
        }
        if (i + 1 < labels.count)
            y -= VERTICALMARGIN;
    }

    return spritenode;
}
Run Code Online (Sandbox Code Playgroud)

顺便说一句,你需要

static inline CGPoint ccp( CGFloat x, CGFloat y )
{
    return CGPointMake(x, y);
}
Run Code Online (Sandbox Code Playgroud)


Dan*_*bib 7

因此,在做了一些研究之后,我了解到SkLabelNode并不打算涉及多行字符串.由于功能受SKLabelNode限制,因此简单地使用UILabel来保存文本的位置更有意义.学习如何顺利地将UI元素实现到精灵工具包中,使生活变得更加轻松.UI元素以编程方式创建,并通过使用添加到场景中

[self.view addsubview:(your UIelement)];
Run Code Online (Sandbox Code Playgroud)

所以你要做的就是1.在这种情况下,初始化UIelement的一个UIlabel实例

UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(50, 50, 100, 100)];
label.backgroundColor = [UIColor whiteColor];
label.textColor = [UIColor blackColor];
label.text = @"helllllllllo";
Run Code Online (Sandbox Code Playgroud)

2.创建UIelement后,只需将其添加到视图中使用上述方法

3.我发现重要的是要注意UI元素和SK元素在定位时不会相同.提供了一些简单的方法,如convertPointToView:

-(CGPoint)convertPointToView(CGPoint);
Run Code Online (Sandbox Code Playgroud)

在转换积分方面提供帮助.我希望这有助于祝你好运!


Ben*_*row 6

我为Swift 3编写了一个解决方案.

开源GitHub项目提供了一个Xcode演示项目:https://github.com/benmorrow/Multilined-SKLabelNode

这是SKLabelNode扩展名:

extension SKLabelNode {
  func multilined() -> SKLabelNode {
    let substrings: [String] = self.text!.components(separatedBy: "\n")
    return substrings.enumerated().reduce(SKLabelNode()) {
      let label = SKLabelNode(fontNamed: self.fontName)
      label.text = $1.element
      label.fontColor = self.fontColor
      label.fontSize = self.fontSize
      label.position = self.position
      label.horizontalAlignmentMode = self.horizontalAlignmentMode
      label.verticalAlignmentMode = self.verticalAlignmentMode
      let y = CGFloat($1.offset - substrings.count / 2) * self.fontSize
      label.position = CGPoint(x: 0, y: -y)
      $0.addChild(label)
      return $0
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

以下是您使用它的方式:

let text = "hot dogs\ncold beer\nteam jerseys"
let singleLineMessage = SKLabelNode()
singleLineMessage.fontSize = min(size.width, size.height) /
  CGFloat(text.components(separatedBy: "\n").count) // Fill the screen
singleLineMessage.verticalAlignmentMode = .center // Keep the origin in the center
singleLineMessage.text = text
let message = singleLineMessage.multilined()
message.position = CGPoint(x: frame.midX, y: frame.midY)
message.zPosition = 1001  // On top of all other nodes
addChild(message)
Run Code Online (Sandbox Code Playgroud)

这是应用程序的样子:

模拟器截图多线SKLabelNode