SKTextureAtlas - Pass in a path to an atlas instead of looking for that specific atlas

匆匆过客 提交于 2019-12-25 03:39:20

问题


I'm working on a class to handle character animations. The animations will have different skin tones that the user chooses from in character creation. The atlases for each of the skin tones have the same name but are stored in differently named folders like this:

this is in the xcassets folder

This should allow my code to be more modular so I don't have to hard-code a ton of stuff. I want my code to locate the chosen skin tone folder and its subdirectories so that the correct animation plays when the animation functions are called.

Current code so far:

class Character : SKNode {
    let character: SKSpriteNode
    let base: String
    var textureArray = [SKTexture]()

    init(Base: String) {
        character = SKSpriteNode(texture: nil, size: CGSize(width: 30, height: 44))
        base = Base
        super.init()

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

    func northAnimation() {
        let textureAtlas = SKTextureAtlas(named: "\(base)")
        var frames:[SKTexture] = []

        for index in 1 ... 6 {
            let textureName = textureAtlas.textureNamed("back_\(index)")
            let texture = textureName
            textureArray = frames

            character.removeAllActions()
            character.run(SKAction.repeatForever(SKAction.animate(with: textureArray, timePerFrame: 0.2)))
        }
    }
}

In the init for the class, the objective is to plug in the name of the folder (which would be set based off of character creation) and then access the corresponding atlases. I'm having trouble figuring out how to find the correct paths to the atlas locations.

How do I pass in a path to an atlas instead of looking for that specific atlas?


回答1:


All assests in .XCAssets are managed in NSSet mode for a speed reason. In other words, there is no path concept in the file and every name is suppose to be unique.

So you only need to assign a unique name to the atlas like :

"male_pale_back" "male_pale_backLeft" "male_pale_backRight"

"male_tan_back" "male_tan_backLeft" "male_tan_backRight"

If any file name is not unique, the result is not defined. Probably you cannot get the atlas.

So here let textureAtlas = SKTextureAtlas(named: "\(base)") if the base name is just back. There are more than one back and the loading of atlas failed.

Change the filenames in atlas first. Then constitute a new filename : SKTextureAtlas(named: "male_\(name)_\(base)") will solve your problem.

Hope you got it.

If you prefer to use filePath, can use second method and not to use .XCASSets.

Refer to SKTextureAtlas.init(dictionary properties: [String : Any])




回答2:


After doing more research into the file structure of Swift, and studying some other games with similar animations, I quickly discovered that what I wanted wasn't possible. I came up with another method that is similar, but not identical to what I wanted in my question.

Here is the altered code. This code is extremely modular and it should work for all the animations I need it to play.

import Foundation
import SpriteKit

class Character : SKNode {
    let character: SKSpriteNode
    let gender: String
    let tone: String
    var textureArray = [SKTexture]()

    init(Tone: String, Gender: String) {
        character = SKSpriteNode(texture: nil, size: CGSize(width: 45, height: 66))
        gender = Gender
        tone = Tone

        super.init()

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

    func moveAnimation(direction: String) {
        let textureAtlas = SKTextureAtlas(named: "\(gender)_\(tone)_\(direction)")
        var frames:[SKTexture] = []

        for index in 1 ... 6 {
            let textureName = textureAtlas.textureNamed("\(gender)_\(tone)_\(direction)_\(index)")
            let texture = textureName
            frames.append(texture)
            textureArray = frames

            character.removeAllActions()
            character.run(SKAction.repeatForever(SKAction.animate(with: textureArray, timePerFrame: 0.1)))
        }
    }
}

I came up with a folder naming format (It happens to pretty much match @E. Coms answer, but there are a couple differences and I came up with it ~8 hours before him.) that allows me to plug any direction, gender, and skin tone with a single function. The format goes \(gender)_\(tone)_\(direction) so my atlas folders are named:

Each of the skin tones will be named male_tan, male_dark instead of male_pale so the atlases won't get confused with each other.

When I initialize a new character, I choose a skin tone and a gender. When I call the animation function, I choose a direction (back, backLeft, forward, etc.)

This is pretty much what I needed.



来源:https://stackoverflow.com/questions/53187032/sktextureatlas-pass-in-a-path-to-an-atlas-instead-of-looking-for-that-specific

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!