Hi!
Mache ja mit Java kleines 2D RPG.
Aber bei einer Sache komm ich nicht weiter, ich will das wenn man z.B. ne Map verlässt erstmal für eine kurze Zeit ein schwarzer Bildschirm kommt.
Jemand hat mir das gesagt:
Das funktioniert auch, er wartet 1-2 Sekunden und dann gehts weiter.
Aber NUR wenn ich die Methode playSound(); da aufrufe!!
Ansonsten wartet er unendlich lange. Will ja nicht jedesmal nen Sound abspielen wenn der Scharze Bildschirm kommt. Gibts da nen Trick oder ne andere Methode?
Thread.sleep hab ich auch als erstes benutzt. Aber er hat dann immer erst den schwarzen Bildschirm gemalt und danach erst gewartet obwohl Thread-sleep VOR dem g.drawImage kam.
Falls DFYX vom richtigen Standpunkt ausgeht, nämlich, dass der erste Codeschnipsel nicht wiederholt wird, dann kommt natürlich das Problem auf, dass im Ablauf von folgendem Code:
500 Millisekunden vorbei gehen müssen, sonst wird GameMode nie auf 2 gesetzt.
Zitat von ~Cloud~
Thread.sleep hab ich auch als erstes benutzt. Aber er hat dann immer erst den schwarzen Bildschirm gemalt und danach erst gewartet obwohl Thread-sleep VOR dem g.drawImage kam.
...
Sollte eigentlich klappen, wie du jetzt plötzlich auf g.drawImage kommst, ist nicht ersichtlich. Aber
oder so ähnlich sollte klappen. (Und sonst gibt es immernoch die Warte-Methode die man als erstes lernt: while(System.currentTimeMillis() >= waitingStartTime + 500){})
Und falls der erste Code trotzdem mehrmals beim if vorbeikommt muss man natürlich darauf achten, dass waitingStartTime nicht jedesmal neu initialisiert wird.
Hm alle Methoden funktionieren bei mir nicht *_*
Also ich habe in der SpielAnsichtsklasse die Run Methode drin, die ruft immer repaint auf.
Repaint beiinhaltet zum Teil dies:
Also wenn man im Titelbildschirm Neues Spiel drückt dann ist GameMode=1 und es wird kurz ein Sound eingespielt und dann wird bei der Mehtode zeichneSchwarz(g) mit g.drawRect ein schwarzenRechteck gezeichnet.
Dann hab ich eben das gemacht das er 1-2 Sekundne wartet das geht aber NUR wenn ich playSound() vorher mache ohne gehts auch nicht.
Hab jetzt das von dir mal getestet mit t.sleep(); Kommt das gleiche Problem das sleep wird VOR dem zeichneSchwarz(); ausgeführt!
Auch diese while schleife will nicht klappen...
Mach ich was falsch?
2. "zeichneSchwarz" ist doch bestimmt ne Methode, die du selbst geschrieben hast - lass die doch TRUE zurückgeben und dann per if-Abfrage prüfen, ob es TRUE ist, um nur dann sleep auszuführen. So sollte das sleep erst ausgeführt werden, wenn die Methode eben TRUE zurückgibt und somit schon vollständig durchgenommen wurde.
Natürlich gibt es switch, aber ich habe gehört, dass es zumindest in C/C++ langsamer ist als if-else-if.
Ausserdem habe ich schon darauf hingewiesen, dass du nicht jedesmal waitingStartTime auf die aktuelle "Zeit" setzen darfst, wie sollte dann auch die > waitingStartTime + 500 wahr werden?
Man hat ein schönes Problem zu lösen, falls das sleep wirklich ausgeführt bevor alles mit Schwarz gefüllt wird, obwohl es wirklich danach im Code ist.
Dein Problem ist, dass du nicht vollkommen verstehst, was du machst und scheinbar auch keine Lust hast, es zu verstehen und stumpf Code abschreibst, der dir vorgegeben wird.
Was genau passiert hier?
Die erste Zeile im Block sichert die aktuellen Millisekunden.
In den nächsten zwei Zeilen spielst du einen Sound ab und zeichnest dein schwarzes Rechteck.
Der Sinn der nächsten Anweisung ist anscheinend dafür zu sorgen, dass mindestens eine halbe Sekunde (500 ms) vergeht, bevor du aufräumst und zum nächsten GameMode-Block wechselst. Hier ist auch dein Problem, denn das was du willst ist aus den folgenden Gründen nicht sichergestellt:
1. Die Ausführungszeit von playSound() ist anscheinend weit über 500 ms. So wie du es schilderst, sind es ein paar Sekunden. Das ist auch der Grund, wieso mit der momentanen Logik das Warten ausschließlich mit playSound() funktioniert.
2. Die Verzweigung sollte eigentlich eine Schleife sein, die solange wartet, bis mindestens die gewollte Zeit verstrichen ist.
Mit einer Fallunterscheidung kann man das Problem nochmal verdeutlichen:
Fall 1: 'System.currentTimeMillis()' ist kleiner als 'waitingStartTime + 500'
Dieser Fall tritt ein, wenn playSound() nicht zuvor aufgerufen wird, da es die einzige Routine ist, die mehrere Sekunden braucht.
Was passiert, ist folgendes: Der if-Block der Verzweigung wird nicht aufgerufen und folglich wird auch nicht in den nächsten Modus gewechselt.
Alle anderen Durchläufe des aktuellen Blocks werden gleich ablaufen und damit ist es effektiv eine unendliche Schleife, die nur durch einen Zufall wieder Verlassen werden kann, nämlich falls durch einen zufälligen "Hänger", der nächste Fall eintritt:
Fall 2: 'System.currentTimeMillis()' ist größer oder gleich 'waitingStartTime + 500'
Dieser Fall tritt ein, wenn playSound() zuvor aufgerufen wird, aus bereits erläutertem Grund.
Im Gegensatz zum ersten Fall, ist hier die Bedingung der Verzweigung erfüllt und so wird auch ihr if-Block aufgerufen und der Modus gewechselt.
Das ist das, was du von vorne herein wolltest.
Die kleine Änderung oben führt schließlich dazu, dass der Modus in jedem Fall gewechselt wird.
Beachte aber, dass playSound() mehrere Sekunden zum Ausführen benötigt, die halbe Sekunde (500 ms) in der Bedingung also in Verbindung mit playSound() vollkommen irrelevant ist. Wenn du z.B. 2 Sekunden warten willst, dann ändere '500' zu '2000'.
Zitat von ~Cloud~
Hab jetzt das von dir mal getestet mit t.sleep(); Kommt das gleiche Problem das sleep wird VOR dem zeichneSchwarz(); ausgeführt!
...
Als erstes sollte man festhalten, dass Thread.sleep() eine statische Methode ist, die immer für den aktuellen Thread gilt.
Anweisungen wie 'Thread t = Thread.currentThread(); t.sleep(...);' oder 'Thread.currentThread().sleep(...);', die auf Instanzen arbeiten, sind also unnötig und schlechter Stil.
Was dein Problem angeht, liegt es daran, dass Javas rendering routinen in einem eigenen Thread laufen. (Oder zumindest wird nicht direkt gezeichnet, sondern verzögert, was z.B. eintreten kann, wenn das Betriebssystem Entscheidungen darüber trifft, wann gezeichnet werden soll und wann nicht.) Was passiert ist also folgendes:
zeichneSchwarz() beauftragt den Rendering-Thread ein schwarzes Rechteck zu zeichnen und dieser wird dem auch nachgehen, sobald er dran kommt.
Als nächstes legst du den aktuellen Thread schlafen, er wird aber nicht unterbrochen wie bei Thread.yield() (andere Threads werden also nicht ausgeführt), was im Endeffekt dazu führt, dass zuerst gewartet wird und erst danach gezeichnet.
Noch was zu Thread.sleep(): Wenn du exakte Wartezeiten zwischen Ausführungen haben willst, solltest du darauf verzichten, denn Thread.sleep() wartet nicht exakt, sondern mindestens, so dass es tatsächlich viele Millisekunden mehr sind, die verstreichen.
Hier sind noch weitere Informationen zu Thread.sleep(), falls es dich interessiert.
Eigentlich solltest du gänzlich auf blockierenden Code verzichten, falls es möglich ist, und deine Programmlogik entsprechend umstrukturieren, denn blockierender Code wird als sehr schlechter Stil angesehen, aus guten Gründen. Aber als Anfänger kann man sich sowas ruhig leisten, man wächst schließlich erst mit seinen Fehlern. ;)
Zitat von Drakes
Natürlich gibt es switch, aber ich habe gehört, dass es zumindest in C/C++ langsamer ist als if-else-if.
...
Dann hast du etwas falsches gehört, denn das ist Unsinn. Im Worst Case-Szenario entsprechen Switch Cases einer If-Else-Verzweigung, können aber bei klug gewählten Case-Argumenten als einfache Jump-Anweisungen realisiert werden, was sehr schnell ist und keine Branch Mispredictions zur Folge haben kann. Im Grunde kann man besonders bei vielen Cases mit Switches also nur gewinnen.
Danke für die Antwort Kyuu ich programmiere mit Java jetzt erst seit einen halben Jahr versteh deshalb auch noch nicht alles.
Trotzdem werd ich gleich wieder verrückt. Ich hab es jetzt mit while() eingebaut, es klappt auch. Aber jetzt kommt was merkwürdiges. Nach dem Intro wird GameMode=3 gemacht dadurch wird eine Weltkarte angezeigt.
Es hat bis heute immer geklappt aber seit ich das geändert habe wird die Weltkarte also das Bild NICHT mehr angezeigt!
Der dazugehörige Text schon, wirklich komisch naja ich versuchs mal alleine vielleicht find ich ja den Fehler obwohl ich ausser der while nichts geändert habe.
EDIT: Ok hab den Fehler gefunden hatte vorher das Bild als BufferedImage gemacht und nicht als Image *_* EDIT2: Jetzt läd das Bild aber die Warteschleife funzt nicht mehr richtig >.< Ach ich mach erstmal woanders weiter...
EDIT3: Jetzt geht es aufeinmal nur teilweise, zwei Schleifen gehen die letzte nicht.
EDIT: Ok hab den Fehler gefunden hatte vorher das Bild als BufferedImage gemacht und nicht als Image *_* EDIT2: Jetzt läd das Bild aber die Warteschleife funzt nicht mehr richtig >.< Ach ich mach erstmal woanders weiter...
EDIT3: Jetzt geht es aufeinmal nur teilweise, zwei Schleifen gehen die letzte nicht.
...
Vielleicht wäre es eine gute Idee deine Werkzeuge zu wechseln? Python und Pygame wären beispielsweise eine viel bessere Wahl als Java und ihre GUI-Bibliotheken, die wirklich für GUI-Applikationen ausgelegt sind. Python ist einfach zu erlernen und Pygame liefert alles, was man zum Entwickeln eines Spieles benötigt. Ein Neuanfang würde dir auch die Chance geben, deine Programmlogik noch einmal von Grund auf zu überdenken.