連載
» 2016年07月13日 05時00分 UPDATE

iOS SDKとSwiftで始めるゲーム作成入門(7):iOS 9のReplayKitでゲームプレー動画を撮影&シェア (1/4)

iPhoneゲームをSwift言語で作成してみたいという初心者向けにiOSのゲームフレームワークを使った作り方を一から解説する入門連載。今回は、ステージを1から3に増やし、出てくる敵の種類もステージに応じて変わるようにします。さらに「ReplayKit」というフレームワークも使ってプレー動画の撮影・共有機能を実装します。

[杉本裕樹,マネーフォワード]

 本連載「iOS SDKとSwiftで始めるゲーム作成入門」は、iPhone向けのゲーム開発の入門連載です。タワーディフェンスを題材に、「SpriteKit」というゲーム開発フレームワークの解説やゲームの開発手法について書いています。

 実装に入る前に本連載で作るアプリの完成形を確認しておきます。本連載では、下記6つのルールを満たすタワーディフェンスを作っていきます。

  1. プレーヤーは開始前に与えられた所持金を元に、敵を攻撃するユニットを設置する
  2. ゲームは「Wave(ウエーブ)」という単位で行われる。基本的には1つのWaveで登場する敵の種類は1種類のみとなっている。Waveが始まると敵は入口から登場し、目的地に向かって行進する。プレーヤーが設置したユニットは攻撃可能範囲に入ると自動的に攻撃を行う
  3. 1Waveの敵を全て全滅させるとWaveクリアとなる。プレーヤーは次のWaveが始まるまでにユニットの増強(新設・アップグレード・売却など)を行う
  4. 以上の2と3を繰り返して行う
  5. 敵が目的地に到達すると、自分が所持しているライフが減少する。全て失うとゲームオーバーとなる
  6. ライフを全て失う前に、最終Waveの敵を全て全滅させることができればクリアとなる

 前回の「FactoryMethodパターンでリファクタリングすると、ゲーム開発がどう便利になるのかをSwiftコードで学ぶ」では自機を3種類から自由に選べるようにしました。それと同時にGoFデザインパターンの1つであるFactoryMethodパターンを使って、複数種類のオブジェクト生成をすっきりさせる方法を学んできました。

 今回はステージも1から3に増やし、出て来る敵の種類もステージに応じて変わるようにします。さらにiOS 9から追加された「ReplayKit」というフレームワークを使ってプレー動画の撮影・共有機能も実装します。

 今回は、こちらのコードを元に実装を進めていきます。

ステージを1から3に増やす

 今は1ステージだけクリアすればゲーム終了になります。これをステージ3までクリアすればゲーム終了になるように変更します。ステージとステージの間では、自機を設置できるようにします。

 まずはSetCharScene.swiftを以下のように変更してください。stageプロパティと前のステージからのデータ引き継ぎ処理を入れます。

class SetCharScene: SKScene {
    var stage = 1
    // 省略
 
    override func didMoveToView(view: SKView) {
        // 省略
        let button = Button(text: "ゲーム開始", rect: buttonRect, afterTap: {
            let scene = GameScene(fileNamed: "GameScene")
            scene?.stage = self.stage // この1行を追加
            scene?.scaleMode = .ResizeFill
            view.presentScene(scene)
            scene?.createChars(self.charData)
        })
        addChild(button)
    }
 
    // 前ステージから情報を引き継ぐ為のメソッド
    func createChars(charData: [(factory: CharFactory, position: CGPoint)]) {
        charData.forEach {
            let char = $0.factory.createChar()
            char.position = $0.position
            char.physicsBody = SKPhysicsBody(rectangleOfSize: char.size)
            addChild(char)
            self.charData.append($0)
        }
    }
 
    // 省略
}

 続けてGameScene.swiftも修正します。

class GameScene: SKScene, SKPhysicsContactDelegate {
    var stage = 1
    var charData = [(factory: CharFactory, position: CGPoint)]()
 
    // 省略
 
    func createChars(charData: [(factory: CharFactory, position: CGPoint)]) {
        charData.forEach {
            let char = $0.factory.createChar()
            char.position = $0.position
            char.physicsBody = SKPhysicsBody(rectangleOfSize: char.size)
            char.physicsBody?.contactTestBitMask = 0x1
            addChild(char)
            chars.append(char)
            self.charData.append($0) // この1行を追加
        }
    }
 
    // 省略
 
    override func update(currentTime: NSTimeInterval) {
        chars.forEach { char in
            char.stateMachine.updateWithDeltaTime(currentTime)
            if let charState = char.stateMachine.currentState as? Char.CharState where charState.enableToAttack() {
                enemyList.enemiesCloseToPoint(char.frame.origin, distance: 50).forEach {
                    $0.life -= charState.power
                    char.stateMachine.enterState(Char.StayState.self)
                    if $0.life <= 0 {
                        $0.physicsBody?.node?.removeFromParent()
                        $0.physicsBody?.node?.removeAllActions()
 
                        if enemyList.isAllEnemyRemoved() {
                            // ここから追加処理
                            if stage < 3 {
                                let scene = SetCharScene()
                                scene.stage = self.stage + 1
                                scene.scaleMode = .ResizeFill
                                scene.createChars(charData)
                                self.view?.presentScene(scene)
                                return
                            }
                            // ここまで追加処理
 
                            state = .GameClear
 
                            let myLabel = SKLabelNode(fontNamed: "HiraginoSans-W6")
                            myLabel.text = "ゲームクリア"
                            myLabel.fontSize = 45
                            myLabel.position = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame) - 20)
                            addChild(myLabel)
                        }
                    }
                }
            }
        }
    }
}

 実行すると、ステージが1から3に増えていることが分かります。

       1|2|3|4 次のページへ

Copyright© 2017 ITmedia, Inc. All Rights Reserved.

@IT Special

- PR -

TechTargetジャパン

この記事に関連するホワイトペーパー

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。