带动画子画面的SKSpriteNode和SKAction

时间:2018-10-03 21:15:04

标签: swift sprite-kit skspritenode skaction

我正试图让我的游戏中的玩家精灵根据自己的行为进行动画处理,例如,走路,进攻,休息。

我有以下文件AgentNode和GameScene。

精灵会随我所愿地生成和移动,只是将精灵添加到场景中时就已经执行了初始动作。

例如,如果我添加带有“ restingFrames”动画的精灵,则它会正确生成,但是当移动该精灵时,该动画仍会根据需要使用“ restingFrames”而不是“ walkingFrames”。无法弄清楚,请帮忙。

AgentNode.swift

import SpriteKit
import GameplayKit

class AgentNode: SKNode, GKAgentDelegate {

var agent = GKAgent2D()
var triangleShape = SKShapeNode()

var player = SKSpriteNode()
var walkingFrames: [SKTexture] = []
var restingFrames: [SKTexture] = []
var attackingFrames: [SKTexture] = []
var firstFrameTexture: SKTexture = SKTexture()

var playerSpawned = false

override init() {
    super.init()
}

init(scene:SKScene, radius: Float, position: CGPoint) {
    super.init()

    self.position = position
    self.zPosition = 10
    scene.addChild(self)

    agent.radius = radius
    agent.position = simd_float2(Float(position.x), Float(position.y))
    agent.delegate = self
    agent.maxSpeed = 100 * 2
    agent.maxAcceleration = 500 * 4
}

func setupPlayer() {
    setupRestingPlayerAnimation()
    setupWalkingPlayerAnimation()
    setupAttackingPlayerAnimation()
}

func setupWalkingPlayerAnimation() {
    let walkingPlayerAtlas = SKTextureAtlas(named: "WalkingPlayer")

    let numImages = walkingPlayerAtlas.textureNames.count
    for i in 1...numImages {
        let walkingPlayerTextureName = "walk_front\(i)"
        walkingFrames.append(walkingPlayerAtlas.textureNamed(walkingPlayerTextureName))
    }
}

func setupRestingPlayerAnimation() {
    let restingPlayerAtlas = SKTextureAtlas(named: "RestingPlayer")

    let numImages = restingPlayerAtlas.textureNames.count
    for i in 1...numImages {
        let restingPlayerTextureName = "still_frame\(i)"
        restingFrames.append(restingPlayerAtlas.textureNamed(restingPlayerTextureName))
    }
}

func setupAttackingPlayerAnimation() {
    let attackingPlayerAtlas = SKTextureAtlas(named: "AttackingPlayer")

    let numImages = attackingPlayerAtlas.textureNames.count
    for i in 1...numImages {
        let attackingPlayerTextureName = "attack_frame\(i)"
        attackingFrames.append(attackingPlayerAtlas.textureNamed(attackingPlayerTextureName))
    }
}

func animatePlayer() {

    var restingSequence = SKAction()
    var walkingSequence = SKAction()
    var attackingSequence = SKAction()

    let restingAnimation = SKAction.animate(with: restingFrames, timePerFrame: 0.15)

    let walkingAnimation = SKAction.animate(with: walkingFrames, timePerFrame: 0.1)

    let attackingAnimation = SKAction.animate(with: attackingFrames, timePerFrame: 0.1)

    restingSequence = SKAction.sequence([restingSequence])
    walkingSequence = SKAction.sequence([walkingSequence])
    attackingSequence = SKAction.sequence([attackingSequence])

    if isSeeking && !isAttacking{
        firstFrameTexture = walkingFrames[0]
        player.run(SKAction.repeatForever(walkingAnimation), withKey: "walkingAction")
        print("walking")

    } else if isAttacking && !isSeeking {
        firstFrameTexture = attackingFrames[0]
        player.run(SKAction.repeatForever(attackingAnimation), withKey: "attackingAction")
        print("attacking")

    } else {
        firstFrameTexture = restingFrames[0]
        player.run(SKAction.repeatForever(restingAnimation), withKey: "restingAction")
        print("resting")
    }
}

func addPlayerToScene() {
    player = SKSpriteNode(texture: firstFrameTexture)
    player.position = CGPoint(x: (frame.midX), y: (frame.midY))
    player.setScale(1.5)
    player.zRotation = CGFloat(Double.pi / 2.0)
    player.zPosition = 10
    self.addChild(player)
    playerSpawned = true
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

func agentWillUpdate(_ agent: GKAgent) {

}

func agentDidUpdate(_ agent: GKAgent) {

    if playerSpawned == false {
        print("player has not spawned")
        setupPlayer()
        animatePlayer()
        addPlayerToScene()
        playerSpawned = true
    } else {
        print("player has spawned")
        animatePlayer()
    }
    print("player isSeeking \(isSeeking)")
    print("player isAttacking \(isAttacking)")

    guard let agent2D = agent as? GKAgent2D else {
        return
    }

    self.position = CGPoint(x: CGFloat(agent2D.position.x), y: CGFloat(agent2D.position.y))
    self.zRotation = CGFloat(agent2D.rotation)

}

}

GameScene.swift

import SpriteKit
import GameplayKit

var isSeeking: Bool = false
var isAttacking: Bool = false

class GameScene: SKScene {

let trackingAgent = GKAgent2D()
var player = AgentNode()
var seekGoal : GKGoal = GKGoal()
let stopGoal = GKGoal(toReachTargetSpeed: 0.0)

var seeking : Bool = false {
    willSet {

        if newValue {
            self.player.agent.behavior?.setWeight(5, for: seekGoal)
            self.player.agent.behavior?.setWeight(0, for: stopGoal)
        } else {
            self.player.agent.behavior?.setWeight(0, for: seekGoal)
            self.player.agent.behavior?.setWeight(5, for: stopGoal)
        }
    }
}

var agentSystem = GKComponentSystem()
var lastUpdateTime: TimeInterval = 0

override func didMove(to view: SKView) {
    super.didMove(to: view)

    self.trackingAgent.position = simd_float2(Float(self.frame.midX), Float(self.frame.midY))

    self.agentSystem = GKComponentSystem(componentClass: GKAgent2D.self)

    self.player = AgentNode(scene: self, radius: Float(20.0), position: CGPoint(x: self.frame.midX, y: self.frame.midY))

    self.player.agent.behavior = GKBehavior()
    self.agentSystem.addComponent(self.player.agent)

    self.seekGoal = GKGoal(toSeekAgent: self.trackingAgent)
}

override func update(_ currentTime: CFTimeInterval) {
    isSeeking = self.seeking

    if lastUpdateTime == 0 {
        lastUpdateTime = currentTime
    }

    let delta = currentTime - lastUpdateTime
    lastUpdateTime = currentTime
    self.agentSystem.update(deltaTime: delta)
}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    self.seeking = true
    handleTouch(touches: touches)
}

override func touchesCancelled(_ touches: Set<UITouch>?, with event: UIEvent?) {
    self.seeking = false
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    self.seeking = false
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    handleTouch(touches: touches)
}

func handleTouch(touches:Set<UITouch>) {
    guard let touch = touches.first
        else {
            return
    }

    let location = touch.location(in: self)

    self.trackingAgent.position = simd_float2(Float(location.x), Float(location.y))
}

}

1 个答案:

答案 0 :(得分:1)

好吧,我知道了。我更新了代码,如下所示,一切正常。

AgentNode.swift

import SpriteKit
import GameplayKit

class AgentNode: SKNode, GKAgentDelegate {

var agent = GKAgent2D()
var triangleShape = SKShapeNode()

var player = SKSpriteNode()

var walkingFrames: [SKTexture] = []
var restingFrames: [SKTexture] = []
var attackingFrames: [SKTexture] = []

var playerSpawned = false

override init() {
    super.init()
}

init(scene:SKScene, radius: Float, position: CGPoint) {
    super.init()

    self.position = position
    self.zPosition = 10
    scene.addChild(self)

    agent.radius = radius
    agent.position = simd_float2(Float(position.x), Float(position.y))
    agent.delegate = self
    agent.maxSpeed = 100 * 2
    agent.maxAcceleration = 500 * 4
}

func setupPlayer() {
    setupRestingPlayerAnimation()
    setupWalkingPlayerAnimation()
    setupAttackingPlayerAnimation()
}

func setupWalkingPlayerAnimation() {
    let walkingPlayerAtlas = SKTextureAtlas(named: "WalkingPlayer")

    let numImages = walkingPlayerAtlas.textureNames.count
    for i in 1...numImages {
        let walkingPlayerTextureName = "walk_front\(i)"
        walkingFrames.append(walkingPlayerAtlas.textureNamed(walkingPlayerTextureName))
    }
}

func setupRestingPlayerAnimation() {
    let restingPlayerAtlas = SKTextureAtlas(named: "RestingPlayer")

    let numImages = restingPlayerAtlas.textureNames.count
    for i in 1...numImages {
        let restingPlayerTextureName = "still_frame\(i)"
        restingFrames.append(restingPlayerAtlas.textureNamed(restingPlayerTextureName))
    }
}

func setupAttackingPlayerAnimation() {
    let attackingPlayerAtlas = SKTextureAtlas(named: "AttackingPlayer")

    let numImages = attackingPlayerAtlas.textureNames.count
    for i in 1...numImages {
        let attackingPlayerTextureName = "attack_frame\(i)"
        attackingFrames.append(attackingPlayerAtlas.textureNamed(attackingPlayerTextureName))
    }
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

func agentWillUpdate(_ agent: GKAgent) {

}

func agentDidUpdate(_ agent: GKAgent) {

    guard let agent2D = agent as? GKAgent2D else {
        return
    }

    self.position = CGPoint(x: CGFloat(agent2D.position.x), y: CGFloat(agent2D.position.y))
    self.zRotation = CGFloat(agent2D.rotation)

}

}

GameScene.swift

import SpriteKit
import GameplayKit

var isSeeking: Bool = false
var isAttacking: Bool = false

class GameScene: SKScene {

let trackingAgent = GKAgent2D()
var player = AgentNode()
var seekGoal : GKGoal = GKGoal()
let stopGoal = GKGoal(toReachTargetSpeed: 0.0)

var seeking : Bool = false {
    willSet {

        if newValue {
            self.player.agent.behavior?.setWeight(5, for: seekGoal)
            self.player.agent.behavior?.setWeight(0, for: stopGoal)
        } else {
            self.player.agent.behavior?.setWeight(0, for: seekGoal)
            self.player.agent.behavior?.setWeight(5, for: stopGoal)
        }
    }
}

var agentSystem = GKComponentSystem()
var lastUpdateTime: TimeInterval = 0

override func didMove(to view: SKView) {
    super.didMove(to: view)

    self.trackingAgent.position = simd_float2(Float(self.frame.midX), Float(self.frame.midY))

    self.agentSystem = GKComponentSystem(componentClass: GKAgent2D.self)

    self.player = AgentNode(scene: self, radius: Float(20.0), position: CGPoint(x: self.frame.midX, y: self.frame.midY))

    self.player.agent.behavior = GKBehavior()
    self.agentSystem.addComponent(self.player.agent)

    self.seekGoal = GKGoal(toSeekAgent: self.trackingAgent)
    player.setupPlayer()
    //player.animatePlayer()
    player.player = SKSpriteNode(imageNamed: "default_pose")
    player.player.position = CGPoint(x: (frame.midX), y: (frame.midY))
    player.player.setScale(1.5)
    player.player.zRotation = CGFloat(Double.pi / 2.0)
    player.player.zPosition = 10
    player.player.run(SKAction.repeatForever(SKAction.animate(with: player.restingFrames, timePerFrame: 0.2)))
    player.addChild(player.player)

}

override func update(_ currentTime: CFTimeInterval) {
    isSeeking = self.seeking

    if lastUpdateTime == 0 {
        lastUpdateTime = currentTime
    }

    let delta = currentTime - lastUpdateTime
    lastUpdateTime = currentTime
    self.agentSystem.update(deltaTime: delta)
}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    self.seeking = true
    player.player.run(SKAction.repeatForever(SKAction.animate(with: player.walkingFrames, timePerFrame: 0.1)))
    handleTouch(touches: touches)
}

override func touchesCancelled(_ touches: Set<UITouch>?, with event: UIEvent?) {
    self.seeking = false

}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    self.seeking = false
    player.player.removeAllActions()
    player.player.run(SKAction.repeatForever(SKAction.animate(with: player.attackingFrames, timePerFrame: 0.1)))
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    handleTouch(touches: touches)
}

func handleTouch(touches:Set<UITouch>) {
    guard let touch = touches.first
        else {
            return
    }

    let location = touch.location(in: self)

    self.trackingAgent.position = simd_float2(Float(location.x), Float(location.y))
}

}