iMuse ähnlicher Effekt

Fragen zu "Adventure Game Studio"? Hier rein!
Antworten
Benutzeravatar
Campusanis
Hobby-Archäologe
Hobby-Archäologe
Beiträge: 108
Registriert: 06.01.2003, 13:22
Kontaktdaten:

iMuse ähnlicher Effekt

Beitrag von Campusanis »

Hoi,

ich bastele gerade an der Musik für mein Adventure und wollte dabei verschiedene Versionen eines Musikstückes iMuse mäßig überblenden, wenn man die Räume wechselt oder auch mit einem anderen Charakter spricht. Für alle, die nicht wissen was ich meine: Dabei soll beim Crossfading quasi die Stelle, an der die Musik vor dem Wechseln des Raumes war, beibehalten werden.
Dazu haben alle Versionen exakt die gleiche Länge, damit ich mit GetMP3PosMillis() und SeekMP3PosMillis(...) jeweils die richtigen Stellen anspringen kann.

Allerdings ergibt sich dabei ein Problem, und zwar ist das Überwechseln zwischen den Variationen nicht ganz exakt. Manchmal startet die Version, in die übergegangen wird, ein bisschen zu früh, manchmal ein bisschen zu spät, und manchmal auch ziemlich genau.
Jetzt hab ich ein bisschen rumgesucht und tatsächlich wurde das Problem schon mal im offiziellen Forum von AGS diskutiert. CJ spricht da von größeren Abschnitten, in die ein Musikstück eingeteilt wird und dass man beim Anspringen einer bestimmten Stelle immer an den Anfang des Abschnitts springt.
Meine Theorie: Wenn man ungefähr die Größe dieser Abschnitte wüsste, könnte man AGS sagen, dass bei einem angeforderten Übergang solange gewartet wird, bis man sich genau am Anfang eines Abschnittes befindet und dann erst den Übergang startet.

Entweder ich spinn mir da was zurecht oder es könnte funktionieren. ;)
Allerdings hab ich da ein paar technische Probleme, das hinzubekommen. Der Code, der einfache, unsaubere Übergänge produziert, sieht so aus:

Code: Alles auswählen

int a=GetMP3PosMillis();
if (GetCurrentMusic() == 1) PlayMusic(2);
else PlayMusic(1);												// Wenn gerade Variante eins spielt, wird nach Variante 2 gewechselt, sonst umgekehrt.
SeekMP3PosMillis(a);
Ich hab schon verschiedenste While Schleifen mit Wait() Befehlen probiert, das resultierte dann aber meistens darin, dass das Spiel einfach komplett auf Wait schaltete und sich nicht mehr bedienen ließ. Falls irgendwer versteht, was ich meine und weiß, wie ich das Problem lösen kann, wäre ich sehr dankbar. ;)
Benutzeravatar
KhrisMUC
Adventure-Gott
Adventure-Gott
Beiträge: 4674
Registriert: 14.03.2005, 00:55
Wohnort: München

Beitrag von KhrisMUC »

Was für while-code hast Du benutzt? Und wofür genau?
Use gopher repellent on funny little man
Benutzeravatar
Campusanis
Hobby-Archäologe
Hobby-Archäologe
Beiträge: 108
Registriert: 06.01.2003, 13:22
Kontaktdaten:

Beitrag von Campusanis »

Diesen:

Code: Alles auswählen

while (GetMP3PosMillis()%1000!=0 && check==0) Wait(1);
(Angenommen, es wären 1000ms Abschnitte)
Wobei ich dann bei dem oben angegebenen Code noch check auf 1 gesetzt habe, damit die Schleife nicht immer weiter geht. Das steht übrigens alles bei der Interaktion, mit der man den Übergang aufruft (zum Testen hab ich "Schau an Luftballons" benutzt).
Denkfehler?
Benutzeravatar
KhrisMUC
Adventure-Gott
Adventure-Gott
Beiträge: 4674
Registriert: 14.03.2005, 00:55
Wohnort: München

Beitrag von KhrisMUC »

Das funktioniert nicht, weil Wait(1) dafür sorgt, dass der nächste check erst ca. 25 Millisekunden später passiert.
Wenn also GetMP3PosMillis() beim ersten mal 24995 geliefert hat, wird es beim nächsten Mal ca. 25020 liefern, anstatt bei 25000 aus dem loop auszusteigen.

Code: Alles auswählen

function noloopcheck wait_for_music_chunk(int chunksize) {
  while(GetMP3PosMillis()%chunksize!=0);
}
Oder:

Code: Alles auswählen

function noloopcheck wait_for_music_chunk(int chunksize) {
  int r;
  bool check=true;
  while(check) {
    r=GetMP3PosMillis()%chunksize;
    if (r<3 && r>-3) check=false;  // 4 Millisekunden Toleranz
  }
}
Use gopher repellent on funny little man
Benutzeravatar
Campusanis
Hobby-Archäologe
Hobby-Archäologe
Beiträge: 108
Registriert: 06.01.2003, 13:22
Kontaktdaten:

Beitrag von Campusanis »

Also bei der ersten Version versteh ich nicht, was du meinst, hast du da was vergessen?. ;)
Aber die zweite ist gut, es funktioniert irgendwie (bis auf den kleinen Fehler "||" statt "&&"). Allerdings war meine Theorie wohl falsch, denn es wird immer noch wahllos zu früh und zu spät angesprungen. Hm, na ja, trotzdem danke für die Hilfe.
Benutzeravatar
KhrisMUC
Adventure-Gott
Adventure-Gott
Beiträge: 4674
Registriert: 14.03.2005, 00:55
Wohnort: München

Beitrag von KhrisMUC »

Hast Du mal meinen Code genau so wie er dasteht, ausprobiert? Ich versichere Dir, beide Vorschläge sind absolut richtig.

Der erste braucht keinen Befehl in der while-Schleife, da das Wait(1); nicht vorhanden sein darf. while(bedingung); ist völlig legitim.

Der zweite berechnet den Rest und überprüft nicht, ob er 0 ist, sondern ob er zwischen -3 und 3 ist.

Alles klar? ;)
Use gopher repellent on funny little man
Benutzeravatar
Campusanis
Hobby-Archäologe
Hobby-Archäologe
Beiträge: 108
Registriert: 06.01.2003, 13:22
Kontaktdaten:

Beitrag von Campusanis »

Hab ich, hab ich.
Die erste Variante lässt sich nicht kompilieren und bei der zweiten Variante mit "&&" bricht das Spiel nach 150001 Durchläufen der Schleife ab (sprich, Endlosschleife). Jetzt wo ich's mir angucke, seh ich wie du das mit dem r<3 und >-3 meintest, allerdings ist es offenbar nie in dem Bereich.
Nachdem ich && durch || ersetzt habe, geht es übrigens doch nicht, d.h. es wird nicht gewartet sondern sofort übergegangen, was ja in dem Fall auch logisch ist.
Benutzeravatar
KhrisMUC
Adventure-Gott
Adventure-Gott
Beiträge: 4674
Registriert: 14.03.2005, 00:55
Wohnort: München

Beitrag von KhrisMUC »

Dann while(bed) {}.

Bringt aber eh nix, da es nie genau Null sein wird. Ich würd mal die Toleranz vergrössern. Oder mit Display Werte von GetMP3Millis()%chunksize ausgeben, um zu kucken, was schief läuft.
Ich hab zwar nen grossen Kochlöffel, aber auch ich schlage blind nach dem Topf ;)
Use gopher repellent on funny little man
Benutzeravatar
Campusanis
Hobby-Archäologe
Hobby-Archäologe
Beiträge: 108
Registriert: 06.01.2003, 13:22
Kontaktdaten:

Beitrag von Campusanis »

Dann while(bed) {}.
Die Idee hatte ich auch, aber nada.
Die Toleranz zu vergrößern hab ich gerade probiert, allerdings muss ich sie bei einer chunksize von 1000 auf 900 stellen, was das Ganze etwas vom Sinn befreit.

EDIT: Hab mir auch eben die Werte per Display mal anzeigen lassen. Entweder es liegt am Display Befehl oder es wird wirklich nur jede Sekunde ein neuer Wert für GetMP3PosMillis genommen (hatte es ins Rep_ex geschrieben). Das Problem ist wohl, dass die While Schleife wesentlich schneller abläuft, als überhaupt neue Werte genommen werden.
Benutzeravatar
KhrisMUC
Adventure-Gott
Adventure-Gott
Beiträge: 4674
Registriert: 14.03.2005, 00:55
Wohnort: München

Beitrag von KhrisMUC »

Hab's jetzt auch mal probiert, mit nem Label:

Code: Alles auswählen

// script for Room: Repeatedly execute
  int a=GetMP3PosMillis();
  String b=String.Format("%06d",a);  
  lbl_loc.Text=b;
Der Labeltext springt immer um runde 200ms weiter, genauer gehts also nicht.
Use gopher repellent on funny little man
Benutzeravatar
Campusanis
Hobby-Archäologe
Hobby-Archäologe
Beiträge: 108
Registriert: 06.01.2003, 13:22
Kontaktdaten:

Beitrag von Campusanis »

Hm, GameSpeed verändern bringt auch nichts...
Ich schätze, diese Erkenntnis bedeutet Good Bye iMuse. Werd mir wohl was anderes überlegen müssen. Danke für die "Mitarbeit". ;)
Hab jetzt für's erste einen sehr langsamen Fade genommen und springe bewusst immer eine Stelle 200ms vor der durch GetMP3PosMillis() zurückgegebenen Zeit an. Ist nicht perfekt, aber in 50% aller Fälle ist es gut und da man es im Spiel sowieso nicht so oft hört, fällt es hoffentlich nicht sooo auf.
Ich bin aber bei jeglichen neuen Einfällen für alles offen.
Antworten