ゲームオーバー処理ができたので、次はゲームクリア処理を書いていきます。
本来はユーザーが自分で味方を設置するのですが、今回は最初から味方を画面上に起きます。そして敵と味方が接触したら敵が消滅してゲームクリアになるようにします。
まずは味方を画面に表示します。GameSceneを下のように書き換えてください。
class GameScene: SKScene {
    // ...略
    let char = SKSpriteNode(imageNamed: "Char")
    
    override func didMoveToView(view: SKView) {
        // ...略
       
        char.position = CGPoint(x:50, y:300)
        addChild(char)
    }
    
    // ...略
}
以降、3行目にあるように「char」は「キャラクター」のインスタンス名であり、char型ではありませんので、注意してください。
これで味方が画面に表示されるようになりました。
敵と味方の衝突判定を実装します。まずはGameSceneのdidMoveToViewの中身を下のように書き換えます。
class GameScene: SKScene {
// …略
 
    override func didMoveToView(view: SKView) {
        // …略
        
        physicsWorld.gravity = CGVectorMake(0, 0)
        
        char.position = CGPoint(x:250, y:300)
        char.physicsBody = SKPhysicsBody(rectangleOfSize: char.size)
        addChild(char)
        
        enemy.position = CGPoint(x:50, y:300)
        enemy.physicsBody = SKPhysicsBody(rectangleOfSize: enemy.size)
        addChild(enemy)
    }
    
// …略
}
今回の修正は下の2つです。
physicsBodyとは物理演算をするためのプロパティです。初期状態ではSKNodeとぶつかっても、すり抜けるし、衝突時に通知がされません。
physicsBodyをセットすることで、他オブジェクトとぶつかったときに通知が来てすり抜けなくなります。
今回は敵と味方が衝突時の通知を受け取りたいので「physicsBody」をセットしました。
gravityとはGameScene上のphysicsBodyにかかる重力です。これを0にしないとcharとenemyが下向きに落下してしまうので、0をセットしました。
charとenemyが衝突できるようになったので、次は衝突したときの処理を記述していきます。GameSceneを下のように書き換えます。
class GameScene: SKScene, SKPhysicsContactDelegate { // 今回修正部分
    override func didMoveToView(view: SKView) {
// …略
 
        physicsWorld.contactDelegate = self // 今回追加部分
        
        char.position = CGPoint(x:250, y:300)
        char.physicsBody = SKPhysicsBody(rectangleOfSize: char.size)
        char.physicsBody?.contactTestBitMask = 0x1 // 今回追加部分
        addChild(char)
        
// …略
    }
 
    func didBeginContact(contact: SKPhysicsContact) {
        state = .GameClear
        enemy.removeFromParent()
        
        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)
    }
}
15行目のdidBeginContactはphysicsBody同士が衝突したときに呼ばれるメソッドです。今回は衝突時に敵の消去、stateをゲームクリア状態へ変更、「ゲームクリア」ラベルの表示を行っています。
5行目のphysicsWorld.contactDelegateは衝突用のdelegateです。ここにselfをセットすることで、SKNode同士の衝突時にGameSceneのdidBeginContactが呼ばれるようになります。
9行目のcontactTestBitMaskは衝突時にdidBeginContactが呼ばれるためのプロパティです。慣れてくれば自然に使えるようになるので、この説明も軽く流し読みするとよいかと思います。
contactTestBitMaskの前にcategoryBitMaskを説明します。categoryBitMaskはphysicsBodyのプロパティです。physicsBodyがどのカテゴリかを表していて、初期値はUIntの最大値(4294967295)です。
単体では意味がなく、contactTestBitMaskなどとセットで使われることで意味が出てくるプロパティです。
charとenemy衝突時にdidBeginContactが呼ばれるためには下のどちらかの条件を満たさないといけません。
式で書くと下のようになります。
(char.physicsBody!.categoryBitMask & enemy.physicsBody!.contactTestBitMask) != 0 || (char.physicsBody!.contactTestBitMask & enemy.physicsBody!.categoryBitMask) != 0
先ほどはchar.physicsBodyのcategoryBitMaskを1にしました。そうすることで1行目の「char.physicsBody!.categoryBitMask & enemy.physicsBody!.contactTestBitMask」が1になり、衝突時にdidBeginContactが呼ばれるようになりました。
今回はゲーム全体の流れを作ってみましたが如何でしたでしょうか。今回作成したコード「TowerDefense.zip」は、こちらからダウンロードできます。
次回からは一つ一つの要素をブラッシュアップしてさらにゲームらしくしていこうと思います。iOS 9から登場したGamePlayKitの機能も徐々に使っていきます。
田町のベンチャーで働くエンジニア。
仕事ではiPhoneアプリの開発やRailsを使ったWebサービス開発を行っている。最近のマイブームはUnityを使った3Dゲーム開発。
 開発者向けiOS 9、WatchOS 2、Swift 2、Xcode 7の新機能と新しいApple Developer Programの参考情報まとめ
開発者向けiOS 9、WatchOS 2、Swift 2、Xcode 7の新機能と新しいApple Developer Programの参考情報まとめ Apple WatchやiPhoneのアプリを作ろう! Playgroundで学ぶSwiftの基礎―変数、定数、型、演算
Apple WatchやiPhoneのアプリを作ろう! Playgroundで学ぶSwiftの基礎―変数、定数、型、演算 iOSアプリ開発でObjective-CからSwiftに移行するための手順、注意点まとめ〜言語仕様の違いは? 連携時の呼び出し方は?
iOSアプリ開発でObjective-CからSwiftに移行するための手順、注意点まとめ〜言語仕様の違いは? 連携時の呼び出し方は? いまなら無料! Unityで始めるiPhoneゲーム作成“超”入門
いまなら無料! Unityで始めるiPhoneゲーム作成“超”入門Copyright © ITmedia, Inc. All Rights Reserved.