Externes Speichern/Laden von Rooms

    • Skript

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

    • Externes Speichern/Laden von Rooms

      Was macht es?
      Das Scriptpaket erlaubt das einfache Ein- und Auslesen der Rooms eines Game Maker Spiels.
      Dies kann ganz nützlich sein, wenn man sein Game Maker Projekt in eine andere Programmierumgebung übersetzen will oder mit mehreren Leuten am selben Projekt gleichzeitig arbeitet.
      Das Zupatchen von Levels oder durch den User erstellte Levels ist auch eine Möglichkeit, für die diese Scripts aber wohl eher noch bearbeitet werden sollten, da sie sonst zuviele Möglichkeiten bieten.

      Im Großen und Ganzen sollen diese Scripts also nur eine Basis für eigene Scripts sein, mit denen sich wohl eher nur erfahrene User rumschlagen werden. Testen kann aber jeder.


      Benutzung
      Nachdem man die Scripts ins Spiel importiert hat, kann es auch schon losgehen. Wer Englisch kann, greift einfach auf die Erklräungen innerhalb der Scripts zurück.
      Ansonsten:
      room_map_write(map) speichert den aktuellen Room in die Map map.
      room_map_read(room,map) ersetzt den Room room mit den Daten der Map map.
      Anm.: room_readwrite_all() ist ein Testscript.
      Mit ds_map_read und ds_map_write kann man diese Maps in Strings umwandeln und extern abspeichern.

      Die Scripts sind damit nicht fürs einfache Plug&Play-Benutzen gedacht. Sie können aber als Basis für komplexere, externe Levelspeicherung genutzt werden.
      Dies ist z.B. in Teamarbeit interessant.
      Ferner macht es die Mapstruktur einfach, allgemeine Änderungen eines Rooms vorzunehmen wie z.B. Tiles zu verschieben.
      Ich selbst werde evtl. noch einen Leveleditor entwickeln, der ein paar Optionen mehr bietet als der Room Editor des GMs.


      Einschränkungen
      Diese Lösung ist sehr allgemein und hat nur wenige Einschränkungen (um die man derzeit leider nicht drum herum kommt).
      So ist es leider nicht möglich, Instance oder Room Creation Codes zu speichern (das sind die, die man im Roomeditor definieren kann).
      Ferner können die Tile- und Instanzen-Ids vorerstellter Tiles bzw. Instanzen nicht beibehalten werden.


      Testen
      Die Scripts sind bisher noch ungetestet und wurden so von mir runtergeschrieben.
      Es mangelt mir derzeit an Spielprojekten und zum Teil auch Zeit, um eigene, umfangreiche Testläufe zu starten.
      Ich würde es daher sehr begrüßen, wenn jeder mit ein bisschen Zeit die Scripts in sein Spiel importiert und einen Probelauf startet.
      Die Anleitung dazu ist im Spoiler "versteckt".


      Testprotokoll
      Spoiler anzeigen

      Voraussetzungen
      • Keine Benutzung von Instance Creation Codes (das sind die, die man im Room Editor für einzelne Instanzen festlegen kann)
      • Keine Benutzung von Room Creation Codes (das sind die, die man im Roomeditor einstellen kann)
      • Registrierte Version des GM 7


      Installation
      1. Scripts (3 an der Zahl) runterladen und ins Spiel importieren
      2. Neuen, leeren Room hinzufügen und ihn zum ersten Raum machen
      3. Ins Room Creation Code dieses Raumes folgenden Code packen:

        GML-Quellcode

        1. room_readwrite_all()


      Testen
      Das Spiel nun einfach starten. Es sollte nun sämtliche Räume durchlaufen und extern speichern. Kurz darauf wird das Spiel sich neustarten.
      Nun gilt es, lediglich das Spiel zu spielen und auf Fehler zu prüfen.
      Sämtliche Fehler, die bei diesem Prozess auftreten, bitte in diesem Thread hier vermerken.


      Vielen Dank im Voraus fürs Testen und viel Spaß damit!

      Wünsche, Kritik, Anregungen etc. natürlich herzlich willkommen.

      Gruß,
      MewX
    • März 2012: Version 1.3
      Ich habe ein paar kleine Typos hier und da korrigiert, allerdings könnten einige Funktionen mit neueren GM-Versionen nicht kompatibel sein. Die Anpassung sollte aber recht einfach sein.

      -----------------------------------

      Es wurde bereits mit einigen Spielen erfolgreich getestet (Dank gilt hier copyboy) und macht einen sehr soliden Eindruck.
      Lediglich die Ausgabedateien sind im Moment riesig, da der GM die Darstellung von Datenstrukturen als Strings nicht gerade sparsam gestaltet.
      Ich werde die ganze Sache wohl mit einem externen Leveleditor kompatibel machen, den ich die Tage gefunden habe. Wenn dann alles so läuft, wie ich mir das vorstelle, haben wir eine echte Alternative zum Room Editor.

      Wer nichts runterladen will, kann auch einfach Copy&Pasten (die folgenden Scripts sind v1.3):
      room_write_map
      Spoiler anzeigen

      GML-Quellcode

      1. // room_write_map(ind)
      2. // Fills the indicated map with (almost) all of the current room's data and settings
      3. // Make sure to call instance_activate_all() before if you want all instances to be saved
      4. // Furthermore, it is advised that you call this function right after entering the room and be aware of persistent instances
      5. // Last but not least: Neither room creation code nor any particular instance creation code can be saved
      6. // coded by MewX, 2009-2012, v1.3
      7. // initial stuff
      8. var m,mt,q,t,b,n;
      9. m = argument0; // main map
      10. mt = ds_map_create(); // secondary map for individual tiles/instances
      11. q = ds_queue_create(); // queue for storing tiles/instances maps
      12. // store settings
      13. ds_map_add(m,"room_id",room);
      14. ds_map_add(m,"room_name",room_get_name(argument0));
      15. ds_map_add(m,"room_caption",room_caption);
      16. ds_map_add(m,"room_width",room_width);
      17. ds_map_add(m,"room_height",room_height);
      18. ds_map_add(m,"room_speed",room_speed);
      19. ds_map_add(m,"room_persistent",room_persistent);
      20. ds_map_add(m,"room_creation_code",""); // currently, room creation code cannot be read
      21. // store tiles
      22. b = background_create_from_screen(0,0,1,1,true,false,false);
      23. t = tile_add(b,0,0,1,1,0,0,0);
      24. tile_delete(t);
      25. background_delete(b);
      26. for (i=10000000;i<t;i+=1) { // tile ids start with 10^7
      27. if !tile_exists(i) continue;
      28. ds_map_clear(mt);
      29. ds_map_add(mt,"id",i);
      30. ds_map_add(mt,"x",tile_get_x(i));
      31. ds_map_add(mt,"y",tile_get_y(i));
      32. ds_map_add(mt,"left",tile_get_left(i));
      33. ds_map_add(mt,"top",tile_get_top(i));
      34. ds_map_add(mt,"width",tile_get_width(i));
      35. ds_map_add(mt,"height",tile_get_height(i));
      36. ds_map_add(mt,"depth",tile_get_depth(i));
      37. ds_map_add(mt,"visible",tile_get_visible(i));
      38. ds_map_add(mt,"xscale",tile_get_xscale(i));
      39. ds_map_add(mt,"yscale",tile_get_yscale(i));
      40. ds_map_add(mt,"background",tile_get_background(i));
      41. ds_map_add(mt,"blend",tile_get_blend(i));
      42. ds_map_add(mt,"alpha",tile_get_alpha(i));
      43. ds_queue_enqueue(q,ds_map_write(mt));
      44. }
      45. ds_map_add(m,"tiles",ds_queue_write(q));
      46. ds_queue_clear(q);
      47. // store backgrounds
      48. ds_map_add(m,"background_color",background_color);
      49. ds_map_add(m,"background_showcolor",background_showcolor);
      50. for (i=0;i<8;i+=1) {
      51. n = string(i);
      52. ds_map_add(m,"background_visible"+n,background_visible[i]);
      53. ds_map_add(m,"background_foreground"+n,background_foreground[i]);
      54. ds_map_add(m,"background_index"+n,background_index[i]);
      55. ds_map_add(m,"background_x"+n,background_x[i]);
      56. ds_map_add(m,"background_y"+n,background_y[i]);
      57. ds_map_add(m,"background_htiled"+n,background_htiled[i]);
      58. ds_map_add(m,"background_vtiled"+n,background_vtiled[i]);
      59. ds_map_add(m,"background_xscale"+n,background_xscale[i]);
      60. ds_map_add(m,"background_yscale"+n,background_yscale[i]);
      61. ds_map_add(m,"background_hspeed"+n,background_hspeed[i]);
      62. ds_map_add(m,"background_vspeed"+n,background_vspeed[i]);
      63. ds_map_add(m,"background_blend"+n,background_blend[i]);
      64. ds_map_add(m,"background_alpha"+n,background_alpha[i]);
      65. }
      66. // store views
      67. ds_map_add(m,"view_enabled",view_enabled);
      68. for (i=0;i<8;i+=1) {
      69. n = string(i);
      70. ds_map_add(m,"view_visible"+n,view_visible[i]);
      71. ds_map_add(m,"view_xview"+n,view_xview[i]);
      72. ds_map_add(m,"view_yview"+n,view_yview[i]);
      73. ds_map_add(m,"view_wview"+n,view_wview[i]);
      74. ds_map_add(m,"view_hview"+n,view_hview[i]);
      75. ds_map_add(m,"view_xport"+n,view_xport[i]);
      76. ds_map_add(m,"view_yport"+n,view_yport[i]);
      77. ds_map_add(m,"view_wport"+n,view_wport[i]);
      78. ds_map_add(m,"view_hport"+n,view_hport[i]);
      79. ds_map_add(m,"view_hborder"+n,view_hborder[i]);
      80. ds_map_add(m,"view_vborder"+n,view_vborder[i]);
      81. ds_map_add(m,"view_hspeed"+n,view_hspeed[i]);
      82. ds_map_add(m,"view_vspeed"+n,view_vspeed[i]);
      83. ds_map_add(m,"view_object"+n,view_object[i]);
      84. }
      85. // store instances
      86. b = object_add();
      87. t = instance_create(0,0,b);
      88. with (t) instance_destroy();
      89. object_delete(b);
      90. for (i=100000;i<t;i+=1) { // instance ids start with 10^5
      91. if !instance_exists(i) continue;
      92. ds_map_clear(mt);
      93. ds_map_add(mt,"id",i);
      94. ds_map_add(mt,"x",i.x);
      95. ds_map_add(mt,"y",i.y);
      96. ds_map_add(mt,"object",i.object_index);
      97. ds_queue_enqueue(q,ds_map_write(mt));
      98. }
      99. // finish
      100. ds_map_destroy(mt);
      101. ds_map_add(m,"instances",ds_queue_write(q));
      102. ds_queue_destroy(q);
      103. return m;
      Alles anzeigen

      room_read_map
      Spoiler anzeigen

      GML-Quellcode

      1. // room_read_map(ind, map)
      2. // Replaces the contents of room ind with data provided in map
      3. // Use this function to re-create a room
      4. // Calling this function for the current room might lead to unexpected results (e.g. the room speed won't be set)
      5. // Currently, neither tile nor instance ids can be restored to their previous values
      6. // coded by MewX, 2009-2012 v1.3
      7. if !room_exists(argument0) return false;
      8. var m,n,q,mt;
      9. m = argument1;
      10. q = ds_queue_create();
      11. mt = ds_map_create();
      12. room_tile_clear(argument0);
      13. room_instance_clear(argument0);
      14. // read settings
      15. /*room_set_name(argument0,ds_map_find_value(m,"room_name"));*/ // currently, no such function exists
      16. room_set_caption(argument0,ds_map_find_value(m,"room_caption"));
      17. room_set_width(argument0,ds_map_find_value(m,"room_width"));
      18. room_set_height(argument0,ds_map_find_value(m,"room_height"));
      19. /*room_set_speed(ds_map_find_value(m,"room_speed",room_speed)); */ // currently, no such function exists
      20. room_set_persistent(argument0,ds_map_find_value(m,"room_persistent"));
      21. room_set_code(argument0,ds_map_find_value(m,"room_speed="+string(ds_map_find_value(m,"room_speed"))+";"+"room_creation_code")); // work-around for setting room speed
      22. // read tiles
      23. ds_queue_read(q,ds_map_find_value(m,"tiles"));
      24. while (!ds_queue_empty(q)) {
      25. ds_map_read(mt,ds_queue_dequeue(q));
      26. room_tile_add_ext(argument0,
      27. ds_map_find_value(mt,"back"),
      28. ds_map_find_value(mt,"left"),
      29. ds_map_find_value(mt,"top"),
      30. ds_map_find_value(mt,"width"),
      31. ds_map_find_value(mt,"height"),
      32. ds_map_find_value(mt,"x"),
      33. ds_map_find_value(mt,"y"),
      34. ds_map_find_value(mt,"depth"),
      35. ds_map_find_value(mt,"xscale"),
      36. ds_map_find_value(mt,"yscale"),
      37. ds_map_find_value(mt,"alpha")
      38. );
      39. }
      40. // read backgrounds
      41. room_set_background_color(argument0,ds_map_find_value(m,"background_color"),ds_map_find_value(m,"background_showcolor"));
      42. for (i=0;i<8;i+=1) {
      43. n = string(i);
      44. room_set_background(argument0,i,
      45. ds_map_find_value(m,"background_visible"+n),
      46. ds_map_find_value(m,"background_foreground"+n),
      47. ds_map_find_value(m,"background_index"+n),
      48. ds_map_find_value(m,"background_x"+n),
      49. ds_map_find_value(m,"background_y"+n),
      50. ds_map_find_value(m,"background_htiled"+n),
      51. ds_map_find_value(m,"background_vtiled"+n),
      52. ds_map_find_value(m,"background_hspeed"+n),
      53. ds_map_find_value(m,"background_vspeed"+n),
      54. ds_map_find_value(m,"background_alpha"+n)
      55. );
      56. }
      57. // read views
      58. room_set_view_enabled(argument0,ds_map_find_value(m,"view_enabled"));
      59. for (i=0;i<8;i+=1) {
      60. n = string(i);
      61. room_set_view(argument0,i,
      62. ds_map_find_value(m,"view_visible"+n),
      63. ds_map_find_value(m,"view_xview"+n),
      64. ds_map_find_value(m,"view_yview"+n),
      65. ds_map_find_value(m,"view_wview"+n),
      66. ds_map_find_value(m,"view_hview"+n),
      67. ds_map_find_value(m,"view_xport"+n),
      68. ds_map_find_value(m,"view_yport"+n),
      69. ds_map_find_value(m,"view_wport"+n),
      70. ds_map_find_value(m,"view_hport"+n),
      71. ds_map_find_value(m,"view_hborder"+n),
      72. ds_map_find_value(m,"view_vborder"+n),
      73. ds_map_find_value(m,"view_hspeed"+n),
      74. ds_map_find_value(m,"view_vspeed"+n),
      75. ds_map_find_value(m,"view_object"+n)
      76. );
      77. }
      78. // read instances
      79. ds_queue_read(q,ds_map_find_value(m,"instances"));
      80. while (!ds_queue_empty(q)) {
      81. ds_map_read(mt,ds_queue_dequeue(q));
      82. room_instance_add(argument0,ds_map_find_value(mt,"x"),ds_map_find_value(mt,"y"),ds_map_find_value(mt,"object"));
      83. }
      84. // finish
      85. ds_map_destroy(mt);
      86. ds_queue_destroy(q);
      87. return true;
      Alles anzeigen

      room_readwrite_all
      Spoiler anzeigen

      GML-Quellcode

      1. // room_readwrite_all([internal use])
      2. // Stores all rooms in a file and restarts the game trying to use the previously saved data
      3. // !!!This function is only for testing purposes!!!
      4. // Call this script in the room creation code of the very first room which should be completely empty (and not the only room)
      5. // Data of non-existing rooms is ignored while reading
      6. // Make sure that your game doesn't use any instance or room creation code
      7. // coded by MewX, 2009-2012, v1.3
      8. // code to be executed at each room start
      9. if (argument0) {
      10. with(all) persistent = false;
      11. var m;
      12. m = ds_map_create();
      13. room_write_map(m);
      14. file_text_write_string(_rooms,ds_map_write(m));
      15. file_text_writeln(_rooms);
      16. ds_map_destroy(m);
      17. if room_exists(room_next(room)) {
      18. room_set_code(room_next(room),"room_readwrite_all(true);");
      19. room_goto_next();
      20. }
      21. else {
      22. file_text_close(_rooms);
      23. show_message("Finished. Restart the game now.");
      24. game_end();
      25. }
      26. return true;
      27. }
      28. // main code
      29. if file_exists(string(game_id)+"_rooms") {
      30. // rooms are already stored, begin replacing
      31. show_message("Replacing rooms...");
      32. var m,file;
      33. m = ds_map_create();
      34. file = file_text_open_read(string(game_id)+"_rooms");
      35. while (!file_text_eof(file)){
      36. ds_map_read(m,file_text_read_string(file));
      37. room_read_map(ds_map_find_value(m,"room_id"),m);
      38. file_text_readln(file);
      39. }
      40. ds_map_destroy(m);
      41. file_text_close(file);
      42. room_goto_next();
      43. }
      44. else {
      45. // store rooms
      46. // free objects from events that could interfere while storing rooms
      47. show_message("Storing rooms...");
      48. var n;
      49. n = object_add();
      50. object_delete(n);
      51. for (i=0;i<n;i+=1) {
      52. if !object_exists(i) continue;
      53. object_event_clear(i,ev_create,false);
      54. object_event_clear(i,ev_draw,false);
      55. object_event_clear(i,ev_other,ev_game_start);
      56. object_event_clear(i,ev_other,ev_room_start);
      57. object_event_clear(i,ev_other,ev_room_end);
      58. object_set_persistent(i,false);
      59. }
      60. // begin storing
      61. globalvar _rooms;
      62. _rooms = file_text_open_write(string(game_id)+"_rooms");
      63. room_set_code(room_next(room),"room_readwrite_all(true);");
      64. room_goto_next();
      65. }
      66. return true;
      Alles anzeigen

      Achtung: In späteren Versionen des GM haben sich ein paar Funktionen geändert. Schaut in die Hilfe und korrigiert einfach die Anzahl der Parameter!
    • Sorry, dass ich diesen alten Thread ausgrabe, aber ich würde die Scripts von MewX testen.
      Aber es ist kein Downloadlink vorhanden. MewX könntest du das Example nochmal hochladen? Ich würde es gerne testen.

      MfG Trixt0r

      Albert Einstein schrieb:

      Probleme kann man niemals mit derselben Denkweise lösen, durch die sie entstanden sind.
    • Das magere Interesse kann ich wirklich nicht verstehen, das ist DAS was ich schon immer gesucht habe.

      Der Game Maker bietet eben nicht den perfekten "Map Editor"

      ich bin für die aktivierung des Bedank o Mats in deinem Post, wirklich sehr nützliches Script, gerade darüber gestolpert, auch wenn die Lösung so genial wie auch "einfach" ist. Ich würde mich sehr freuen wenn du die Arbeit an diesem Script wieder aufnehmen könntest, denn so etwas könnte eine echte Alternative sein

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

    • Ich hab da nen Fehler gefunden ;)

      ___________________________________________
      COMPILATION ERROR in Script: room_write_map
      Error in code at line 23:
      b = background_create_from_screen(0,0,1,1,true,false,false);
      ^
      at position 60: Wrong number of arguments to function or script.
      ___________________________________________
      @7rust-dev

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

    • Das ging ja schnell ;)

      ..und gleich noch einen, nachdem ich mein Game das 2. mal ausführte kam der hier ;)
      ___________________________________________
      EXECUTION ERROR in creation code of room room_ex
      In script room_readwrite_all:
      In script room_read_map:
      Error in code at line 27:
      room_tile_add_ext(i,
      ^
      at position 24: Unknown variable i

      ___________________________________________
      @7rust-dev
    • Diese Lösung ist sehr allgemein und hat nur wenige Einschränkungen (um die man derzeit leider nicht drum herum kommt).
      So ist es leider nicht möglich, Instance oder Room Creation Codes zu speichern (das sind die, die man im Roomeditor definieren kann).
      Ferner können die Tile- und Instanzen-Ids vorerstellter Tiles bzw. Instanzen nicht beibehalten werden.


      Ansonsten wird das auch mit dem Game Maker 9 überflüssig, da man die Dinger dann sinnvoll (xml) exportieren kann. Vielleicht auch schon jetzt, wenn man das Export-Format "knackt".
      Das hier ist also eher "Legacy".
    • Wenn ich alle Scripte rein hab(3 Stück) und es so aufrufe:

      GML-Quellcode

      1. room_write_map("map")

      bekomme ich immer den Fehler: Data structure with index does not exist.

      Wenn ich es aufrufe mit:

      GML-Quellcode

      1. room_map_write("map")

      Unknown function or script: room_map_write

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

    • Rufst du das Script wirklich mit "map" als Parameter auf? Mach dich bitte mal genau mit maps vertraut und versuche es dann nochmal.

      Da diese Scripts mit dem GM9 wohl komplett überflüssig werden, werde ich sie wohl auch nicht mehr groß fixen. Wenn jemand wirklich darauf angewiesen ist und Hilfe, braucht leiste ich gerne meinen Beitrag, aber ansonsten werde ich sie wohl eher in Frieden ruhen lassen.