我想减少基本相同的方法中的代码并传入参数但不知道从哪里开始?

I want to reduce the code in methods that are basically identical and pass in the parameters but don't know where to begin?

我有一个 spriteKit 项目,我在几个场景中有很多角色。

作为初学者,我只是为每个场景单独构建了一个 - 这会产生大量额外代码。

我知道我可以用“构建角色 class”或类似的东西来清理它...

我只是不确定从哪里开始。

这是一个场景中两个角色的代码...但想象一下每个场景有 5-10 个角色?

属性 列表是否可以用于存储这些类型的属性?

//BEAR
 
 func buildBear() {
        let bearAnimatedAtlas = SKTextureAtlas(named: "Bear")
        var bearFrames: [SKTexture] = []
        
        let numImages = bearAnimatedAtlas.textureNames.count
        for i in 1...numImages {
            let bearTextureName = "bear\(i)"
            
            bearFrames.append(bearAnimatedAtlas.textureNamed(bearTextureName))
        }
        animatedBear = bearFrames
        let firstFrameTexture = animatedBear[0]
        bear = SKSpriteNode(texture: firstFrameTexture)
        bear.size.height = 370
        bear.size.width = 370
        bear.position = CGPoint(x: 295, y: 25)
        bear.zPosition = 1
        bear.name = "bear"
        isUserInteractionEnabled = true
        addChild(bear)
        
    }
    
    //CAT
    func buildCat() {
        let catAnimatedAtlas = SKTextureAtlas(named: "Cat")
        var catFrames: [SKTexture] = []
        
        let numImages = catAnimatedAtlas.textureNames.count
        for i in 1...numImages {
            let catTextureName = "cat\(i)"
            
            catFrames.append(catAnimatedAtlas.textureNamed(catTextureName))
        }
        animatedCat = catFrames
        let firstFrameTexture = animatedCat[0]
        cat = SKSpriteNode(texture: firstFrameTexture)
        cat.size.height = 240
        cat.size.width = 240
        cat.position = CGPoint(x: 134, y: -38)
        cat.zPosition = 2
        cat.name = "cat"
        isUserInteractionEnabled = true
        addChild(cat)
        
    }

我怎样才能清理这样的东西 - 每个场景我需要不同的 position/size 但我想我可以覆盖每个场景?

我知道我知道怎么做! - 不知道从哪里开始?

请轻推一下!

存在这么多语言的一个令人困惑的事情是它们都有自己的行话和约定。但是,问题的根源与 Swift 或 Sprite Kit 无关。当我阅读您的问题时,我看到可以使用某些抽象数据类型的代码。在 Java 中,您将创建一个接口,在 C++ 中,您将创建一个“纯虚拟”class。好吧,任何其他名字的玫瑰仍然可以完成工作。我建议创建一个协议,可能称为 Spritable,以定义您打算构建到 sprite 中的对象类型。它可能就这么简单:

protocol Spritable {
    var species: String { get }
    var height: Int { get }
    var width: Int { get }
}

这两个函数之间唯一不同的地方似乎是起始位置。由于这不是 Spritable 对象的固有含义,我会单独打包该数据。元组应该完成这项工作。通过这些修改,您的两个功能可以合并为一个:

func buildSprite(of creature: Spritable, at position: (x: Int, y: Int, z: Int)) {
    let spriteAnimatedAtlas = SKTextureAtlas(named: creature.species)
    var spriteFrames: [SKTexture] = []
    
    let numImages = spriteAnimatedAtlas.textureNames.count
    for i in 1...numImages {
        let spriteTextureName = "\(creature.species.lowercased())\(i)"
        spriteFrames.append(spriteAnimatedAtlas.textureNamed(spriteTextureName))
    }
    animatedSprite = spriteFrames
    let firstFrameTexture = animatedSprite[0]
    sprite = SKSpriteNode(texture: firstFrameTexture)
    sprite.size.height = creature.height
    sprite.size.width = creature.width
    sprite.position = CGPoint(x: position.x, y: position.y)
    sprite.zPosition = position.z
    sprite.name = creature.species
    isUserInteractionEnabled = true
    addChild(sprite)
}

要建造熊,除了车间外,您还需要定义一个实现 Spritable:

的结构
struct Bear: Spritable {
    var species: String { return "Bear" }
    var height: Int
    var width: Int

    init(height: Int, width: Int) {
        self.height = height
        self.width = width
    }
}

那么这里就是你的函数调用:

buildSprite(of: Bear(height: 370, width: 370), at: (295, 25, 1))

这是一个非常简单的示例,可以通过一些比这更简单的方法来解决。但是,我发现项目越大,围绕抽象数据类型组织代码的好处就越大,因此即使在像这样的简单情况下也值得采用这种方法。

None 这必须在代码中完成。使用 Sprite Kit,您可以通过 Sprite Kit 编辑器创建熊和猫,然后使用按文件名加载的构造函数加载 sks 文件。

这与游戏对象在 unity 中的工作方式类似。

我最终没有使用协议。

我只是构建了一个构造精灵的方法 - 类似于@TallChuck 建议的方法。

func buildCharacter(name:String, height: CGFloat, width: CGFloat, position: CGPoint, zPosition: CGFloat) {
    let animatedAtlas = SKTextureAtlas(named: name)
    var animationFrames: [SKTexture] = []
    
    let numImages = animatedAtlas.textureNames.count
    for i in 1...numImages {
        let textureName = "\(name)\(i)"
        
        animationFrames.append(animatedAtlas.textureNamed(textureName))
    }
    
    animatedCharacter = animationFrames
    let firstFrameTexture = animatedCharacter[0]
    builtCharacter = SKSpriteNode(texture: firstFrameTexture)
    builtCharacter.size.height = height
    builtCharacter.size.width = width
    builtCharacter.position = position
    builtCharacter.zPosition = zPosition
    builtCharacter.name = name
    
    isUserInteractionEnabled = true
    addChild(builtCharacter)
    
   }

它非常适合构建和添加到场景 - 在访问节点名称以进行触摸检测时遇到一些问题,但已将其排序。现在试图弄清楚如何在节点上调用操作——这与正常方式完全不同。所以接下来我很可能会问这个问题。但总体上减少了大量的重复代码!感谢您的帮助。