Fade In / Fade Out Problem (ohne Raumwechsel)

  • Allgemein

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Fade In / Fade Out Problem (ohne Raumwechsel)

    Hallo zusammen,

    für mein J&R Spiel versuche ich gerade folgendes Scenario:

    Der Spieler stirbt (durch Fall in ein Loch oder Berühung des Gegners) -> Script wird ausgeführt
    Im Script wird der Spieler wieder auf Position XY gesetzt (hab bewusst kein room_restart gemacht - evtl später mal)
    Anschliessend wird das Objekt fade_in_out erstellt mit drei Events:

    Create Event

    GML-Quellcode

    1. alarm[0]=60


    Alarm Event

    GML-Quellcode

    1. instance_destroy()


    Draw Event

    GML-Quellcode

    1. draw_set_color(c_black);
    2. draw_set_alpha(alarm[0]/60);
    3. draw_rectangle(0,0,room_width,room_height,false);



    Im Prinzip klappts ja schon so ähnlich wie ich möchte. Er fadet von Schwarz auf Transparent. Schöner wäre der Effekt, dass erstmal von Transparent auf Schwarz und dann wieder von Schwarz wieder auf Transparent und das alles in einem Durchgang... wie ne Blende halt.

    Das viel grössere übel ist jedoch, das sobald der Fade"effekt" durch ist und das Objekt sich zerstört hat die Hälfte meiner Objekte nicht mehr angezeigt werden... die werden gleich mit transparent gemacht und erscheinen nicht mehr wieder.

    Selbst mit der R-Taste wo ich den Raum zu Testzwecken komplett resette (room_restart()) erscheinen die Objekte - bzw eher dessen Srpites nicht mehr. Als Beispiel fast der gesamte Boden auf dem der Spieler läuft verschwindet. Komischerweise aber nicht der ganze Boden sondern nur bestimmte Teile... manche sind wiederum da. Habe keine Ahnung woran das liegt und suche seit Stunden Google rauf und runter, schaue mir Videos an ohne Ende... und letzenlich muss ich doch fragen :(

    Irgendjemand ne Idee?

    LG
    Mirko
  • Ich nehme jetzt mal an du hast mehrere Objekte mit proprietären Draw-Events.

    Wenn dem so ist, solltest du immer vor einem Draw-Befehl auch den Alpha-Wert direkt zuweisen. Ich vermute dass der GM einfach den Alpha-Wert nimmt
    und ihn auf andere Objekte überträgt, und zwar auf jene, welche keine eigene Alpha-Draw-Einstellung haben.

    In deinem Fall kannst du dir vermutlich einfach helfen indem du nach dem hier ...

    GML-Quellcode

    1. draw_set_color(c_black);
    2. draw_set_alpha(alarm[0]/60);
    3. draw_rectangle(0,0,room_width,room_height,false);

    noch das hier hinzufügst:

    GML-Quellcode

    1. draw_set_alpha(1)

    Die Veränderung vom Alpha-Wert soll sich ja nur auf das Rechteck beziehen soweit ich verstanden habe.

    ---

    Was das Faden von Schwarz auf Transparent und umgekehrt angeht, könntest du beispielsweise Sinus verwenden:

    GML-Quellcode

    1. draw_set_alpha(sin((alarm[0]*pi)/60))


    Das hat allerdings einen exponentiellen Anstieg und Abstieg zur Folge. Wenn es ein linearer Übergang sein soll,
    könntest du beispielsweise mit einer Variable abfragen ob die Hälfte des Übergangs erreicht wurde (nach 30 Steps in deinem Fall),
    und davon ausgehend den Alpha Wert um 1/30 erhöhen oder verringern.
    Hoffe du weißt was ich meine, sonst kann ich noch einen Beispielcode schreiben.

    edit/

    Der Vollständigkeit halber schreibe ich meine (lineare) Lösung noch dazu:

    GML-Quellcode

    1. if alarm[0] < 30
    2. draw_set_alpha(alarm[0]/30);
    3. else
    4. draw_set_alpha(1-((alarm[0]-30)/30));

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von RLP ()

  • Hey RLP,

    super vielen Dank für den Hinweis für das draw_set_alpha(1)... damit klappt es exakt so wie es gewollt ist. Hab zum testen noch das Sinusbeispiel verwendet und gefällt mir sehr gut der Effekt ;)

    Dann weiten wir mal diesen "Stirb-und-FadeOut"-Effekt mal weiter aus :D

    Mein Script, wenn der Spieler stirbt ist ganz simpel:

    GML-Quellcode

    1. instance_create(0,0,obj_room_fade_in_out)
    2. obj_player.x = xstart;
    3. obj_player.y = ystart;


    So... durch das Objekt wird ja der Fade-Effekt durchgeführt, allerdings sieht man auch direkt noch das der Spieler auf die Position xstart und ystart "teleportiert" wird da ja noch der Fadeeffekt läuft. Dieser Teleport soll allerdings erst stattfinden wenn das Alpha bei 1 ist - also der Bildschirm komplett schwarz.

    Wie kann ich das realisieren?

    GML-Quellcode

    1. instance_create(0,0,obj_room_fade_in_out)
    2. if draw_get_alpha() == 1 {
    3. obj_player.x = xstart;
    4. obj_player.y = ystart;
    5. }


    So funzt es nicht... kann ja auch nicht da er das Alpha ja nicht aus dem entsprechenden Objekt bezieht sondern vom Skript welches ja kein Alpha-Wert erzeugt (so verstehe ich es zumindestens).

    Wie müsste es dann aussehen oder liege ich mit diesem obigen Beispiel komplett daneben? Habs auch in einem Destroy-Event vom Fade-Objekt probiert - sprich wenn das Objekt zerstört wird dann soll das Spielerobjekt dort hin teleportiert werden... klappt aber genauso wenig.

    Und dann noch ein weiterer Punkt:
    Das Spiel soll in dem Moment wo dieser Teleport stattfindet komplett angehalten werden... ich finde keine richtige "Pause"-Funktion.... oder ich übreseh es einfach nur :(
  • Hmm eigentlich würde ich das ganz anders angehen.
    Wenn du zum Beispiel ein Controllerobjekt hast, obj_controller zum Beispiel, lassen sich viele Sachen einfacher steuern, weil man quasi ein übergeordnetes Gottobjekt hat.

    Wenn du dann beispielsweise im Step-Event vom obj_controller schreibst:

    GML-Quellcode

    1. if not instance_exists(obj_spieler) && player_rebirth == 0
    2. {
    3. //Wiedergeburt des Spielers
    4. if deathalpha == 1
    5. instance_create(obj_spieler,x,y); //hier kannst du bei x und y einfach die gewünschten Roomkoordinaten eingeben
    6. //Alpha-Fade
    7. deathalpha = sin((alarm[0]*pi)/60);
    8. //Setzen von player_rebirth auf 0 wenn das Alarm-Event bzw. der Fade-Effekt abgelaufen ist
    9. if alarm[0] == 0
    10. player_rebirth = 1;
    11. }
    Alles anzeigen


    Und im Draw-Event das hier:

    GML-Quellcode

    1. //Alpha-Fade
    2. draw_set_color(c_black);
    3. draw_set_alpha(deathalpha);
    4. draw_rectangle(0,0,room_width,room_height,false);

    Hierfür musst du allerdings im Create-Event player_rebirth und deathalpha erstmal auf 0 setzen (initialisieren),
    und den Alarm-0-Event vom Spielerobjekt ins obj_controller übertragen:

    GML-Quellcode

    1. with obj_spieler
    2. instance_destroy();


    Wenn ich jetzt keinen Fehler gemacht habe sollte es so funktionieren.^^

    Eventuell musst du dein Spielerobjekt aber gar nicht mal löschen, wenn du beim Tod einfach x auf xstart und y auf ystart setzt.
    Beachte nur, wenn du das z.B. vom Controllerobjekt aus machst, dass das in etwa so aussieht:

    GML-Quellcode

    1. obj_spieler.x = obj_spieler.xstart;
    2. obj_spieler.y = obj_spieler.ystart;

    Also hier den Punkt-Operator beachten (das Objekt vor dem Punkt ist das Objekt bzw. eine Instanz des Objektes welche du ansprichst)
    Oder so, mit with:

    GML-Quellcode

    1. with obj_spieler
    2. {
    3. x = xstart;
    4. y = ystart;
    5. }

    Ist natürlich dir überlassen ob du es mit Controllerobjekt oder ohne machst, ich würde es aber generell empfehlen.
    Hoffentlich habe ich dir genug Ansatzpunkte gegeben, sonst frage einfach nochmal.
  • Hm....

    nun komm ich nicht mehr mit :)

    ich versuch's mal auf mein Projekt detaillierter zu beschreiben.

    Mein Charakter hat den Objektnamen "obj_player". Mein Controllerelement, was die Punkte, das Leben, die Zeit usw anzeigt und beim Spielstart die Hintergrundmusik verwaltet lautet "obj_controller".

    Bei meinem Charakter steht im Step-Event folgender Befehlwenn ich in ein "Loch" falle:

    GML-Quellcode

    1. //Player die when fall out of Map
    2. if(obj_player.y > room_height)
    3. {
    4. audio_play_sound(sound_player_die,1,0)
    5. global.lives1 -= 1
    6. loosecode()
    7. }


    Wie man sieht startet er nun sobald der Spieler "stirbt" das "loosecode"-Skript.

    Dies sieht wie folgt aus:

    GML-Quellcode

    1. instance_create(0,0,obj_room_fade_in_out)
    2. obj_player.x = xstart;
    3. obj_player.y = ystart;


    Das "loosecode"-Skript wiederum erstellt das Fade-Objekt "obj_room_fade_in_out" welches ja nun inhaltlich aus den ersten Postings bekannt ist. Mein Controllerobjekt wird derzeit eigentlich gar nicht direkt mit meinem Spieler verwendet, ausser die Variablen global.lives1 usw werden an den Controller übergeben, damit mir auch die Leben angezogen werden beim Tod.

    Es sieht vom Code her evtl alles etwas wirr aus, aber es macht derzeit genau das was ich mir vorstelle.

    Wie ich jetzt mein looscode-Skript ersetze gegen Teile die dann im Controllerobjekt stehen das verstehe ich nicht. Ich kann im Controllerobjekt ja kein Alarm starten, da dieser Alarm sich ja auf alles im Controller bezieht? Ich blick da noch nicht wirklich ganz durch...
  • Ok, ich glaube ich habe mal wieder über das Ziel hinausgeschossen, sorry.^^
    Ich probiere es nochmal: Vergiss das was ich über das Controllerobjekt geschrieben habe. Ich bin davon ausgegangen, dass du so ein Objekt nicht besitzt, was falsch war.

    mirko2002 schrieb:

    So... durch das Objekt wird ja der Fade-Effekt durchgeführt, allerdings sieht man auch direkt noch das der Spieler auf die Position xstart und ystart "teleportiert" wird da ja noch der Fadeeffekt läuft. Dieser Teleport soll allerdings erst stattfinden wenn das Alpha bei 1 ist - also der Bildschirm komplett schwarz.

    Wie kann ich das realisieren?

    GML-Quellcode

    1. instance_create(0,0,obj_room_fade_in_out)
    2. if draw_get_alpha() == 1 {
    3. obj_player.x = xstart;
    4. obj_player.y = ystart;
    5. }

    Verwende statt draw_get_alpha() eine eigene Variable, zum Beispiel deathalpha, dann hast du mehr Kontrolle.
    Setze diese Variable im Create-Event des Spielers auf 0 um sie zu initialisieren.

    Dann müsstest du dein Draw-Event aktualisieren:

    GML-Quellcode

    1. draw_set_color(c_black);
    2. draw_set_alpha(deathalpha);
    3. draw_rectangle(0,0,room_width,room_height,false);
    4. draw_set_alpha(1);

    Wie du siehst findet die Berechnung mit Sinus hier nicht mehr statt, die könnten wir stattdessen ins Step-Event des Spielers implementieren:

    GML-Quellcode

    1. deathalpha = sin((alarm[0]*pi)/60)


    mirko2002 schrieb:

    Und dann noch ein weiterer Punkt:
    Das Spiel soll in dem Moment wo dieser Teleport stattfindet komplett angehalten werden... ich finde keine richtige "Pause"-Funktion.... oder ich übreseh es einfach nur :(

    Vor GM-Studio gab es mal eine Sleep-Funktion, welche das Spiel für eine bestimmte Zeit einfriert,
    ich vermute mal, dass du GM-Studio benutzt, da wurde die Funktion jedenfalls entfernt (sie war auch irgendwie etwas unschön).
    Mir fällt da jetzt nur eine Möglichkeit ein: Eine eigene Pausenvariable welche vor jedem Step überprüft wird, also wenn pause == false ist werden Aktionen ausgeführt.

    Wegen der deathalpha-Variable bin ich mir nicht sicher ob die oft genug abgefragt wird, im Moment verknotet sich gerade mein Gehirn, vielleicht liegt es an der Müdigkeit.^^
    Wenn es nicht funktionieren sollte schaue ich da morgen nochmals drüber, wenn mir niemand anderer zuvor kommt. ;)
  • Also.... grad mal versucht das geschriebene umzusetzen... funtz nicht :)

    Lass uns die Sleep-Geschichte dabei noch etwas in den Hintergrund rücken und weiter an dem Punkt arbeiten, dass der Teleport erst erfolgt wenn der Alphawert 1 erreicht hat - der Bildschirm ist schwarz und der Spieler vor dem Bildschirm bekommt von dem Teleport nichts mit.

    Eigentlich muss das doch genau mit der IF Abfrage im loosecode möglich sein....
  • Irgendwie ist mir das etwas zu abstrakt ... ich habe mehrere Fehlerquellen als Verdacht.
    Vielleicht lädst du mir ein Example hoch, dann kann ich es mir anschauen und mir ein besseres Bild davon machen.
    Wenn du es nicht öffentlich posten willst, kannst du es mir auch per PN senden.
  • Aaalso, die bzw. meine Lösung ist:

    GML-Quellcode

    1. //Player die when fall out of Map
    2. if(obj_player.y > room_height) && !instance_exists(obj_room_fade_in_out)
    3. {
    4. audio_play_sound(sound_player_die,1,0)
    5. global.lives1 -= 1
    6. loosecode()
    7. }
    8. //Neuerstellung des Players
    9. if instance_exists(obj_room_fade_in_out)
    10. {
    11. if obj_room_fade_in_out.alarm[0] == 30
    12. {
    13. with obj_player
    14. {
    15. x = xstart
    16. y = ystart
    17. }
    18. }
    19. }
    Alles anzeigen

    Mein Verdacht hat sich bestätigt, und eigentlich hätte ich die Lösung auch ohne Beispiel wissen können, aber ich habe mich zu sehr verwirren lassen.^^

    Das Problem war, dass der loosecode-Skript ja nur einmal ausgeführt wird wenn der Player unterhalb der Map ist (sonst würde auch global.lives1 -= 1 zu viele Leben auf einmal abziehen).
    draw_get_alpha() wird also nur am Anfang abgefragt wo es noch keinen Sinn macht. Es hätte sowieso keinen Sinn gehabt da man das nicht im Step-Event abfragen kann (der Draw-Event findet nach dem Step-Event statt).
    Ich habe deshalb einfach die alarm[0]-Variable verwendet, und das Objekt obj_room_fade_in_out bei beiden Codeblöcken unterschiedlich abfragen lassen.
    Der loosecode-Skript sieht jetzt so aus, und ist jetzt eigentlich überflüssig geworden:

    GML-Quellcode

    1. instance_create(0,0,obj_room_fade_in_out)
  • Aaaalso... :D

    Hast Du das geschriebene auch selber ins Detail getestet?^^

    Ich hab's jetzt mal von oben so übernommen. Nun hab ich gleich zwei riesen Probleme:

    Zum einem bleibt die Zeit stehen und läuft partout nicht mehr weiter.
    Zum anderen wird das global.lives1 -= 1 nun ganze 30 Mal ausgelöst beim Tod des Spieler. Ich habe also Anfangs 3 Leben, sterbe einmal und zack... Leben -27

    Da haut doch irgendwas nicht hin ;)
  • Hmmmmmm....

    irgendwie haut da was nicht hin. Haben da irgendwelchen globalen GMS Einstellungen Einfluss die ausserhalb vom Projekt gelten?

    Habe jetzt Deine modifizierte Version genommen und es passiert exakt dasselbe wie wo ich die Änderungen bei mir selber vorgenommen habe.

    Sprich der Spieler stirbt, man hört die "Player_died" sound etliche Male abspielen (in extrem schneller Reihenfolge) und es werden 30 Leben abgezogen. Er führt also das ganze Skript genau einen halben Step lang ununterbrochen aus.... also ein Step sind bei mir eingestellt 60 FPS und hier macht er genau bis zur Hälfte alle Aktionen durchgängig... versteh ich nicht. Also 30 mal den Sound abspielen, 30 mal die Leben abziehen... die Teleportaktion die macht er dann allerdings nur einmal...

    Hab mal zum testen den Part
    audio_play_sound(sound_player_die,1,0)
    global.lives1 -= 1
    in den loosecode eingefügt und beim zweiten Test in den Teil von if instance_exists(room_obj_fade_in_out) aber überall exakt dasselbe... er führt die Aktion generell 30 mal durch während er es nur einmal tut wenn ich den original Code verwende....

    Irgendwie alles sehr seltsam...


    Ooookay:
    Nach weiteren Test hat sich ergeben, dass dieses "ich führ Aktion XYZ jetzt mal 30x aus" durch diesen Teil hier verursacht wird:

    if obj_room_fade_in_out.alarm[0] == 30

    Lasse ich diesen Teil weg führt er alle Aktionen "normal" aus, nur das ohne diese Abfrage jetzt natürlich der Teleport sofort erfolgt und nicht erst wenn der Alphawert 1 erreicht hat - sprich der Bildschirm schwarz ist. Evtl hilft das weiter?
  • Also langsam ist das echt seltsam ...
    Ich stürze mich über die erste Klippe, falle unter die Map, und zwei der drei Herzen leuchten rot, also sollte auch nur ein Leben abgezogen sein.
    Das ist das was ich die ganze Zeit mache, und bei mir funktioniert es.

    Schau mal ob es so funktioniert, ansonsten kannst du es mal mit einer selbsterstellten Variable probieren die du statt alarm[0] abfragen lässt:

    GML-Quellcode

    1. //Neuerstellung des Players
    2. if instance_exists(obj_room_fade_in_out)
    3. {
    4. with obj_room_fade_in_out
    5. {
    6. if alarm[0] == 30
    7. {
    8. with obj_player
    9. {
    10. x = xstart
    11. y = ystart
    12. }
    13. }
    14. }
    15. }
    Alles anzeigen


    Vielleicht funktioniert es wie hier im Code mit with,
    aber es ist so oder so schon seltsam, dass die gleiche Version auf meinem PC anders funktioniert als auf deinem ...
    Welche Version von Studio verwendest du? Ich momentan 1.3.1344.
  • Leider, leider, leider passiert mit der Variante immer noch exakt dasselbe. Es werden nach wie vor 30 Leben abgezogen (musste die Lebensanzeige zum Testen wieder mit Text einbauen damit ich sehen konnte wie weit er ins Minus geht).

    Ich nutze hier die Version 1.3.1380, kann mir aber nicht so vorstellen das es daran liegt? Oder doch?
  • Habe es nun mit der Version 1.3.1386 (Stable) probiert, und es läuft auch da ohne Probleme.
    Es ist mir echt ein Rätsel ...

    Probiere doch mal eine andere Version downzuloaden.
    Übrigens kann ich 1.3.1380 nicht finden, bist du sicher, dass das die Version ist die du besitzt?
  • Hm.... interessante Sache. Es lag tatsächlich an der Version. Die 1380 war noch veraltet. Hab grad auf die aktuelle geupdated und siehe da - es funktioniert. Oh man ich glaub da kann man im Code lange suchen wenn das Problem durch das Programm selber verursacht wird :)

    RLP - vielen vielen vielen Dank für den tollen Support!


    ---------
    Tante Edith sagt:


    Eieieiei jetzt hab ich doch noch den Fehler...

    Was auf jeden Fall funktioniert ist wenn der Charakter in das Loch fällt. Er führt das Skript nur einmal aus. Super!

    Aber bei der Kollision mit dem Gegner führt er es weiterhin extrem oft aus - und das war was ich bisher immer nur getestet hatte. Nicht den Sprung in den Tod sondern das laufen in die Gegner :)

    Warscheinlich lief also auch mit der alten Version schon Dein Skriptteil :)

    Ich wollte soeben den Teil für das Collision-Event mit dem Gegner anpassen, damit es genauso klappt wie beim Fall in das Loch, jedoch hatte ich dort zur Erstellung DnD verwendet da ich die GML dafür nicht kenne und dort kann ich das leider nicht anpassen.

    Würdest Du noch ein letztes Mal im Skript anschauen wie ich also auch für den Tod mit dem Gegner realisieren kann?

    Gern stelle ich Dir auch das aktuelle Skript wieder zur Verfügung, da es hier schon viele Fortschritte gab.

    LG
    Mirko

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von mirko2002 ()

  • Ah, gut, dass das Kernproblem jetzt aufgedeckt ist. :)

    mirko2002 schrieb:

    Oh man ich glaub da kann man im Code lange suchen wenn das Problem durch das Programm selber verursacht wird :)

    Man kann sich bei GM-Studio nie sicher sein, es gibt zwar viele Stimmen die sagen, dass es mittlerweile bugfrei geworden ist, aber das ist nunmal nicht so.
    Auch bei den sogenannten "Stable"-Versionen, darf man das "Stable" nicht zu ernst nehmen. Hängt natürlich auch damit zusammen, dass es ein komplexes Programm ist und ständig neue Verbesserungen und Funktionen hinzugefügt werden.

    mirko2002 schrieb:

    RLP - vielen vielen vielen Dank für den tollen Support!

    Keine Ursache, Probleme sind ja da um gelöst zu werden. ;)

    mirko2002 schrieb:

    Würdest Du noch ein letztes Mal im Skript anschauen wie ich also auch für den Tod mit dem Gegner realisieren kann?

    Gern stelle ich Dir auch das aktuelle Skript wieder zur Verfügung, da es hier schon viele Fortschritte gab.

    Einen Quickfix kann ich dir gleich geben. Hier bei diesem Code im Kollisionsevent vom obj_player mit dem obj_enemy:

    GML-Quellcode

    1. if vspeed > 0
    2. {
    3. vspeed = -5
    4. //sound_play(sound_enemy_die)
    5. audio_play_sound(sound_enemy_die,1,0)
    6. global.points += 10
    7. instance_create(other.x,other.y+13,obj_enemy_die)
    8. with other do instance_destroy()
    9. }
    10. else
    11. {
    12. if deathhit == 0
    13. {
    14. //sound_play(sound_player_die)
    15. audio_play_sound(sound_player_die,1,0)
    16. global.lives1 -= 1
    17. loosecode()
    18. deathhit = 1
    19. }
    20. }
    Alles anzeigen

    Das Problem ist ja, dass der Spieler wenn er eigentlich gekillt werden soll, noch an der Stelle bleiben soll bis der Alphawert vom Übergang 1 erreicht hat.
    Dafür habe ich hier eine lokale Variable "deathhit" erstellt, alternativ kannst du auch das Gegnerobjekt löschen bei der Kollision -> damit wird die Überprüfung auch nur einmal ausgeführt, weil die Gegnerinstanz ja nachher nicht mehr existiert.
    Oder, du lässt beide Objekte, Player und Gegner, voneinander abbouncen mit move_bounce_all.
    Wenn du die Variante mit Variable verwendest muss diese natürlich zuerst im Create-Event erstellt und auf 0 gestellt werden werden, sowie im Step-Event im Abschnitt "Neuerstellung des Players" - da der Spieler ansonsten durch die Gegner durchlaufen würde.

    Eventuell lässt sich das Prinzip für dich ja ganz leicht auf deinen neuen Code übertragen. Wenn nicht, dann schicke mir einfach den Codefetzen, oder ein neues Example per PN. ;)
  • Wunderbar....

    Das ich auf die Idee mit der Variable nicht selber kam wurmt mich gerade etwas ;)

    Auf jeden Fall herzlichen Dank... werde mich nun dem Levelbau etwas widmen damit dort etwas Leben ins Spiel kommt. Wobei noch tausende Fragen sind aber das kommt alles nach und nach :)

    Gruss
  • Benutzer online 1

    1 Besucher