none
Virtuelles drehbares Quadrat in mehreren Threads benutzen?

    Frage

  • Hallo,

    ich habe eine Art Spiel programmiert, in dem man ein kleines Quadrat steuern kann. Das Spiel ist ein Mehrspielerspiel (übers Internet). In der Host-Anwendung wird die "Welt" nur virtuell dargestellt; in der Client-Anwendung graphisch angezeigt. Das Quadrat wird durch Gegenstände blockiert. Deshalb muss erkannt werden, ob das Quadrat etwas berührt oder nicht. Eigentlich kein Problem, aber die Schwierigkeit liegt darin, dass sich das Quadrat auch drehen soll und dann selbstverständlich auch entsprechend geblockt wird (oder nicht).

    Das Problem ist, dass das alles in der Hostanwendung wegen des Mehrspielermodus pro Spieler (jeder Spieler hat sein eigenes Quadrat) in einem eigenen Thread passiert. Mit der Klasse Rect ging das eigentlich ganz gut, da man dann keinen einzigen Dispatcher braucht - leider geht das Drehen nicht; ein Steuerelement erben geht auch nicht, da das Erstellen von einem STA-Thread aus passieren muss. Was nun?


    Gruß, Bolzen PS: Ich programmiere mit VS12(Desktop) und VS10

    Montag, 1. Juli 2013 18:40

Antworten

  • Hi,
    unklar ist, warum Du für jeden Spieler einen separaten thread benötigst. Üblicherweise reicht in Spielen neben dem UI-thread nur ein weitere thread für Berechnung, z.B. die Kollisionsberechnungen. In diesem thread werden die Werte neu berechnet und dann der Oberfläche über NotifyPropertyChanged mitgeteilt, dass sich etwas geändert hat. Nachfolgend eine kleine Demo dazu:

    <Window x:Class="MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525"
        xmlns:local="clr-namespace:WpfApplication1">
      <Window.Resources>
        <local:ViewModel x:Key="vm"/>
      </Window.Resources>
      <Grid DataContext="{Binding Source={StaticResource vm}}">
        <Rectangle x:Name="rec" Width="100" Height="50" Fill="Red">
          <Rectangle.RenderTransform>
            <RotateTransform CenterX="50" CenterY="25" Angle="{Binding Winkel}"/>
          </Rectangle.RenderTransform>
        </Rectangle>
      </Grid>
    </Window>

    Und dazu noch der ViewModel:


    Imports System.ComponentModel
    Public Class ViewModel
      Implements INotifyPropertyChanged
      Public Sub New()
        Call (New System.Threading.Thread(New System.Threading.ParameterizedThreadStart(AddressOf Drehen))).Start()
      End Sub
      Private Sub Drehen(obj As Object)
        Do
          Winkel += 1
          RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("Winkel"))
          System.Threading.Thread.Sleep(100)
        Loop
      End Sub
      Public Property Winkel As Double = 0
      Public Event PropertyChanged(sender As Object, e As PropertyChangedEventArgs) Implements INotifyPropertyChanged.PropertyChanged
    End Class

    --
    Peter
    Dienstag, 2. Juli 2013 07:51

Alle Antworten

  • Hallo, ich denke mal, das du mit WPF arbeitest.

    Warum nutzt du nicht einfach die Standarttransformationen (RotateTransform) und einen Dispatcher? Die Verwendung dieses ist nicht wirklich schwer.
    Siehe hier: http://visualbasic.about.com/od/usingvbnet/a/wpfintro6_2.htm

    Das wendest du auf eine Instanz der Rectangle-Klasse an. Dieses muss nur zum Inhalt des Fensters hinzugefügt werden. Natürlich kannst du auch die Transformationsdaten usw. in der Klasse speichern und dann aus dem XAML heruas binden.

    Für mein Verständnis bildet die Rect-Struktur keine Vorteile.


    - Koopakiller [kuːpakɪllɐ] (Tom Lambert)
    ; Webseite | Code Beispiele | Facebook | Snippets | Twitter
    Wenn die Frage beantwortet ist, dann markiert die hilfreichsten Beiträge als Antwort und bewertet die Beiträge. Danke.
    Einen Konverter zwischen C# und VB.NET Code gibt es hier.

    Montag, 1. Juli 2013 19:38
  • Hi,
    unklar ist, warum Du für jeden Spieler einen separaten thread benötigst. Üblicherweise reicht in Spielen neben dem UI-thread nur ein weitere thread für Berechnung, z.B. die Kollisionsberechnungen. In diesem thread werden die Werte neu berechnet und dann der Oberfläche über NotifyPropertyChanged mitgeteilt, dass sich etwas geändert hat. Nachfolgend eine kleine Demo dazu:

    <Window x:Class="MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525"
        xmlns:local="clr-namespace:WpfApplication1">
      <Window.Resources>
        <local:ViewModel x:Key="vm"/>
      </Window.Resources>
      <Grid DataContext="{Binding Source={StaticResource vm}}">
        <Rectangle x:Name="rec" Width="100" Height="50" Fill="Red">
          <Rectangle.RenderTransform>
            <RotateTransform CenterX="50" CenterY="25" Angle="{Binding Winkel}"/>
          </Rectangle.RenderTransform>
        </Rectangle>
      </Grid>
    </Window>

    Und dazu noch der ViewModel:


    Imports System.ComponentModel
    Public Class ViewModel
      Implements INotifyPropertyChanged
      Public Sub New()
        Call (New System.Threading.Thread(New System.Threading.ParameterizedThreadStart(AddressOf Drehen))).Start()
      End Sub
      Private Sub Drehen(obj As Object)
        Do
          Winkel += 1
          RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("Winkel"))
          System.Threading.Thread.Sleep(100)
        Loop
      End Sub
      Public Property Winkel As Double = 0
      Public Event PropertyChanged(sender As Object, e As PropertyChangedEventArgs) Implements INotifyPropertyChanged.PropertyChanged
    End Class

    --
    Peter
    Dienstag, 2. Juli 2013 07:51
  • Vielen Dank für die Antworten, mein Problem ist gelöst.

    Gruß, Bolzen PS: Ich programmiere mit VS12(Desktop) und VS10

    Dienstag, 2. Juli 2013 17:44