iPhone向け鬼ごっこアプリを作りながら人工知能(AI)について学んでいく連載。今回は、SwiftのGameplayKitでAIの敵キャラに、追いかける、避ける、逃げる処理を追加する方法を解説する。
本連載『ゲームの「敵」キャラで分かる「人工知能」の作り方』では、iPhone向け鬼ごっこアプリを作りながら人工知能(AI)について学んでいきます。鬼の動きにAIを活用して、自動でプレイヤーを追いかけるようなAIを作りたいと思います。
前回の「iOS GameplayKitの「Agents, Goals, and Behaviors」で作る、鬼ごっごの鬼AI」では「Agents, Goals, and Behaviors」を使って、鬼がプレイヤーを追いかける処理を実装しました。
今回はAIをさらに進化させて、「追いかける」だけではなく「避ける」「逃げる」といった挙動をするAIを作ろうと思います。
前回のソースコードはこちらです。今回はこのソースコードを元に機能追加していきます。
まずはAIに「避ける」動作を追加します。フィールド上に障害物を配置し、鬼がそれを避けるような実装をしていきます。
その前に画面に障害物を設置します。今回は障害物は5つランダムに配置される仕様とします。「GameScene.swift」を以下のように修正してください。
class GameScene: SKScene {
// 省略
override func didMove(to view: SKView) {
player.fillColor = UIColor(red: 0.93, green: 0.96, blue: 0.00, alpha: 1.0)
addChild(player)
createObstacles() // 今回追加
setCreateEnemyTimer()
physicsWorld.gravity = CGVector()
}
// ここから今回追加
func createObstacles() {
guard let viewFrame = view?.frame else {
return
}
var obstacleNodes = [SKShapeNode]()
while obstacleNodes.count < 5 {
let point = CGPoint(
x: CGFloat(arc4random_uniform(UInt32(viewFrame.width))) - viewFrame.width / 2,
y: CGFloat(arc4random_uniform(UInt32(viewFrame.height))) - viewFrame.height / 2)
let radius = CGFloat(arc4random_uniform(50) + 50)
// 障害物かPlayerが衝突していたら設置しない
let isObstacleOverlapped = obstacleNodes.contains {
let dx = (point.x - $0.position.x)
let dy = (point.y - $0.position.y)
if sqrt(dx*dx + dy*dy) < $0.frame.width + radius {
return true
}
return false
}
let dx = point.x - player.position.x
let dy = point.y - player.position.y
let isPlayerOverlapped = sqrt(dx*dx + dy*dy) < radius + player.frame.width
if isObstacleOverlapped || isPlayerOverlapped {
continue
}
let obstacleNode = SKShapeNode(circleOfRadius: CGFloat(radius))
obstacleNode.fillColor = UIColor(red: 0.7, green: 0.7, blue: 0.7, alpha: 1.0)
obstacleNode.position = point
obstacleNode.physicsBody = SKPhysicsBody(circleOfRadius: CGFloat(radius))
obstacleNode.physicsBody?.pinned = true
addChild(obstacleNode)
obstacleNodes.append(obstacleNode)
}
}
// ここまで今回追加
// 省略
}
アプリを起動すると、画面上に5つの障害物が配置されていることが分かります。
次はプレイヤーを修正します。今はプレイヤーが障害物と重なるところができてしまうので、重ならないように修正します。
GameScene.swiftのdidMoveメソッドに処理を追加します。
class GameScene: SKScene {
// 省略
override func didMove(to view: SKView) {
player.fillColor = UIColor(red: 0.93, green: 0.96, blue: 0.00, alpha: 1.0)
player.physicsBody = SKPhysicsBody(circleOfRadius: 10) // 今回追加
addChild(player)
createObstacles()
setCreateEnemyTimer()
physicsWorld.gravity = CGVector()
}
// 省略
}
これでプレイヤーが障害物と重ならなくなりました。
今回追加したphysicsBodyは物理演算に使うプロパティーです。Node同士の衝突時の挙動をコントールしたり、重力などの外部からの力を加えるときに使います。
今回はプレイヤーと障害物にphysicsBodyを設定することで、お互いが衝突して重ならないようにしました。
iOS 9の最新機能で自動ルート検索を簡単にゲームに組み込む
iOS 10 SDKの新機能SiriKit、音声認識、iMessage拡張を自作アプリに生かすには
スマホ世代でも分かるMacの基本的な使い方&Xcodeをインストールする手順Copyright © ITmedia, Inc. All Rights Reserved.