创建具有轻微变化的多个精灵节点?

时间:2016-07-25 09:37:53

标签: swift sprite-kit swift2 skspritenode

我有一个游戏菜单,显示多个成就,定义为SKSpriteNodes,其中有18个,并且它们的定位只有轻微的变化,这里是代码片段:

    Achievement1 = SKSpriteNode(color: SKColor.whiteColor(), size: CGSize(width: 100, height: 100))
    Achievement1.position = CGPointMake(-120, 100)
    page1ScrollView.addChild(Achievement1)

    Achievement2 = SKSpriteNode(color: SKColor.whiteColor(), size: CGSize(width: 100, height: 100))
    Achievement2.position = CGPointMake(0, 100)
    page1ScrollView.addChild(Achievement2)

    Achievement3 = SKSpriteNode(color: SKColor.whiteColor(), size: CGSize(width: 100, height: 100))
    Achievement3.position = CGPointMake(120, 100)
    page1ScrollView.addChild(Achievement3)

    Achievement4 = SKSpriteNode(color: SKColor.whiteColor(), size: CGSize(width: 100, height: 100))
    Achievement4.position = CGPointMake(-120, -25)
    page1ScrollView.addChild(Achievement4)

此外,我已经竭尽全力将它们逐一定义为vars,如下所示:

  var Achievement1: SKSpriteNode!
  var Achievement2 = SKSpriteNode()
  var Achievement3 = SKSpriteNode()
  var Achievement4 = SKSpriteNode()
  var Achievement5 = SKSpriteNode()
  var Achievement6 = SKSpriteNode()
  var Achievement7 = SKSpriteNode()
  var Achievement8 = SKSpriteNode()

它看起来像一团糟,只占用太多空间。我希望能够定义所有的精灵节点,并让它们都能够被按下以显示一个框,其中说明了成就是什么样的:

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

    let touch: UITouch = touches.first!
    let location: CGPoint = touch.locationInNode(self)
    let node: SKNode = self.nodeAtPoint(location)


    if (node == Achievement1) {

        //achievement details here

   }

我仍然对这种快速的语言不熟悉而且我不是很先进但我会很感激帮助。

3 个答案:

答案 0 :(得分:3)

如果您认为代码很乱,请尝试在代码中找到模式

查看Achievement1Achievement2Achievement3Achievement4个东西?当你看到这种模式时,你应该创建一个数组来存储成就。

我确定你知道如何使用数组,所以我不会谈论太多。有关详细信息,您可以转到Array类的定义。

您可能会注意到的另一种模式是使用相同的参数来创建精灵节点。成就之间的唯一区别在于他们的立场。

解决此问题的最佳方法是创建方法:

func createAchievement(location: CGPoint) -> SKSpriteNode {
    let node = SKSpriteNode(color: SKColor.whiteColor(), size: CGSize(width: 100, height: 100))
    node.position = location
    return node
}

您只需要一行就可以为上述阵列添加新成就:

someArray.append(createAchievement(CGPointMake(-120, 100)))

编辑:

如果你使用indexOf(_:)(或swift 3中的index(of:)),你可以创建一个switch语句而不是if语句:

switch someArray.indexOf(node) {
    case 0:
        // this means that the first achievement is tapped!
    case 1:
        // this means that the second achievement is tapped!
    case 2:
        // this means that the third achievement is tapped!
}

答案 1 :(得分:1)

关于当您要显示大量项目时的布局,您可以考虑使用表格或页面控件。因为我很懒,所以我不喜欢滚动表只看到所有的游戏成就,所以通常我会首先使用PageControl。 您可以在UIKit内置UIPageControl并将其集成到游戏菜单中。 如果您不知道如何集成UIPageControl,可以使用此精灵工具包项目 GBPageControl

import GBPageControl

var pageControl:PageControl!
//Add the page control to the scene. Add any content that will be paged directly to the pageControl:
override func didMoveToView(view: SKView) {
    pageControl = PageControl(scene: self)
    addContent()
    pageControl.enable(4)
}

private func addContent() {
    for var i = 0; i < 4; i++ {
        let node = SKShapeNode(circleOfRadius: 10)
        node.strokeColor = UIColor.blueColor()
        let x = self.size.width / 2.0 + self.size.width * CGFloat(i)
        let y = self.size.height / 2.0
        node.position = CGPoint(x:x, y:y)
        pageControl.addChild(node)
    }
}

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    for touch in touches {
        if pageControl.handleTouch(touch) {
            //no op
        }
        else {
            //handle touch
        }
    }
}
override func willMoveFromView(view: SKView) {
    pageControl.willMoveFromView(view)
}

<强>输出

enter image description here

<强>更新

关于您可以尝试的成就代码:

enum MedalType: Int {
    case Gold = 1
    case Silver = 2
    case Bronze = 3
}
class Achievement:SKSpriteNode {
    init(color:SKColor,size:CGSize,name:String,medalType:MedalType) {
        super.init(texture: nil,color:color,size:size)
        self.name = name
    }
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

class GameScene: SKScene {
    var achievements:[Achievement]!
    var aNames: [String]!
    var totalAchievements: Int = 45

  override func didMoveToView(view: SKView) {
    var counter : Int = 0
    let deltaX:CGFloat = 120
    let deltaY:CGFloat = 10
    for i in 0..<totalAchievements {
        var aColor = SKColor.whiteColor()
        var aSize = CGSizeMake(100,100)
        var medal = MedalType.Bronze

        switch i {
        case 10:
            aColor = SKColor.redColor()
            aSize = CGSizeMake(100,150)
            medal = MedalType.Silver
        case 25:
            aColor = SKColor.blueColor()
            aSize = CGSizeMake(100,200)
            medal = MedalType.Gold
        default:
            break
        }
        let name = "achievement\(i)"
        let a = Achievement.init(color: aColor, size: aSize, name: name, medalType: medal)
        aNames.append(name)

        //handle your position has you wish with counter, deltaX e deltaY
        //...
        a.position = CGPointMake(deltaX, deltaY)
        addChild(a)
       }
    }
    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {

        let touch: UITouch = touches.first!
        let location: CGPoint = touch.locationInNode(self)
        let node: SKNode = self.nodeAtPoint(location)

        if (aNames.contains(node.name!)) {

            print("You have touch achievement \(node.name)")
            let currentAchievement = achievements[aNames.indexOf(node.name!)!]
            // Use your currentAchievement touched
        }
    }
}

答案 2 :(得分:0)

您可以使用数组......

let achievements = [SKSpriteNode](repeating: SKSpriteNode(color: SKColor.white(), size: CGSize(width: 100, height: 100)), count: 8) // Swift 3 colour name
let positions = [CGPoint(x: -120, y: 100), CGPoint(x: 0, y: 100) /* ... */]
for i in 0 ..< min(achievements.count, positions.count) { // For safety - obviously these should be the same
    achievements[i].position = positions[i]
}

// Then in your touch routine...
if let index = achievements.index(of: self.nodeAtPoint(location)) {
    // do something with achievements[index]
}

...并且不要将变量大写 - Swift惯例是只有类型大写......