SpriteKitフレームワークを使って文字からラベルを作り、重力や力を加えたりしてインタラクションなアニメーションを作ります。
作業工程:
- テキストからノードを作る!
- SKViewを貼る!
- SKSceneを追加する!
- 素材となるテキストからノードを作る! - 突然重力を与えて落とす!
- ランダムな方向にぶっ飛ばす!
1. テキストからノードを作る!
SKViewを貼る!
まずは基礎となるSKViewを貼る。
UIViewController のview クラスをSKView に変更する。
Main.storyboardでViewを選択してFile Inspector > Identity Inspectorで変更する
SKSceneを追加する!
import UIKit
import SpriteKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let skView = self.view as! SKView
let scene = HelloScene(size: skView.bounds.size)
skView.presentScene(scene)
skView.showsFPS = true
skView.showsNodeCount = true
}
}
素材となるテキストからノードを作る!
定義したテキストからSKLabelNodeを生成して配列に入れておく
fileprivate func initializeContent() {
guard let view = view else {
return
}
self.physicsBody = SKPhysicsBody(edgeLoopFrom:CGRect(x: 0, y: 200.0, width: self.size.width, height: 200.0))
self.physicsBody?.categoryBitMask = 0x1 << 1
self.physicsBody?.contactTestBitMask = 0x1 << 0
self.physicsBody?.collisionBitMask = 0xFFFFFFFF
let helloText = "Hello Everyone!"
for (idx, character) in helloText.characters.enumerated() {
let fontSize: CGFloat = 44.0
let positionX = (view.bounds.size.width - fontSize * CGFloat(helloText.characters.count)) / 2.0 + fontSize * CGFloat(idx)
let labelNode = SKLabelNode(text:String(character))
labelNode.fontName = "AvenirNext-Bold"
labelNode.fontColor = UIColor(red: 131.0/255, green: 204.0/255, blue: 212.0/255, alpha: 1.0)
labelNode.fontSize = fontSize
labelNode.position = CGPoint(x:positionX, y:view.bounds.midY + 200.0)
labelNode.alpha = 1.0
self.addChild(labelNode)
helloLabelNodes.append(labelNode)
}
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(tapGesture(_:)))
view.addGestureRecognizer(tapGestureRecognizer)
}
2. 突然重力を与えて落とす!
restitution は物体の反発力、
friction は物体の摩擦力。
@objc fileprivate func applyPhysicsBody() {
helloLabelNodes.forEach {
$0.physicsBody = SKPhysicsBody(rectangleOf:$0.frame.size, center:CGPoint(x:0, y:$0.frame.size.height / 2.0))
$0.physicsBody?.isDynamic = true
$0.physicsBody?.restitution = 0.6
$0.physicsBody?.allowsRotation = true
$0.physicsBody?.friction = 0.4
$0.physicsBody?.categoryBitMask = 0x1 << 0
$0.physicsBody?.contactTestBitMask = 0x1 << 1
$0.physicsBody?.collisionBitMask = 0xFFFFFFFF
}
}
タップして実行する
@objc fileprivate func tapGesture(_ gestureRecognizer: UITapGestureRecognizer) {
self.applyPhysicsBody()
}
3. ランダムな方向にぶっ飛ばす!
1文字づつランダムな角度と一定速度の力を与えるCGVector をセットする
@objc fileprivate func applyRandomImpluse() {
helloLabelNodes.forEach {
var angle: CGFloat = 0
var value: CGFloat = 0
var vector: CGVector?
$0.physicsBody = SKPhysicsBody(rectangleOf:$0.frame.size, center:CGPoint(x:0, y:$0.frame.size.height / 2.0))
$0.physicsBody?.isDynamic = true
$0.physicsBody?.restitution = 0.6
$0.physicsBody?.allowsRotation = true
$0.physicsBody?.friction = 0.4
$0.physicsBody?.categoryBitMask = 0x1 << 0
$0.physicsBody?.contactTestBitMask = 0x1 << 1
$0.physicsBody?.collisionBitMask = 0xFFFFFFFF
angle = self.randomFloatValue(0, high: 360) * CGFloat.pi / 180.0
value = 50.0
vector = CGVector(dx: (value * CGFloat(cos(Double(angle)))), dy: (value * CGFloat(sin(Double(angle)))))
$0.physicsBody?.applyImpulse(vector!)
}
}
fileprivate func randomFloatValue(_ low: CGFloat, high: CGFloat) -> CGFloat {
return ((CGFloat(arc4random()) / CGFloat(RAND_MAX)) * (high - low) + low)
}
タップして実行する
@objc fileprivate func tapGesture(_ gestureRecognizer: UITapGestureRecognizer) {
self.applyRandomImpluse()
}
決して、人名などでは行わないようにしましょう^_^
おしまい。