【问题标题】:How can I animate a SKPhysicsBody texture from an SKTextureAtlas如何从 SKTextureAtlas 为 SKPhysicsBody 纹理设置动画
【发布时间】:2019-01-07 04:05:36
【问题描述】:

我有一个 SKTextureAtlas,其中包含 7 帧具有透明背景的动画精灵。

我已经能够使用图集中的单个帧作为物理体的边界,但我想知道,如果可能的话,如何让物理体为图集中的每一帧更新其轮廓.

这里我有使用名为“Run0”的框架的物理体,并且它被正确应用。我只是想看看这是否可能,或者让物理体使用图集中从“Run0”到“Run7”的每一帧是否完全不切实际。

Image of physics body with the outline of "Run0"

这是我正在处理的代码:

import SpriteKit

类 GameScene:SKScene {

let dogSpriteNode = SKSpriteNode(imageNamed: "Run0")
var dogFrames = [SKTexture]()

override func didMove(to view: SKView) {

    physicsWorld.gravity = CGVector(dx: 0, dy: -9.8)
    physicsBody = SKPhysicsBody(edgeLoopFrom: frame)

    dogSpriteNode.setScale(0.1)
    dogSpriteNode.position = CGPoint(x: frame.midX, y: frame.midY)
    addChild(dogSpriteNode)

    let textureAtlas = SKTextureAtlas(named: "Dog Frames")

    for index in 0..<textureAtlas.textureNames.count {
        let textureName = "Run" + String(index)
        dogFrames.append(textureAtlas.textureNamed(textureName))
    }

    dogSpriteNode.physicsBody = SKPhysicsBody(
        texture: textureAtlas.textureNamed("Run0"),
        alphaThreshold: 0.5,
        size: dogSpriteNode.frame.size)

}

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

    dogSpriteNode.run(SKAction.group([SKAction.repeatForever(SKAction.animate(with: dogFrames, timePerFrame: 0.1))]))
    dogSpriteNode.run(SKAction.applyImpulse(CGVector(dx: 0, dy: 1000), duration: 0.1))

}

}

【问题讨论】:

    标签: ios swift sprite-kit skphysicsbody sktextureatlas


    【解决方案1】:

    实现此目的的一种方法是使用自定义SKAction

    extension SKAction {
    
        public class func animateTexturesWithPhysics(_ frames: [(texture: SKTexture, duration: TimeInterval)], repeatForever: Bool=true) -> SKAction {
            var actions: [SKAction] = []
            for frame in frames {
                // define a custom action for each frame
                let customAction = SKAction.customAction(withDuration: frame.duration) { node, _ in
                    // if the action target is a sprite node, apply the texture & physics
                    if node is SKSpriteNode {
                        let setTextureGroup = SKAction.group([
                                SKAction.setTexture(frame.texture, resize: false),
                                SKAction.wait(forDuration: frame.duration),
                                SKAction.run {
                                    node.physicsBody = SKPhysicsBody(texture: frame.texture, alphaThreshold: 0.5, size: frame.texture.size())
                                    // add physics attributes here
                                }
                            ])
                        node.run(setTextureGroup)
                    }
                }
                actions.append(customAction)
            }
    
            // add the repeating action
            if (repeatForever == true) {
                return SKAction.repeatForever(SKAction.sequence(actions))
            }
            return SKAction.sequence(actions)
        }
    }
    

    要实现它,您需要创建一个由帧 + 持续时间组成的数组并将动作应用到精灵:

    typealias Frame = (texture: SKTexture, duration: TimeInterval)
    let timePerFrame: TimeInterval = 0.1
    let dogFrames: [Frame] = dogTextures.map {
        return ($0, timePerFrame)
    }
    
    dogSpriteNode = SKSpriteNode(texture: dogFrames.first)
    let dogAnimationAction = SKAction.animateTexturesWithPhysics(dogFrames)
    dogSpriteNode.run(dogAnimationAction)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-20
      • 2012-04-03
      • 1970-01-01
      • 1970-01-01
      • 2013-10-24
      相关资源
      最近更新 更多