Große 2D-Zeichnung skrollbar (Image-Grenze)

Fragen zu Grafik- & Soundproblemen und zur Spieleprogrammierung haben hier ihren Platz.
Benutzeravatar
Hyper
Beiträge: 194
Registriert: 19.04.2005 19:14

Große 2D-Zeichnung skrollbar (Image-Grenze)

Beitrag von Hyper »

Hallo Gefährten,

ich brauche mal einen Rat von Euch:
Ich möchte einen Netzplan darstellen. Dieser Netzplan kann jedoch beliebig groß werden. Daher möchte ich ihn im Scroll-Gadget zeichnen.

Theoretisch ist die angenehmste Methode ja die, zunächst in ein Image zu zeichnen und dieses dann in einem Image-Gadget darzustellen. Jedoch wenn das Bild zu groß wird, erreiche ich die Image-Grenze. Falls ich nur 2D-Zeichnen würde, hätte ich diese Beschränkung nicht. Allerdings weiß ich nicht, ob man überhaupt in ein Gadget direkt zeichnen kann oder nur auf ein Window. Außerdem ist das Thema Aktualisierung, Scroll, etc nicht so angenehm. Oder ist es doch unproblematisch?

Oder sollte ich mehrere Image-Gadgets anbringen und dort dann irgendwie Bild-Stücken einsetzen? Da ich durch Ermittlung der Mausposition aber auch interaktiv auf Klicks im Bild reagieren möchte, verkompliziert das dann natürlich alle Berechnungen.

Hat jemand schon einmal so etwas gemacht? Oder hat jemand nen Tipp für mich?

Danke im Voraus :allright:
PB 5.72
Kekskiller
Beiträge: 752
Registriert: 14.09.2004 21:39
Kontaktdaten:

Beitrag von Kekskiller »

Egal ob Fenster oder Gadget - man sollte nie etwas zum späteren Gebrauch auf eine Fensterfläche malen, da beim nächsten Minimizen des Fenster alles wieder gelöscht wird, es müsste mit Neuaufwand wieder aktualisiert werden. Ich empfehle daher eine Datenstruktur im Speicher, die du dann auf einem WindowedScreen anzeigst. So kannst du das Fenster auch Minimieren, ohne das alles verschwindet. Falls dir ein WindowsScreen zu speicherfressend ist, würd ich dir immer noch zu der Datenstruktur raten, damit man alles schnell wieder aufzeichnen kann. Dann brauchst du nur den aktuell im Scrollbereich befindlichen Bereich aus dem Speicher holen und kannst es passend darstellen.

Da ich grad Schreiblaune hab, schreib ich noch was zum Aktualiseren der Grafik: Normalerweise gibt PB ein Redraw_Window oder so zurück, wenn was neugezeichnet werden muss. Falls nur ein Teil neugezeichnet werden muss, ist diese Message natürlich nicht dazu in der Lage, zu entscheiden, wo neugezeichnet werden muss. Daher kannst du ja versuchen, das Bild in einer Art Raster einzuteilen, das die verschiedenen Redraw-Bereiche darstellt. So prüfst du einfach nur, ob jeder Bereich noch genauso aussieht wie vorher (so muss man nicht alles neuzeichnen, hat aber auch eine eventuell zeitaufreibenden Vergleicharbeit, musste sehen, wie du das machst). Natürlich ist es auch viel einfacher, als "Stay on top" zu setzen...
Benutzeravatar
PMV
Beiträge: 2765
Registriert: 29.08.2004 13:59
Wohnort: Baden-Württemberg

Beitrag von PMV »

Hm, also wenn das Bild in Echtzeit gerendert werden muss,
weil sich dort immer was bewegt, dann machs doch so:

Erstelle ein Fenster mit 2 Scrollbars, einen Links Senkrecht
und einen unten Wagerecht.

Jetzt zeichneste dein Netzplan oder was auch immer in ein
Image das fast so groß ist wie das Fenster. Die "Seitenränder"
wo die Scrollbars sind dürfen nicht übermalt werden. Wenn
alles in diesem Image gerendert ist dann zeichneste das Image
auf das Fenster an der Position 0,0 .

So wirkt das Image als ne art Buffer und es gibt keine unschönen
Flimmerefekte. Dabei nur mit Images arbeiten, aber wenn
Transparents hinzu kommt musste auf die performence aufpassen.
Von den 2 Scrollbars kannst du dann ablesen, welcher Bereich
gerade angezeigt werden soll :D .

Zum Thema ImageGadget, du könntest ja mal einfach ein Fenster
mit einem ImageGadget erstellen, dem ImageGadget ein Image
zuweisen und dann anschließend auf diesem Image Drawingbefehle
durchführen, wenn diese Veränderungen nciht auf dem Fenster
sichtbar sind, dann ist es nötig, das veränderte Image erneut dem
Gadget zu zu weisen, dann ist es wirklich besser, alles direkt auf dem
Fenster zu malen.

Alternative zu dem obigen könnteste auch einen Screen verwenden,
aber hier müssteste z.B. die Scrollbars selber Programmieren ...

Hm, oder ich lehn mich ma außem Fenster und geb diesen Tip:
Wart einfach noch ein paar Wochen bis meine Userlib draußen ist,
damit könnte dann so was wesentlich einfacher zu handeln sein,
sofern alles nach wunsch funzt :lol: , dann könnteste dir auch selber
überlegen ob Windowedscreen (Sprites) oder "normales" Fenster
(Images)

MFG PMV
alte Projekte:
TSE, CWL, Chatsystem, GameMaker, AI-Game DLL, Fileparser, usw. -.-
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

@Hyper

wieweit besteht denn dieser netzplan aus wiederkehrenden elementen?

wäre es evtl. eine mögliche lösung, ihn aus bausteinen bestehen zu lassen,
und dann nur ne MAP abzuspeichern anstatt jedes Pixel?
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
Hyper
Beiträge: 194
Registriert: 19.04.2005 19:14

Beitrag von Hyper »

Vielen herzlich Dank für Eure Ausführungen! Waren auch schon viele sehr gute Ideen dabei.

Noch mal zur Illustration, was ist so ein Netztplan: Er besteht aus Rechtecken mit Text, die durch Linien miteinander verbunden sind. Im Hintergrund befindet sich ein Gitternetz und unten eine Datumsleiste.
Also keine echt wiederkehrende Elemente, aber Elemente und dazwischen "viel Nichts" somit tut es mir auch um die Pixel leid, die ich im Image speichere ohne Information. Auch weil so ein Bild im Speicher dann relativ groß wird - ist ja eigentlich nicht notwendig für ein Paar Kästchen, Texte und Linien. Daher die Idee von Kaeru Gaman schon ganz gut. Aber wie dann? Sind Sprites evtl. eine Lösung?

Tja, ich denke ich muss wirklich jedes Objekt in einer Datenstruktur abspeichern, damit ich dann bei Mauscklick, weiß was wo ist.

Mit dem Selbstbau eines Scrollbereiches (wie Du PMV geschrieben hast) weiß ich nicht, ob das nicht sehr kompliziert wird, vor allem, wenn der User nur minimal scrollt, muss ich ja auch neu zeichnen oder?
PB 5.72
Benutzeravatar
freedimension
Admin
Beiträge: 1987
Registriert: 08.09.2004 13:19
Wohnort: Ludwigsburg
Kontaktdaten:

Beitrag von freedimension »

Hyper hat geschrieben:Tja, ich denke ich muss wirklich jedes Objekt in einer Datenstruktur abspeichern, damit ich dann bei Mauscklick, weiß was wo ist.
Das musst du definitiv so machen!
Also eine Linked List für die Knotenpunkte anlegen und dann nur die Teile zeichnen welche gerade sichtbar sind.

Code: Alles auswählen

Structure node
  xPos.l
  yPos.l
  name.s
  link.l  // Verbindungen zwischen den Knoten (das wird evtl. etwas komplizierter da m:n-Beziehung
EndStructure
...
StartDrawing(ImageOutput)
  ForEach ...
    If xPos>xScroll ...
      Box ...
      ...
    EndIf
  Next
StopDrawing
Mit dem Selbstbau eines Scrollbereiches (wie Du PMV geschrieben hast) weiß ich nicht, ob das nicht sehr kompliziert wird, vor allem, wenn der User nur minimal scrollt, muss ich ja auch neu zeichnen oder?
Ja, aber das hält sich in Grenzen. Ich habe auch einmal etwas ähnliches für eine Timeline gemacht, wenn man es richtig macht und wirklich nur wenn es nötig ist neuzeichnet sollte es eigentlich nicht flackern.
Beginne jeden Tag als ob es Absicht wäre!
Bild
BILDblog
Benutzeravatar
PMV
Beiträge: 2765
Registriert: 29.08.2004 13:59
Wohnort: Baden-Württemberg

Beitrag von PMV »

Also wenn das Flackern das problem ist, ich hab ja nun schon einige Tests gemacht und auch schon ziemlich fortgeschrittene Ergebnise, wo ich mit Images die Fenster selber zeichne.

Wenn man alles wie schon gesagt erst in ein Image zeichnet und nicht direkt auf das Fenster und das Image dann auf dem Fenster darstellt, flackert bei mir zumindest nichts.

Wenn du speicherst, wo jedes Objekt usw. sich auf deiner Karte aufhält und du speicherst, wo gerader der Benutzter drauf schaut, dann ist das eigentlich ganz einfach, alles neu zu zeichnen. Dass heißt wenn du erst mal geschaft hast, das überhaupt dar zu stellen sollte es auch kein Problem sein, die Positionen beim Scrollen neu zu bestimmen :D .

MFG PMV
alte Projekte:
TSE, CWL, Chatsystem, GameMaker, AI-Game DLL, Fileparser, usw. -.-
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

wenn du auf einem fenster arbeitest, wäre das weniger etwas für sprites,
aber du kannst auch mit images eine 'Map' darstellen.

im endeffekt läuft es darauf hinaus, daß du eine tabelle hast,
die eben maßstäblich darstellt, was an welcher stelle ist,
also, das prinzip einer tilemap, so wie ich das auch oben meinte.

so wie ein 'karopapier' wo du auf jedem karo eben ne kleine grafik haben kannst,
du speicherst aber eben in ner tabelle ab, welches grafiksteinchen dort sitzt.

{wenn du die daten vorher in einer anderen struktur hast,}
{so mit knotenpunkten wie FD das meinte, dann mußt du eben}
{nen algo haben, der das auf die Map umrechnet.}

zur darstellung überträgst du nun halt nen teil der großen map in ne image-matrix.
also, daß du den darstellungsbereich aufm fenster z.b. aus 20x15 image-gadgets zusammensetzt,
und du gibst denen eben inhalte, die dem Mapausschnitt an dieser stelle entspricht.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
Hyper
Beiträge: 194
Registriert: 19.04.2005 19:14

Beitrag von Hyper »

Also, wenn ich das jetzt richtig verstehe bieten sich 3 Lösungen an:

1) Über 1 Image und Scollgadget:
- Erstelle ein Scrollgadget
- Erstelle ein Image, welches so groß ist wie der sichtbare Bereich
- Berechne im Hintergrund, wo der sichtbare Bereich ist
- Erstelle dort das ImageGadget
- Berechne, was wo ist, beachte dabei die Scrollpositionen und die Größe (wegen Rezise Window)
- Zeichne die Objekte ins Image
- Zeige das Image über Imagegadget so an, dass es im sichtbaren Bereich landet
- Bei jedem Scrolling --> Beginne von vorn

2) Über 1 Image und eigene Scrollbalken
- Erstelle ein Image, welches so groß ist wie der sichtbare Bereich
- Erstelle 2 Scrollbalken
- Berechne im Hintergrund, was wo ist, beachte dabei die Scrollpositionen
und die Größe (wegen Rezise Window)
- Zeige das Image über Imagegadget immer an der gleichen Stelle an
- Bei jedem Scrolling --> Beginne von vorn

3) Über mehrere ImageGadgets und Images
- Erstelle X ImageGadgets per Rasterung
- Erstelle in jedem ImageGadgets in welchem laut Raster ein Objekt sein müsste ein Image
- Berechne was drauf muss und bringe drauf

Habe ich die Alternativen richtig wiedergegeben? Falls ja, was ist nun am geschicktesten? Wenn ich mir jetzt vorstelle eine Linie von links oben nach rechts unten und Text und Datumsachse und Gitternetzlinien etc...
Gerade Text beim Scrollen: Ein Buchstabe kann ja nur komplett dargestellt werden und nicht halb (Bei Vertical-Scroll um eine halbe Zeile) - oder? Wenn nun Textkästchen immer versetzt dargestellt sind (extrem immer um einen Punkt vertikal versetzt, wie dann die Ausschnitte zeichnen?
PB 5.72
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

ich geh mal nur auf die Tile-Lösung ein...

du kannst grundsätzlich Tile-weise scrollen, d.h. bei jedem
scrollvorgang springt die information eine komplette Tile weiter.

ein fine-scrolling bei dieser lösung benötigt ein pixelweises plazieren der anzeige-imagegadgets.

außerdem meinte ich, die benötigten elemente vorab zu erstellen,
und die, die angezeigt werden sollen, darzustellen.

also, im grunde erzeugt man zu beginn eine image-bibliothek.
aus den images dieser bibliothek wird eine beliebig große map zusammengestellt.

klar wäre hier text ein problem...

man könnte aber eben auch die images in der bibliothek so klein wie einzelne buchstaben machen.
dann muss man eben symbole im plan aus mehreren zusammen setzen...
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Antworten