Array zu langsam??
Übersicht

beginrBetreff: Array zu langsam?? |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Ich möchte die Bewegungen des Mauszeigers in einem Array speichen, etwa so:
Code: [AUSKLAPPEN] SetBuffer BackBuffer()
Dim ArrX(10000) Dim ArrY(10000) Zeit = MilliSecs() Repeat ArrX(Zaehler) = MouseX() ArrY(Zaehler) = MouseY() ReloadScreen() DrawImage Maus, MouseX(), MouseY() Flip Zaehler = Zaehler + 1 Until MilliSecs() >= Zeit + 250 ReloadScreen() ist so geschrieben, dass es das Hintergrundbild lädt. Nachher sollten die x- und y-Koordinaten der Bewegungen des Mauszeigers in den beiden Arrays "ArrX" und "ArrY" gespeichert sein. Das sind sie aber nur bruchstückhaft. Wer hat einen Tip, wie man alle Koordinaten in den beiden Arrays speichern kann?[/code] |
||
![]() |
ProfJakeehemals "DTC" / "Fabian Niemann" |
![]() Antworten mit Zitat ![]() |
---|---|---|
Also wenn du irgendetwas in einer Schleife lädst, dann geht dadurch die Performance total in den Keller.
Dass wird warscheinlich der Grund sein. |
||
beginr |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Ja OK aber wie soll ich das sonst machen...? | ||
![]() |
ProfJakeehemals "DTC" / "Fabian Niemann" |
![]() Antworten mit Zitat ![]() |
---|---|---|
Code: [AUSKLAPPEN] Graphics 640,480 Setbuffer Backbuffer() ; Bilder laden Dim mouse(10000,1) time = Millisecs() index = 0 Repeat Cls mouse(index,0) = MouseX() mouse(index,1) = MouseY() index = index + 1 ; Bilder anzeigen Flip Until Millisecs() >= time + 250 End Allerdings bekomme ich bei einem 10000er Array einen Array Index Out Of Bounds Error! Und der Sinn dieses Codes ist mir in dieser Form nicht ganz klar, da man nur 250 Millisekunden Zeit hat um die Maus zu bewegen. Um das ganze praxistauglich zu machen, müsstest du die Aufzeichnungszeit verlängern, einen Timer einbauen oder manuell testen ob eine Zeit (z.B.: 1 Millisekunde) vergangen ist und erst dann einen neuen Wert ins Array packen, sonst müsstest du es wirklich riesig machen. |
||
![]() |
skey-z |
![]() Antworten mit Zitat ![]() |
---|---|---|
noch einfacher, teste, ob die Maus sich bewegt hat, das kannst du mit MouseX(Y)Speed() herausfinden, wenn dieser Wert ungleich 0 ist, dann hat sich die maus seit dem letzten aufruf bewegt. | ||
Awards:
Coffee's Monatswettbewerb Feb. 08: 1. Platz BAC#57: 2. Platz |
![]() |
hecticSieger des IS Talentwettbewerb 2006 |
![]() Antworten mit Zitat ![]() |
---|---|---|
Um so emens große (für Computerspielerei) Datenmengen zu begrenzen, solltest du anstelle eines Array doch lieber eine Bank nehmen. Denn diese lassen sich auf 1,2 oder 4 Byte pro Wert begrenzen. Wenn die Mausposition nicht ganz genau auf ein Pixel zugewiesen werden muss, so kann man dieses auch auf ein Byte quetschen. MouseX() / Float(GraphicsWidth) * 256 oder so... Du kannst das ganze auch in ein Type speichern. Ein Type hat den Vorteil, dass eben nur soviele Einträge vorhanden sind, wie gerade benötigt werden. Nachteil ist aber, dass so eine Verwaltung mit so großen Datenmengen dann doch extrem langsam wird. Von daher solltest du uns lieber erzählen, was du genau machen willst. | ||
Download der Draw3D2 V.1.1 für schnelle Echtzeiteffekte über Blitz3D |
beginr |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
@pupil:
Zitat: Allerdings bekomme ich bei einem 10000er Array einen Array Index Out Of Bounds Error!
Das liegt nicht daran, dass das Array zu groß ist, sondern daran, dass in BlitzBasic (anders als in den meisten anderen Sprachen) der Index eines Arrays der Größe n der Index bei 1 anfängt (und nicht bei n - 1, sondern bei n aufhört). Es muss also Code: [AUSKLAPPEN] Dim Array(10000,2)
; Der Rest... mouse(index,1) = MouseX() mouse(index,2) = MouseY() ; und so weiter heißen. Was ich allerdings nicht verstehe, ist, dass du zuerst schreibst, die Performance geht wegen der Schleife in den Keller, und dann aber an der Schleife nichts änderst, sondern stattdessen ein zweidimensionales statt des 1D-Arrays verwendest. Das ist vielleicht praktischer (hätte ich auch drauf kommen können), aber auch schneller? Na ja, werds mal probieren. @hectic: Zitat: Um so emens große (für Computerspielerei) Datenmengen zu begrenzen, solltest du anstelle eines Array doch lieber eine Bank nehmen.
Sorry, muss nochmal nachlesen, was eine Bank ist. Zitat: Wenn die Mausposition nicht ganz genau auf ein Pixel zugewiesen werden muss, so kann man dieses auch auf ein Byte quetschen. MouseX() / Float(GraphicsWidth) * 256 oder so...
Leider brauche ich die Mausbewegungen pixelgenau. Zitat: Von daher solltest du uns lieber erzählen, was du genau machen willst.
Ich möchte die Mausbewegungen in einer bestimmten Zeitspanne pixelgenau aufzeichnen (hier habe ich 250 Millisekunden genommen), um sie später auswerten zu können (ob man mit der Maus ein bestimmtes Objekt getroffen hat o. ä.). |
||
![]() |
hecticSieger des IS Talentwettbewerb 2006 |
![]() Antworten mit Zitat ![]() |
---|---|---|
Sorry, 10'000 sollten kein so großes Problem sein. Hatte irgendwie 100'000 gelesen. Hier hängt es natürlich auch daran, wie die Daten bearbeitet werden. Kann es sein, dass du pro Schleifendurchlauf alle Daten ''in einer Schlange'' nach vorne kopierst?
Nur so als Tipp: Ein Maustreiber gibt in etwa 100mal pro Skunde seine Position an Windows weiter. Es gibt zwar Peogramme, mit denen man das ganze bis auf 500mal erhöhen kann. Doch bringen solche Programme kaum Besserung, da die Programme selbst ja meistens auf Bildaufbaufrequenz ausgelegt sind. Doom 3 z.B. fest auf 60 FPS. Daher ergibt sich: Für 250 ms Zwischenspeicherung benötigt man maximal 25 X/Y -Einträge bei einem Bildaufbau von 100 FPS. Da es eh sinnvoll ist, sein Programm auf eine Maximalaufbaufrequenz (FPS) einzustellen, würde ich folgenden Weg vorschlagen: Erstelle ein ql:WaitTimer und setze diese auf z.B. 100 FPS und stelle dabei Flip auf 0. Da nun pro Sekunde 100 FPS maximal bearbeitet werden können, sind 250 ms (1/4 Sekunde) eben 25 Einträge für jeweils X und Y. Sicherheitshalber mal Dim (30,1) machen. Nun speicherst du alle Werte der Maus da rein, und hast ein recht kleines Array zur Bearbeitung. Dabei kann man bei so kleinen Arrays auch eine art eines ''Datenkarussels'' machen. Das ist zumindest am einfachsten. |
||
Download der Draw3D2 V.1.1 für schnelle Echtzeiteffekte über Blitz3D |
beginr |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
@hectic:
Ich wusste nicht, was ein WaitTimer ist, aber die Erklärung sieht eher so aus, als ob er das Spiel langsamer machen sollte... Mir ist es zu langsam, und ich schätze mal, dass das an der lahmen Speicherung des Arrays liegt. Da ich mich mit dem WaitTimer nicht auskenne, fände ich ein konkretes Codebeispiel gut, das ich direkt ausprobieren könnte. Was soll "in einer Schlange kopieren" heißen? Wenn ich die Daten "in einer Schlange kopiere", sieht man das nicht in meinem Codeschnipsel? |
||
![]() |
hecticSieger des IS Talentwettbewerb 2006 |
![]() Antworten mit Zitat ![]() |
---|---|---|
Mehr als 100 FPS können nicht zu langsam sein, da die meisten Bildschirme nichtmal diese 100 FPS erreichen können. Bei Flachbildschirmen ist die mir bekannte ''Schmerzgrenze'' ja sogar noch kleiner. Die liegt da bei 76 FPS. Nur wenige und gute alte CRT können bis 200 FPS schaffen. Doch das ist eh unnütz, da eben kaum jemand so einen hohen Bildaufbau bei sich eingestellt hat. Macht dein Programm dann mehr, wird es zwar berechnet, aber der Bildschirm zeigt trotzem nicht mehr an!
Von daher ist eine Framegrenze eine gute Angelegenheit. Vor allem mit ''Flip 0'' ersparst du dir Totalperformanceverluste, da ''Flip 1'' (Standardeinstellung) eben 100% Systemleistung frisst. Bei Mehrkernsystemen eben dann nur den einen Kern absolut lahm legt. Da kann man sich noch so sehr anstellen. Dazu gibt es genügend Beiträge hier im Forum. Wenn man sich also Einnig ist, dass mehr als 100 FPS sowieso keinen Sinn ergeben, so kann man diese also begrenzen und damit dann weiter arbeiten. |
||
Download der Draw3D2 V.1.1 für schnelle Echtzeiteffekte über Blitz3D |
![]() |
ProfJakeehemals "DTC" / "Fabian Niemann" |
![]() Antworten mit Zitat ![]() |
---|---|---|
beginr hat Folgendes geschrieben: Das liegt nicht daran, dass das Array zu groß ist, sondern daran, dass in BlitzBasic (anders als in den meisten anderen Sprachen) der Index eines Arrays der Größe n der Index bei 1 anfängt (und nicht bei n - 1, sondern bei n aufhört).
Nicht wirklich. Dass liegt daran, dass mein Rechner zu schnell ist und schnell den 10000. Eintrag überschreitet. Desderwegen solltest du auch mit WaitTimer arbeiten. Natürlich hast du mit der BlitzBasic-Array-Zählweise recht (arbeite halt eher mit BlitzMax), aber bei mir funktioniert das trotzdem. beginr hat Folgendes geschrieben: Was ich allerdings nicht verstehe, ist, dass du zuerst schreibst, die Performance geht wegen der Schleife in den Keller, ..
Da hab ich mich wohl falsch ausgedrückt. Ich meinte, dass es langsam wird, weil du in der Schleife etwas lädst. Also LoadImage oder so ähnlich in einer Schleife. |
||
beginr |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
@pupil:
Zitat: Ich meinte, dass es langsam wird, weil du in der Schleife etwas lädst. Also LoadImage oder so ähnlich in einer Schleife.
Vielleicht bin ich etwas schwer von Begriff, aber mein Problem war eigentlich, dass das Array meine Maus-Daten zu langsam speichert. Ich habe das ganze nämlich auch schon probiert, ohne die Bilder zu laden. Trotzdem landen die Koordinaten nur im Abstand von ca. 10 Pixeln im Array. @hectic: Zitat: Nur so als Tipp: Ein Maustreiber gibt in etwa 100mal pro Sekunde seine Position an Windows weiter.
100mal pro Sekunde wären einmal in 10 Millisekunden. Das müsste doch reichen, um auch schnelle Mausbewegungen in meinem Array pixelgenau zu speichern, oder nicht? Zitat: Mehr als 100 FPS können nicht zu langsam sein, da die meisten Bildschirme nichtmal diese 100 FPS erreichen können. Bei Flachbildschirmen ist die mir bekannte ''Schmerzgrenze'' ja sogar noch kleiner. Die liegt da bei 76 FPS. Nur wenige und gute alte CRT können bis 200 FPS schaffen. Doch das ist eh unnütz, da eben kaum jemand so einen hohen Bildaufbau bei sich eingestellt hat. Macht dein Programm dann mehr, wird es zwar berechnet, aber der Bildschirm zeigt trotzem nicht mehr an!
Es funktioniert auch ohne das Laden der Bilder nicht (s. o.)! Daher ist die Ursache meiner Meinung nach nicht am Bildschirm, sondern am Array zu suchen. Wen du noch eine gute Ide hast, dann gib doch bitte einmal ein Codebeispiel. Ich kann mir darunter so nichts vorstellen... Sorry, ich meinte eine Idee, keine IDE... |
||
beginr |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Moment mal... Wenn der Maustreiber nur alle 10 ms die Position weitergibt, hieße das ja, dass eine pixelgenaue Speicherung nur bei Mauszeigergeschwindigkeiten unter 10 ms/Pixel möglich ist. Das heißt, dass ich für eine normale Bildschirmauflösung (1024px Breite) über 10 Sekunden vom linken zum rechten Rand bräuchte. Bist du sicher?? Es muss doch irgendeinen Weg geben, um schnelle Bewegungen aufzuzeichnen (eher 0,3 ms/px als 10). | ||
![]() |
hecticSieger des IS Talentwettbewerb 2006 |
![]() Antworten mit Zitat ![]() |
---|---|---|
Wenn ihr wissen wollt, wie schnell eurer Maustreiber die Mausposition updatet, so ladet euch doch einfach den mouse rate checker (über ''download'' gehen) runter. Meine Standardeinstellung war am Anfang auf ~80 eingestellt. Da ich aber mein CRT auf jeglicher Auflösung auf 100 Hz laufen lasse, habe ich meine Maus auf 125 Hz gesetzt. Im übrigen habe ich auch keine Billigmaus ''Razer Diamondback''. Da Razer eines der ersten Maushersteller war, der auf äusserst präzise steuerbare optische Mäuse setzte (noch lange vor MS, Logitech oder sonst was), gehe ich einfach mal davon aus, dass andere Hersteller auch keine wesentlich höhere Standardeinstellung haben. Der Grund ist einfach, dass es keinen Sinn ergibt, das System mit einer Mausrate von 500 Hz zu füttern. Diese Fütterungsrate hat nichts mit der Abtastrate der Maus selbst zu tun!
Wenn ich nun eine Programmschleife mit 1000 Hz ablaufen lasse, und jedes Frame die Mausposition abspeichere, dann bekomme ich reihenweise immer die gleichen Werte abgespeichert, obwohl die Maus ständig bewegt wird. Hier ein Beispiel, welches alle Mauspositionen für etwa eine Sekunde zwischenspeichert. Das ganze wird in so einem Datenkarussel bearbeitet. So ein Datenkarussel hat den Vorteil, dass es besonders einfach zu programmieren ist. Jedoch den Nachteil, dass es bei größeren Datenmengen zu langsam wird. Will man also mehr als eine Sekunde speichern, so sollte man sich eine andere Methode überlegen. Da du aber was von 250 ms gesprochen hast, sollte 1/4 davon reichen. Code: [AUSKLAPPEN] Graphics 800,600,0,2
SetBuffer BackBuffer() Local Timer=CreateTimer(100) Local MX,MY,Loop Dim MousePos(100,1) While Not KeyHit(1) MX=MouseX() MY=MouseY() MousePos(100,0)=MX MousePos(100,1)=MY LockBuffer BackBuffer() For Loop=0 To 99 MousePos(Loop,0)=MousePos(Loop+1,0) MousePos(Loop,1)=MousePos(Loop+1,1) WritePixelFast MousePos(Loop,0),MousePos(Loop,1),-1 Next UnlockBuffer BackBuffer() WaitTimer(Timer) Flip 0 Cls Wend End |
||
Download der Draw3D2 V.1.1 für schnelle Echtzeiteffekte über Blitz3D |
beginr |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Danke... werds später mal ausprobieren. Also, es sollte auch mit Zeiten höher als 250 ms gehen, aber mehr als 1 sec Zwischenspeicherung werde ich wohl nicht brauchen. Den Code kann ich ja dann entscprechend anpassen. | ||
![]() |
BtbN |
![]() Antworten mit Zitat ![]() |
---|---|---|
Warum guckst du nicht einfach in jedem Hauptschleifen-Durchgang, ob sich die Mausposition verändert hat, und speicherst nur dann, wenn sich etwas ändert, die neue Position sammt Systemzeit(MilliSecs) in einem Type?
Dann hättest du eine sehr genaue und vorallem speicherschonende Aufzeichnung der Mausbewegung. |
||
![]() |
hecticSieger des IS Talentwettbewerb 2006 |
![]() Antworten mit Zitat ![]() |
---|---|---|
Bei einer festgelegten Datenmenge sind Types nicht grad vom Vorteil. Auch die Methode mit MilliSecs die man noch zwischenspeichert bedeutet, dass eine weitere zusätzliche Variable hinzu kommt (Speicherschonung bei Dauermausbewegung adee) und dass diese auch noch auf ''Ewig'' mitberechnet werden muss. Das heisst, es muss ständig mit aktuellen MilliSecs aus den der ganzen Type -Einträge verglichen werden. Man hat letztendlich nur eine sehr schlechte Zeitkontrolle. Bei einem Array mit ''Datenkarussel'' ist die verstrichene Zeit = die Arrayposition selbst.
Types würde ich gegenrell nur für Sachen nutzen, wo die Anzahl von Daten unbekannt ist. Sie ist jedoch nicht unbekannt, da der Zeitspeicher bekannt ist und die FPS sowieso begrenzt werden sollten. Arrays dagegen sind dafür gemacht, um feste Strukturen auf zu bauen. 100 Doppeleinträge zu verwalten halte ich nicht so als Datenschleudermethode. Es soll mir aber egal sein, wie es gemacht wird. Wer es unbedingt mit Types machen will oder nur diese verstanden hat, soll er es so machen. Der Performanceverlust ist bei beiden Methoden verschwindent gering, wenn man Grafikausgabe und anderes mitberücksichtigt. |
||
Download der Draw3D2 V.1.1 für schnelle Echtzeiteffekte über Blitz3D |
beginr |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
@hectic:
Sorry, aber dein Programm funktioniert nicht so, wie ich es mir vorgestellt habe. In der BlitzBasic-Hilfe heißt es unter Command Reference -> Graphics -> WritePixelFast: Zitat: This command will allow you fast access to a specific pixel in the buffer selected. While the ReadPixelFast command reads the pixel quickly (and it is written back quickly with this command, it is still not fast enough for real-time screen effects.
Dein Programm versucht nun aber, den WritePixelFast-Befehl für besagte "real-time screen effects" zu nutzen. Kein Wunder, dass die Maus blinkt und auch nicht alle Pixel angezeigt werden. Ich wollte nur die Bewegungen des Mauszeigers zur späteren Auswertung zwischenspeichern und nicht sie in Echtzeit ausgeben. Dafür ist es mir aber eben wichtig, dass jedes Pixel gespeichert wird (250 bis 750 ms Speicherung sollten reichen). |
||
Gast |
![]() Antworten mit Zitat |
|
---|---|---|
Damit ist gemeit, dass du nicht effekte wie
Code: [AUSKLAPPEN] Graphics 800,600,0,1
Lockbuffer Backbuffer() For X = 0 To 800 For Y = 0 To 600 WritePixelFast X,Y,X*Y,BackBuffer() Next Next Flip WaitKey End In Realtime Machen Kannst. Es ist Schneller als Plot, und WritePixel |
||
![]() |
Tankbuster |
![]() Antworten mit Zitat ![]() |
---|---|---|
beginr hat Folgendes geschrieben: @hectic:
Sorry, aber dein Programm funktioniert nicht so, wie ich es mir vorgestellt habe. In der BlitzBasic-Hilfe heißt es unter Command Reference -> Graphics -> WritePixelFast: Zitat: This command will allow you fast access to a specific pixel in the buffer selected. While the ReadPixelFast command reads the pixel quickly (and it is written back quickly with this command, it is still not fast enough for real-time screen effects.
Dein Programm versucht nun aber, den WritePixelFast-Befehl für besagte "real-time screen effects" zu nutzen. Kein Wunder, dass die Maus blinkt und auch nicht alle Pixel angezeigt werden. Ich wollte nur die Bewegungen des Mauszeigers zur späteren Auswertung zwischenspeichern und nicht sie in Echtzeit ausgeben. Dafür ist es mir aber eben wichtig, dass jedes Pixel gespeichert wird (250 bis 750 ms Speicherung sollten reichen). Ich weiß nicht was du hast o.0 Die Maus blinkt nicht, und es werden alle Pixel auf denen die Maus stand gezeichnet. Hectic wird dir sicherlich nicht ein komplettes Programm vorlegen, so wie du es haben willst. Das kannst du schön selber machen. Ist ja auch Sinn des Programmierens Probleme zu lösen. Er bietet dir lediglich einen Denkanstoß an ![]() PS: Mit "real-time screen effects" meinen die Ersteller der CR die Real-Time-Bearbeitung von Bildern in einer Schleife. Beispiel: Transparents- oder Farbänderung. Wenn du 100000 Pixel oder so neu zeichnen musst, wird das auf die Leistung gehen, ist ganz klar ![]() Aber für einzelne Pixel schneller als Plot. |
||
Twitter
Download Jewel Snake! Windows|Android |
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group