2011-07-28 10 views
5

Mam grę XNA + Silverlight w Mango: głównie XNA z niektórymi interfejsami Silverlight na wierzchu. Problem, który mam, polega na tym, że po naciśnięciu przycisku lub interakcji z kontrolką Silverlight informacje dotyku są nadal przekazywane do pętli gry XNA. Jak to tłumisz?WP7: Tłumienie wejścia dotykowego XNA podczas obsługi przez Silverlight?

+0

Dlaczego tag 'windows-phone-mango' automatycznie przekształcił się w' windows-phone-7.1', jeśli tak nie jest? – RandomEngy

+0

Jest to synonim. 7.1 jest rzeczywiście wersją zestawu SDK dla systemu operacyjnego Mango (7.5). –

+0

Oficjalna nazwa nowego systemu operacyjnego to 7.5. Zobacz: http://windowsteamblog.com/windows_phone/b/windowsphone/archive/2011/07/26/windows-phone-mango-released-to-manufacturing.aspx –

Odpowiedz

4

Wrote klasę, aby wykonać śledzenie dla mnie. Po załadowaniu strony (w obsadzie Loaded) utwórz ją i nadaj jej element główny (aby mógł dołączyć do zdarzenia LayoutUpdated). Zarejestruj wszystkie kontrolki, które mogą nakładać się na powierzchnię gry podczas gry. Następnie zadzwoń do TouchesControl i podaj w pozycji dotykowej, aby dowiedzieć się, czy powinieneś zignorować ten punkt, czy nie. Buforuje regiony kontrolek i aktualizuje je, gdy pojawia się aktualizacja układu.

Powinny pracować dla elementów prostokątnych przesuwających się, zmieniających rozmiar lub zwijających/powiększających.

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

(edit) Zaktualizowany przykład do pracy z dominujących elementów zmieniających Visibility.

+0

Nadal sprawdzam lokalizację, ale kudos - wpadłeś na pomysł! –

3

Ze względu na sposób współdziałania z XNA, zawsze otrzymasz dane wejściowe dotyku przetworzone zarówno przez XNA, jak i Silverlight - do pewnego stopnia XNA dostaje priorytet, więc Silverlight działa na nim. Co można zrobić, jeśli trzeba ignorować konkretne lokalizacje gestów (np, gdzie znajdują się przyciski Silverlight), można sprawdzić położenie gest:

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

     } 
    } 
} 
+0

Nie ma sposobu, aby rozwiązać ten problem w ogóle? Czy muszę ręcznie utrzymywać te "martwe strefy"? Może mógłbym napisać coś tam, gdzie zarejestrujesz kontrolki Silverlight do śledzenia i może ci powiedzieć, czy punkt dotykowy jest ważny (na podstawie tego, gdzie jest kontrola, czy jest widoczna czy zwinięta). Następnie pętla XNA wykonuje tę kontrolę przed przetworzeniem dotyku. – RandomEngy

+0

Wystarczy mieć określoną strefę dla elementów sterujących SL i sprawdzić to. Lub przemyśl sposób, w jaki używasz elementów sterujących SL w trakcie gry, aby prosty dotyk nie wpłynął na proces. –

+0

Nie chcę ograniczać mojej gry, usuwając obszar "Silverlight". Zamierzam wypróbować moje podejście do ich rejestrowania i automatycznie ignorować dotknięcia w obszarach, w których są kontrole. Ostatnią rzeczą, której chcę, jest błąd, w którym przeniosłem kontrolę i zapomniałem zaktualizować magiczną strefę tylko dla srebra. – RandomEngy

Powiązane problemy