ゲームのState管理を簡単にするiOS 9 GameplayKitのクラスとは:iOS SDKとSwiftで始めるゲーム作成入門(5)(1/4 ページ)
iPhoneゲームをSwift言語で作成してみたいという初心者向けにiOSのゲームフレームワークを使った作り方を一から解説する入門連載。今回は、GoFデザインパターンの1つである「Stateパターン」やiOS 9から登場した「GKStateMachine」クラスを取り入れることで、今後の開発に役立つ知見を共有します。
本連載「iOS SDKとSwiftで始めるゲーム作成入門」は、iPhone向けのゲーム開発の入門連載です。タワーディフェンスを題材に、「SpriteKit」というゲーム開発フレームワークの解説やゲームの開発手法について書いています。
実装に入る前に本連載で作るアプリの完成形を確認しておきます。本連載では、下記6つのルールを満たすタワーディフェンスを作っていきます。
- プレーヤーは開始前に与えられた所持金を元に、敵を攻撃するユニットを設置する
- ゲームは「Wave(ウエーブ)」という単位で行われる。基本的には1つのWaveで登場する敵の種類は1種類のみとなっている。Waveが始まると敵は入口から登場し、目的地に向かって行進する。プレーヤーが設置したユニットは攻撃可能範囲に入ると自動的に攻撃を行う
- 1Waveの敵を全て全滅させるとWaveクリアとなる。プレーヤーは次のWaveが始まるまでにユニットの増強(新設・アップグレード・売却など)を行う
- 以上の2と3を繰り返して行う
- 敵が目的地に到達すると、自分が所持しているライフが減少する。全て失うとゲームオーバーとなる
- ライフを全て失う前に、最終Waveの敵を全て全滅させることができればクリアとなる
前回の『デザインパターン「ファーストクラスコレクション」でSwiftコードの保守性・可読性を上げる方法をゲームのコードから学ぶ』では、敵が何体も登場して、全てを倒すとゲームクリアになるように実装しました。
今回の記事では自機の動きを改善していきます。それと平行してGoFデザインパターンの1つである「Stateパターン」やiOS 9から登場した「GKStateMachine」クラスを取り入れることで、今後の開発に役立つ知見を共有できればと思います。
自機の近くにいる敵を攻撃させる
今は自機と敵が接触したときに敵が消滅する仕様になっています。それを実際のタワーディフェンスのように敵が自機近くに来ると攻撃をするように改善しようと思います。
ソースコードは、こちらをベースに改善していきます。
まずはGameScene.swiftを修正して自機が敵の進路方向に入らないようにします。
class GameScene: SKScene, SKPhysicsContactDelegate { // 略... // char.position = CGPoint(x:250, y:300) char.position = CGPoint(x:270, y:280) // 略... }
次にEnemyList.swiftへ自機付近の敵一覧を取得するメソッドを追加します。
class EnemyList { // 略... func enemiesCloseToPoint(point: CGPoint, distance: Double) -> [SKSpriteNode] { return enemies.filter { let dx = Double(point.x - $0.frame.origin.x) let dy = Double(point.y - $0.frame.origin.y) let distanceFromEnemy = sqrt(dx*dx + dy*dy) return distanceFromEnemy < distance } } // 略... }
最後にGameScene.swiftに自機付近の敵を攻撃する処理を追加します。近くの敵を攻撃して敵の削除をする処理と、全ての敵が消えたらゲームクリアにする処理を追加します。
class GameScene: SKScene, SKPhysicsContactDelegate { // 略... override func update(currentTime: NSTimeInterval) { enemyList.enemiesCloseToPoint(char.frame.origin, distance: 50).forEach { $0.physicsBody?.node?.removeFromParent() $0.physicsBody?.node?.removeAllActions() if enemyList.isAllEnemyRemoved() { 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) } } } // 略... }
これで攻撃範囲に入った敵を攻撃するようになりました。
今まで使っていた、自機と敵が衝突したときの処理は不要なので削除します。
// これらの処理を丸ごと削除する // func didBeginContact(contact: SKPhysicsContact) { // [contact.bodyA, contact.bodyB].forEach { // if $0.node?.name == "enemy" { // $0.node?.removeFromParent() // $0.node?.removeAllActions() // } // } // // if enemyList.isAllEnemyRemoved() { // 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) // } // }
Copyright © ITmedia, Inc. All Rights Reserved.
関連記事
- 開発者向け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の基礎―変数、定数、型、演算
本連載では、これからプログラミングやiPhoneアプリ開発を始めてみたい方を対象に、開発に必要な知識を基礎から解説していきます。今回は、Swiftの変数、定数、型、演算などについてサンプルプログラムを交えて解説します。 - iOSアプリ開発でObjective-CからSwiftに移行するための手順、注意点まとめ〜言語仕様の違いは? 連携時の呼び出し方は?
開発生産性や品質を向上させたいiOSアプリ開発者のためにObjective-CからSwiftへ移行するメリットや手順、注意点など勘所をまとめて紹介します。