| |
VB.NET - FortgeschritteneWPF: 14000 Paths | | | Autor: Maas | Datum: 04.10.11 12:59 |
| Hallo,
Ich beschäftige mich z.Z. mit dem Strategie-Spiel Hearts of Iron III und will mir dafür einen Editor basteln.
Es gibt für mein Problem folgende Voraussetzungen:
Das Spiel ist sehr Modder-freundlich aufgebaut. Das heißt, dass es für die verschiedenen Provinzen der Spielkarte eine Bitmap, welche dann auch das Spiel selber benutzt. Die Karte sieht so aus (in echt ist sie gespiegelt und gedreht, aber das ist egal):
Das hier ist der Ausschnitt für den Nordseeteil. Die Provinzen erstrecken sich über die ganze Welt und insgesamt gibt es über 14000 davon. Die Karte hat 5616x2160 Pixel. Jede Provinz hat einen RGB-Farbcode, welcher auch in einer csv-Datei zu finden ist, zusammen mit der ID (Integer) der Provinz. Mit dieser ID ist dann eine ganze Menge möglich, u.a. das Bearbeiten der Provinz-Werte in einem Save Game.
Ich habe also schon folgendes geschafft:
-Einlesen der RGB-ID Kombinationen
-Einlesen der Karte
-Analysieren der Karte nach "ProvincePixelGroups" (es werden für jede Provinz die Pixelkoordinaten erfasst; ca. 1000-2000)
-Löschen der inneren Pixel einer ProvincePixelGroup (es bleiben nur die Umriss-Koordinaten; ca. 100-200)
Jetzt will ich die Karte also neu "Zeichnen", aber mit Objekten. Ich hatte zuerst nur die Bitmap geladen und bei MouseOver auf den Farbcode geprüft. Das hat soweit auch super funktioniert. Jetzt will ich es aber so gestalten, dass man die Karte in verschiedenen Sichten ansehen kann (politisch, Infrastruktur, Anzahl der stationierten Einheiten, etc.), es müssen also die Farben der Provinzen angepasst werden. Dass dann die Identifizierung über den Farbcode nicht mehr funktioniert, ist klar. Deswegen will ich mit (FrameworkElement-)Objekten arbeiten, da diese z.B. ein MouseEnter und MouseLeftButtonUp Event haben. Ich muss dann nur noch den sender auswerten und dazu den DataContext mit der ID.
Dazu benutze ich die Path und StreamGeometry-Klassen. Das funktioniert auch soweit, außer dass es verdammt langsam ist (nicht das Laden). Ich habe dann also in einem Canvas 14000 Paths und das scheint WPF irgendwie nicht zu mögen. Der GUI-Thread ist schon komplett ausgelastet, wenn ich nur mit der Maus über die Provinzen gleite. Eine ID-/Namens-Ausgabe per MouseEnter dauert so um die 1-2 Sekunden. Das macht ein vernünftiges Arbeiten natürlich so gut wie unmöglich.
Gibt es hier jetzt eine bessere Möglichkeit zu "zeichnen"? Ich will ja nicht wirklich zeichnen (also mit den Geometry-Klassen), denn dann hätte ich keinen DataContext und keine Events. (Außerdem könnt ich mir dann das alles sparen und einfach die Original-Bitmap laden). Vielleicht ist ein Canvas auch einfach nicht der beste Container für so viele Paths?!? Ich kann mir leider auch nicht erklären, warum die GUI-Thread Auslastung überhaupt bei 100% liegt. Wieso bezieht er, wenn ich z.B. mit der Maus über 4 Provinzen gleite, alle 14000 Paths mit ein? Was haben die mit dem kleinen Bereich zu tun, in dem ich mit der Maus arbeite?
Hier mal der Code zum Erstellen der Paths:
"ProvinceMapDefinition" ist eine Datenklasse für Farbcode, ID und Name einer Provinz.
"drawTable" ist das Canvas.
Dim geos As New List(Of Path)
Dim lstDefs As New List(Of ProvinceMapDefinition)( _
GameData.MapDefinitions)
Dim pathGeo As New PathGeometry
For Each ppg As ProvincePixelGroup In mPixelGroups
Dim myPath As New Path
myPath.Stroke = New SolidColorBrush(Color.FromRgb(ppg.Color(2), _
ppg.Color(1), ppg.Color(0)))
myPath.StrokeThickness = 2
Dim geo As New StreamGeometry
geo.FillRule = FillRule.Nonzero
Using ctx = geo.Open()
ctx.BeginFigure(ppg.Positions(0), True, True)
ctx.PolyLineTo(ppg.Positions, True, True)
End Using
geo.Freeze()
myPath.Data = geo
For Each prov In lstDefs
If prov.Color.R = ppg.Color(2) And prov.Color.G = ppg.Color(1) _
And prov.Color.B = ppg.Color(0) Then
myPath.DataContext = prov
lstDefs.Remove(prov)
Exit For
End If
Next
AddHandler myPath.MouseEnter, AddressOf Me.path_MouseEnter
AddHandler myPath.MouseLeave, AddressOf Me.path_MouseLeave
drawTable.Children.Add(myPath)
Next Schonmal Danke im Voraus
Maas | |
Re: WPF: 14000 Paths | | | Autor: Maas | Datum: 04.10.11 13:01 |
| Hallo nochmal,
(jaja, die 5KB Grenze...)
Frage nebenbei: Kennt jemand einen Algorithmus, mit dem ich meine Umriss-Koordinaten ordnen kann? Z.Z sind diese noch unsortiert und es kann bei gekrümmten Provinzen passieren, dass sie einen Strich über die Provinz nebenan ziehen. Dies ist aber bei weitem nicht so wichtig, sonder nur für's Auge. Ich denke nicht, dass es wirklich stört bei vielleicht 30-40 von 14000.
Noch was zu LinQToObject:
Wie effizient ist eine LinQ-Abfrage im Gegensatz zu einer For-Schleife. Bei über 14000 Abfragen ist das schonmal von Interesse. Ich habe mittlerweile zur For-Schleife gewechselt, da ich das Gefühl habe, es geht schneller. Kann das jemand validieren? (In diesem Fall hat das Ergebnis der LinQ-Abfrage immer 1 oder kein Ergebnis)
Danke nochmal
Maas | |
| Sie sind nicht angemeldet! Um auf diesen Beitrag zu antworten oder neue Beiträge schreiben zu können, müssen Sie sich zunächst anmelden.
Einloggen | Neu registrieren |
|
|
sevISDN 1.0
Überwachung aller eingehender Anrufe!
Die DLL erkennt alle über die CAPI-Schnittstelle eingehenden Anrufe und teilt Ihnen sogar mit, aus welchem Ortsbereich der Anruf stammt. Weitere Highlights: Online-Rufident, Erkennung der Anrufbehandlung u.v.m. Weitere InfosTipp des Monats Neu! sevCommand 4.0
Professionelle Schaltflächen im modernen Design!
Mit nur wenigen Mausklicks statten auch Sie Ihre Anwendungen ab sofort mit grafischen Schaltflächen im modernen Look & Feel aus (WinXP, Office, Vista oder auch Windows 8), inkl. große Symbolbibliothek. Weitere Infos
|