19
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

posted at

updated at

Organization

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

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

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


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
Sign upLogin
19
Help us understand the problem. What are the problem?