iOS 9の最新機能で自動ルート検索を簡単にゲームに組み込む:iOS SDKとSwiftで始めるゲーム作成入門(3)(3/3 ページ)
iPhoneゲームをSwift言語で作成してみたいという初心者向けにiOSのゲームフレームワークを使った作り方を一から解説する入門連載。今回は、敵の動きを改善する。GameplayKitのPathfindingを使ったルートの自動探索の使い方についてSpriteKitのSKActionでの実装と比べて解説。
GameplayKitのPathfindingを使ったルートの自動探索
前節で敵の移動を実装しましたが、移動先を自分で計算して書いているので柔軟性がありません。今後、もし「道に沿わずに移動できる飛行ユニットを作る」「プレーヤーが任意の場所に障害物を置ける」などの仕様が出てきたときには、今の実装方法では対応できません。
そこで移動ルートは自動で探索できるようにしようと思います。移動ルートの自動探索にはiOS 9から登場したGameplayKitという最新フレームワークを使っていきます。
今回はGameplayKitの中の「Pathfinding」という機能を使ってルートを探索します。Pathfindingのさまざまな方法でルート探索ができるのですが、今回は障害物情報を使ったルート作成を行います。
下図はPathfindingのサンプルで、ピンクの四角が障害物で赤い線がルートです。これを見ると、障害物を避けたルートを表示できているのが分かると思います。
サンプルコードは「tnantoka/GameplayKitSandbox」のものを利用させていただきました
ルートの自動探索をしてくれる「GKObstacleGraph」
GameplayKitの「GKObstacleGraph」クラスに障害物の位置情報・移動開始位置・移動終了位置を渡すとルートを返却してくれます。受け取ったルート情報を基にSKActionを作って敵を移動させる実装を今回は行います。
GKObstacleGraphを使ったソースコード
実際に処理を書いていきます。前節の「敵をルートに沿って行動させる」で作った箇所を以下のように書き換えてください。
class GameScene: SKScene, SKPhysicsContactDelegate { // …略 override func didMoveToView(view: SKView) { // …略 // 障害物情報を取得 let fields = children.filter { $0.name == "Field0" } let obstacles = SKNode.obstaclesFromNodePhysicsBodies(fields) // ルート情報を取得 let graph = GKObstacleGraph(obstacles: obstacles, bufferRadius: 10) let start = GKGraphNode2D(point: vector_float2(Float(fieldImageLength * 2), Float(view.frame.height))) let end = GKGraphNode2D(point: vector_float2(Float(fieldImageLength * 13), Float(view.frame.height - fieldImageLength * 9))) graph.connectNodeUsingObstacles(start) graph.connectNodeUsingObstacles(end) let nodes = graph.findPathFromNode(start, toNode: end) // アクションの作成 let actions = nodes.flatMap { $0 as? GKGraphNode2D }.map { SKAction.moveTo(CGPoint(x: Double($0.position.x), y: Double($0.position.y)), duration: 5) } enemy.position = CGPoint(x: fieldImageLength * 2, y: view.frame.height) enemy.physicsBody = SKPhysicsBody(rectangleOfSize: enemy.size) enemy.runAction(SKAction.sequence(actions)) { self.state = .GameOver let myLabel = SKLabelNode(fontNamed: "HiraginoSans-W6") myLabel.text = "ゲームオーバー" myLabel.fontSize = 45 myLabel.position = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame) - 20) self.addChild(myLabel) } addChild(enemy) } }
今回は「障害物情報を取得」「ルート情報を取得」「アクションの作成」という3種類の処理を追加しました。
障害物情報の取得
障害物情報の取得では、芝画像(nameが"Field0"のSKNode)一覧を取得してobstaclesFromNodePhysicsBodiesメソッドを通して障害物一覧を取得しています。
// 障害物情報を取得 let fields = children.filter { $0.name == "Field0" } let obstacles = SKNode.obstaclesFromNodePhysicsBodies(fields)
ルート情報の取得
下記は、ルート情報の取得処理です。GKObstacleGraphクラスに障害物の情報・開始位置・終了位置を渡した上でfindPathFromNodeメソッドを使って取得しています。
// ルート情報を取得 let graph = GKObstacleGraph(obstacles: obstacles, bufferRadius: 0) let start = GKGraphNode2D(point: vector_float2(Float(fieldImageLength * 2), Float(view.frame.height))) let end = GKGraphNode2D(point: vector_float2(Float(fieldImageLength * 13), Float(view.frame.height - fieldImageLength * 9))) graph.connectNodeUsingObstacles(start) graph.connectNodeUsingObstacles(end) let nodes = graph.findPathFromNode(start, toNode: end)
アクションの作成
最後はアクションの生成です。上のfindPathFromNodeメソッドでは移動先の一覧を取得できました。ここでは取得した移動先情報を基に移動アクションの一覧を生成しています。
// アクションの作成 let actions = nodes.flatMap { $0 as? GKGraphNode2D }.map { SKAction.moveTo(CGPoint(x: Double($0.position.x), y: Double($0.position.y)), duration: 5) }
移動先を取得したら、それを使って敵を動かします。これで敵が自動生成したルートに沿って移動してくれるようになります。
enemy.runAction(SKAction.sequence(actions)) { self.state = .GameOver let myLabel = SKLabelNode(fontNamed: "HiraginoSans-W6") myLabel.text = "ゲームオーバー" myLabel.fontSize = 45 myLabel.position = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame) - 20) self.addChild(myLabel) }
Pathfinding以外のGameplayKitの機能も使ってみよう
今回はiOS 9から登場したGameplayKitという新しい機能も使ってみながら実装を進めてみました。今回のソースコード「TowerDefense.zip」は、こちらからダウンロードできます。
GameplayKitは機能の多いライブラリで、Pathfinding以外にも、さまざまな機能があります。今回の記事中でも紹介しましたが、GitHubにサンプルを置いている方もいるので、触ってみてはいかがでしょうか。
ゲームの方は、今回で敵の移動を実装できました。次回は敵の行動をさらに改善していきます。
- 2Dゲームを例にSwift 2からSwift 3への変更点と移行のポイントを見る
- iOS 9のReplayKitでゲームプレー動画を撮影&シェア
- FactoryMethodパターンでリファクタリングすると、ゲーム開発がどう便利になるのかをSwiftコードで学ぶ
- ゲームのState管理を簡単にするiOS 9 GameplayKitのクラスとは
- デザインパターン「ファーストクラスコレクション」でSwiftコードの保守性・可読性を上げる方法をゲームのコードから学ぶ
- iOS 9の最新機能で自動ルート検索を簡単にゲームに組み込む
- SwiftのSpriteKitで実装―タワーディフェンスゲームの大枠の作り方とコツ
- 初心者でもiOS 9/tvOS向け2Dゲームが作れる標準フレームワークSpriteKitの基礎知識とチュートリアル
筆者紹介
杉本裕樹
田町のベンチャーで働くエンジニア。
仕事ではiPhoneアプリの開発やRailsを使ったWebサービス開発を行っている。最近のマイブームはUnityを使った3Dゲーム開発。
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へ移行するメリットや手順、注意点など勘所をまとめて紹介します。 - いまなら無料! Unityで始めるiPhoneゲーム作成“超”入門
3Dコンテンツ開発ツール「Unity」を使った、簡単な3Dミニゲーム制作の流れを一から解説していきます