Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

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

More than 3 years have 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

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


yumemi
みんなが知ってるあのサービス、実はゆめみが作ってます。スマホアプリ/Webサービスの企画・UX/UI設計、開発運用。Swift, Kotlin, PHP, Vue.js, React.js, Node.js, AWS等エンジニア・クリエイターの会社です。Twitterで情報配信中https://twitter.com/yumemiinc
http://www.yumemi.co.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away