2011-07-28 25 views
5

我在芒果有一個XNA + Silverlight遊戲:主要是XNA上面有一些Silverlight UI。我遇到的問題是,當您按下按鈕或與Silverlight控件交互時,觸摸信息仍然傳遞到XNA遊戲循環。你如何壓制這一點?WP7:Silverlight處理時抑制XNA觸摸輸入?

+0

爲什麼標籤'windows-phone-mango'自動解析爲'windows-phone-7.1',如果這不是真的? – RandomEngy

+0

這是一個同義詞。 7.1的確是Mango(7.5)OS的SDK版本。 –

+0

新操作系統的官方名稱是7.5。請參閱:http://windowsteamblog.com/windows_phone/b/windowsphone/archive/2011/07/26/windows-phone-mango-released-to-manufacturing.aspx –

回答

4

寫了一個類做跟蹤我。加載頁面後(在加載的處理程序中),創建併爲其提供根元素(以便它可以附加到LayoutUpdated事件)。在播放過程中註冊可能覆蓋遊戲表面的任何控件。然後,只需調用TouchesControl並傳遞觸摸位置,以確定是否應該忽略該點。它緩存控件的區域,並在佈局更新時更新它們。

適用於移動矩形元素,更改大小或摺疊/展開。

public class ControlTouchTracker 
{ 
    private List<FrameworkElement> controls = new List<FrameworkElement>(); 
    private Dictionary<FrameworkElement, ControlRegion> controlBounds = new Dictionary<FrameworkElement, ControlRegion>(); 

    public ControlTouchTracker(FrameworkElement rootElement) 
    { 
     rootElement.LayoutUpdated += this.OnLayoutUpdated; 
    } 

    public void RegisterControl(FrameworkElement control) 
    { 
     controls.Add(control); 
    } 

    public void RemoveControl(FrameworkElement control) 
    { 
     controls.Remove(control); 
     controlBounds.Remove(control); 
    } 

    private void OnLayoutUpdated(object sender, EventArgs e) 
    { 
     foreach (Control control in this.controls) 
     { 
      this.RefreshControlBounds(control); 
     } 
    } 

    private void RefreshControlBounds(FrameworkElement control) 
    { 
     if (this.ControlIsVisible(control)) 
     { 
      try 
      { 
       GeneralTransform controlTransform = control.TransformToVisual(Application.Current.RootVisual); 
       Point offset = controlTransform.Transform(new Point(0, 0)); 

       this.controlBounds[control] = new ControlRegion 
       { 
        Left = (float)offset.X, 
        Right = (float)(offset.X + control.ActualWidth), 
        Top = (float)offset.Y, 
        Bottom = (float)(offset.Y + control.ActualHeight) 
       }; 
      } 
      catch (ArgumentException) 
      { 
      } 
     } 
     else 
     { 
      if (this.controlBounds.ContainsKey(control)) 
      { 
       this.controlBounds.Remove(control); 
      } 
     } 
    } 

    private bool ControlIsVisible(FrameworkElement control) 
    { 
     // End case 
     if (control == null) 
     { 
      return true; 
     } 

     if (control.Visibility == Visibility.Collapsed) 
     { 
      return false; 
     } 

     return this.ControlIsVisible(control.Parent as FrameworkElement); 
    } 

    public bool TouchesControl(Vector2 touchPosition) 
    { 
     foreach (ControlRegion region in this.controlBounds.Values) 
     { 
      if (touchPosition.X >= region.Left && touchPosition.X <= region.Right && 
       touchPosition.Y >= region.Top && touchPosition.Y <= region.Bottom) 
      { 
       return true; 
      } 
     } 

     return false; 
    } 

    public class ControlRegion 
    { 
     public float Left { get; set; } 
     public float Right { get; set; } 
     public float Top { get; set; } 
     public float Bottom { get; set; } 
    } 
} 

(編輯)使用父元素更改的更新示例Visibility

+0

仍在檢查位置,但讚譽 - 你明白了! –

3

由於與XNA互操作的方式,您將始終獲得由XNA和Silverlight處理的觸摸輸入 - 在某種程度上,XNA會獲得優先級,所以Silverlight會在其上面發揮作用。你可以做的,如果你需要忽略特定手勢的位置(例如其中的Silverlight按鈕的位置),你可以檢查的手勢位置:

if (TouchPanel.IsGestureAvailable) 
{ 
    if (TouchPanel.ReadGesture().GestureType == GestureType.Tap) 
    { 
     if (TouchPanel.ReadGesture().Position == new Vector2(120, 120)) 
     { 

     } 
    } 
} 
+0

有沒有辦法解決這個一般?我需要手動維護這些「死區」?也許我可以寫一些東西在你註冊Silverlight控件的地方進行跟蹤,它可以告訴你觸摸點是否有效(根據控件的位置以及它是否可見或摺疊)。然後XNA循環在處理觸摸之前運行此檢查。 – RandomEngy

+0

只有SL控制的特定區域並檢查它。或者,重新考慮在遊戲中使用SL控制的方式,以便簡單的觸控不會影響過程。 –

+0

我不想通過封鎖一些「Silverlight」區域來限制我的遊戲。我將嘗試我的註冊方法,並自動忽略控件所在區域的觸摸。我想要的最後一件事是一個錯誤,我移動了控件,忘記更新魔術silverlight專用區域。 – RandomEngy