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を設定することで、お互いが衝突して重ならないようにしました。
Copyright © ITmedia, Inc. All Rights Reserved.