/* |
Copyright (C) 2014 Apple Inc. All Rights Reserved. |
See LICENSE.txt for this sample’s licensing information |
|
Abstract: |
|
Defines the class for AI that chases a character |
|
*/ |
|
import SpriteKit |
|
class ChaseArtificialIntelligence: ArtificialIntelligence { |
// MARK: Types |
|
struct Constants { |
static let enemyAlertRadius = Character.Constants.collisionRadius * 500 |
} |
|
// MARK: Properties |
|
// Bosses and goblins have different attack and alert radii. These both have default values |
// that match goblins, but will change if they correspond to a boss. |
var attackRadius: CGFloat = Character.Constants.collisionRadius * 2.0 |
var maxAlertRadius: CGFloat = Constants.enemyAlertRadius * 2.0 |
|
// MARK: Scene Processing Support |
|
override func updateWithTimeSinceLastUpdate(timeInterval: NSTimeInterval) { |
// The goal of the implementation of this method is to find the closest hero within the |
// enemy alert radius. After finding the closest hero, chase it! |
|
// No need to move / attack the character if it's dying. |
if character.dying { |
target = nil |
|
return |
} |
|
if let (closestHeroDistance, closestHero) = closestHeroWithinEnemyAlertRadius() { |
target = closestHero |
|
chaseTargetWithinDistance(closestHeroDistance, timeInterval: timeInterval) |
} |
else { |
target = nil |
} |
} |
|
// MARK: Intelligence Implementation |
|
func closestHeroWithinEnemyAlertRadius() -> (closestHeroDistance: CGFloat, closestHero: HeroCharacter)? { |
let position = character.position |
|
// Start off with the maximum distance possible away from any of the heroes. |
var closestHeroDistance = CGFloat.max |
var closestHero: HeroCharacter? |
|
for hero in character.characterScene.heroes { |
let distance = position.distanceToPoint(hero.position) |
|
if distance < Constants.enemyAlertRadius && distance < closestHeroDistance && !hero.dying { |
closestHeroDistance = distance |
closestHero = hero |
} |
} |
|
if closestHero != nil && closestHeroDistance <= maxAlertRadius { |
return (closestHeroDistance: closestHeroDistance, closestHero: closestHero!) |
} |
|
return nil |
} |
|
func chaseTargetWithinDistance(closestHeroDistance: CGFloat, timeInterval: NSTimeInterval) { |
if let heroPosition = target?.position { |
if closestHeroDistance > attackRadius { |
character.moveTowards(heroPosition, withTimeInterval: timeInterval) |
} |
else { |
character.faceTo(heroPosition) |
character.performAttackAction() |
} |
} |
} |
} |