Какой был бы лучший подход для выделения или отбрасывания шрифта?
Я не нахожу поддержки для dropshadow или контура шрифта в Sprite Kit. Для dropshadow я предполагаю, что могу создать второй SKLabelNode и смещать его за другим.
Есть ли способ, которым я мог бы использовать SKEffectNode для контура или dropshadow? Возможно, SKLabelNode является дочерним элементом SKEffectNode?
update:
Я смог получить приличную dropshadow, используя второй SKLabelNode за первым, черный и смещенный. Все еще интересуются другими потенциальными вариантами, но это, похоже, хорошо работает.
Ответы
Ответ 1
Это, скорее всего, то, что вы делаете, но оно работает и прост.
- (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...
Ответ 2
Мне удалось достичь несколько приемлемого "наброска", не только используя описанные здесь методы "тени", но и добавив еще три "тени тени".
Другими словами, как только у вас будет нижняя тень, добавьте еще три. Одно смещение к вершине, одно смещение вправо и одно смещение влево - так что у меня есть четыре "тени тени" внизу, а главная метка сверху для всего пяти SKLabelNodes просто для создания этого контурного эффекта.
В моем приложении мне нужно оживить этот текст, поэтому я сделал еще один шаг и создал текстуру растрового изображения из этих пяти ярлыков и создал из этой текстуры один SKSpriteNode, что позволило мне удалить пять исходных узлов ярлыков, и анимировать версию растрового изображения.
Можно также отметить, что, создав текстуру из узлов метки, это привело к размытой текстуре, которую я исправил, удвоив размер узлов метки перед созданием текстуры, а затем уменьшив размер сгенерированной текстуры на 50%.
Я прикрепляю изображение, чтобы показать результат. Это может быть не самый элегантный подход, но, похоже, он работает для моей конкретной ситуации. Надеюсь, это поможет!
![введите описание изображения здесь]()
Ответ 3
Я предлагаю MKOutlinedLabelNode.
Пример:
let textNode = MKOutlinedLabelNode(fontNamed: "Helvetica", fontSize: 32)
textNode.borderColor = UIColor.blackColor()
textNode.horizontalAlignmentMode = SKLabelHorizontalAlignmentMode.Center
textNode.fontColor = UIColor.blueColor()
textNode.outlinedText = "Test"
![введите описание изображения здесь]()
Вы также можете проверить ASAttributedLabelNode.
Ответ 4
Это сработало для меня:
http://battleofbrothers.com/sirryan/outline-text-in-spritekit
Здесь код, который я использовал в сочетании с ASAttributedLabelNode (некоторые из них специфичны для меня, такие как имя/размер шрифта /fillcolor/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)
Ответ 5
Так как iOS 11 SKLabelNode имеет attributedText
свойство. Вам нужно указать strokeColor
, strokeWidth
и не забывать font
и foregroundColor
.
Ответ 6
Что касается описания:
Короткий ответ: у вас есть ваша работа, вырезанная для вас.
Длинный ответ: у вас действительно есть ваша работа, вырезанная для вас.
Мы делали это в проекте, и основным подходом было создание UILabel и рендеринг его текстуре, которая входит в спрайт.
Чтобы получить схему на UILabel, вы можете использовать это:
Как сделать отображаемый текст в UILabel?
и сделать это в UIImage (чтобы вы могли сделать текстуру с помощью [SKTexture textureWithImage: img]), используйте это:
Как создать образ из UILabel?
Это связано с множеством проблем, главным из которых является медленный, жадный рендеринг, который в значительной степени решался путем предварительного рендеринга, когда это возможно, для статического текста.
Я не думаю, что вы сможете сделать это с эффектом node из-за точности, которую, как правило, требуют шрифты. Оглядываясь назад, я подумал бы дважды, прежде чем идти по этому пути.
Ответ 7
Использовать ООП!
Я реализовал это как новый компонент, потомок 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")
}
}
Создайте и добавьте родительский элемент (другой node или сцену) так:
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, которое я сейчас создаю. С уважением, Тед.
Ответ 8
Я создал класс, наследующий от 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