2013-10-06 2 views
13

Я не нахожу поддержки для dropshadow или контура шрифта в Sprite Kit. Для dropshadow я предполагаю, что могу создать второй SKLabelNode и смещать его за другим.Каким будет лучший подход для выделения или отбрасывания шрифта?

Есть ли способ, которым я мог бы использовать SKEffectNode для контура или dropshadow? Возможно, SKLabelNode является дочерним элементом SKEffectNode?

обновление:

Я был в состоянии получить приличный Dropshadow с использованием второго SKLabelNode позади первой, то есть черный и смещение. Все еще интересуются другими потенциальными вариантами, но это, похоже, работает хорошо.

+1

Отбрасывание и очертание не отличаются от светящихся. См. [Мой ответ на ваш другой вопрос об этом] (http://stackoverflow.com/a/19237349/957768), и вы можете настроить технику, чтобы получить необходимый эффект. – rickster

+0

Да, это именно то, что пришло в голову. Но я хочу, чтобы схема была более резкой, поэтому мне нужно посмотреть, что я могу придумать. – prototypical

+0

Размытая копия изображения создает хороший эффект свечения. Чтобы превратить это нечеткое свечение в сплошной контур, просто увеличьте альфу размытого изображения - попробуйте фильтр 'CIColorMatrix' с параметром' inputAVector' чего-то типа '[0 0 0 10]'. – rickster

ответ

17

Это, скорее всего, то, что вы делаете, но оно работает и прост.

- (SKLabelNode *) makeDropShadowString:(NSString *) myString 
{ 
    int offSetX = 3; 
    int offSetY = 3; 

    SKLabelNode *completedString = [SKLabelNode labelNodeWithFontNamed:@"Arial"]; 
    completedString.fontSize = 30.0f; 
    completedString.fontColor = [SKColor yellowColor]; 
    completedString.text = myString; 


    SKLabelNode *dropShadow = [SKLabelNode labelNodeWithFontNamed:@"Arial"]; 
    dropShadow.fontSize = 30.0f; 
    dropShadow.fontColor = [SKColor blackColor]; 
    dropShadow.text = myString; 
    dropShadow.zPosition = completedString.zPosition - 1; 
    dropShadow.position = CGPointMake(dropShadow.position.x - offSetX, dropShadow.position.y - offSetY); 

    [completedString addChild:dropShadow]; 

    return completedString; 
} 

будет пытаться сделать наброски один, а ... но у меня есть чувство, что это будет сложнее ... там должен быть способ использовать растровые шрифты .. ??? bmGlyph ...

+0

Я выяснил тень, как у вас здесь. План, который я до сих пор не понял, способ сделать. Я тоже думаю о растровых шрифтах, но все равно одинаково заинтересован в том, как это сделать. Я уверен, что это будет очень распространенный вопрос для людей, начинающих работу с Sprite Kit. – prototypical

+0

звучит так, как будто они идут http://stackoverflow.com/questions/18954144/sprite-kit-and-bitmap-fonts – DogCoffee

+0

Да, я видел этот комментарий раньше. Я должен поверить, что скоро мы увидим больше возможностей. Я не слишком близко смотрел на код SpriteKit, чтобы понять, что это может быть. – prototypical

0

Что касается описанием:

Короткий ответ: У вас есть ваша работа вырезал для вас.
Длинный ответ: У вас действительно есть ваша работа, вырезанная для вас.

Мы делали это над проектом, и основным подходом было создание UILabel и визуализация его в текстуру, которая входит в спрайт.
Чтобы получить контур на UILabel, вы можете использовать это: How do I make UILabel display outlined text? и сделать что в UIImage (которые вы можете сделать текстуру с [SKTexture textureWithImage: IMG]), используйте: How to create an image from UILabel? Это приходит с проблемы с кулаком, главными из которых были медленное, жадное рендеринг, который в значительной степени решался путем предварительного рендеринга, когда это возможно, для статического текста.

Я не думаю, что вы сможете снять это с помощью узла эффекта из-за точности, которую, как правило, требуют шрифты. Оглядываясь назад, я подумал бы дважды, прежде чем идти по этому пути.

+0

Теперь я смог получить приличную пробную тень с двумя SKLabelNodes, один из которых смещен и черный. С помощью SKEffectNode вы можете использовать опцию shouldRasterize для ее кеширования. – prototypical

+0

Извините, я довольно много говорил об изложении. Я отредактирую ответ, чтобы отразить его. Почему бы просто не использовать две SKLabels для создания тени, как вы сказали. – Kardasis

+0

Да, как я уже сказал, я сейчас пробовал это, и он работает для dropshadow. Я искал варианты, о которых я, может быть, и не подумал бы или не знал бы о том, чтобы очертить и отбросить. – prototypical

1

Это работает для меня:

http://battleofbrothers.com/sirryan/outline-text-in-spritekit

Вот код, который я использовал в сочетании с ASAttributedLabelNode (некоторые из его характерных для меня, как имя шрифта/размер/Цвет заливки/outlinecolor но Конечно, просто использовать свои собственные):

func outlinedCenteredString(string : String, size: CGFloat) -> NSAttributedString 
{ 
    var myMutableString : NSMutableAttributedString 
    var font = UIFont(name: "Super Mario 256", size: size)! 
    var alignment : CTTextAlignment = CTTextAlignment.TextAlignmentCenter 
    let alignmentSetting = [CTParagraphStyleSetting(spec: .Alignment, valueSize: Int(sizeofValue(alignment)), value: &alignment)] 
    var paragraphRef = CTParagraphStyleCreate(alignmentSetting, 1) 

    let textFontAttributes = [ 
     NSFontAttributeName : font, 
     // Note: SKColor.whiteColor().CGColor breaks this 
     NSForegroundColorAttributeName: UIColor.yellowColor(), 
     NSStrokeColorAttributeName: UIColor.blackColor(), 
     // Note: Use negative value here if you want foreground color to show 
     NSStrokeWidthAttributeName:-3 
     //,NSParagraphStyleAttributeName: paragraphRef 
    ] 

    myMutableString = NSMutableAttributedString(string: string, attributes: textFontAttributes as [NSObject : AnyObject]) 

    let para = NSMutableParagraphStyle() 
    para.headIndent = 00 
    para.firstLineHeadIndent = 00 
    para.tailIndent = 0 
    para.lineBreakMode = .ByWordWrapping 
    para.alignment = .Center 
    para.paragraphSpacing = 0 
    myMutableString.addAttribute(
     NSParagraphStyleAttributeName, 
     value:para, range:NSMakeRange(0,1)) 
    return myMutableString 
} 

вместе со следующим использовать эту функцию:

let hintSize = CGFloat(80.0) 
    let hintLabel = ASAttributedLabelNode(size:CGSizeMake(playableRect.size.width*0.9, hintSize)) 

    hintLabel.attributedString = outlinedCenteredString("Touch the Rope to Release the Wood", size: hintSize) 

    hintLabel.position = 
     CGPointMake(
      size.width/2.0, 
      ((size.height - playableRect.size.height)/2.0) + hintSize/2.0 
    ) 

    hintLabel.zPosition = kHintZPosition 
    addChild(hintLabel) 
+0

Хорошее дополнение. С тех пор я тоже делал такое решение. В то время надеялся, что есть чистое решение SpriteKit. Возможно в будущем ? – prototypical

4

Я смог достичь несколько приемлемого «контура», используя не только описанные здесь методы «тени», но и добавив еще три «тени тени».

Другими словами, как только у вас есть нижняя тень на месте, добавьте еще три. Одно смещение к вершине, одно смещение вправо и одно смещение влево - так что у меня есть четыре «тени тени» внизу, а главная ярлык сверху - всего пять SKLabelNodes - только для создания этого контурного эффекта.

В моем приложении я должен анимировать этот текст, поэтому я сделал еще один шаг и создал текстуру растрового изображения из этих пяти меток и создал из этой текстуры один SKSpriteNode, что позволило мне удалить пять исходных ярлыков узлов и анимировать версию растрового изображения.

Он также может быть стоит отметить, что при создании текстуры из узлов этикетки, это привело к размытости текстур, которые я установил на удвоение размера узлов метки перед тем создания текстуры, то уменьшая размер сгенерированной текстуры на 50%.

У меня есть изображение, чтобы показать вам результат. Это может быть не самый элегантный подход, но, похоже, он работает для моей конкретной ситуации. Надеюсь это поможет!

enter image description here

0

Использование ООП! Я реализовал это как новый компонент, потомок SKNode, который содержит два SKLabelNodes, один для самого текста, а другой для его тени:

final class TgSKLabelWithShadow: SKNode 
{ 
    private var lblText: SKLabelNode! 
    private var lblShadow: SKLabelNode! 

    var text: String? 
     {  get { return lblText.text } 
     set { lblText.text = newValue 
       lblShadow.text = newValue } } 

    var fontColor: UIColor? 
     { get { return lblText.fontColor  } 
      set { lblText.fontColor = newValue } } 
    // define additional getters/setters, if necessary. 


    init( position: CGPoint, 
       alignment: SKLabelHorizontalAlignmentMode, 
       text: String, 
       fontName: String, 
       fontSize: CGFloat, 
       fontColor: UIColor, 
       shadowColor: UIColor, 
       shadowOffSet: CGPoint) 
    { 
     super.init() 
     self.position = position 

     lblShadow = SKLabelNode(text: text) 
     lblShadow.fontName = fontName 
     lblShadow.fontColor = shadowColor 
     lblShadow.fontSize = fontSize 
     lblShadow.horizontalAlignmentMode = alignment 
     lblShadow.position = shadowOffSet 
     self.addChild(lblShadow) // add shadow first 

     lblText = SKLabelNode(text: text) 
     lblText.fontName = fontName 
     lblText.fontColor = fontColor 
     lblText.fontSize = fontSize 
     lblText.horizontalAlignmentMode = alignment 
     self.addChild(lblText) // on top of shadow 
    } 

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

Instantiate и добавить к родителю (другой узел или сцены) так:

ndInfo2 = TgSKLabelWithShadow(
     position: CGPoint(x: size.width/2, y: size.height - 170), 
     alignment : .Center, 
     text: "ndInfo2: ???", 
     fontName: "Avenir", 
     fontSize: 40, 
     fontColor: colorText, 
     shadowColor: UIColor.blueColor(), 
     shadowOffSet: CGPoint(x:1, y:-1)) 
    addChild(ndInfo2) 

Очертания? Ну, ничто не мешает вам вложить еще один SKLabelNode, чтобы установить контур. (можно было бы рассчитать его немного больше, чем метка.) Обратите внимание, что порядок добавления дочерних меток является релевантным.

Этот код был протестирован и в настоящее время активно используется в приложении Apple TV, которое я сейчас создаю. С уважением, Тед.

2

Предлагаю MKOutlinedLabelNode.

Пример:

let textNode = MKOutlinedLabelNode(fontNamed: "Helvetica", fontSize: 32) 
textNode.borderColor = UIColor.blackColor() 
textNode.horizontalAlignmentMode = SKLabelHorizontalAlignmentMode.Center 
textNode.fontColor = UIColor.blueColor() 
textNode.outlinedText = "Test" 

enter image description here

Вы также можете проверить ASAttributedLabelNode.

0

Я создал класс, наследующий от SKSpriteNode, где он создает необходимые SKLabelNode и 4 теневые метки в соответствии с параметрами, переданными конструктору.

При изменении любого общедоступного свойства необходимо вызвать метод update(). (BorderSize более 6-7 выглядит смешно.)

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)) 
     } 
    } 
} 

недавний код можно найти на https://gist.github.com/detaybey/214b23731a3b4d0344ce58643795f4b7

1

С прошивкой 11 SKLabelNode имеет attributedText property. Вам необходимо указать strokeColor, strokeWidth и не забудьте указать font и foregroundColor.

Смежные вопросы