獣は月夜に何を見る...

【iPhone】Swiftでアプリ開発 | SKShapeNodeAnimation

f:id:tukumosanzou:20180826223315j:plain




今回は、SkShapeNodeをつかった、かんたん泡泡なアニメーションの作り方です。


開発環境
iOS12
Swift 4,2
Xcode 10 Beta


f:id:tukumosanzou:20180826223441g:plain


プロジェクトをつくります

新しいプロジェクトをつくります。


プロジェクト名はSKShapeNodeAnimationとでもしましょう。


GameScene.swiftを開いて、余分なコードを削除して以下のようにします。


import SpriteKit

class GameScene: SKScene {
    
    override func didMove(to view: SKView) {
        
    }
    
    
    override func update(_ currentTime: TimeInterval) {
       
    }
}




プロジェクト作成時にintegrate GamePlayKitのチェックを入れているとimport GamePlayKitの一文があると思いますが、今回は使わないので削除して良いです。



では、先ず背景をつくるcreateBackground()を作成します。

class GameScene: SKScene {
    
    //背景用の変数を作成。
    var background: SKShapeNode!
    
    override func didMove(to view: SKView) {
        
   //関数の呼び出し
        createBackground()

    }
    
    
    func createBackground() {

        //画面と同じ大きさの四角形を作成する。
        let rect = CGRect(x: frame.minX - 1, y: frame.minY - 1, width: frame.width, height: frame.height + 2)

        //四角形をSKShapeNodeとして登録する。
        background = SKShapeNode(rect: rect, cornerRadius: 0.01)

        //四角形の面の部分の色を決める。
        background.fillColor = SKColor.darkGray

        //z軸方向の重なり順を決める。
        background.zPosition = 2

        //GameSceneに追加する。
        self.addChild(background)
    }
}




特に変わったことはしていません、今回は画像を使わずに背景となる四角形を作成するようにしました。



frame.midXは画面サイズのx軸のちょうど真ん中、frame.heightは画面サイズの高さの値をそれぞれ表してます。



frame.minX - 1、frame.minY - 1としているのは、そのままだと上下に少し隙間ができるため1px分下げて下側の隙間を埋めて、その分frame.height + 2で上の隙間を埋めてます。



ほかにも、midY minX minY maxX maxY width などがあります。



SKShapeNode - SpriteKit | Apple Developer Documentation
CGRect - Core Graphics | Apple Developer Documentation



シミュレーターで見てみると以下のようになってれば大丈夫です。
f:id:tukumosanzou:20180806072742j:plain

泡をつくる、createBubble()を作成します。



createBackground()の直前に追加します。

class GameScene: SKScene {
    
    var background: SKShapeNode!
    
    override func didMove(to view: SKView) {
        
        createBackground()
    }
    
    
    override func update(_ currentTime: TimeInterval) {

        //関数の呼び出し。
        createBubble()
    }
    
    
   func createBubble() {
        let bubble = SKSpriteNode(color: SKColor.white, size: CGSize(width: 10, height: 10))
        let startPosition = CGPoint(x: frame.width / 2, y: frame.minY - bubble.size.width)
        bubble.position = startPosition
        bubble.zPosition = 3
        background.addChild(bubble)
    }
    
    
    func createBackground() {
    }
}



関数の呼び出しはoverride update()の中で行います。


これでシミュレーターで見てみると特に変わっていないのですが、それは泡の発生する位置が画面の外になっているからです。

stratPosition- bubble.size.widthで泡の大きさ分画面の外のなっているので試しにその部分を消してみると画面の一番下に出てくると思います。



floatBubbles()を作ります。

いまのままだと、同じ位置にしか泡ができないので徐々に浮上するようにしたいと思います。

呼び出しを、createBubble()の直後に追加します。

floatBubbles()createBubble()の直前に追加します。

class GameScene: SKScene {
    
    var background: SKShapeNode!
    
    var activeBubbles: [SKSpriteNode] = []
    
    override func didMove(to view: SKView) {
        
        createBackground()
    }
    
    
    override func update(_ currentTime: TimeInterval) {
        createBubble()

   //関数の呼び出し。
        floatBubbles()
    }
    
    
    func floatBubbles() {

        //for inでループさせる。
        for i in background.children {

            //泡をx軸方向に少しだけ動かすための値。
            let xOffset = CGFloat(arc4random_uniform(20)) - 10.0

    //泡をy軸方向に動かすための値。
            let yOffset = CGFloat(20.0)

            //移動先の値を決める
            let newLocation = CGPoint(x: i.position.x + xOffset, y: i.position.y + yOffset)

            //移動先へ0.2秒間隔で動かす。
            let newAction = SKAction.move(to: newLocation, duration: 0.2)

            //アクションを実行する。
            i.run(newAction)
         }
    }

    func createBubble() {




arc4random_uniform()は乱数を生成します。

CGFloat(arc4random_uniform(20))では、現在表示されている泡を上に浮かべるために、フレームごとにxの値に0〜19の幅で乱数をつくります。


CGFloat(arc4random_uniform(20)) - 10.0は、結局のところ-10~9の間で乱数をつくり、それを泡のx軸方向の値に足すことでx軸方向の位置を変化させるという事になります。

つまり、泡が左右に動くことになります。

yの位置に関しては20を追加する事で、一定間隔で上に浮かぶようにします。

これで、ゆらゆらとしながら泡が浮かんでいくように見えます。




removeExcessBubbles()を作ります。

最後に、画面の上部に到達した後に泡を取り除かなければ、泡がいつまでも増え続けるのは、好ましくないので、画面外に出たら削除するようにしたいと思います。

以下のようにします。

呼び出しをupdate()内のfloatBunnles()の直後に、関数removeExcessBubbles()func floatBubbles()の直前に追加します。




最後に、全体のコードで表示します。

import SpriteKit

class GameScene: SKScene {
    
    var background: SKShapeNode!
    
    override func didMove(to view: SKView) {
        
        createBackground()
    }
    
    
    override func update(_ currentTime: TimeInterval) {
        createBubble()
        floatBubbles()

        //関数呼び出し。
        removeExcessBubbles()
    }
    
    
    func removeExcessBubbles() {

        //for inでループさせる。
        for i in background.children {

            //画面の最上部より上になったら
            if i.position.y > frame.maxY {

                //泡を削除する。
                i.removeFromParent()
            }
        }
    }


    func floatBubbles() {
        for i in background.children {
            let xOffset = CGFloat(arc4random_uniform(20)) - 10.0
            let yOffset = CGFloat(20.0)
            let newLocation = CGPoint(x: i.position.x + xOffset, y: i.position.y + yOffset)
            let newAction = SKAction.move(to: newLocation, duration: 0.2)
            i.run(newAction)
         }
    }

    
    func createBubble() {
        let bubble = SKSpriteNode(color: SKColor.white, size: CGSize(width: 10, height: 10))
        let startPosition = CGPoint(x: frame.width / 2, y: frame.minY - bubble.size.width)
        bubble.position = startPosition
        bubble.zPosition = 3
        background.addChild(bubble)
    }
    
    
    func createBackground() {
        let rect = CGRect(x: frame.minX - 1, y: frame.minY - 1, width: frame.width, height: frame.height + 2)
        background = SKShapeNode(rect: rect, cornerRadius: 0.01)
        background.fillColor = SKColor.darkGray
        background.zPosition = 2
        self.addChild(background)
    }
}







今回は、基本的なSpriteKitでのアニメーションの紹介でした。 では、また次回。





今のスマホ時代、ブルーライト対策は必要!

わたしも、「pcめがね」を使ってます。 使わないと、違いはわからない!。 「J!NS SCREEN」、デザインがおしゃれでわたしは好きです。


JINS PC」は、疲れと戦うメガネ「JINS SCREEN」に生まれ変わりました! 眠りが浅い、寝つきが悪い、その原因はブルーライトかもしれません。ブルーライトを防いで、快適な眠りを体験してみませんか?