如何在 SpriteKit 中使用不同大小的纹理制作动画

Posted

技术标签:

【中文标题】如何在 SpriteKit 中使用不同大小的纹理制作动画【英文标题】:How to animate with textures of different sizes in SpriteKit 【发布时间】:2017-11-16 20:34:49 【问题描述】:

我正在尝试为行走角色的死亡设置动画,但死亡精灵的比例与行走的角色不同。

首先我在 func didMove(to view: SKView) 上创建一个 SKSpriteNode 并将其添加到场景中:

//create monster, add physics to detect collision with projectile and add to scene with walking animation
let monster = SKSpriteNode(imageNamed: "zombie")
monster.yScale = CGFloat(-0.58)
monster.xScale = CGFloat(0.58)
monster.physicsBody = SKPhysicsBody(rectangleOf: monster.size)
monster.physicsBody?.isDynamic = true
monster.physicsBody?.categoryBitMask = PhysicsCategory.Monster
monster.physicsBody?.contactTestBitMask = PhysicsCategory.Projectile
monster.physicsBody?.collisionBitMask = PhysicsCategory.None
// Determine where to spawn the monster along the Y axis
 let actualY = random(min: monster.size.height/2, max: size.height - (monster.size.height/2)-20)
 // Position the monster slightly off-screen along the right edge,
 // and along a random position along the Y axis as calculated above
 monster.position = CGPoint(x: size.width + monster.size.width/2, y: actualY)

// Add the monster to the scene
        worldNode.addChild(monster)

        // Determine speed of the monster

        let actualDuration = random(min: CGFloat(2.0)-CGFloat(self.level/10), max: CGFloat(4.0)-CGFloat(self.level/10))

        // Create the actions
        let actionMove = SKAction.move(to: CGPoint(x: -monster.size.width/2, y: actualY), duration: TimeInterval(actualDuration))

        let actionMoveDone = SKAction.removeFromParent()

        let atlas = SKTextureAtlas(named: monsterVariant)
        var m0 = SKTexture()
        var m1 = SKTexture()
        var m2 = SKTexture()
        var m3 = SKTexture()
        var m4 = SKTexture()
        var m5 = SKTexture()
        m0 = atlas.textureNamed("\(monsterVariant)_Walk1") //222x396
        m1 = atlas.textureNamed("\(monsterVariant)_Walk2")//222x366
        m2 = atlas.textureNamed("\(monsterVariant)_Walk3")//250x375
        m3 = atlas.textureNamed("\(monsterVariant)_Walk4")//237×379
        m4 = atlas.textureNamed("\(monsterVariant)_Walk5")//221×371
        m5 = atlas.textureNamed("\(monsterVariant)_Walk6")//228×402

        let textures = [m0,m1,m2,m3,m4,m5]
        let walkAnimation = SKAction.animate(with:textures, timePerFrame: 0.07)
        monster.run(SKAction.repeatForever(walkAnimation))

然后,当弹丸和怪物相撞时,我希望播放骰子动画并让怪物消失。请注意 cmets 上的纹理尺寸:

func projectileDidCollideWithMonster(projectile: SKSpriteNode, monster: SKSpriteNode) 
        let dyingMonsterPosition = monster.position
        addToScoreBasedOnPosition(monster:monster)
        projectile.removeFromParent()

        let atlas = SKTextureAtlas(named: String(monster.name!))
        print(String(monster.name!))
        var m1 = SKTexture()
        var m2 = SKTexture()
        var m3 = SKTexture()
        var m4 = SKTexture()
        var m5 = SKTexture()
        var m6 = SKTexture()
        var m7 = SKTexture()
        var m8 = SKTexture()
        m1 = atlas.textureNamed("\(String(monster.name!))_Dead1")//220 × 374
        m2 = atlas.textureNamed("\(String(monster.name!))_Dead2")//272 × 377
        m3 = atlas.textureNamed("\(String(monster.name!))_Dead3")//349 × 355
        m4 = atlas.textureNamed("\(String(monster.name!))_Dead4")//384 × 296
        m5 = atlas.textureNamed("\(String(monster.name!))_Dead5")//380 × 248
        m6 = atlas.textureNamed("\(String(monster.name!))_Dead6")//406 × 218
        m7 = atlas.textureNamed("\(String(monster.name!))_Dead7")//465 × 211
        m8 = atlas.textureNamed("\(String(monster.name!))_Dead8")//475 × 193
        let textures = [m1,m2,m3,m4,m5,m6,m7,m8]

        let playSound = SKAction.run 
            SKAction.playSoundFileNamed("163442__under7dude__man-dying.wav", waitForCompletion: false)
        
        let dieAnimation = SKAction.animate(with: textures, timePerFrame: 0.1, resize: false, restore: true)
        let removeMonster =  SKAction.run 
            monster.removeFromParent()
        
        let monsterDieSequence = SKAction.sequence([playSound,dieAnimation,removeMonster])
        monster.removeAllActions()
        monster.run(monsterDieSequence)

如果我使用 SKAction.animate 中的 resize:true 我有一个完美的动画,但我失去了原始的 monster.xScale 和 monster.yScale。怪物“生不如死”。

如果我使用 resize:false 动画会变形:

这个问题有一个可能的答案: animate-an-skspritenode-with-textures-that-have-a-size-different-from-the-origin

但我认为使所有精灵大小相同并添加透明度并不是解决此问题的唯一选择。

【问题讨论】:

【参考方案1】:

你试过不使用旋转的精灵吗?我的意思是,在人物肖像上绘制整个垂死序列,并使用 ZRotation 方法与使用 SKAction.group( [旋转,动画])。

【讨论】:

以上是关于如何在 SpriteKit 中使用不同大小的纹理制作动画的主要内容,如果未能解决你的问题,请参考以下文章

SpriteKit 部分纹理映射

在 SpriteKit 中预加载纹理

是否可以在Spritekit项目中以编程方式更改纹理色调?

使用纹理图集时 SpriteKit 中的高内存使用率

如何避免 SpriteKit 中的平滑效果?

如何在 iOS7 SpriteKit 中为不同大小的图像设置动画?