为 SKLabelNode 中的单个角色设置动画
Animating individual characters in a SKLabelNode
有没有一种更有效的方法来在一个 sklabelnode 中通过打字来动画文本颤抖?我正在尝试在某些游戏中实现这种效果,例如 undertale,其中的文字在同时发抖的同时出现打字风格。
到目前为止,我只能做到这一点,但幸运的是:
class TextEffectScene: SKScene {
var typeWriterLabel : SKLabelNode?
var shiveringText_L : SKLabelNode?
var shiveringText_O : SKLabelNode?
var shiveringText_S : SKLabelNode?
var shiveringText_E : SKLabelNode?
var shiveringText_R : SKLabelNode?
var button : SKSpriteNode?
override func sceneDidLoad() {
button = self.childNode(withName: "//button") as? SKSpriteNode
self.scaleMode = .aspectFill //Very important for ensuring that the screen sizes do not change after transitioning to other scenes
typeWriterLabel = self.childNode(withName: "//typeWriterLabel") as? SKLabelNode
shiveringText_L = self.childNode(withName: "//L") as? SKLabelNode
shiveringText_O = self.childNode(withName: "//O") as? SKLabelNode
shiveringText_S = self.childNode(withName: "//S") as? SKLabelNode
shiveringText_E = self.childNode(withName: "//E") as? SKLabelNode
shiveringText_R = self.childNode(withName: "//R") as? SKLabelNode
}
// Type writer style animation
override func didMove(to view: SKView) {
fireTyping()
shiveringText_L?.run(SKAction.repeatForever(SKAction.init(named: "shivering")!))
shiveringText_O?.run(SKAction.repeatForever(SKAction.init(named: "shivering2")!))
shiveringText_S?.run(SKAction.repeatForever(SKAction.init(named: "shivering3")!))
shiveringText_E?.run(SKAction.repeatForever(SKAction.init(named: "shivering4")!))
shiveringText_R?.run(SKAction.repeatForever(SKAction.init(named: "shivering5")!))
}
let myText = Array("You just lost the game :)".characters)
var myCounter = 0
var timer:Timer?
func fireTyping(){
typeWriterLabel?.text = ""
timer = Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(TextEffectScene.typeLetter), userInfo: nil, repeats: true)
}
func typeLetter(){
if myCounter < myText.count {
typeWriterLabel?.text = (typeWriterLabel?.text!)! + String(myText[myCounter])
//let randomInterval = Double((arc4random_uniform(8)+1))/20 Random typing speed
timer?.invalidate()
timer = Timer.scheduledTimer(timeInterval: 0.2, target: self, selector: #selector(TextEffectScene.typeLetter), userInfo: nil, repeats: false)
} else {
timer?.invalidate() // stop the timer
}
myCounter += 1
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first
if let location = touch?.location(in: self) {
if (button?.contains(location))! {
print("doggoSceneLoaded")
let transition = SKTransition.fade(withDuration: 0.5)
let newScene = SKScene(fileNamed: "GameScene") as! GameScene
self.view?.presentScene(newScene, transition: transition)
}
}
}
}
如您所见,我必须在一个单词中为每个单独的标签节点设置动画 "loser"。
要创建此效果:
我在这方面有很多经验......除了你已经在做的事情之外,没有办法正确地做到这一点。我的解决方案(对于文本游戏)是将 NSAttributedString 与 CoreAnimation 一起使用,这使您可以在 UILabels 上获得疯狂的好动画...然后将 UILabels 添加到 SpriteKit 之上。
我正在研究一个更好的 SKLabel 子类,但最终放弃了,因为我意识到如果不做更多的工作就无法获得正确的字距调整。
可以使用 SKSpriteNode 并将视图作为纹理,然后您只需每帧更新纹理,但这需要更多的时间/资源。
执行此操作的最佳方法是在 SK 编辑器中按照您的操作方式进行操作。如果你需要 lot 的动画文本,那么你需要使用 UIKit
和 NSAttributedString 以及 CoreAnimation 来实现花哨的东西。
这是 IMO 的一个巨大的疏忽,是 SpriteKit 的一个相当大的缺点。 SKLabelNode 糟透了。
正如我在评论中所说,您可以从 SKNode 子类化并使用它为每个字符生成标签。然后将标签存储在数组中以供将来参考。
我很快就把一些东西放在一起,而且效果很好。我不得不玩一点定位,所以它看起来不错,因为空间有点太小了。另外每个标签的水平对齐必须是.left 否则,它会全部歪斜。
总之,超级好用!去试试吧!
这是我刚刚创建的要点 link。
https://gist.github.com/sonoblaise/e3e1c04b57940a37bb9e6d9929ccce27
对于那些可能对 Swift 4 感兴趣的人,我实现了一个 gitHub 项目此特殊请求称为 SKAdvancedLabelNode。
您可以找到 here 所有来源。
用法:
// horizontal alignment : left
var advLabel = SKAdvancedLabelNode(fontNamed:"Optima-ExtraBlack")
advLabel.name = "advLabel"
advLabel.text = labelTxt
advLabel.fontSize = 20.0
advLabel.fontColor = .green
advLabel.horizontalAlignmentMode = .left
addChild(self.advLabel)
advLabel.position = CGPoint(x:frame.width / 2.5, y:frame.height*0.70)
advLabel.sequentiallyBouncingZoom(delay: 0.3,infinite: true)
输出:
有没有一种更有效的方法来在一个 sklabelnode 中通过打字来动画文本颤抖?我正在尝试在某些游戏中实现这种效果,例如 undertale,其中的文字在同时发抖的同时出现打字风格。
到目前为止,我只能做到这一点,但幸运的是:
class TextEffectScene: SKScene {
var typeWriterLabel : SKLabelNode?
var shiveringText_L : SKLabelNode?
var shiveringText_O : SKLabelNode?
var shiveringText_S : SKLabelNode?
var shiveringText_E : SKLabelNode?
var shiveringText_R : SKLabelNode?
var button : SKSpriteNode?
override func sceneDidLoad() {
button = self.childNode(withName: "//button") as? SKSpriteNode
self.scaleMode = .aspectFill //Very important for ensuring that the screen sizes do not change after transitioning to other scenes
typeWriterLabel = self.childNode(withName: "//typeWriterLabel") as? SKLabelNode
shiveringText_L = self.childNode(withName: "//L") as? SKLabelNode
shiveringText_O = self.childNode(withName: "//O") as? SKLabelNode
shiveringText_S = self.childNode(withName: "//S") as? SKLabelNode
shiveringText_E = self.childNode(withName: "//E") as? SKLabelNode
shiveringText_R = self.childNode(withName: "//R") as? SKLabelNode
}
// Type writer style animation
override func didMove(to view: SKView) {
fireTyping()
shiveringText_L?.run(SKAction.repeatForever(SKAction.init(named: "shivering")!))
shiveringText_O?.run(SKAction.repeatForever(SKAction.init(named: "shivering2")!))
shiveringText_S?.run(SKAction.repeatForever(SKAction.init(named: "shivering3")!))
shiveringText_E?.run(SKAction.repeatForever(SKAction.init(named: "shivering4")!))
shiveringText_R?.run(SKAction.repeatForever(SKAction.init(named: "shivering5")!))
}
let myText = Array("You just lost the game :)".characters)
var myCounter = 0
var timer:Timer?
func fireTyping(){
typeWriterLabel?.text = ""
timer = Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(TextEffectScene.typeLetter), userInfo: nil, repeats: true)
}
func typeLetter(){
if myCounter < myText.count {
typeWriterLabel?.text = (typeWriterLabel?.text!)! + String(myText[myCounter])
//let randomInterval = Double((arc4random_uniform(8)+1))/20 Random typing speed
timer?.invalidate()
timer = Timer.scheduledTimer(timeInterval: 0.2, target: self, selector: #selector(TextEffectScene.typeLetter), userInfo: nil, repeats: false)
} else {
timer?.invalidate() // stop the timer
}
myCounter += 1
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first
if let location = touch?.location(in: self) {
if (button?.contains(location))! {
print("doggoSceneLoaded")
let transition = SKTransition.fade(withDuration: 0.5)
let newScene = SKScene(fileNamed: "GameScene") as! GameScene
self.view?.presentScene(newScene, transition: transition)
}
}
}
}
如您所见,我必须在一个单词中为每个单独的标签节点设置动画 "loser"。
要创建此效果:
我在这方面有很多经验......除了你已经在做的事情之外,没有办法正确地做到这一点。我的解决方案(对于文本游戏)是将 NSAttributedString 与 CoreAnimation 一起使用,这使您可以在 UILabels 上获得疯狂的好动画...然后将 UILabels 添加到 SpriteKit 之上。
我正在研究一个更好的 SKLabel 子类,但最终放弃了,因为我意识到如果不做更多的工作就无法获得正确的字距调整。
可以使用 SKSpriteNode 并将视图作为纹理,然后您只需每帧更新纹理,但这需要更多的时间/资源。
执行此操作的最佳方法是在 SK 编辑器中按照您的操作方式进行操作。如果你需要 lot 的动画文本,那么你需要使用 UIKit
和 NSAttributedString 以及 CoreAnimation 来实现花哨的东西。
这是 IMO 的一个巨大的疏忽,是 SpriteKit 的一个相当大的缺点。 SKLabelNode 糟透了。
正如我在评论中所说,您可以从 SKNode 子类化并使用它为每个字符生成标签。然后将标签存储在数组中以供将来参考。
我很快就把一些东西放在一起,而且效果很好。我不得不玩一点定位,所以它看起来不错,因为空间有点太小了。另外每个标签的水平对齐必须是.left 否则,它会全部歪斜。
总之,超级好用!去试试吧!
这是我刚刚创建的要点 link。
https://gist.github.com/sonoblaise/e3e1c04b57940a37bb9e6d9929ccce27
对于那些可能对 Swift 4 感兴趣的人,我实现了一个 gitHub 项目此特殊请求称为 SKAdvancedLabelNode。 您可以找到 here 所有来源。
用法:
// horizontal alignment : left
var advLabel = SKAdvancedLabelNode(fontNamed:"Optima-ExtraBlack")
advLabel.name = "advLabel"
advLabel.text = labelTxt
advLabel.fontSize = 20.0
advLabel.fontColor = .green
advLabel.horizontalAlignmentMode = .left
addChild(self.advLabel)
advLabel.position = CGPoint(x:frame.width / 2.5, y:frame.height*0.70)
advLabel.sequentiallyBouncingZoom(delay: 0.3,infinite: true)
输出: