2015-07-12 84 views
1

我開始通過聲明兩個SKSpriteNodes,把手和刀片,並添加手柄自我的孩子,和刀片的柄的子如何使touch.locationInNode()識別節點與其子節點之間的區別?

var handle = SKSpriteNode(imageNamed: "Handle.png") 
var blade = SKSpriteNode(imageNamed: "Blade.png") 

override func didMoveToView(view: SKView) { 

    handle.position = CGPointMake(self.size.width/2, self.size.height/14) 
    blade.position = CGPointMake(0, 124) 

    self.addChild(Handle) 
    Handle.addChild(Blade) 
} 

當我點擊手柄,它打印到控制檯「手柄被點擊「,但是當我點擊刀片時,它也會打印」手柄被點擊「。這是清楚地認識到,刀片是手柄的孩子,但我怎麼能做到這一點,當我點擊刀片,它打印「刀片被點擊」?

override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) { 
    for touch in (touches as! Set<UITouch>) { 
     let location = touch.locationInNode(self) 
     if (Handle.containsPoint(location)){ 
      NSLog("Handle was clicked") 
     } 
     else if (Blade.containsPoint(location)){ 
      NSLog("Blade was clicked") 
     } 

    } 
} 
+0

您可以通過使用分配每個節點唯一的名稱屬性和檢查的方法的touchesBegan節點名稱區分。 – sangony

+0

但這正是我所做的,並沒有奏效。我命名其中一個手柄,另一個刀片,當我點擊刀片時它以爲我點擊了手柄 – Lahav

+0

你好@Lahav。你是對的,因爲它是一個孩子,你不能使用'containsPoint',因爲它基本上是使用精靈的框架,並查看場景座標系中的點是否與其中一個子節點相匹配,但是你想要孩子的孩子。永遠不要害怕幫助!無論是我自己還是Sprite Kit Alliance成員之一,我們都將盡快提供幫助。 PLZ支持。 –

回答

3

確定用戶是否觸摸了劍的手柄或刀片是相當直接的一些警告。以下假定:1.當劍的形象朝向右邊的時候,zRotation = 0,2.anchorPoint的劍是(0,0.5),3.劍(劍和柄)是單個精靈節點。當您將一個精靈添加到另一個精靈時,父級框架的大小會展開以包含子節點。這就是爲什麼無論您點擊劍的哪個位置,您的Handle.containsPoint測試都是正確的。

下圖顯示了一個帶有深灰色手柄(左側)和淺灰色刀片的劍精靈。圍繞劍的黑色矩形表示精靈的框架,圓圈表示用戶的觸摸位置。標記爲a的線的長度是從觸摸點到劍的底部的距離。我們可以測試此距離以查看用戶是否觸摸了手柄(如果a <= handleLength)或刀片(如果a > handleLength)。當zRotation = 0,a = x那麼測試是x <= handleLength,那裏的劍的底部是x = 0

enter image description here

在下面的圖中,劍被旋轉90度(即,zRotation = M_PI_2)。類似地,如果a <= handleLength,則用戶觸摸了手柄,否則用戶觸摸了刀片。由於劍的旋轉,唯一的區別是a現在是y的值而不是x。在這兩種情況下,框架的邊界框都可以用來檢測用戶是否觸摸了劍。

enter image description here

當子畫面是由45度旋轉,但是,它的幀自動擴展以包圍精靈如由下面的圖中的黑色矩形。因此,當用戶觸摸矩形的任何地方時,測試if sprite.frame.contains(location)將成立。當觸摸的位置相對遠離劍時(即,當距離大時),這可能導致用戶拿起劍。如果我們希望所有旋轉角度的最大觸摸距離相同,則需要進行附加測試。

enter image description here

好消息是雪碧套件提供了一個方法,從一個座標系轉換成另一種。在這種情況下,我們需要從場景座標轉換爲劍座標。這極大地簡化了問題,因爲它也將點旋轉到新的座標系。將場景轉換爲劍座標後,轉換的觸摸位置的xy值與所有旋轉角度上的距離ab相同!現在我們知道ab,我們可以確定觸摸對劍的接近程度以及用戶是否觸摸了手柄或刀片。

從上面,我們可以實現下面的代碼:

let location = touch.locationInNode(self) 
    // Check if the user touched inside of the sword's frame (see Figure 1-3) 
    if (sword.frame.contains(location)) { 
     // Convert the touch location from scene to sword coordinates 
     let point = sword.convertPoint(location, fromNode: self) 
     // Check if the user touched any part of the sword. Note that a = point.x and b = point.y 
     if (fabs(point.y) < sword.size.height/2 + touchTolerance) { 
      // Check if the user touched the handle 
      if (point.x <= handleLength) { 
       println("touched handle") 
      } 
      else { 
       println("touched blade") 
      } 
     } 
    } 
1

這應該在不改變太多現有的代碼的工作...

override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) { 
    for touch in (touches as! Set<UITouch>) { 

     let locationInScene = touch.locationInNode(self) 
     let locationInHandel = touch.locationInNode(Handle) 

     if (Blade.containsPoint(locationInHandel)){ 

      NSLog("Blade was clicked") 

     } 
     else if (Handle.containsPoint(locationInScene)){ 

      NSLog("Handle was clicked") 

     } 

    } 
} 

注意你檢查刀片第一,那麼你檢查處理。另外請注意,您必須將觸點轉換爲從句柄內給出一個點。

由於這樣說可以在小範圍內工作,但您可能需要考慮爲SKSpriteNode創建一個名爲Handle或Sword的子類(這就是爲什麼您不使用第一個大寫字母來表示變量名稱的原因對類使用第一個大寫字母),將其設置爲userInteractionEnabled,然後覆蓋該子類中的touchesBegan,並查看它是否觸及刀片,如果不是,則知道它觸及了柄。

希望這有幫助和有道理。