Mouse-Darstellung ?!?!?
-
Ich habe folgendes Problem: In meinem reinem DOS-Programm läuft die ganze Zeit eine Schleife durch und kopiert einen Bildschirmpuffer in den Videospeicher. Nun stellt sich das Problem der Mouse-Darstellung: Benutze ich den Mouse-Treiber und stelle die Maus darüber dar, muss ich sie vor dem kopieren ausschalten und danach wieder einschalten. Das flackert. Lasse ich das ein- und ausschalten sein, klappt die Darstellung der Mouse nicht korrekt(Bildschirmhintergrund der Mouse stimmt meist nicht ganz.) Bisher mache ich es so, dass ich den Mousezeiger selberzeichnen lasse anhand der Koordinaten die der Moustreiber mir liefert. Das funktioniert auch, ist aber auf älteren Rechnern zu langsam. Wie kann ich die Maus schnell und korrekt bei ständiger Bildschirmneuzeichnung darstellen ? Wie macht ihr eure Mausdarstellung ?
-
Selbst Code schreiben, der den Cursor zeichnet. Die meisten Mousetreiber bieten auch eine Funktion, mit der du den Pointer zu Code angeben kannst, der jedesmal ausgefuehrt werden soll, wenn sich am Mousestatus was aendert. (int 33h, ax=000Ch) Das sollte bei verstecktem mousecursor dann eigentlich nicht viel langsamer sein...
-
Aber es geht ja darum, dass das Bild jeden Schleifendurchgang neugezeichnet wird. Im Moment mache ich fast so wie du mir geraten hast. Der Mauszeiger wird unmittelbar vor dem kopieren des Puffers in den Videospeicher in den Puffer gezeichnet. Somit klappt es. Allerdings ist das auf langsameren Rechnern nicht mehr akzeptabel, da das Programm dann nur 3-4 Schleifendurchgänge pro Sekunde schafft. Und somit hinkt die Mausdarstellung extrem hinterher. Würde ich den Maustreiber das Zeichnen selber machen lassen, wäre es schnell genug, allerdings flackert es dann, da ich die Maus vorm Zeichnen unsichtbar schlaten muss und danach wieder sichtbar. Und wenn ich dieses Aus- und Einschalten unterlassen würde, dann ist der Hintergrund vom Mauszeiger bei Bewegungen nicht korrekt. Ich glaube das liegt daran, dass der Maustreiber sich vorher den Hintergrund sichert und dann das ganze mit Hintergrund kopiert. Aber in dieser kurzen Zeit, die der Maustreiber dafür braucht, wurde das Bild schon neukopiert und der Hintergrund stimmt nicht mehr. Ich hoffe, mein Problem wurde jetzt klar. Gebe es eine Möglichkeit dem Maustreiber zu sagen, er soll nur die Mausdrauflegen ohne den alten Hintergrund zu kopieren ? Oder hat jemand eine andere Idee ?
-
@Nubuo T. : Müßte ich nach deinem Weg dem Pointer für den Code dann die Adresse der Funktion, die sonst meinen Mauscursor zeichnet, übergeben ?
-
Also, 3-4 Schleifendurchgänge pro Sekunde kommt mir verdammt langsam vor. Was machst du denn alles in der Schleife?
-
@<Steffen Vogel>: Weiss zwar nicht, was du mit "sonst" meinst, aber in dem Pointer kann zB. die Addresse zu einer Routine stehen, die einen Mousecursor zeichnet und das hatte ich fuer deinen Fall auch angedacht, um sicher zu stellen, dass bei jeder Mousebewegung der Cursor gezeichnet wird. Genau so gut kannst du da code reinschreiben, der checkt, ob an einer Bestimmten Position geklickt wurde, egal... Hier nochmal eine genaue Beschreibung der entsprechenden Funktion:
ax=000Ch
es:dx=Pointer zu deinem Code (RM)
cx=Interrupt Mask:
Bits F-5: Reserviert
4: Code wird ausgefuehrt, wenn rechter Button gedrueckt und losgelassen wurde.
3: Code wird ausgefuehrt, wenn rechter Button gedrueckt wird
2: Wie Bit 4 fuer links
1: Wie Bit 3 fuer links
0: Code wird ausgefuehrt, wenn Mouse bewegt wurde
Innerhalb dieses codes gibt der Mousetreiber folgende Informationen:
ax=Bits der Mask, die den call ausgeloest haben.
bx=Button state (Bit0=links Bit1=rechts Bit2=Mitte(?))
cx=horizontale cursorposition
dx=vertikale cursorposition
ds=driver datasegment
Beim Beenden des Programms sollte der alte Behandlungscode wieder hergestellt werden. Das geht mit int 33h, ax=0014h (schau zB. mal in Ralf Browns Interrupt List nach)
Muss Cocaine aber recht geben:
Wenn die Darstellung des Mousecursors durch deinen Code (durch Mousetreiber aufgerufen oder nicht ist eigentlich egal) langsamer ist, als wenn du den Mousetreiber den Cursor an und ausschalten laesst, machst du irgendwas ziemlich falsch
ein entsprechender codeausschnitt koennte vielleicht helfen, den Fehler zu finden.[ Dieser Beitrag wurde am 10.06.2002 um 20:20 Uhr von Nobuo T editiert. ]
-
Also um mal was klarzustellen, die 3-4 Schleifendurchgänge beziehen sich auf einen 386 SX-Prozessor. Auf meinem 486 DX-33 schafft mein Programm 10-12, und das ist gerade so okay. Aber ich mache dieses Programm eigentlich aus Nostalgie, und ausserdem soll das Programm von der Technik her auch auf langsameren Rechnern laufen.
In jedem Schleifendurchgang wird das Hintergrundbild kopiert, Sprites ins Bild gesetzt, ein Menü gezeichnet, gecheckt, ob der Spieler reagiert hat und der Puffer in den Videospeicher kopiert. Aber selbst wenn ich fast alle Sachen disable, bleibt die Anzahl der Schleifendurchgänge ungefähr so.
@Nubuo T. : Also weise ich diesem Pointer die Adresse der Funktion zu, mit der ich normalerweise die Maus in den Puffer schreibe ? Aber damit würde die Maus vielleicht gerade gezeichnet, bevor der Hintergrund gezeichnet würde, das würde auch zum Flimmern der Maus führen.
-
Jop.
Mir faellt dabei aber auf, dass du vielleicht recht haben koenntest, und das in deinem Fall nicht so ideal ist, wenn du in jeder Schleife den gesamten Puffer, der in den Bildschirmspeicher kopiert wird, voellig neu zeichnest.
Um ein manuelles Zeichnen des Cursors in jeder Schleife fuehrt dann wohl Kein Weg vorbei...
Mein Vorschlag waere dann wirklich effektiv, wenn nur bei einer Eingabe durch den User etwas veraendert werden soll. :pIch weiss ja nicht, was fuer ein Spiel du da programmierst, aber wenn da mehrere Frames etc. animiert werden sollen, kannst du auf einem 386-Rechner mit 4fps glaube ich ganz zufrieden sein Nicht umsonst hatten die damals nur Textadventures und Rundenbasierte Strategiespiele mit aeusserst wenigen Animatioenen. Falls die Sprites jedoch nicht animiert sind, solltest du uU. darauf verzichten in jedem Schleifendurchgang alles neu zu zeichnen... Vor allem das Menu muss doch nicht jeden Schleifendurchgang neu gezeichnet werden, ausser der User klickt drauf
[ Dieser Beitrag wurde am 10.06.2002 um 21:21 Uhr von Nobuo T editiert. ]
-
@Nubuo T.:
Dein Tip funktioniert leider überhaupt nicht. Ich habe die Adresse meiner C-Fkt, die die Maus zeichnet, übergeben, aber keine Reaktion.
Kannst du das vielleicht nochmal genauer erklären, wie man das codet. Vielleicht hab ich nen Fehler gemacht.
-
hm. Hast du auch die Interruptmask in cx richtig gesetzt?
zB. wenn cx=0001h ist, wird der code nur ausgefuehrt, wenn die Mouse bewegt wird.
Laeuft dein Programm auch sicher im RealMode? Bin mir nicht sicher, ob int 33h fuer Protected mode reflektiert wirdZuletzt nochmal: Wenn unabhaengig davon, ob der user irgendwas mit der mouse oder Tastatur gemacht hat, der Bildschirm immer wieder neu gezeichnet wird, taugt das ganze sowieso nicht viel