动画阵列没有动画精灵

时间:2018-05-16 14:19:35

标签: ios swift sprite-kit

我正在使用SpriteKit在Swift中制作一个简单的RPG。我写了一个字符类来帮助我处理所有的动画,我在动画方面遇到了一些麻烦。

角色等级:

class Character: SKSpriteNode {

    var walkSouthArray = [SKTexture]()
    var walkNorthArray = [SKTexture]()
    var walkEastArray = [SKTexture]()
    var walkWestArray = [SKTexture]()

    override init(texture: SKTexture?, color: UIColor, size: CGSize) {
        super.init(texture: nil, color: UIColor.clear, size: CGSize(width: 100, height: 150))
        self = CGSize(width: 100, height: 150)
        self.position = CGPoint(x: 0, y: 0)
        self.texture = SKTexture(imageNamed: "walk_south_1")

        let northAtlas = SKTextureAtlas(named: "walk_north")
        var northFrames:[SKTexture] = []
        for index in 1 ... 8 {
            let textureName = "walk_north_\(index)"
            let texture = northAtlas.textureNamed(textureName)
            northFrames.append(texture)
            walkNorthArray = northFrames
        }

        let southAtlas = SKTextureAtlas(named: "walk_south")
        var southFrames:[SKTexture] = []
        for index in 1 ... 8 {
            let textureName = "walk_south_\(index)"
            let texture = southAtlas.textureNamed(textureName)
            southFrames.append(texture)
            walkSouthArray = southFrames
        }

        let eastAtlas = SKTextureAtlas(named: "walk_east")
        var eastFrames:[SKTexture] = []
        for index in 1 ... 8 {
            let textureName = "walk_east_\(index)"
            let texture = eastAtlas.textureNamed(textureName)
            eastFrames.append(texture)
            walkEastArray = eastFrames
        }

        let westAtlas = SKTextureAtlas(named: "walk_west")
        var westFrames:[SKTexture] = []
        for index in 1 ... 8 {
            let textureName = "walk_\(index)"
            let texture = westAtlas.textureNamed(textureName)
            westFrames.append(texture)
            walkWestArray = westFrames
        }


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

    func walkNorth() {
        self.run(SKAction.repeatForever(SKAction.animate(with: walkNorthArray, timePerFrame: 0.2)))
    }

    func walkSouth() {
        self.run(SKAction.repeatForever(SKAction.animate(with: walkSouthArray, timePerFrame: 0.2)))
    }

    func walkEast() {
        self.run(SKAction.repeatForever(SKAction.animate(with: walkEastArray, timePerFrame: 0.2)))
    }

    func walkWest() {
        self.run(SKAction.repeatForever(SKAction.animate(with: walkWestArray, timePerFrame: 0.2)))
    }
}

尚未绘制Walk West的框架

游戏场景类:

class GameScene: SKScene {
    var v = CGVector()

    var xJoystickDelta = CGFloat()
    var yJoystickDelta = CGFloat()

    var UINode = SKNode()
    var WorldNode = SKNode()

    var character = Character()

    var DPad = SKSpriteNode()
    var thumbNode = SKSpriteNode()

    var isTracking:Bool = false

    override func didMove(to view: SKView) {
        DPad = SKSpriteNode(texture: SKTexture(imageNamed: "base"))
        DPad.size = CGSize(width: 150, height: 150)
        DPad.position = CGPoint(x: -200, y: -100)
        DPad.zPosition = 3
        UINode.addChild(DPad)

        thumbNode = SKSpriteNode(texture: SKTexture(imageNamed: "stick"))
        thumbNode.size = CGSize(width: 50, height: 50)
        thumbNode.position = CGPoint(x: -200, y: -100)
        thumbNode.zPosition = 4
        UINode.addChild(thumbNode)

        self.addChild(UINode)
        self.addChild(character)
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        for touch in touches {
            let location = touch.location(in: self)
            if isTracking == false && DPad.contains(location) {
                isTracking = true
            }
        }
    }

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        for touch in touches {
            let location: CGPoint = touch.location(in: self)
            if isTracking == true {

                v = CGVector(dx: location.x - DPad.position.x, dy: location.y - DPad.position.y)
                let angle = atan2(v.dy, v.dx)
                let deg = angle * CGFloat(180 / Double.pi)

                let Length:CGFloat = DPad.frame.size.height / 2
                let xDist: CGFloat = sin(angle - 1.57079633) * Length
                let yDist: CGFloat = cos(angle - 1.57079633) * Length

                xJoystickDelta = location.x - DPad.position.x
                yJoystickDelta = location.y - DPad.position.y

                if DPad.contains(location) {
                    thumbNode.position = location
                } else {
                    thumbNode.position = CGPoint(x: DPad.position.x - xDist, y: DPad.position.y + yDist)
                }
            }
        }
    }

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        isTracking = false
        thumbNode.run(SKAction.move(to: CGPoint(x: -200, y: -100), duration: 0.01))
        xJoystickDelta = 0
        yJoystickDelta = 0
    }

    override func update(_ currentTime: TimeInterval) {
        // Called before each frame is rendered
        if v.dx > abs(v.dy) {
            // right
            character.walkEast()
        } else if v.dx < -abs(v.dy) {
            // left
            character.walkWest()
        } else if v.dy > 0 {
            // up
            character.walkNorth()
        } else if v.dy < 0 {
            // down
            character.walkSouth()
        }
    }
}

它以这样的方式设置,所以我所要做的就是调用动画的函数。当我打电话给他们时,我得到的是一张静止图像(Atlas中的第一张图片)

据我所知,我的地图集已正确设置:

Image 1

我单击“+”按钮并选择“New Sprite Atlas”然后将我的图像拖放到新文件夹中并重命名。

1 个答案:

答案 0 :(得分:1)

在更新周期中做事时要小心。

对于大多数设备,此操作默认以60 FPS运行,因此其中的任何命令都将以该速率触发。

在您的特定情况下,您在每次更新时都添加了一个新的动画操作,因此就应用程序而言,它正在绘制动画,但您继续添加新的开始动画。

因为你没有&#34; X-Ray&#34;视觉,你无法透过最顶层的动画层来注意下面绘制的其他动画。 (这只是概念,当然,系统并没有真正将层叠在一起)

我建议您更改代码,以便只调用一次动画,并将其从更新周期中删除。

我喜欢住的好规则就是:

  

如果每帧都没有发生变化,那么不要在更新功能中包含处理它的代码

这意味着如果然后检查if v.dx > abs(v.dy),则删除浪费时间,因为如果v.dx&gt;不需要检查每一帧v.dy,我们只需要在dxdy更改时进行检查。

在您的情况下,这发生在touchedMoved事件期间。

在此功能中更改v后,请执行更新功能中的代码以运行动画。

当然,您还需要删除其他移动动作,这样您就不会加倍动作。

您的代码应如下所示:

class GameScene: SKScene {
    enum Direction
    {
       case none
       case up
       case down
       case left
       case right
    }
    var charDir = Direction.none
    var v = CGVector()

    var xJoystickDelta = CGFloat()
    var yJoystickDelta = CGFloat()

    var UINode = SKNode()
    var WorldNode = SKNode()

    var character = Character()

    var DPad = SKSpriteNode()
    var thumbNode = SKSpriteNode()

    var isTracking:Bool = false

    override func didMove(to view: SKView) {
        DPad = SKSpriteNode(texture: SKTexture(imageNamed: "base"))
        DPad.size = CGSize(width: 150, height: 150)
        DPad.position = CGPoint(x: -200, y: -100)
        DPad.zPosition = 3
        UINode.addChild(DPad)

        thumbNode = SKSpriteNode(texture: SKTexture(imageNamed: "stick"))
        thumbNode.size = CGSize(width: 50, height: 50)
        thumbNode.position = CGPoint(x: -200, y: -100)
        thumbNode.zPosition = 4
        UINode.addChild(thumbNode)

        self.addChild(UINode)
        self.addChild(character)
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        for touch in touches {
            let location = touch.location(in: self)
            if isTracking == false && DPad.contains(location) {
                isTracking = true
            }
        }
    }

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        for touch in touches {
            let location: CGPoint = touch.location(in: self)
            if isTracking == true {

                v = CGVector(dx: location.x - DPad.position.x, dy: location.y - DPad.position.y)
                var newDirection = Direction.none
                if v.dx > abs(v.dy) {
                  // right
                  newDirection = .right
                } else if v.dx < -abs(v.dy) {
                  // left
                  newDirection = .left
                } else if v.dy > 0 {
                // up
                  newDirection = .up
                } else if v.dy < 0 {
                // down
                  newDirection = .down
                }                    
                if charDir != newDirection
                {
                  charDir = newDirection
                  character.removeAllActions()
                  switch charDir{
                    case .right: character.walkEast()
                    case .left:  character.walkWest()
                    case .up:    character.walkNorth()
                    case .down:  character.walkSouth()
                    default: break
                  }
                }
                let angle = atan2(v.dy, v.dx)
                let deg = angle * CGFloat(180 / Double.pi)

                let Length:CGFloat = DPad.frame.size.height / 2
                let xDist: CGFloat = sin(angle - 1.57079633) * Length
                let yDist: CGFloat = cos(angle - 1.57079633) * Length

                xJoystickDelta = location.x - DPad.position.x
                yJoystickDelta = location.y - DPad.position.y

                if DPad.contains(location) {
                    thumbNode.position = location
                } else {
                    thumbNode.position = CGPoint(x: DPad.position.x - xDist, y: DPad.position.y + yDist)
                }
            }
        }
    }

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        isTracking = false
        thumbNode.run(SKAction.move(to: CGPoint(x: -200, y: -100), duration: 0.01))
        xJoystickDelta = 0
        yJoystickDelta = 0
    }

    override func update(_ currentTime: TimeInterval) {

    }
}

如果您的角色正在进行其他操作,您可能需要考虑为动画分配一个键。