2016-07-25 3 views
2

У меня есть игровое меню, которое отображает несколько достижений, которые определены как 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) 

Кроме того, я пошел на большой длины, чтобы определить, все они один за другим, как вары, как показано здесь:

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

Если вы считаете, что ваш код является беспорядок, попытайтесь найти шаблоны в вашем коде.

См. Эти Achievement1, Achievement2, Achievement3, Achievement4 штук? Когда вы видите такой шаблон, вам, вероятно, следует создать массив для хранения достижений.

Я уверен, что вы знаете, как использовать массив, поэтому я не буду говорить об этом слишком много. Для получения дополнительной информации вы можете перейти к определению класса 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))) 

EDIT:

Если вы используете indexOf(_:) (или index(of:) в быстрой версии 3), вы можете создать оператор 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! 
} 
+0

Это все еще позволяет мне использовать узлы, созданные в моем методе touchhesbegan? – Astrum

+0

@Astrum Да, конечно! Чтобы проверить, является ли 'node' первым достижением, используйте' node == someArray [0] '! Чтобы проверить второе достижение, используйте 'node == someArray [1]'. Вы можете понять все остальное! – Sweeper

+0

@Astrum Вы также можете использовать метод 'index (of:)', упомянутый Grimxn в его ответе. Но если вы используете Swift 2.x, вместо этого используйте 'indexOf (_ :)'. – Sweeper

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] 
} 

... и не капитализировать переменные - Свифт конвенции является то, что только типы капитализируются ...

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

Update:

О ваших достижениях код вы можете попробовать сделать:

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 
     } 
    } 
}