Edited at

[Swift3.0][iOS][SpriteKit]SpriteKitでテキストを落としたり、ぶっ飛ばしたりした!

More than 1 year has passed since last update.

SpriteKitフレームワークを使って文字からラベルを作り、重力や力を加えたりしてインタラクションなアニメーションを作ります。


作業工程:

1. テキストからノードを作る!

 - SKViewを貼る!

 - SKSceneを追加する!

 - 素材となるテキストからノードを作る!

2. 突然重力を与えて落とす!

3. ランダムな方向にぶっ飛ばす!



1. テキストからノードを作る!


SKViewを貼る!

まずは基礎となるSKViewを貼る。

UIViewController のview クラスをSKView に変更する。

Main.storyboardでViewを選択してFile Inspector > Identity Inspectorで変更する

Create_SKView.png


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

Drop480.gif


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

Impluse480.gif

決して、人名などでは行わないようにしましょう^_^

おしまい。