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

  • 28
    Like
  • 0
    Comment

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

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