Приключение/Приключение Shared/Sprites/HeroCharacter.swift

/*
  Copyright (C) 2014 Apple Inc. All Rights Reserved.
  See LICENSE.txt for this sample’s licensing information
  
  Abstract:
  
        Defines the common class for hero characters
      
*/
 
import SpriteKit
 
var sSharedProjectileSoundAction = SKAction()
 
let kPlayer = "kPlayer"
 
let kHeroProjectileSpeed: CGFloat = 480.0
let kHeroProjectileLifetime: NSTimeInterval = 1.0
let kHeroProjectileFadeOutTime: NSTimeInterval = 0.6
 
class HeroCharacter: Character {
    // MARK: Properties
    
    var player: Player!
 
    // MARK: Initializers
 
    convenience init(atPosition position: CGPoint, withTexture texture: SKTexture? = nil, player: Player) {
        self.init(texture: texture, atPosition: position)
        self.player = player
        
        zRotation = CGFloat(M_PI)
        zPosition = -0.25
        name = "Hero"
    }
    
    // MARK: Setup
 
    override func configurePhysicsBody() {
        // Assign the physics body; unwrap the physics body to configure it.
        physicsBody = SKPhysicsBody(circleOfRadius: Character.Constants.collisionRadius)
        physicsBody!.categoryBitMask = ColliderType.Hero.rawValue
        physicsBody!.collisionBitMask = ColliderType.allButProjectile
        physicsBody!.contactTestBitMask = ColliderType.GoblinOrBoss.rawValue
    }
    
    func projectile() -> SKSpriteNode? {
        return nil
    }
    
    func projectileEmitter() -> SKEmitterNode? {
        return nil
    }
    
    func projectileSoundAction() -> SKAction {
        return sSharedProjectileSoundAction
    }
 
    // MARK: Scene Processing Support
 
    override func animationDidComplete(animation: AnimationState) {
        super.animationDidComplete(animation)
 
        switch animation {
            case .Death:
                let actions = [SKAction.waitForDuration(4.0),
                               SKAction.runBlock {
                                   self.characterScene.heroWasKilled(self)
                               },
                               SKAction.removeFromParent()]
                runAction(SKAction.sequence(actions))
 
            case .Attack:
                fireProjectile()
 
           default:
                () // Do nothing
        }
    }
 
    override func collidedWith(other: SKPhysicsBody) {
        if other.categoryBitMask & ColliderType.GoblinOrBoss.rawValue == 0 {
            return
        }
 
        if let enemy = other.node as? Character {
            if !enemy.dying {
                applyDamage(5.0)
                requestedAnimation = .GetHit
            }
        }
    }
 
    func fireProjectile() {
        let projectile = self.projectile()!.copy() as SKSpriteNode
        projectile.position = position
        projectile.zRotation = zRotation
 
        let emitter = projectileEmitter()!.copy() as SKEmitterNode
        emitter.targetNode = scene!.childNodeWithName("world")
        projectile.addChild(emitter)
 
        characterScene.addNode(projectile, atWorldLayer: .Character)
        let rot = zRotation
 
        let x = -sin(rot) * kHeroProjectileSpeed * CGFloat(kHeroProjectileLifetime)
        let y =  cos(rot) * kHeroProjectileSpeed * CGFloat(kHeroProjectileLifetime)
        projectile.runAction(SKAction.moveByX(x, y: y, duration: kHeroProjectileLifetime))
 
        let waitAction = SKAction.waitForDuration(kHeroProjectileFadeOutTime)
        let fadeAction = SKAction.fadeOutWithDuration(kHeroProjectileLifetime - kHeroProjectileFadeOutTime)
        let removeAction = SKAction.removeFromParent()
        let sequence = [waitAction, fadeAction, removeAction]
 
        projectile.runAction(SKAction.sequence(sequence))
        projectile.runAction(projectileSoundAction())
 
        let data: NSMutableDictionary = ["kPlayer" : self.player]
        projectile.userData = data
    }
 
    // MARK: Asset Pre-loading
 
    class func loadSharedHeroAssets() {
        sSharedProjectileSoundAction = SKAction.playSoundFileNamed("magicmissile.caf", waitForCompletion: false)
    }
}