SwiftのGameplayKitでAIに追いかける、避ける、逃げる処理を追加するには:ゲームの「敵」キャラで分かる「人工知能」の作り方(2)(4/4 ページ)
iPhone向け鬼ごっこアプリを作りながら人工知能(AI)について学んでいく連載。今回は、SwiftのGameplayKitでAIの敵キャラに、追いかける、避ける、逃げる処理を追加する方法を解説する。
鬼が味方から逃げる処理(GameplayKitを使わない場合)
鬼が味方から逃げる処理についても、もしGameplayKitを使わない場合にどのような実装になるか考えてみます。下のような配置を想定して考えます。
今回は「障害物を避ける」「味方キャラから逃げる」という複数のルールがあるため、障害物を避ける時とは別のルールが必要になります。
実装としては下のようなものが考えられます。
- フィールドを格子状に区切る
- プレイヤーに近いフィールドにプラスの点数を付与する
- 味方キャラに近いフィールドにマイナスの点数を付与する
- 鬼は隣接するフィールドの中で、一番点数の高い箇所に移動する
・1. フィールドを格子状に区切る
まずはフィールドを下のように区切ります。
・2. プレイヤーに近いフィールドを加点する
次にフィールドに点数を付けます。点数はプレイヤーからの距離に応じたものを付けます。障害物がある場所だけは例外として0点とします。
・3. 味方キャラに近いフィールドを減点する
今度は逆に味方キャラから近いフィールドにマイナス点を付けます。
加点と減点を合計すると、以下のような点数になります。
・4. 隣接するフィールドの中で、一番点数の高い箇所に移動する
最後に今までの結果を使って鬼を動かします。鬼は「隣接しているフィールドの中で一番点数の高いところへ移動する」というルールで動かします。
実行結果
実際に動かすと以下のようになります。今回はフィールド5x5で区切っているので無駄が多いですが、さらに細かく区切ればより正確な最短ルートを出すことができます。
鬼の出現位置をランダムにする
最後に、鬼の出現位置を、右端でなく画面上のランダムな位置にします。ランダムな位置の生成はGameplayKitの「Randomization」機能を使ってみようと思います。
Randomizationはランダムな数字や真偽値を出力する機能です。arc4random_uniform関数に近いのですが、乱数の上限下限の設定やガウス分布に従う乱数の生成などさまざまな機能を備えています。
今回はこの機能を使って鬼の出現位置をランダムにしてみます。GameSceneのcreateEnemyメソッドを以下のように修正してください。
class GameScene: SKScene { // 省略 func createEnemy() { // ここから今回追加 guard let viewFrame = view?.frame else { return } let xDistribution = GKShuffledDistribution(lowestValue: -Int(viewFrame.width / 2), highestValue: Int(viewFrame.width / 2)) let yDistribution = GKShuffledDistribution(lowestValue: -Int(viewFrame.height / 2), highestValue: Int(viewFrame.height / 2)) // ここまで今回追加 let enemy = SKShapeNode(circleOfRadius: 10) enemy.position.x = CGFloat(xDistribution.nextInt()) // 今回修正 enemy.position.y = CGFloat(yDistribution.nextInt()) // 今回修正 enemy.fillColor = UIColor(red: 0.94, green: 0.14, blue: 0.08, alpha: 1.0) enemy.physicsBody = SKPhysicsBody(circleOfRadius: enemy.frame.width / 2) addChild(enemy) enemies.append(enemy) let anemyAgent = GKAgent2D() anemyAgent.maxAcceleration = 200 anemyAgent.maxSpeed = 70 anemyAgent.position = vector_float2(x: Float(enemy.position.x), y: Float(enemy.position.y)) anemyAgent.delegate = self anemyAgent.behavior = GKBehavior(goals: [ GKGoal(toSeekAgent: playerAgent), GKGoal(toAvoid: obstacles, maxPredictionTime: 10), GKGoal(toFleeAgent: sweeperAgent) ], andWeights: [NSNumber(value: 5), NSNumber(value: 50), NSNumber(value: 1)]) agentSystem.addComponent(anemyAgent) enemyAgents.append(anemyAgent) let goals = enemyAgents.map { GKGoal(toSeekAgent: $0) } sweeperAgent.behavior = GKBehavior(goals: goals + [GKGoal(toAvoid: obstacles, maxPredictionTime: 10)]) } // 省略 }
これで鬼が画面上のランダムな位置に出現するようになりました。
次回は、3Dゲームにおける「Agents, Goals, and Behaviors」の使い方
今回は「Agents, Goals, and Behaviors」を使った複雑なAIを作ってみましたが如何でしたか。
次回は鬼ごっこから離れて3Dゲームにおける「Agents, Goals, and Behaviors」の使い方を紹介します。
筆者紹介
杉本裕樹
田町のベンチャーで働くエンジニア。
仕事ではiPhoneアプリの開発やRailsを使ったWebサービス開発を行っている。最近のマイブームはUnityを使った3Dゲーム開発。
Copyright © ITmedia, Inc. All Rights Reserved.
関連記事
- iOS 9の最新機能で自動ルート検索を簡単にゲームに組み込む
iPhoneゲームをSwift言語で作成してみたいという初心者向けにiOSのゲームフレームワークを使った作り方を一から解説する入門連載。今回は、敵の動きを改善する。GameplayKitのPathfindingを使ったルートの自動探索の使い方についてSpriteKitのSKActionでの実装と比べて解説。 - iOS 10 SDKの新機能SiriKit、音声認識、iMessage拡張を自作アプリに生かすには
iOS 10で開発者にAPIが解放されたと話題の音声アシスタント「Siri」。その実態はどんなものなのか。SiriKit、Speech/Messages Frameworkの使い方と併せて、簡単なアプリを作りながら解説します。 - スマホ世代でも分かるMacの基本的な使い方&Xcodeをインストールする手順
本連載では、これからプログラミングやiPhoneアプリ開発を始めてみたい方を対象に、開発に必要な知識を基礎から解説していきます。今回は、プログラミングを学び始める前に、まずはMacの基本的な使い方を学び、Xcodeをインストールし、Playgroundを起動してみましょう。